viza 1.9.18 → 1.9.21

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.
@@ -2,7 +2,8 @@ export function getGlobalOptions() {
2
2
  return [
3
3
  { flags: "--status", description: "Show status only (no execution)" },
4
4
  { flags: "--keep-log", description: "Keep execution logs after completion" },
5
- { flags: "--self-hosted", description: "Use self-hosted runner (viza-builder)" }
5
+ { flags: "--self-hosted", description: "Use self-hosted runner (viza-builder)" },
6
+ { flags: "--cancel", description: "Cancel current running command (logical cancel, does not kill underlying job)" }
6
7
  ];
7
8
  }
8
9
  export function registerGlobalOptions(program) {
@@ -33,7 +33,9 @@ export async function bootstrapAgeCommand(options) {
33
33
  flowGates: {
34
34
  secrets: true,
35
35
  },
36
- payload: {}
36
+ payload: {
37
+ action: options.cancel ? "cancel" : "start"
38
+ }
37
39
  }, {
38
40
  status: options.status === true,
39
41
  log: "show",
@@ -31,7 +31,9 @@ export async function bootstrapAwsRolesAnywhereCommand(options) {
31
31
  flowGates: {
32
32
  secrets: true,
33
33
  },
34
- payload: {}
34
+ payload: {
35
+ action: options.cancel ? "cancel" : "start"
36
+ }
35
37
  }, {
36
38
  status: options.status === true,
37
39
  log: "show",
@@ -31,7 +31,9 @@ export async function rebootstrapAwsRolesAnywhereCommand(options) {
31
31
  flowGates: {
32
32
  secrets: true,
33
33
  },
34
- payload: {}
34
+ payload: {
35
+ action: options.cancel ? "cancel" : "start"
36
+ }
35
37
  }, {
36
38
  status: options.status === true,
37
39
  log: "show",
@@ -31,7 +31,9 @@ export async function rotateAwsRolesAnywhereCommand(options) {
31
31
  flowGates: {
32
32
  secrets: true,
33
33
  },
34
- payload: {}
34
+ payload: {
35
+ action: options.cancel ? "cancel" : "start"
36
+ }
35
37
  }, {
36
38
  status: options.status === true,
37
39
  log: "show",
@@ -31,7 +31,9 @@ export async function updateAwsRolesAnywhereRoleCommand(options) {
31
31
  flowGates: {
32
32
  secrets: true,
33
33
  },
34
- payload: {}
34
+ payload: {
35
+ action: options.cancel ? "cancel" : "start"
36
+ }
35
37
  }, {
36
38
  status: options.status === true,
37
39
  log: "show",
@@ -24,8 +24,8 @@ export async function loginBillingAwsCommand(options) {
24
24
  runType: "runtime",
25
25
  targetEnv: "prod",
26
26
  allowedTeams,
27
- selfHosted: options.selfHosted === true,
28
- keepLog: options.keepLog === true,
27
+ selfHosted: false,
28
+ keepLog: false,
29
29
  flowGates: {
30
30
  secrets: false,
31
31
  },
@@ -24,8 +24,8 @@ export async function logsCommand(runId, options) {
24
24
  runType: "infra",
25
25
  targetEnv: env,
26
26
  allowedTeams,
27
- selfHosted: options.selfHosted === true,
28
- keepLog: options.keepLog === true,
27
+ selfHosted: false,
28
+ keepLog: false,
29
29
  flowGates: {
30
30
  secrets: false,
31
31
  },
@@ -34,8 +34,8 @@ export async function runsCommand(options) {
34
34
  runType: "runtime",
35
35
  targetEnv: env,
36
36
  allowedTeams,
37
- selfHosted: options.selfHosted === true,
38
- keepLog: options.keepLog === true,
37
+ selfHosted: false,
38
+ keepLog: false,
39
39
  flowGates: {
40
40
  secrets: false,
41
41
  },
@@ -1,38 +1,6 @@
1
1
  import chalk from "chalk";
2
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
- }
3
+ import { formatAge, formatDuration, pad } from "../../../ui/theme.js";
36
4
  export async function showDispatchRuns(result) {
37
5
  const env = result;
38
6
  if (env.status !== "success" ||
@@ -33,7 +33,9 @@ export async function backupGithubSecretsCommand(options) {
33
33
  flowGates: {
34
34
  secrets: true,
35
35
  },
36
- payload: {}
36
+ payload: {
37
+ action: options.cancel ? "cancel" : "start"
38
+ }
37
39
  }, {
38
40
  status: options.status === true,
39
41
  log: "show",
@@ -50,14 +50,14 @@ export async function restoreGithubSecretsCommand(options) {
50
50
  runType: "runtime",
51
51
  targetEnv: env,
52
52
  allowedTeams,
53
- selfHosted: options.selfHosted === true,
54
- keepLog: options.keepLog === true,
53
+ selfHosted: false,
54
+ keepLog: false,
55
55
  flowGates: {
56
56
  secrets: true,
57
57
  },
58
58
  payload
59
59
  }, {
60
- status: options.status === true,
60
+ status: false,
61
61
  log: "show",
62
62
  });
63
63
  }
@@ -45,7 +45,8 @@ export async function deployCommandHubCommand(options) {
45
45
  secrets: true,
46
46
  },
47
47
  payload: {
48
- workerIntent
48
+ workerIntent,
49
+ action: options.cancel ? "cancel" : "start"
49
50
  }
50
51
  }, {
51
52
  status: options.status === true,
@@ -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,66 @@
1
+ import chalk from "chalk";
2
+ import { pad } from "../../../../ui/theme.js";
3
+ export async function showRuntimeUsage(result) {
4
+ const env = result;
5
+ if (env.status !== "success" ||
6
+ env.kind !== "runtime" ||
7
+ !env.data) {
8
+ console.log("Invalid runtime response");
9
+ return;
10
+ }
11
+ const { log, result: data } = env.data;
12
+ // -------------------------------
13
+ // 1. Render execution log
14
+ // -------------------------------
15
+ if (Array.isArray(log) && log.length > 0) {
16
+ console.log("\n🧩 Execution Steps");
17
+ console.log("─".repeat(80));
18
+ for (const step of log) {
19
+ const statusIcon = step.status === "ok" ? "✅" : "❌";
20
+ const duration = step.durationMs ? `${step.durationMs}ms` : "-";
21
+ console.log(`${statusIcon} [${step.step}] ${step.title} ${chalk.gray(`(${duration})`)}`);
22
+ if (step.message) {
23
+ console.log(chalk.gray(` ↳ ${step.message}`));
24
+ }
25
+ }
26
+ console.log("─".repeat(80));
27
+ }
28
+ // -------------------------------
29
+ // 2. Render usage by month
30
+ // -------------------------------
31
+ if (data?.usage) {
32
+ console.log("\n📊 Usage by Month");
33
+ console.log("─".repeat(60));
34
+ for (const m of data.usage) {
35
+ console.log(`${pad(m.month, 10)} ${pad(String(m.totalMinutes) + " min", 15)}`);
36
+ if (Array.isArray(m.byOS)) {
37
+ for (const os of m.byOS) {
38
+ console.log(chalk.gray(` ↳ ${os.os}: ${os.minutes} min`));
39
+ }
40
+ }
41
+ }
42
+ console.log("─".repeat(60));
43
+ }
44
+ // -------------------------------
45
+ // 3. Render usage by org + month
46
+ // -------------------------------
47
+ if (data?.byOrg) {
48
+ console.log("\n🏢 Usage by Organization");
49
+ console.log("─".repeat(60));
50
+ for (const org of data.byOrg) {
51
+ console.log(`\n${chalk.bold(org.org)}`);
52
+ for (const m of org.months || []) {
53
+ console.log(` ${pad(m.month, 10)} ${pad(String(m.totalMinutes) + " min", 15)}`);
54
+ }
55
+ }
56
+ console.log("─".repeat(60));
57
+ }
58
+ // -------------------------------
59
+ // 4. Raw hint (optional)
60
+ // -------------------------------
61
+ if (data?.raw?.usageItems) {
62
+ console.log();
63
+ console.log(chalk.gray("💡 Raw usage items available (use debug mode if needed)"));
64
+ }
65
+ console.log();
66
+ }
@@ -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
+ import { showRuntimeUsage } from "./show-usage.js";
6
+ /**
7
+ * viza dispatch runs
8
+ *
9
+ * Flow:
10
+ * 1) Resolve env (deterministic)
11
+ * 2) If --app → show GitHub Actions link locally (no dispatch)
12
+ * 3) Otherwise dispatch intent to hub
13
+ */
14
+ export async function usageCommand(options) {
15
+ // 1️⃣ Resolve environment
16
+ const env = getEnv();
17
+ const intent = RUNTIME_WORKER_CONTROL_INTENT;
18
+ const runner = getRunner();
19
+ // Resolve allowed teams (same contract as other commands)
20
+ const allowedTeams = Array.from(policy.byEnv[env]);
21
+ // 3️⃣ Dispatch intent to hub
22
+ const result = await dispatchIntentAndWait({
23
+ intent,
24
+ commandType: "actions.usage",
25
+ infraKey: "core",
26
+ runType: "runtime",
27
+ targetEnv: env,
28
+ allowedTeams,
29
+ selfHosted: false,
30
+ keepLog: false,
31
+ flowGates: {
32
+ secrets: false,
33
+ },
34
+ payload: {
35
+ runner,
36
+ },
37
+ }, {
38
+ status: false,
39
+ log: "show",
40
+ });
41
+ await showRuntimeUsage(result);
42
+ return result;
43
+ }
@@ -29,8 +29,8 @@ export async function loginAwsCommand(options) {
29
29
  runType: "runtime",
30
30
  targetEnv: env,
31
31
  allowedTeams,
32
- selfHosted: options.selfHosted === true,
33
- keepLog: options.keepLog === true,
32
+ selfHosted: false,
33
+ keepLog: false,
34
34
  flowGates: {
35
35
  secrets: false,
36
36
  },
@@ -38,7 +38,7 @@ export async function loginAwsCommand(options) {
38
38
  ...(options.ssm ? { intent: "ssm" } : {}),
39
39
  }
40
40
  }, {
41
- status: options.status === true,
41
+ status: false,
42
42
  log: "show",
43
43
  });
44
44
  if (!result ||
@@ -1 +1,34 @@
1
1
  export const theme = {};
2
+ export function formatAge(iso) {
3
+ const diff = Date.now() - new Date(iso).getTime();
4
+ const sec = Math.floor(diff / 1000);
5
+ if (sec < 60)
6
+ return `${sec}s`;
7
+ const min = Math.floor(sec / 60);
8
+ const remSec = sec % 60;
9
+ // < 10 minutes → "Xm Ys"
10
+ if (min < 10)
11
+ return `${min}m ${remSec}s`;
12
+ // < 60 minutes → "Xm"
13
+ if (min < 60)
14
+ return `${min}m`;
15
+ const hr = Math.floor(min / 60);
16
+ const remMin = min % 60;
17
+ // < 10 hours → "Xh Ym"
18
+ if (hr < 10)
19
+ return `${hr}h ${remMin}m`;
20
+ // ≥ 10 hours → "Xh"
21
+ return `${hr}h`;
22
+ }
23
+ export function formatDuration(start, end) {
24
+ const diff = new Date(end).getTime() - new Date(start).getTime();
25
+ const sec = Math.floor(diff / 1000);
26
+ if (sec < 60)
27
+ return `${sec}s`;
28
+ const min = Math.floor(sec / 60);
29
+ const rem = sec % 60;
30
+ return `${min}m ${rem}s`;
31
+ }
32
+ export function pad(v, n) {
33
+ return v.padEnd(n, " ");
34
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "viza",
3
- "version": "1.9.18",
3
+ "version": "1.9.21",
4
4
  "type": "module",
5
5
  "description": "Viza unified command line interface",
6
6
  "bin": {
@@ -28,7 +28,7 @@
28
28
  "release:full": "rm -rf dist && npx npm-check-updates -u && npm install && git add package.json package-lock.json && git commit -m 'chore(deps): auto update dependencies before release' || echo 'No changes' && node versioning.js && npm login && npm publish --tag latest --access public && git push"
29
29
  },
30
30
  "dependencies": {
31
- "@vizamodo/viza-dispatcher": "^1.5.51",
31
+ "@vizamodo/viza-dispatcher": "^1.5.52",
32
32
  "adm-zip": "^0.5.16",
33
33
  "chalk": "^5.6.2",
34
34
  "clipboardy": "^5.3.1",