viza 1.9.17 → 1.9.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,10 @@
1
+ import { registerCommand } from "../../../../core/commandRegistry.js";
2
+ import { usageCommand } from "./usage.js";
3
+ const descriptor = {
4
+ command: "actions usage",
5
+ description: "Show GitHub Actions usage (monthly, by OS)",
6
+ options: [],
7
+ run: usageCommand
8
+ };
9
+ registerCommand(descriptor);
10
+ export default descriptor;
@@ -0,0 +1,16 @@
1
+ export const policy = {
2
+ byEnv: {
3
+ "dev": [
4
+ "viza-designer",
5
+ "viza-deployer",
6
+ "viza-manager",
7
+ "viza-admin",
8
+ "viza-super"
9
+ ],
10
+ "prod": [
11
+ "viza-publisher",
12
+ "viza-admin",
13
+ "viza-super"
14
+ ]
15
+ }
16
+ };
@@ -0,0 +1,144 @@
1
+ import chalk from "chalk";
2
+ import { formatDateTime, renderCommandInline } from "../../../../ui/primitives/render-command.js";
3
+ function formatAge(iso) {
4
+ const diff = Date.now() - new Date(iso).getTime();
5
+ const sec = Math.floor(diff / 1000);
6
+ if (sec < 60)
7
+ return `${sec}s`;
8
+ const min = Math.floor(sec / 60);
9
+ const remSec = sec % 60;
10
+ // < 10 minutes → "Xm Ys"
11
+ if (min < 10)
12
+ return `${min}m ${remSec}s`;
13
+ // < 60 minutes → "Xm"
14
+ if (min < 60)
15
+ return `${min}m`;
16
+ const hr = Math.floor(min / 60);
17
+ const remMin = min % 60;
18
+ // < 10 hours → "Xh Ym"
19
+ if (hr < 10)
20
+ return `${hr}h ${remMin}m`;
21
+ // ≥ 10 hours → "Xh"
22
+ return `${hr}h`;
23
+ }
24
+ function formatDuration(start, end) {
25
+ const diff = new Date(end).getTime() - new Date(start).getTime();
26
+ const sec = Math.floor(diff / 1000);
27
+ if (sec < 60)
28
+ return `${sec}s`;
29
+ const min = Math.floor(sec / 60);
30
+ const rem = sec % 60;
31
+ return `${min}m ${rem}s`;
32
+ }
33
+ function pad(v, n) {
34
+ return v.padEnd(n, " ");
35
+ }
36
+ export async function showUsage(result) {
37
+ const env = result;
38
+ if (env.status !== "success" ||
39
+ env.kind !== "runtime" ||
40
+ !env.data?.result) {
41
+ return;
42
+ }
43
+ const { runs } = env.data.result;
44
+ if (!Array.isArray(runs)) {
45
+ throw new Error("invalid_dispatch_runs_result_shape");
46
+ }
47
+ console.log("\n📋 Dispatch Runs");
48
+ console.log("─".repeat(131));
49
+ const header = [
50
+ pad("RUN", 15),
51
+ pad("STATUS", 18),
52
+ pad("CONCLUSION", 15),
53
+ pad("COMMITTER", 18),
54
+ pad("CREATED_AT", 22),
55
+ pad("AGE", 13),
56
+ pad("DURATION", 13),
57
+ "ATTEMPT",
58
+ ].join(" ");
59
+ console.log(header);
60
+ console.log("─".repeat(131));
61
+ if (runs.length === 0) {
62
+ const emptyRow = chalk.gray(" (no dispatch runs found)");
63
+ console.log(emptyRow);
64
+ console.log("─".repeat(131));
65
+ console.log();
66
+ return;
67
+ }
68
+ for (const run of runs) {
69
+ let status;
70
+ let conclusion;
71
+ if (run.status === "completed") {
72
+ status = "completed";
73
+ switch (run.conclusion) {
74
+ case "success":
75
+ conclusion = "✅ success";
76
+ break;
77
+ case "failure":
78
+ conclusion = "❌ failure";
79
+ break;
80
+ case "cancelled":
81
+ conclusion = "⚪ cancelled";
82
+ break;
83
+ case "timed_out":
84
+ conclusion = "⏱ timed_out";
85
+ break;
86
+ case "skipped":
87
+ conclusion = "⏭ skipped";
88
+ break;
89
+ default:
90
+ conclusion = run.conclusion ?? "-";
91
+ }
92
+ }
93
+ else if (run.status === "in_progress") {
94
+ status = "⏳ in progress";
95
+ conclusion = "...";
96
+ }
97
+ else {
98
+ status = "⏳ queued";
99
+ conclusion = "-";
100
+ }
101
+ const committer = run.committer
102
+ ? `${run.committer.name}`
103
+ : "unknown";
104
+ const age = formatAge(run.createdAt);
105
+ const duration = run.status === "completed"
106
+ ? formatDuration(run.createdAt, run.updatedAt)
107
+ : "-";
108
+ const row = [
109
+ pad(String(run.id), 15),
110
+ pad(status, 18),
111
+ pad(conclusion, 14),
112
+ pad(committer, 18),
113
+ pad(formatDateTime(run.createdAt), 22),
114
+ pad(age, 13),
115
+ pad(duration, 13),
116
+ `#${run.attempt}`,
117
+ ].join(" ");
118
+ console.log(row);
119
+ }
120
+ console.log("─".repeat(131));
121
+ console.log();
122
+ // Hint section
123
+ if (runs.length > 0) {
124
+ const [firstRun] = runs;
125
+ if (!firstRun)
126
+ return;
127
+ const firstRunId = firstRun.id;
128
+ // derive binary name from process.argv (fallback safe)
129
+ const bin = (process.argv[1] || "viza").split("/").pop();
130
+ const sampleCmd = `${bin} dispatch logs ${firstRunId}`;
131
+ console.log();
132
+ console.log("💡 " + "\x1b[1mQuick Hint\x1b[0m");
133
+ console.log();
134
+ console.log(chalk.gray(" 👉 To quickly list fewer runs, use --limit:"));
135
+ console.log(` ${renderCommandInline(`${bin} dispatch runs --limit <n>`)}`);
136
+ console.log();
137
+ console.log(chalk.gray(" 👉 To view detailed logs for a specific run, use:"));
138
+ console.log(` ${renderCommandInline(`${bin} dispatch logs <runId>`)}`);
139
+ console.log();
140
+ console.log(chalk.gray(" 👉 Example:"));
141
+ console.log(` ${renderCommandInline(sampleCmd)}`);
142
+ console.log();
143
+ }
144
+ }
@@ -0,0 +1,43 @@
1
+ import { getEnv } from "../../../../context/env.js";
2
+ import { getRunner, RUNTIME_WORKER_CONTROL_INTENT } from "../../../../context/hubIntent.js";
3
+ import { dispatchIntentAndWait } from "../../../../core/dispatch.js";
4
+ import { policy } from "./policy.js";
5
+ /**
6
+ * viza dispatch runs
7
+ *
8
+ * Flow:
9
+ * 1) Resolve env (deterministic)
10
+ * 2) If --app → show GitHub Actions link locally (no dispatch)
11
+ * 3) Otherwise dispatch intent to hub
12
+ */
13
+ export async function usageCommand(options) {
14
+ // 1️⃣ Resolve environment
15
+ const env = getEnv();
16
+ const intent = RUNTIME_WORKER_CONTROL_INTENT;
17
+ const runner = getRunner();
18
+ // Resolve allowed teams (same contract as other commands)
19
+ const allowedTeams = Array.from(policy.byEnv[env]);
20
+ // 3️⃣ Dispatch intent to hub
21
+ const result = await dispatchIntentAndWait({
22
+ intent,
23
+ commandType: "actions.usage",
24
+ infraKey: "core",
25
+ runType: "runtime",
26
+ targetEnv: env,
27
+ allowedTeams,
28
+ selfHosted: options.selfHosted === true,
29
+ keepLog: options.keepLog === true,
30
+ flowGates: {
31
+ secrets: false,
32
+ },
33
+ payload: {
34
+ runner,
35
+ },
36
+ }, {
37
+ status: false,
38
+ log: "show",
39
+ });
40
+ console.log(JSON.stringify(result, null, 2));
41
+ // await showUsage(result);
42
+ return result;
43
+ }
@@ -142,7 +142,7 @@ export async function dispatchIntentAndWait(input, opts = {}) {
142
142
  showDispatchBanner(input, { cliVersion }, opts.status);
143
143
  // Show dispatch timestamp for log correlation
144
144
  const ts = formatDateTime(new Date().toISOString());
145
- console.log(chalk.dim(`\n🕒 Dispatch at `), chalk.yellow(`${ts}`), `\n`);
145
+ console.log(chalk.dim(`🕒 Dispatch at`), chalk.white(`${ts}`));
146
146
  // 1. Khởi tạo các Promise nhưng CHƯA await ngay
147
147
  const updateCheckPromise = checkForCliUpdateSoft().catch(() => null);
148
148
  const spinner = startSpinner("Waiting for dispatch session");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "viza",
3
- "version": "1.9.17",
3
+ "version": "1.9.20",
4
4
  "type": "module",
5
5
  "description": "Viza unified command line interface",
6
6
  "bin": {