@marcusrbrown/infra 0.13.11 → 0.13.12

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.
Files changed (2) hide show
  1. package/dist/cli.js +36 -4
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -6949,7 +6949,7 @@ import { goke } from "goke";
6949
6949
  // package.json
6950
6950
  var package_default = {
6951
6951
  name: "@marcusrbrown/infra",
6952
- version: "0.13.11",
6952
+ version: "0.13.12",
6953
6953
  description: "Infrastructure management CLI \u2014 deploy automation, health checks, and MCP bridge",
6954
6954
  keywords: [
6955
6955
  "infra",
@@ -9356,6 +9356,36 @@ import { z as z13 } from "zod";
9356
9356
  var REPO2 = "marcusrbrown/infra";
9357
9357
  var WORKFLOW_NAME2 = "Deploy Dashboard";
9358
9358
  var WORKFLOW_URL2 = "https://github.com/marcusrbrown/infra/actions/workflows/deploy-dashboard.yaml";
9359
+ var CALVER_RE = /^\d{4}\.\d{2}\.\d+$/;
9360
+ var DIGEST_RE = /^sha256:[0-9a-f]{64}$/;
9361
+ function validateReleaseFlags(options) {
9362
+ const { imageVersion, digest, local } = options;
9363
+ if (local && (imageVersion !== undefined || digest !== undefined)) {
9364
+ throw new Error("--image-version and --digest are remote-only flags and cannot be used with --local. " + "Remove --local to dispatch the GitHub Actions workflow with release flags.");
9365
+ }
9366
+ if (imageVersion !== undefined && !CALVER_RE.test(imageVersion)) {
9367
+ throw new Error(`Invalid version ${JSON.stringify(imageVersion)}: must match YYYY.MM.N (e.g. 2026.06.47). ` + "Rejected: 'latest', semver, and injection strings are not accepted.");
9368
+ }
9369
+ if (digest !== undefined && imageVersion === undefined) {
9370
+ throw new Error("--digest requires --image-version. Either omit all release flags (no-version fallback) or provide --image-version (+ optional --digest).");
9371
+ }
9372
+ if (digest !== undefined && !DIGEST_RE.test(digest)) {
9373
+ throw new Error(`Invalid digest ${JSON.stringify(digest)}: must match sha256:<64 hex chars> (e.g. sha256:abc...def). ` + "Rejected: malformed digests are not accepted.");
9374
+ }
9375
+ }
9376
+ function buildRemoteArgv(options) {
9377
+ const argv = ["gh", "workflow", "run", WORKFLOW_NAME2, "--repo", REPO2];
9378
+ if (options.imageVersion !== undefined) {
9379
+ argv.push("-f", `version=${options.imageVersion}`);
9380
+ }
9381
+ if (options.digest !== undefined) {
9382
+ argv.push("-f", `digest=${options.digest}`);
9383
+ }
9384
+ return argv;
9385
+ }
9386
+ function formatArgv(argv) {
9387
+ return argv.map((arg) => /^[\w./:=@-]+$/.test(arg) ? arg : JSON.stringify(arg)).join(" ");
9388
+ }
9359
9389
  function getDashboardDeployEnv() {
9360
9390
  const path = process.env.PATH;
9361
9391
  const home = process.env.HOME;
@@ -9384,7 +9414,8 @@ function validateDashboardRemotePreconditions() {
9384
9414
  }
9385
9415
  }
9386
9416
  function registerDashboardDeploy(cli) {
9387
- cli.command("dashboard deploy", "Deploy the dashboard. Default mode triggers the GitHub Deploy Dashboard workflow, while --local runs apps/dashboard deploy directly with Bun.").option("--local", z13.boolean().default(false).describe("Run local deployment with Bun using apps/dashboard instead of triggering GitHub Actions.")).option("--dry-run", z13.boolean().default(false).describe("Validate deploy prerequisites and print planned actions without executing local deploy or dispatching workflow.")).example("# Trigger remote GitHub Actions deploy (default mode)").example("infra dashboard deploy").example("# Validate local deploy preconditions and planned command").example("infra dashboard deploy --local --dry-run").example("# Run local deploy with explicit SSH agent context").example("infra dashboard deploy --local").action(async (options) => {
9417
+ cli.command("dashboard deploy", "Deploy the dashboard. Default mode triggers the GitHub Deploy Dashboard workflow, while --local runs apps/dashboard deploy directly with Bun.").option("--local", z13.boolean().default(false).describe("Run local deployment with Bun using apps/dashboard instead of triggering GitHub Actions.")).option("--dry-run", z13.boolean().default(false).describe("Validate deploy prerequisites and print planned actions without executing local deploy or dispatching workflow.")).option("--image-version <version>", z13.string().optional().describe("CalVer version to deploy (e.g. 2026.06.47). Remote-only. Triggers the versioned release path and requires dashboard environment approval. Must match YYYY.MM.N. Forwarded as -f version=<value> to gh workflow run.")).option("--digest <digest>", z13.string().optional().describe("Expected sha256 digest (e.g. sha256:abc...def). Remote-only. Requires --image-version. When set, the workflow fails if GHCR resolves the tag to a different digest. Must match sha256:<64 hex chars>.")).example("# Trigger remote GitHub Actions deploy (default mode)").example("infra dashboard deploy").example("# Deploy a specific CalVer release via GitHub Actions").example("infra dashboard deploy --image-version 2026.06.47").example("# Deploy a specific release with digest cross-check").example("infra dashboard deploy --image-version 2026.06.47 --digest sha256:<64 hex>").example("# Validate local deploy preconditions and planned command").example("infra dashboard deploy --local --dry-run").example("# Run local deploy with explicit SSH agent context").example("infra dashboard deploy --local").action(async (options) => {
9418
+ validateReleaseFlags({ imageVersion: options.imageVersion, digest: options.digest, local: options.local });
9388
9419
  if (options.local) {
9389
9420
  const command = ["bun", "run", "--cwd", "apps/dashboard", "deploy"];
9390
9421
  if (options.dryRun) {
@@ -9405,13 +9436,14 @@ function registerDashboardDeploy(cli) {
9405
9436
  return;
9406
9437
  }
9407
9438
  validateDashboardRemotePreconditions();
9439
+ const remoteArgv = buildRemoteArgv({ imageVersion: options.imageVersion, digest: options.digest });
9408
9440
  if (options.dryRun) {
9409
9441
  console.log("Dry run: remote dashboard deploy");
9410
- console.log(`- command: gh workflow run "${WORKFLOW_NAME2}" --repo ${REPO2}`);
9442
+ console.log(`- command: ${formatArgv(remoteArgv)}`);
9411
9443
  console.log(`- workflow URL: ${WORKFLOW_URL2}`);
9412
9444
  return;
9413
9445
  }
9414
- const child = Bun.spawn(["gh", "workflow", "run", WORKFLOW_NAME2, "--repo", REPO2], {
9446
+ const child = Bun.spawn(remoteArgv, {
9415
9447
  stdout: "inherit",
9416
9448
  stderr: "inherit"
9417
9449
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marcusrbrown/infra",
3
- "version": "0.13.11",
3
+ "version": "0.13.12",
4
4
  "description": "Infrastructure management CLI — deploy automation, health checks, and MCP bridge",
5
5
  "keywords": [
6
6
  "infra",