@intentius/chant 0.124.28 → 0.124.29
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.
- package/dist/build-params.d.ts +34 -1
- package/dist/build-params.d.ts.map +1 -1
- package/dist/build-params.js +31 -1
- package/dist/change-set-graph.d.ts +8 -1
- package/dist/change-set-graph.d.ts.map +1 -1
- package/dist/change-set-graph.js +4 -2
- package/dist/change-set.d.ts +10 -0
- package/dist/change-set.d.ts.map +1 -1
- package/dist/change-set.js +4 -3
- package/dist/cli/build-params-cli.d.ts +7 -1
- package/dist/cli/build-params-cli.d.ts.map +1 -1
- package/dist/cli/build-params-cli.js +17 -8
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/commands/build.js +6 -3
- package/dist/cli/handlers/approve.d.ts.map +1 -1
- package/dist/cli/handlers/approve.js +45 -0
- package/dist/cli/handlers/build.d.ts.map +1 -1
- package/dist/cli/handlers/build.js +15 -4
- package/dist/cli/handlers/fan-out.d.ts +9 -0
- package/dist/cli/handlers/fan-out.d.ts.map +1 -1
- package/dist/cli/handlers/fan-out.js +40 -3
- package/dist/cli/handlers/lifecycle-gc.d.ts +19 -0
- package/dist/cli/handlers/lifecycle-gc.d.ts.map +1 -0
- package/dist/cli/handlers/lifecycle-gc.js +143 -0
- package/dist/cli/handlers/pr.d.ts +11 -3
- package/dist/cli/handlers/pr.d.ts.map +1 -1
- package/dist/cli/handlers/pr.js +134 -26
- package/dist/cli/handlers/promote.d.ts +7 -0
- package/dist/cli/handlers/promote.d.ts.map +1 -1
- package/dist/cli/handlers/promote.js +210 -33
- package/dist/cli/handlers/release.d.ts +62 -5
- package/dist/cli/handlers/release.d.ts.map +1 -1
- package/dist/cli/handlers/release.js +414 -28
- package/dist/cli/handlers/run.d.ts +11 -1
- package/dist/cli/handlers/run.d.ts.map +1 -1
- package/dist/cli/handlers/run.js +67 -6
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +61 -10
- package/dist/cli/parse-args.d.ts.map +1 -1
- package/dist/cli/parse-args.js +24 -2
- package/dist/cli/registry.d.ts +15 -3
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/cli/run-events.d.ts +3 -2
- package/dist/cli/run-events.d.ts.map +1 -1
- package/dist/cli/run-events.js +5 -3
- package/dist/components/auto-release.d.ts +2 -0
- package/dist/components/auto-release.d.ts.map +1 -1
- package/dist/components/auto-release.js +1 -0
- package/dist/components/capability.d.ts +9 -0
- package/dist/components/capability.d.ts.map +1 -1
- package/dist/components/driver.d.ts +8 -0
- package/dist/components/driver.d.ts.map +1 -1
- package/dist/components/driver.js +35 -0
- package/dist/components/fan-out-inputs.d.ts +69 -0
- package/dist/components/fan-out-inputs.d.ts.map +1 -0
- package/dist/components/fan-out-inputs.js +169 -0
- package/dist/components/fan-out-record.d.ts +13 -0
- package/dist/components/fan-out-record.d.ts.map +1 -1
- package/dist/components/fan-out-record.js +16 -0
- package/dist/components/fan-out-run.d.ts.map +1 -1
- package/dist/components/fan-out-run.js +50 -0
- package/dist/components/fan-out.d.ts +4 -0
- package/dist/components/fan-out.d.ts.map +1 -1
- package/dist/components/pr-pipeline.d.ts +25 -0
- package/dist/components/pr-pipeline.d.ts.map +1 -1
- package/dist/components/pr-pipeline.js +22 -4
- package/dist/components/promote.d.ts +23 -0
- package/dist/components/promote.d.ts.map +1 -1
- package/dist/components/promote.js +60 -2
- package/dist/components/release-compile.d.ts +9 -0
- package/dist/components/release-compile.d.ts.map +1 -1
- package/dist/components/release-compile.js +9 -3
- package/dist/components/release-gate.d.ts +11 -1
- package/dist/components/release-gate.d.ts.map +1 -1
- package/dist/components/release-gate.js +10 -4
- package/dist/components/wave-plan.d.ts +5 -0
- package/dist/components/wave-plan.d.ts.map +1 -1
- package/dist/components/wave-plan.js +10 -2
- package/dist/config.d.ts +38 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +2 -0
- package/dist/flag-params.d.ts +54 -0
- package/dist/flag-params.d.ts.map +1 -0
- package/dist/flag-params.js +130 -0
- package/dist/lifecycle/__fixtures__/publish-fakes.d.ts +120 -0
- package/dist/lifecycle/__fixtures__/publish-fakes.d.ts.map +1 -0
- package/dist/lifecycle/__fixtures__/publish-fakes.js +304 -0
- package/dist/lifecycle/change-set-store.d.ts +2 -1
- package/dist/lifecycle/change-set-store.d.ts.map +1 -1
- package/dist/lifecycle/change-set-store.js +2 -1
- package/dist/lifecycle/delivery-metrics.d.ts +139 -0
- package/dist/lifecycle/delivery-metrics.d.ts.map +1 -0
- package/dist/lifecycle/delivery-metrics.js +145 -0
- package/dist/lifecycle/deploy-outcome.d.ts +81 -0
- package/dist/lifecycle/deploy-outcome.d.ts.map +1 -0
- package/dist/lifecycle/deploy-outcome.js +101 -0
- package/dist/lifecycle/gate-change-set.d.ts +10 -1
- package/dist/lifecycle/gate-change-set.d.ts.map +1 -1
- package/dist/lifecycle/gate-change-set.js +35 -3
- package/dist/lifecycle/gate-ledger.d.ts +2 -3
- package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
- package/dist/lifecycle/git.d.ts +30 -1
- package/dist/lifecycle/git.d.ts.map +1 -1
- package/dist/lifecycle/git.js +31 -5
- package/dist/lifecycle/index.d.ts +4 -0
- package/dist/lifecycle/index.d.ts.map +1 -1
- package/dist/lifecycle/index.js +4 -0
- package/dist/lifecycle/mixed-environment.d.ts +95 -0
- package/dist/lifecycle/mixed-environment.d.ts.map +1 -0
- package/dist/lifecycle/mixed-environment.js +154 -0
- package/dist/lifecycle/publish-attachments.d.ts +79 -0
- package/dist/lifecycle/publish-attachments.d.ts.map +1 -0
- package/dist/lifecycle/publish-attachments.js +179 -0
- package/dist/lifecycle/publish-credentials.d.ts +37 -0
- package/dist/lifecycle/publish-credentials.d.ts.map +1 -0
- package/dist/lifecycle/publish-credentials.js +69 -0
- package/dist/lifecycle/publish-declaration.d.ts +97 -0
- package/dist/lifecycle/publish-declaration.d.ts.map +1 -0
- package/dist/lifecycle/publish-declaration.js +83 -0
- package/dist/lifecycle/publish-forge.d.ts +53 -0
- package/dist/lifecycle/publish-forge.d.ts.map +1 -0
- package/dist/lifecycle/publish-forge.js +298 -0
- package/dist/lifecycle/publish-npm.d.ts +61 -0
- package/dist/lifecycle/publish-npm.d.ts.map +1 -0
- package/dist/lifecycle/publish-npm.js +242 -0
- package/dist/lifecycle/publish-oci.d.ts +64 -0
- package/dist/lifecycle/publish-oci.d.ts.map +1 -0
- package/dist/lifecycle/publish-oci.js +383 -0
- package/dist/lifecycle/publish-record.d.ts +66 -0
- package/dist/lifecycle/publish-record.d.ts.map +1 -0
- package/dist/lifecycle/publish-record.js +84 -0
- package/dist/lifecycle/publish-targets.d.ts +45 -0
- package/dist/lifecycle/publish-targets.d.ts.map +1 -0
- package/dist/lifecycle/publish-targets.js +85 -0
- package/dist/lifecycle/release-cut.d.ts +48 -1
- package/dist/lifecycle/release-cut.d.ts.map +1 -1
- package/dist/lifecycle/release-cut.js +116 -23
- package/dist/lifecycle/release-join.d.ts +95 -0
- package/dist/lifecycle/release-join.d.ts.map +1 -0
- package/dist/lifecycle/release-join.js +139 -0
- package/dist/lifecycle/release-publish.d.ts +312 -0
- package/dist/lifecycle/release-publish.d.ts.map +1 -0
- package/dist/lifecycle/release-publish.js +335 -0
- package/dist/lifecycle/release-revocation.d.ts +80 -0
- package/dist/lifecycle/release-revocation.d.ts.map +1 -0
- package/dist/lifecycle/release-revocation.js +123 -0
- package/dist/lifecycle/release-store.d.ts +12 -2
- package/dist/lifecycle/release-store.d.ts.map +1 -1
- package/dist/lifecycle/release-store.js +4 -2
- package/dist/lifecycle/release-verify.d.ts +61 -0
- package/dist/lifecycle/release-verify.d.ts.map +1 -0
- package/dist/lifecycle/release-verify.js +92 -0
- package/dist/lifecycle/release-workstation.d.ts +91 -0
- package/dist/lifecycle/release-workstation.d.ts.map +1 -0
- package/dist/lifecycle/release-workstation.js +180 -0
- package/dist/lifecycle/retention-policy.d.ts +45 -0
- package/dist/lifecycle/retention-policy.d.ts.map +1 -0
- package/dist/lifecycle/retention-policy.js +43 -0
- package/dist/lifecycle/retention.d.ts +185 -0
- package/dist/lifecycle/retention.d.ts.map +1 -0
- package/dist/lifecycle/retention.js +400 -0
- package/dist/plan-summary.d.ts.map +1 -1
- package/dist/plan-summary.js +8 -2
- package/dist/pr-loop.d.ts +7 -0
- package/dist/pr-loop.d.ts.map +1 -1
- package/dist/pr-loop.js +23 -4
- package/dist/pr-report-url.d.ts +82 -0
- package/dist/pr-report-url.d.ts.map +1 -0
- package/dist/pr-report-url.js +174 -0
- package/dist/provenance.d.ts +2 -2
- package/dist/provenance.d.ts.map +1 -1
- package/dist/run-event-store.d.ts +29 -2
- package/dist/run-event-store.d.ts.map +1 -1
- package/dist/run-event-store.js +50 -3
- package/dist/run-event-stream.d.ts +2 -1
- package/dist/run-event-stream.d.ts.map +1 -1
- package/dist/run-event-stream.js +5 -1
- package/dist/run-event.d.ts +19 -1
- package/dist/run-event.d.ts.map +1 -1
- package/dist/run-event.js +2 -0
- package/dist/wave-runtime.mjs +260 -229
- package/dist/workspace/__fixtures__/flag-workspace.d.ts +31 -0
- package/dist/workspace/__fixtures__/flag-workspace.d.ts.map +1 -0
- package/dist/workspace/__fixtures__/flag-workspace.js +114 -0
- package/dist/workspace/change-set.schema.json +5 -1
- package/dist/workspace/check.schema.json +4 -2
- package/dist/workspace/checks/records.d.ts +9 -1
- package/dist/workspace/checks/records.d.ts.map +1 -1
- package/dist/workspace/checks/records.js +35 -1
- package/dist/workspace/checks.d.ts +1 -0
- package/dist/workspace/checks.d.ts.map +1 -1
- package/dist/workspace/checks.js +2 -1
- package/dist/workspace/ci-green.d.ts +8 -0
- package/dist/workspace/ci-green.d.ts.map +1 -1
- package/dist/workspace/ci-green.js +10 -3
- package/dist/workspace/declaration.d.ts +16 -0
- package/dist/workspace/declaration.d.ts.map +1 -1
- package/dist/workspace/declaration.js +26 -0
- package/dist/workspace/declaration.schema.json +64 -0
- package/dist/workspace/declared-kinds.d.ts +16 -0
- package/dist/workspace/declared-kinds.d.ts.map +1 -1
- package/dist/workspace/declared-kinds.js +25 -0
- package/dist/workspace/delivery-metrics.d.ts +91 -0
- package/dist/workspace/delivery-metrics.d.ts.map +1 -0
- package/dist/workspace/delivery-metrics.js +217 -0
- package/dist/workspace/delivery-metrics.schema.json +519 -0
- package/dist/workspace/flags-read.d.ts +37 -0
- package/dist/workspace/flags-read.d.ts.map +1 -0
- package/dist/workspace/flags-read.js +103 -0
- package/dist/workspace/flags.d.ts +100 -0
- package/dist/workspace/flags.d.ts.map +1 -0
- package/dist/workspace/flags.js +98 -0
- package/dist/workspace/graph-cli.js +1 -1
- package/dist/workspace/intent-cli.d.ts +11 -2
- package/dist/workspace/intent-cli.d.ts.map +1 -1
- package/dist/workspace/intent-cli.js +54 -5
- package/dist/workspace/intent-trace.d.ts +219 -0
- package/dist/workspace/intent-trace.d.ts.map +1 -0
- package/dist/workspace/intent-trace.js +314 -0
- package/dist/workspace/intent.d.ts +30 -6
- package/dist/workspace/intent.d.ts.map +1 -1
- package/dist/workspace/intent.js +141 -21
- package/dist/workspace/intent.schema.json +702 -6
- package/dist/workspace/overlap.d.ts +146 -0
- package/dist/workspace/overlap.d.ts.map +1 -0
- package/dist/workspace/overlap.js +276 -0
- package/dist/workspace/reason-codes.d.ts +2 -0
- package/dist/workspace/reason-codes.d.ts.map +1 -1
- package/dist/workspace/reason-codes.js +3 -0
- package/dist/workspace/records.d.ts +15 -2
- package/dist/workspace/records.d.ts.map +1 -1
- package/dist/workspace/records.js +32 -0
- package/dist/workspace/records.schema.json +21 -2
- package/dist/workspace/reference-kinds/flag/flag.kind.mjs +32 -0
- package/dist/workspace/reference-kinds/flag/flag.schema.json +53 -0
- package/dist/workspace/releases.d.ts +9 -0
- package/dist/workspace/releases.d.ts.map +1 -1
- package/dist/workspace/releases.js +9 -0
- package/dist/workspace/releases.schema.json +123 -1
- package/dist/workspace/run-event.schema.json +10 -3
- package/dist/workspace/status-gates.d.ts +8 -0
- package/dist/workspace/status-gates.d.ts.map +1 -1
- package/dist/workspace/status.d.ts +78 -0
- package/dist/workspace/status.d.ts.map +1 -1
- package/dist/workspace/status.js +170 -3
- package/dist/workspace/status.schema.json +198 -1
- package/dist/workspace/wip.d.ts.map +1 -1
- package/dist/workspace/wip.js +11 -3
- package/package.json +1 -1
- package/src/build-params.test.ts +46 -0
- package/src/build-params.ts +55 -1
- package/src/change-set-graph.ts +10 -2
- package/src/change-set.ts +14 -3
- package/src/cli/build-params-cli.ts +22 -9
- package/src/cli/commands/build.ts +6 -3
- package/src/cli/handlers/approve-release.test.ts +5 -1
- package/src/cli/handlers/approve-revoked.test.ts +155 -0
- package/src/cli/handlers/approve.ts +47 -0
- package/src/cli/handlers/build.test.ts +15 -0
- package/src/cli/handlers/build.ts +17 -4
- package/src/cli/handlers/fan-out.test.ts +180 -1
- package/src/cli/handlers/fan-out.ts +38 -3
- package/src/cli/handlers/intent-trace.e2e.test.ts +201 -0
- package/src/cli/handlers/lifecycle-gc.test.ts +126 -0
- package/src/cli/handlers/lifecycle-gc.ts +146 -0
- package/src/cli/handlers/pr.test.ts +148 -1
- package/src/cli/handlers/pr.ts +139 -28
- package/src/cli/handlers/promote.test.ts +280 -2
- package/src/cli/handlers/promote.ts +210 -34
- package/src/cli/handlers/release-implicit.e2e.test.ts +12 -4
- package/src/cli/handlers/release-join.e2e.test.ts +185 -0
- package/src/cli/handlers/release-publish-targets.e2e.test.ts +295 -0
- package/src/cli/handlers/release-verify.e2e.test.ts +117 -0
- package/src/cli/handlers/release-workstation-ci.e2e.test.ts +135 -0
- package/src/cli/handlers/release.e2e.test.ts +146 -32
- package/src/cli/handlers/release.ts +415 -28
- package/src/cli/handlers/run-auto-release.test.ts +9 -0
- package/src/cli/handlers/run-release.test.ts +55 -0
- package/src/cli/handlers/run.ts +69 -5
- package/src/cli/main.test.ts +1 -0
- package/src/cli/main.ts +61 -10
- package/src/cli/parse-args.ts +19 -2
- package/src/cli/registry.ts +15 -3
- package/src/cli/run-events.ts +5 -2
- package/src/components/auto-release.test.ts +9 -0
- package/src/components/auto-release.ts +3 -0
- package/src/components/capability.ts +9 -0
- package/src/components/driver.test.ts +24 -0
- package/src/components/driver.ts +36 -0
- package/src/components/fan-out-inputs.test.ts +85 -0
- package/src/components/fan-out-inputs.ts +192 -0
- package/src/components/fan-out-record.test.ts +10 -0
- package/src/components/fan-out-record.ts +19 -0
- package/src/components/fan-out-run.ts +48 -0
- package/src/components/fan-out.ts +4 -0
- package/src/components/pr-pipeline.ts +35 -4
- package/src/components/promote.ts +68 -2
- package/src/components/release-compile.ts +17 -3
- package/src/components/release-gate.ts +18 -4
- package/src/components/wave-plan.ts +15 -2
- package/src/config.ts +8 -0
- package/src/flag-params.test.ts +144 -0
- package/src/flag-params.ts +134 -0
- package/src/lifecycle/__fixtures__/publish-fakes.ts +351 -0
- package/src/lifecycle/change-set-store.ts +2 -1
- package/src/lifecycle/delivery-metrics.ts +263 -0
- package/src/lifecycle/deploy-outcome.ts +147 -0
- package/src/lifecycle/gate-change-set.ts +37 -6
- package/src/lifecycle/gate-ledger.ts +2 -2
- package/src/lifecycle/git.ts +61 -8
- package/src/lifecycle/index.ts +4 -0
- package/src/lifecycle/mixed-environment.test.ts +97 -0
- package/src/lifecycle/mixed-environment.ts +204 -0
- package/src/lifecycle/publish-attachments.ts +196 -0
- package/src/lifecycle/publish-credentials.ts +84 -0
- package/src/lifecycle/publish-declaration.ts +95 -0
- package/src/lifecycle/publish-forge.ts +325 -0
- package/src/lifecycle/publish-npm.ts +259 -0
- package/src/lifecycle/publish-oci.ts +396 -0
- package/src/lifecycle/publish-record.ts +113 -0
- package/src/lifecycle/publish-resume.test.ts +168 -0
- package/src/lifecycle/publish-targets.test.ts +494 -0
- package/src/lifecycle/publish-targets.ts +100 -0
- package/src/lifecycle/release-cut.test.ts +74 -2
- package/src/lifecycle/release-cut.ts +158 -22
- package/src/lifecycle/release-flag.test.ts +112 -0
- package/src/lifecycle/release-join.test.ts +68 -0
- package/src/lifecycle/release-join.ts +182 -0
- package/src/lifecycle/release-publish.test.ts +225 -0
- package/src/lifecycle/release-publish.ts +568 -0
- package/src/lifecycle/release-revocation.ts +147 -0
- package/src/lifecycle/release-store.ts +15 -4
- package/src/lifecycle/release-verify.test.ts +110 -0
- package/src/lifecycle/release-verify.ts +120 -0
- package/src/lifecycle/release-workstation.test.ts +204 -0
- package/src/lifecycle/release-workstation.ts +216 -0
- package/src/lifecycle/retention-growth.e2e.test.ts +279 -0
- package/src/lifecycle/retention-policy.ts +63 -0
- package/src/lifecycle/retention.test.ts +363 -0
- package/src/lifecycle/retention.ts +508 -0
- package/src/plan-summary.test.ts +20 -0
- package/src/plan-summary.ts +8 -1
- package/src/pr-loop.ts +25 -4
- package/src/pr-report-url.test.ts +131 -0
- package/src/pr-report-url.ts +209 -0
- package/src/provenance.ts +2 -2
- package/src/run-event-store.ts +63 -3
- package/src/run-event-stream.ts +4 -1
- package/src/run-event.ts +21 -1
- package/src/workspace/__fixtures__/flag-workspace.ts +132 -0
- package/src/workspace/__fixtures__/older-records/change-set-984534ea9.json +100 -0
- package/src/workspace/__fixtures__/older-records/older-records.json +326 -0
- package/src/workspace/change-set.schema.json +5 -1
- package/src/workspace/check.schema.json +4 -2
- package/src/workspace/checks/records.ts +35 -1
- package/src/workspace/checks.ts +2 -1
- package/src/workspace/ci-green.ts +14 -3
- package/src/workspace/declaration.schema.json +64 -0
- package/src/workspace/declaration.test.ts +28 -0
- package/src/workspace/declaration.ts +38 -0
- package/src/workspace/declared-kinds.ts +40 -1
- package/src/workspace/delivery-metrics.schema.json +519 -0
- package/src/workspace/delivery-metrics.test.ts +236 -0
- package/src/workspace/delivery-metrics.ts +286 -0
- package/src/workspace/flags-read.ts +121 -0
- package/src/workspace/flags.test.ts +141 -0
- package/src/workspace/flags.ts +157 -0
- package/src/workspace/graph-cli.ts +1 -1
- package/src/workspace/intent-cli.ts +46 -5
- package/src/workspace/intent-trace.test.ts +173 -0
- package/src/workspace/intent-trace.ts +484 -0
- package/src/workspace/intent.schema.json +702 -6
- package/src/workspace/intent.ts +148 -25
- package/src/workspace/older-records.test.ts +412 -0
- package/src/workspace/overlap.test.ts +165 -0
- package/src/workspace/overlap.ts +340 -0
- package/src/workspace/read-contract.e2e.test.ts +2 -1
- package/src/workspace/reason-codes.test.ts +5 -0
- package/src/workspace/reason-codes.ts +3 -0
- package/src/workspace/record-assets.test.ts +2 -1
- package/src/workspace/records-contract.e2e.test.ts +2 -1
- package/src/workspace/records.schema.json +21 -2
- package/src/workspace/records.ts +36 -2
- package/src/workspace/reference-kinds/flag/flag.kind.mjs +32 -0
- package/src/workspace/reference-kinds/flag/flag.schema.json +53 -0
- package/src/workspace/releases.schema.json +123 -1
- package/src/workspace/releases.ts +11 -0
- package/src/workspace/run-event.schema.json +10 -3
- package/src/workspace/status-contract.test.ts +29 -0
- package/src/workspace/status-gates.ts +8 -0
- package/src/workspace/status-mixed.test.ts +152 -0
- package/src/workspace/status-revoked.test.ts +153 -0
- package/src/workspace/status.schema.json +198 -1
- package/src/workspace/status.ts +254 -3
- package/src/workspace/wip.ts +11 -2
package/src/cli/handlers/run.ts
CHANGED
|
@@ -15,7 +15,7 @@ import { pointAnswerCommand, renderHuman, renderJson } from "../../op/local-outp
|
|
|
15
15
|
import { loadPlugins } from "../plugins";
|
|
16
16
|
import { recordGateApproval } from "./operator";
|
|
17
17
|
import { formatError, formatWarning, formatSuccess, formatBold, formatInfo } from "../format";
|
|
18
|
-
import {
|
|
18
|
+
import { parseParamFlags } from "../build-params-cli";
|
|
19
19
|
import type { CommandContext } from "../registry";
|
|
20
20
|
import { stewardBesideFor, stewardFormFor, stewardTurnLeaseName, DEFAULT_STEWARD_ENV, type StewardDeclaration } from "../../op/steward";
|
|
21
21
|
import { holdBesideLease } from "../../op/steward-beside";
|
|
@@ -470,7 +470,13 @@ async function runOpLogOnRuntime(ctx: CommandContext, name: string): Promise<num
|
|
|
470
470
|
export function humanRunEventLine(e: RunEvent): string {
|
|
471
471
|
const x = e as unknown as Record<string, unknown>;
|
|
472
472
|
const where = [x.component, x.phase, x.step].filter((v): v is string => typeof v === "string").join("/");
|
|
473
|
-
const detail = [
|
|
473
|
+
const detail = [
|
|
474
|
+
where,
|
|
475
|
+
typeof x.status === "string" ? x.status : "",
|
|
476
|
+
// A blocked component (#4007) names what held it back.
|
|
477
|
+
typeof x.blockedBy === "string" ? `by ${x.blockedBy}` : "",
|
|
478
|
+
typeof x.error === "string" ? x.error : "",
|
|
479
|
+
].filter(Boolean).join(" ");
|
|
474
480
|
return `${String(x.at ?? "")} ${String(x.type).padEnd(16)}${detail}`.trimEnd();
|
|
475
481
|
}
|
|
476
482
|
|
|
@@ -926,6 +932,7 @@ export async function recordAutoReleasesForRun(
|
|
|
926
932
|
runId: string,
|
|
927
933
|
disabled: boolean,
|
|
928
934
|
runOrigin: RunOrigin = { forge: "local" },
|
|
935
|
+
releaseDigest?: string,
|
|
929
936
|
): Promise<ReleaseRecord[]> {
|
|
930
937
|
const recorded: ReleaseRecord[] = [];
|
|
931
938
|
for (const componentResult of results) {
|
|
@@ -942,6 +949,8 @@ export async function recordAutoReleasesForRun(
|
|
|
942
949
|
// #1035, #4020: who approved at the gate and which resolution admitted the deploy.
|
|
943
950
|
...(gateApprover(componentResult) ? { approver: gateApprover(componentResult) } : {}),
|
|
944
951
|
...(gateAdmission(componentResult) ? { admission: gateAdmission(componentResult) } : {}),
|
|
952
|
+
// #4043: the release the deploy was made under, when `--release` named one.
|
|
953
|
+
...(releaseDigest !== undefined ? { releaseDigest } : {}),
|
|
945
954
|
},
|
|
946
955
|
{ disabled },
|
|
947
956
|
);
|
|
@@ -1051,6 +1060,44 @@ function refusesNoRecordOn(runtime: Pick<OpRuntimeProvider, "name">): boolean {
|
|
|
1051
1060
|
return true;
|
|
1052
1061
|
}
|
|
1053
1062
|
|
|
1063
|
+
/**
|
|
1064
|
+
* Resolve the release `chant run --components --release` names (#4043), or the
|
|
1065
|
+
* reason it can't be used. The run builds from the checked-out commit, so the
|
|
1066
|
+
* release's commit must be HEAD, and the release needs a target for `env`.
|
|
1067
|
+
*/
|
|
1068
|
+
export async function resolveRunRelease(ref: string, env: string, cwd: string) {
|
|
1069
|
+
const { fetchLifecycle, getHeadCommit } = await import("../../lifecycle/git");
|
|
1070
|
+
const { resolveRelease } = await import("../../lifecycle/release-store");
|
|
1071
|
+
const { targetFor } = await import("../../components/release-promote");
|
|
1072
|
+
await fetchLifecycle({ cwd }).catch(() => false);
|
|
1073
|
+
const found = await resolveRelease(ref, { cwd });
|
|
1074
|
+
if (!found) return `no release is labelled or digested "${ref}" in this member`;
|
|
1075
|
+
const name = found.label ?? found.release.releaseDigest;
|
|
1076
|
+
const head = await getHeadCommit({ cwd });
|
|
1077
|
+
if (found.release.commit !== head) {
|
|
1078
|
+
return `release ${name} was cut from ${found.release.commit.slice(0, 12)} and this checkout is at ${head.slice(0, 12)}; run builds from the checkout, so check out the release's commit, or deploy it with \`chant components promote --release\``;
|
|
1079
|
+
}
|
|
1080
|
+
const target = targetFor(found.release, env);
|
|
1081
|
+
if ("error" in target) return target.error;
|
|
1082
|
+
return { releaseDigest: found.release.releaseDigest, label: found.label, release: found.release };
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
/** A rebuilt image need not digest as the release's own did; say so, as promote does. Never fails the run. */
|
|
1086
|
+
async function warnOnArtifactMismatch(release: import("../../lifecycle/release-store").Release, recorded: readonly ReleaseRecord[]): Promise<void> {
|
|
1087
|
+
try {
|
|
1088
|
+
const { releaseArtifactMismatches } = await import("../../components/release-promote");
|
|
1089
|
+
const { readBuildManifest } = await import("../../lifecycle/build-ledger-store");
|
|
1090
|
+
const mismatches = await releaseArtifactMismatches(
|
|
1091
|
+
release,
|
|
1092
|
+
recorded.map((r) => ({ component: r.component, source: r })),
|
|
1093
|
+
(digest) => readBuildManifest(digest).catch(() => null),
|
|
1094
|
+
);
|
|
1095
|
+
for (const message of mismatches) console.error(formatWarning({ message }));
|
|
1096
|
+
} catch {
|
|
1097
|
+
// The record is written; a manifest that can't be read is not worth failing the run for.
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1054
1101
|
async function runComponentSelection(ctx: CommandContext): Promise<number> {
|
|
1055
1102
|
const selector = ctx.args.path;
|
|
1056
1103
|
if (!selector || selector === ".") {
|
|
@@ -1066,11 +1113,13 @@ async function runComponentSelection(ctx: CommandContext): Promise<number> {
|
|
|
1066
1113
|
|
|
1067
1114
|
const projectPath = resolve(".");
|
|
1068
1115
|
const { config } = await loadChantConfig(projectPath).catch(() => ({ config: {} as ChantConfig }));
|
|
1069
|
-
|
|
1116
|
+
// #4024: with --env, a workspace member's flag records back their parameters.
|
|
1117
|
+
const { resolveFlaggedBuildParams } = await import("../../flag-params");
|
|
1118
|
+
const paramsResolution = await resolveFlaggedBuildParams(projectPath, config.buildParams, {
|
|
1070
1119
|
cli: parseParamFlags(ctx.args.param),
|
|
1071
1120
|
paramsFile: ctx.args.paramsFile,
|
|
1072
1121
|
verbose: ctx.args.verbose,
|
|
1073
|
-
});
|
|
1122
|
+
}, ctx.args.env);
|
|
1074
1123
|
if (!paramsResolution.success) {
|
|
1075
1124
|
for (const message of paramsResolution.errors) console.error(message);
|
|
1076
1125
|
return 1;
|
|
@@ -1088,6 +1137,20 @@ async function runComponentSelection(ctx: CommandContext): Promise<number> {
|
|
|
1088
1137
|
}
|
|
1089
1138
|
|
|
1090
1139
|
const env = ctx.args.env ?? "local";
|
|
1140
|
+
|
|
1141
|
+
// #4043: `--release <label|digest>` says this run deploys that release. The
|
|
1142
|
+
// run builds from the checked-out commit, so the release must have been cut
|
|
1143
|
+
// from it, and must have a target for the environment. Both are checked
|
|
1144
|
+
// before anything deploys; nothing is inferred when the flag is absent.
|
|
1145
|
+
let underRelease: { releaseDigest: string; label: string | null; release: import("../../lifecycle/release-store").Release } | undefined;
|
|
1146
|
+
if (ctx.args.release) {
|
|
1147
|
+
const refused = await resolveRunRelease(ctx.args.release, env, projectPath);
|
|
1148
|
+
if (typeof refused === "string") {
|
|
1149
|
+
console.error(formatError({ message: refused, hint: "List the releases with: chant release list" }));
|
|
1150
|
+
return 1;
|
|
1151
|
+
}
|
|
1152
|
+
underRelease = refused;
|
|
1153
|
+
}
|
|
1091
1154
|
// Seed cross-component/cross-stack outputs from upstream jobs' dumped files
|
|
1092
1155
|
// (`--seed-outputs`), so a single-component run resolves references to a
|
|
1093
1156
|
// component that ran in an earlier CI job.
|
|
@@ -1207,7 +1270,8 @@ async function runComponentSelection(ctx: CommandContext): Promise<number> {
|
|
|
1207
1270
|
if (result.success && result.run) {
|
|
1208
1271
|
// #3955: a run that records nothing has no release to report either.
|
|
1209
1272
|
const disabled = resolveAutoReleaseDisabled(config, ctx.args.noReleaseRecord) || ledgerRecordingOff();
|
|
1210
|
-
const recorded = await recordAutoReleasesForRun(result.run.results, env, release.runId, disabled, release.runOrigin);
|
|
1273
|
+
const recorded = await recordAutoReleasesForRun(result.run.results, env, release.runId, disabled, release.runOrigin, underRelease?.releaseDigest);
|
|
1274
|
+
if (underRelease) await warnOnArtifactMismatch(underRelease.release, recorded);
|
|
1211
1275
|
// `--digest-file` (#2602): the releases this run recorded, one
|
|
1212
1276
|
// `<component>=<digest>` line each, the form `chant components promote
|
|
1213
1277
|
// --digest` takes. A generated promote job reads it to promote exactly
|
package/src/cli/main.test.ts
CHANGED
package/src/cli/main.ts
CHANGED
|
@@ -263,12 +263,18 @@ CI:
|
|
|
263
263
|
signs its tags with.
|
|
264
264
|
|
|
265
265
|
Releases:
|
|
266
|
-
release cut [<label>] [--build <command>] [--param <k=v>]
|
|
267
|
-
[--src <dir>] [-o <file>] [--lexicon <name>]
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
266
|
+
release cut [<label>] [--yes] [--build <command>] [--param <k=v>]
|
|
267
|
+
[--params-file <file>] [--src <dir>] [-o <file>] [--lexicon <name>]
|
|
268
|
+
[--actor <name>] [--sign [<key file>]] [--json]
|
|
269
|
+
A dry run of a cut of this member from HEAD, which
|
|
270
|
+
must be clean, on trunk and pushed, and carry a
|
|
271
|
+
ci/green tag: compile every environment in the
|
|
272
|
+
config's environments and print what the cut would
|
|
273
|
+
build, record and tag, and what publishes where.
|
|
274
|
+
--yes cuts: builds the artifacts once, stores the
|
|
275
|
+
release on chant/lifecycle under its digest, records
|
|
276
|
+
the actor and run id, tags the commit release/<label>
|
|
277
|
+
here, and prints the next command.
|
|
272
278
|
--build runs before each environment's templates are
|
|
273
279
|
read, with CHANT_ENV set; {env} in --params-file is
|
|
274
280
|
replaced by the environment. --sign signs the cut with
|
|
@@ -277,6 +283,21 @@ Releases:
|
|
|
277
283
|
what chant build --env <env> writes: --src <dir> is
|
|
278
284
|
the build root, -o <file> the output (dist/build.yaml),
|
|
279
285
|
--lexicon narrows it.
|
|
286
|
+
release publish <label|digest> [--yes] [--allow-unsigned]
|
|
287
|
+
[--require-provenance] [--json]
|
|
288
|
+
Publish a cut release to the targets release.publish
|
|
289
|
+
in chant.config.ts declares (npm, OCI registries,
|
|
290
|
+
forge release assets), each with an SBOM and the
|
|
291
|
+
release's provenance. A dry run without --yes.
|
|
292
|
+
Refuses a revoked release, one whose signature does
|
|
293
|
+
not verify against .chant/allowed_signers unless
|
|
294
|
+
--allow-unsigned, and with a target a checkout that
|
|
295
|
+
is not the release's commit. Warns first when the run
|
|
296
|
+
has no OIDC token, so what it publishes carries no
|
|
297
|
+
OIDC provenance; --require-provenance refuses instead.
|
|
298
|
+
release verify <label|digest> [--json]
|
|
299
|
+
Check, offline, that the release was signed by a key
|
|
300
|
+
.chant/allowed_signers lists at the release's commit.
|
|
280
301
|
release list [--json] Every release of this member with its targets, its
|
|
281
302
|
cuts and the environments that run it.
|
|
282
303
|
release export <label|digest> --env <env> [-o <dir>] [--json]
|
|
@@ -344,7 +365,9 @@ Ops:
|
|
|
344
365
|
run, and prints that order first (#3950).
|
|
345
366
|
On success, auto-emits a release-ledger record per
|
|
346
367
|
component that published a digest (default: on;
|
|
347
|
-
--no-release-record to opt out; #597)
|
|
368
|
+
--no-release-record to opt out; #597).
|
|
369
|
+
--release <label|digest>: the run is of that release,
|
|
370
|
+
cut from this checkout's commit; the records name it (#4043)
|
|
348
371
|
--progress-json: stream one NDJSON RunProgressEvent
|
|
349
372
|
per line to stdout while the run executes, for a
|
|
350
373
|
consumer to render live wave/component/phase/step
|
|
@@ -443,6 +466,13 @@ Workspace (level 1, #2524):
|
|
|
443
466
|
beside it and marks the members whose digests differ.
|
|
444
467
|
Read only; never fetches. --json prints the
|
|
445
468
|
read-contract document
|
|
469
|
+
workspace metrics [dir] [--env <env>] [--member <name>] [--since <date>] [--json]
|
|
470
|
+
The four DORA metrics per member and environment
|
|
471
|
+
(#4039): deployment frequency, lead time from commit
|
|
472
|
+
to running release, change failure rate and time to
|
|
473
|
+
restore, from the deploy records, releases and ci
|
|
474
|
+
revoked tags. Eight weeks back by default. Read only;
|
|
475
|
+
never fetches. --json prints the read-contract document
|
|
446
476
|
workspace records [--kind <kind file>] [--current] [--uncommitted | --at <rev>] [--base <rev>] [--require attested] [--json]
|
|
447
477
|
Without --kind, every record kind the declaration
|
|
448
478
|
names. Read the records a record kind locates, validated
|
|
@@ -757,7 +787,7 @@ Workspace (level 1, #2524):
|
|
|
757
787
|
Each composite instance the members declare, with the
|
|
758
788
|
components whose contract can deploy it; an instance
|
|
759
789
|
with none lists an empty set
|
|
760
|
-
workspace graph --intent <path[:start-end]|path#symbol> [--at <rev>] [--kind <kind file>...] [--follow-squash] [--json]
|
|
790
|
+
workspace graph --intent <path[:start-end]|path#symbol|member/node|sha> [--at <rev>] [--kind <kind file>...] [--follow-squash] [--json]
|
|
761
791
|
The intent graph over one region: the commits that
|
|
762
792
|
touched it, the decisions whose constrains cover it,
|
|
763
793
|
the artifacts they pin, and findings with closed codes.
|
|
@@ -796,6 +826,13 @@ Lifecycle (alias: lc):
|
|
|
796
826
|
executes the plan (production-like names also need
|
|
797
827
|
--confirm-prod, or an interactive confirmation)
|
|
798
828
|
lifecycle log [env] History of lifecycle snapshots
|
|
829
|
+
lifecycle gc [--yes] [--push] [--json]
|
|
830
|
+
Prune stored change sets, releases and run event
|
|
831
|
+
files by the retention policy (#4036). A dry run
|
|
832
|
+
without --yes; --yes writes one commit removing
|
|
833
|
+
them on the local chant/lifecycle and deletes the
|
|
834
|
+
run event files; --push pushes it. History is
|
|
835
|
+
never rewritten, and the ledgers are never pruned
|
|
799
836
|
|
|
800
837
|
Plan scenarios (#1292):
|
|
801
838
|
scenario check Evaluate every declared Scenario's expect clause
|
|
@@ -834,7 +871,11 @@ Component release ledger + status:
|
|
|
834
871
|
--member <name>, both commands: a workspace
|
|
835
872
|
member's loop, gate op pr-<n>-<member>;
|
|
836
873
|
--resume <file> finishes an apply that failed
|
|
837
|
-
partway under the same approval
|
|
874
|
+
partway under the same approval;
|
|
875
|
+
--events-json, both commands: the run-event
|
|
876
|
+
stream on stdout; --report-url <s3 or file URL>,
|
|
877
|
+
both commands: copy the report, the change set
|
|
878
|
+
and the events to <url>/<pr>/<commit>/)
|
|
838
879
|
components release <env> Append one immutable release record
|
|
839
880
|
(--component <name> --digest <sha256:...>
|
|
840
881
|
[--git-sha <sha>] [--run-id <id>] [--actor <name>]);
|
|
@@ -858,7 +899,9 @@ Component release ledger + status:
|
|
|
858
899
|
components rollback <env> Redeploy an earlier release of an environment
|
|
859
900
|
from its recorded digest (--component <name>
|
|
860
901
|
[--digest <sha256:...>]; defaults to the release
|
|
861
|
-
before the current one; --dry-run prints the plan)
|
|
902
|
+
before the current one; --dry-run prints the plan).
|
|
903
|
+
--release <label|digest> restores every component
|
|
904
|
+
of that release through the release gate (#4035)
|
|
862
905
|
components redeploy <env> Redeploy the release an environment's ledger
|
|
863
906
|
records as current, after a deploy that failed
|
|
864
907
|
partway (--component <name> [--digest <sha256:...>];
|
|
@@ -1265,6 +1308,10 @@ export const commandRegistry: CommandDef[] = [
|
|
|
1265
1308
|
{ name: "ci workflow", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/ci-green-cli")).runCiWorkflow(ctx) },
|
|
1266
1309
|
// #4026: the release cut from a green commit (ws-104). Imported on first use.
|
|
1267
1310
|
{ name: "release cut", runsNoConfig: true, handler: async (ctx) => (await import("./handlers/release")).runReleaseCut(ctx) },
|
|
1311
|
+
// #4027: publish a cut release, to the targets #4047 declares.
|
|
1312
|
+
{ name: "release publish", runsNoConfig: true, handler: async (ctx) => (await import("./handlers/release")).runReleasePublish(ctx) },
|
|
1313
|
+
// #4049: check a release's signature offline.
|
|
1314
|
+
{ name: "release verify", runsNoConfig: true, handler: async (ctx) => (await import("./handlers/release")).runReleaseVerify(ctx) },
|
|
1268
1315
|
{ name: "release list", runsNoConfig: true, handler: async (ctx) => (await import("./handlers/release")).runReleaseList(ctx) },
|
|
1269
1316
|
{ name: "release export", runsNoConfig: true, handler: async (ctx) => (await import("./handlers/release")).runReleaseExport(ctx) },
|
|
1270
1317
|
{ name: "release compile", runsNoConfig: true, handler: async (ctx) => (await import("./handlers/release")).runReleaseCompile(ctx) },
|
|
@@ -1323,6 +1370,8 @@ export const commandRegistry: CommandDef[] = [
|
|
|
1323
1370
|
{ name: "workspace work", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/work-cli")).runWorkspaceWork(ctx) },
|
|
1324
1371
|
// #3033 — the agent run record: what each run cost and which commits it made. chant records runs and never starts one.
|
|
1325
1372
|
{ name: "workspace runs", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/runs-cli")).runWorkspaceRuns(ctx) },
|
|
1373
|
+
// #4039 — DORA metrics from the deploy, release and revocation records.
|
|
1374
|
+
{ name: "workspace metrics", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/delivery-metrics")).runWorkspaceMetrics(ctx) },
|
|
1326
1375
|
{ name: "workspace status", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/status")).runWorkspaceStatus(ctx) },
|
|
1327
1376
|
{ name: "workspace lineage", handler: async (ctx) => (await import("../workspace/lineage-cli")).runWorkspaceLineage(ctx) },
|
|
1328
1377
|
{ name: "workspace upgrade", handler: async (ctx) => (await import("../workspace/lineage-upgrade-cli")).runWorkspaceUpgrade(ctx) },
|
|
@@ -1373,6 +1422,8 @@ export const commandRegistry: CommandDef[] = [
|
|
|
1373
1422
|
{ name: "lifecycle whoami", requiresPlugins: true, handler: runLifecycleWhoami },
|
|
1374
1423
|
{ name: "lifecycle teardown", requiresPlugins: true, handler: runLifecycleTeardown },
|
|
1375
1424
|
{ name: "lifecycle log", handler: runLifecycleLog },
|
|
1425
|
+
// #4036 — retention's garbage collection. Imported on first use.
|
|
1426
|
+
{ name: "lifecycle gc", runsNoConfig: true, handler: async (ctx) => (await import("./handlers/lifecycle-gc")).runLifecycleGc(ctx) },
|
|
1376
1427
|
|
|
1377
1428
|
// Plan scenarios (#1292) — fully offline, no plugin network calls, but
|
|
1378
1429
|
// requiresPlugins:true so the build step has serializers to partition
|
package/src/cli/parse-args.ts
CHANGED
|
@@ -74,12 +74,15 @@ const BOOLEAN_FLAGS = new Set([
|
|
|
74
74
|
"--uncommitted",
|
|
75
75
|
"--allow-code",
|
|
76
76
|
"--allow-skip",
|
|
77
|
+
"--allow-unsigned",
|
|
78
|
+
"--require-provenance",
|
|
77
79
|
"--root-only",
|
|
78
80
|
"--generated",
|
|
79
81
|
"--decide",
|
|
80
82
|
"--record-plans",
|
|
81
83
|
"--loopback",
|
|
82
84
|
"--artifacts",
|
|
85
|
+
"--push",
|
|
83
86
|
]);
|
|
84
87
|
|
|
85
88
|
/**
|
|
@@ -248,6 +251,9 @@ export function parseArgs(args: string[]): ParsedArgs {
|
|
|
248
251
|
result.dryRun = true;
|
|
249
252
|
} else if (arg === "--yes") {
|
|
250
253
|
result.yes = true;
|
|
254
|
+
} else if (arg === "--push") {
|
|
255
|
+
// `chant lifecycle gc --yes --push` (#4036): push the prune commit.
|
|
256
|
+
result.push = true;
|
|
251
257
|
} else if (arg === "--confirm-prod") {
|
|
252
258
|
result.confirmProd = true;
|
|
253
259
|
} else if (arg === "--strict") {
|
|
@@ -375,6 +381,17 @@ export function parseArgs(args: string[]): ParsedArgs {
|
|
|
375
381
|
if (!result.forge || result.forge.startsWith("-")) throw new Error("--forge needs a forge: --forge github|gitlab|forgejo");
|
|
376
382
|
} else if (arg === "--require-review") {
|
|
377
383
|
result.requireReview = true;
|
|
384
|
+
} else if (arg === "--report-url") {
|
|
385
|
+
// `chant components pr-plan|pr-apply --report-url <url>` (#4007).
|
|
386
|
+
const url = args[++i];
|
|
387
|
+
if (!url || url.startsWith("-")) throw new Error("--report-url needs a URL: --report-url s3://<bucket>/<prefix> or file://<directory>");
|
|
388
|
+
result.reportUrl = url;
|
|
389
|
+
} else if (arg === "--allow-unsigned") {
|
|
390
|
+
// `chant release publish --allow-unsigned` (#4049).
|
|
391
|
+
result.allowUnsigned = true;
|
|
392
|
+
} else if (arg === "--require-provenance") {
|
|
393
|
+
// `chant release publish --require-provenance` (#4049).
|
|
394
|
+
result.requireProvenance = true;
|
|
378
395
|
} else if (arg === "--pr-loop") {
|
|
379
396
|
result.prLoop = true;
|
|
380
397
|
} else if (arg === "--before-script") {
|
|
@@ -427,11 +444,11 @@ export function parseArgs(args: string[]): ParsedArgs {
|
|
|
427
444
|
// `chant workspace graph --composites` (#2662)
|
|
428
445
|
result.composites = true;
|
|
429
446
|
} else if (arg === "--intent") {
|
|
430
|
-
// `chant workspace graph --intent <path[:start-end]|path#symbol>` (#2651), or `--intent --record <id>` with no region.
|
|
447
|
+
// `chant workspace graph --intent <path[:start-end]|path#symbol|member/node|sha>` (#2651), or `--intent --record <id>` with no region.
|
|
431
448
|
const value = args[i + 1];
|
|
432
449
|
if (value !== undefined && !value.startsWith("-")) result.intent = args[++i];
|
|
433
450
|
else if (args.includes("--record")) result.intent = "";
|
|
434
|
-
else throw new Error("--intent needs a region: --intent <path[:start-end]|path#symbol>, or --intent --record <id>");
|
|
451
|
+
else throw new Error("--intent needs a region: --intent <path[:start-end]|path#symbol|member/node|sha>, or --intent --record <id>");
|
|
435
452
|
} else if (arg === "--follow-squash") {
|
|
436
453
|
// `chant workspace graph --intent ... --follow-squash` and `chant workspace runs --follow-squash` (#3035)
|
|
437
454
|
result.followSquash = true;
|
package/src/cli/registry.ts
CHANGED
|
@@ -149,6 +149,10 @@ export interface ParsedArgs {
|
|
|
149
149
|
allowCode?: boolean;
|
|
150
150
|
/** `chant components promote --allow-skip` (#4030): promote past a step of the member's declared promotion order. */
|
|
151
151
|
allowSkip?: boolean;
|
|
152
|
+
/** `chant release publish --allow-unsigned` (#4049): publish a release with no signature that verifies, with a warning. Never overrides identity.gates.release. */
|
|
153
|
+
allowUnsigned?: boolean;
|
|
154
|
+
/** `chant release publish --require-provenance` (#4049): refuse a run with no OIDC token, where it warns. */
|
|
155
|
+
requireProvenance?: boolean;
|
|
152
156
|
/** `chant workspace upgrade --source <repo>[#<member>]` (#2551): move the scope to another template. */
|
|
153
157
|
source?: string;
|
|
154
158
|
/** `chant workspace adopt-lineage --tags <glob>` and `hash-index --tags` (#2551): the tags to compare. */
|
|
@@ -164,6 +168,8 @@ export interface ParsedArgs {
|
|
|
164
168
|
/** `chant lifecycle teardown <env> --yes` — execute the planned deletion
|
|
165
169
|
* (#1222). Without it the command plans and stops. */
|
|
166
170
|
yes?: boolean;
|
|
171
|
+
/** `chant lifecycle gc --yes --push` (#4036): push the commit the prune wrote to chant/lifecycle. Without it the prune stays local. */
|
|
172
|
+
push?: boolean;
|
|
167
173
|
/** `chant lifecycle teardown <env> --yes --confirm-prod` — the non-interactive
|
|
168
174
|
* form of the extra confirmation a production-like environment name demands
|
|
169
175
|
* (#1222). Meaningless without `--yes`. */
|
|
@@ -308,6 +314,12 @@ export interface ParsedArgs {
|
|
|
308
314
|
* request. Needs `--forge`.
|
|
309
315
|
*/
|
|
310
316
|
requireReview?: boolean;
|
|
317
|
+
/**
|
|
318
|
+
* `chant components pr-plan|pr-apply --report-url <url>` (#4007) — copy
|
|
319
|
+
* the stage's report, change set and run events to `<url>/<pr>/<commit>/`,
|
|
320
|
+
* an `s3://` or `file://` URL, the events as each wave and component settles.
|
|
321
|
+
*/
|
|
322
|
+
reportUrl?: string;
|
|
311
323
|
/**
|
|
312
324
|
* `chant build --components --generate <lexicon> --pr-loop` (#3183) —
|
|
313
325
|
* generate the pull-request pipeline: plan on the pull request, apply on
|
|
@@ -404,7 +416,7 @@ export interface ParsedArgs {
|
|
|
404
416
|
noCache?: boolean;
|
|
405
417
|
/** `chant workspace graph --composites` (#2662): print each composite instance with the components that can deploy it. */
|
|
406
418
|
composites?: boolean;
|
|
407
|
-
/** `chant workspace graph --intent <path[:start-end]|path#symbol>` (#2651): the region the intent graph is over. Empty with `--record`. */
|
|
419
|
+
/** `chant workspace graph --intent <path[:start-end]|path#symbol|member/node|sha>` (#2651): the region the intent graph is over. Empty with `--record`. */
|
|
408
420
|
intent?: string;
|
|
409
421
|
/** `chant workspace graph --intent` and `chant workspace runs` (#3035): follow squash merges to their pull requests' original commits, fetching missing pull request refs. */
|
|
410
422
|
followSquash?: boolean;
|
|
@@ -561,7 +573,7 @@ export interface ParsedArgs {
|
|
|
561
573
|
digest?: string;
|
|
562
574
|
/** `chant components release record --release-plan <file>` (ws-055, #2733) — path to a release plan JSON file, persisted content-addressed to `_plans/<digest>.json` on chant/lifecycle and read back through the read contract (`chant workspace status --json`). The plan's own `digest` field supplies `--digest` when it is omitted, and must match it when both are given. Distinct from `--plan` (#2300, below), the Op gate-approval plan digest. */
|
|
563
575
|
releasePlanFile?: string;
|
|
564
|
-
/** `chant components promote --release <label|digest>` (#4026): deploy under that release, reading the templates its target for `--to` recorded. */
|
|
576
|
+
/** `chant components promote --release <label|digest>` (#4026): deploy under that release, reading the templates its target for `--to` recorded. `chant run --components --release <label|digest>` (#4043): the run is of that release, which must have been cut from the checked-out commit and have a target for `--env`; the release records the run writes name it. */
|
|
565
577
|
release?: string;
|
|
566
578
|
/** `chant release cut --build <command>` (#4026): the shell command run in the member's directory before each environment's templates are read, with `CHANT_ENV` set to the environment. */
|
|
567
579
|
buildCommand?: string;
|
|
@@ -660,7 +672,7 @@ export interface ParsedArgs {
|
|
|
660
672
|
plan?: string;
|
|
661
673
|
/** `chant operator log --op <name>` (#2029) — restrict the tick history to one ConvergeOp by name. Omitted, every discovered ConvergeOp's ticks are merged into one timeline. */
|
|
662
674
|
op?: string;
|
|
663
|
-
/** `chant operator log --since <iso>` (#2029) — only entries at or after this ISO-8601 instant. `chant workspace records --since <rev>` (#2673) — the revision to compare the records with. */
|
|
675
|
+
/** `chant operator log --since <iso>` (#2029) — only entries at or after this ISO-8601 instant. `chant workspace records --since <rev>` (#2673) — the revision to compare the records with. `chant workspace metrics --since <date>` (#4039) — the start of the window the metrics count. */
|
|
664
676
|
since?: string;
|
|
665
677
|
/** `chant operator log --limit <n>` (#2029) — keep only the newest n entries (still printed oldest-first). */
|
|
666
678
|
limit?: number;
|
package/src/cli/run-events.ts
CHANGED
|
@@ -37,18 +37,21 @@ export const stdoutLine = (line: string): void => void process.stdout.write(line
|
|
|
37
37
|
|
|
38
38
|
/**
|
|
39
39
|
* The run's stream on stdout when `--events-json` was passed, else
|
|
40
|
-
* undefined.
|
|
40
|
+
* undefined. Each line goes to stdout, to this host's store and to `also`
|
|
41
|
+
* when given. The run is named by `runId` when the caller has one (so a
|
|
41
42
|
* release record and the stream name the same run), else by the CI run or a
|
|
42
43
|
* local id.
|
|
43
44
|
*/
|
|
44
45
|
export async function openCliRunEvents(
|
|
45
46
|
args: Pick<ParsedArgs, "eventsJson">,
|
|
46
47
|
run: { kind: RunEventKind; name: string; runId?: string; cwd?: string },
|
|
48
|
+
also?: (line: string) => void,
|
|
47
49
|
): Promise<RunEventStream | undefined> {
|
|
48
50
|
if (!args.eventsJson) return undefined;
|
|
49
51
|
const resolved = await resolveRunEventRun(run);
|
|
50
52
|
// #4042: the stream is also kept on this host, so `chant run events <run>`
|
|
51
53
|
// replays it. Only a command that was asked for a stream keeps one.
|
|
52
54
|
const store = await openRunEventStore(run.cwd ?? process.cwd(), resolved.runId);
|
|
53
|
-
|
|
55
|
+
// `also`: a third copy of each line, such as `--report-url`'s upload (#4007).
|
|
56
|
+
return openRunEventStream(resolved, teeLines(stdoutLine, store?.write.bind(store), also)!);
|
|
54
57
|
}
|
|
@@ -108,6 +108,15 @@ describe("maybeRecordAutoRelease", () => {
|
|
|
108
108
|
expect(input).toMatchObject({ runId: "9001", runOrigin: { forge: "github", repo: "acme/app" }, approver: "alice", admission });
|
|
109
109
|
});
|
|
110
110
|
|
|
111
|
+
test("a run under a release records its releaseDigest, and one under none records none (#4043)", async () => {
|
|
112
|
+
appendReleaseRecordMock.mockResolvedValue({ commit: "c".repeat(40), record: { version: 1 } });
|
|
113
|
+
const releaseDigest = `jcs1-sha256:${"c".repeat(64)}`;
|
|
114
|
+
await maybeRecordAutoRelease({ component: "svc", env: "dev", success: true, records: [publishRecord("sha256:abc")], runId: "r", releaseDigest }, { actor: "alice" });
|
|
115
|
+
await maybeRecordAutoRelease({ component: "svc", env: "dev", success: true, records: [publishRecord("sha256:abc")], runId: "r" }, { actor: "alice" });
|
|
116
|
+
expect(appendReleaseRecordMock.mock.calls[0][0]).toMatchObject({ releaseDigest });
|
|
117
|
+
expect(appendReleaseRecordMock.mock.calls[1][0]).not.toHaveProperty("releaseDigest");
|
|
118
|
+
});
|
|
119
|
+
|
|
111
120
|
test("an ungated deploy records neither", async () => {
|
|
112
121
|
appendReleaseRecordMock.mockResolvedValue({ commit: "c".repeat(40), record: { version: 1 } });
|
|
113
122
|
await maybeRecordAutoRelease({ component: "svc", env: "prod", success: true, records: [publishRecord("sha256:abc")], runId: "r" }, { actor: "alice" });
|
|
@@ -101,6 +101,8 @@ export interface AutoReleaseRunInfo {
|
|
|
101
101
|
profileOverride?: string;
|
|
102
102
|
/** The deploy's input-side digest, when `digest` is a rendered-content identity (a pinned helm deploy, chant #1242) — recorded as the release record's `inputDigest` so ledger queries can still join on inputs across clusters whose bytes legitimately differ. */
|
|
103
103
|
inputDigest?: string;
|
|
104
|
+
/** The release the deploy was made under (#4043), recorded as the release record's `releaseDigest`. Set only when the caller named a release; never inferred. */
|
|
105
|
+
releaseDigest?: string;
|
|
104
106
|
}
|
|
105
107
|
|
|
106
108
|
/** Opt-out + field-override knobs for auto-release recording, threaded from CLI flags/config (#597: "opt-out-able (flag/config), documented default"). */
|
|
@@ -191,6 +193,7 @@ export async function maybeRecordAutoRelease(
|
|
|
191
193
|
...(run.admission ? { admission: run.admission } : {}),
|
|
192
194
|
...(run.profileOverride ? { profileOverride: run.profileOverride } : {}),
|
|
193
195
|
...(run.inputDigest ? { inputDigest: run.inputDigest } : {}),
|
|
196
|
+
...(run.releaseDigest ? { releaseDigest: run.releaseDigest } : {}),
|
|
194
197
|
},
|
|
195
198
|
{ cwd: options.cwd },
|
|
196
199
|
);
|
|
@@ -61,6 +61,15 @@ export interface DeployContext {
|
|
|
61
61
|
* Absent outside a fan-out that writes a record.
|
|
62
62
|
*/
|
|
63
63
|
carry?: (member: string, value: unknown) => void;
|
|
64
|
+
/**
|
|
65
|
+
* Set when a step is planned (#4084): the components or stacks whose
|
|
66
|
+
* outputs this step's input reads through `stackOutput()` or
|
|
67
|
+
* `@<component>.publish.*` and which had nothing to read yet, so the input
|
|
68
|
+
* holds `undefined` there. Their values are known only when the run
|
|
69
|
+
* applies them. A `plan` that needs them can say so instead of planning
|
|
70
|
+
* against missing values.
|
|
71
|
+
*/
|
|
72
|
+
unresolvedInputs?: string[];
|
|
64
73
|
}
|
|
65
74
|
|
|
66
75
|
/**
|
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
resolveWiring,
|
|
27
27
|
runComponentDeploy,
|
|
28
28
|
runInterpretDriver,
|
|
29
|
+
unresolvedWiringSources,
|
|
29
30
|
type DriverComponent,
|
|
30
31
|
type DriverStepRecord,
|
|
31
32
|
type RunProgressEvent,
|
|
@@ -1149,3 +1150,26 @@ describe("the release a deploy step sees (#3061, ws-081)", () => {
|
|
|
1149
1150
|
expect(deploy.calls[0]!.ctx.release).toEqual({ revision: "r0", version: "sha256:recorded" });
|
|
1150
1151
|
});
|
|
1151
1152
|
});
|
|
1153
|
+
|
|
1154
|
+
describe("unresolvedWiringSources (#4084)", () => {
|
|
1155
|
+
it("names each component whose cross-component output has no value yet, sorted and once", () => {
|
|
1156
|
+
const input = {
|
|
1157
|
+
template: "dist/a.json",
|
|
1158
|
+
inputs: {
|
|
1159
|
+
topic: { stackOutput: { stack: "network", name: "TopicArn" } },
|
|
1160
|
+
queue: { stackOutput: { stack: "network", name: "QueueUrl" } },
|
|
1161
|
+
table: { stackOutput: { stack: "cluster-a", name: "TableName" } },
|
|
1162
|
+
image: "@api-image.publish.digest",
|
|
1163
|
+
local: "@Publish.digest",
|
|
1164
|
+
},
|
|
1165
|
+
};
|
|
1166
|
+
expect(unresolvedWiringSources(input, {})).toEqual(["api-image", "cluster-a", "network"]);
|
|
1167
|
+
expect(
|
|
1168
|
+
unresolvedWiringSources(input, {
|
|
1169
|
+
network: { TopicArn: "t", QueueUrl: "q" },
|
|
1170
|
+
"cluster-a": { TableName: "x" },
|
|
1171
|
+
"api-image": { publish: { digest: "sha256:1" } },
|
|
1172
|
+
}),
|
|
1173
|
+
).toEqual([]);
|
|
1174
|
+
});
|
|
1175
|
+
});
|
package/src/components/driver.ts
CHANGED
|
@@ -345,6 +345,42 @@ export function resolveStepInput(
|
|
|
345
345
|
return walk(input) as Record<string, unknown>;
|
|
346
346
|
}
|
|
347
347
|
|
|
348
|
+
/**
|
|
349
|
+
* The components (or stacks) whose outputs `input` reads through
|
|
350
|
+
* cross-component wiring, `stackOutput()` or `@<component>.publish.*`, and
|
|
351
|
+
* which have no value for it in `componentOutputs`, sorted and each once
|
|
352
|
+
* (#4084). {@link resolveStepInput} turns each such reference into
|
|
353
|
+
* `undefined`; a plan uses this to say whose outputs it is waiting on.
|
|
354
|
+
*/
|
|
355
|
+
export function unresolvedWiringSources(
|
|
356
|
+
input: Record<string, unknown>,
|
|
357
|
+
componentOutputs: Record<string, Record<string, unknown>>,
|
|
358
|
+
): string[] {
|
|
359
|
+
const found = new Set<string>();
|
|
360
|
+
const walk = (value: unknown): void => {
|
|
361
|
+
if (typeof value === "string") {
|
|
362
|
+
if (PRIOR_STEP_REF.test(value)) return;
|
|
363
|
+
const ref = value.match(COMPONENT_ARTIFACT_REF);
|
|
364
|
+
if (ref && resolvePath(componentOutputs[ref[1]]?.publish, ref[2]) === undefined) found.add(ref[1]);
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
if (Array.isArray(value)) {
|
|
368
|
+
value.forEach(walk);
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
if (value && typeof value === "object") {
|
|
372
|
+
if ("stackOutput" in value) {
|
|
373
|
+
const { stack, name } = (value as { stackOutput: { stack: string; name: string } }).stackOutput;
|
|
374
|
+
if (resolvePath(componentOutputs[stack], name) === undefined) found.add(stack);
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
Object.values(value as Record<string, unknown>).forEach(walk);
|
|
378
|
+
}
|
|
379
|
+
};
|
|
380
|
+
walk(input);
|
|
381
|
+
return [...found].sort();
|
|
382
|
+
}
|
|
383
|
+
|
|
348
384
|
// ── Step + phase execution ───────────────────────────────────────────────
|
|
349
385
|
|
|
350
386
|
/**
|