@intentius/chant 0.124.31 → 0.124.33
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/bin/chant +7 -2
- package/dist/ci-jobs.d.ts +4 -0
- package/dist/ci-jobs.d.ts.map +1 -1
- package/dist/ci-jobs.js +9 -2
- package/dist/cli/commands/check-lexicon-plugin.d.ts +7 -4
- package/dist/cli/commands/check-lexicon-plugin.d.ts.map +1 -1
- package/dist/cli/commands/check-lexicon-plugin.js +10 -7
- package/dist/cli/commands/check-lexicon.d.ts.map +1 -1
- package/dist/cli/commands/check-lexicon.js +18 -12
- package/dist/cli/commands/import.d.ts +10 -0
- package/dist/cli/commands/import.d.ts.map +1 -1
- package/dist/cli/commands/import.js +37 -0
- package/dist/cli/commands/init-lexicon/templates/project.d.ts.map +1 -1
- package/dist/cli/commands/init-lexicon/templates/project.js +4 -3
- package/dist/cli/commands/onboard.d.ts.map +1 -1
- package/dist/cli/commands/onboard.js +8 -4
- package/dist/cli/commands/update.d.ts.map +1 -1
- package/dist/cli/commands/update.js +2 -1
- package/dist/cli/dependencies.d.ts +18 -0
- package/dist/cli/dependencies.d.ts.map +1 -0
- package/dist/cli/dependencies.js +120 -0
- package/dist/cli/handlers/build.d.ts.map +1 -1
- package/dist/cli/handlers/build.js +38 -4
- package/dist/cli/handlers/fan-out.d.ts.map +1 -1
- package/dist/cli/handlers/fan-out.js +12 -4
- package/dist/cli/handlers/graph.d.ts.map +1 -1
- package/dist/cli/handlers/graph.js +16 -6
- package/dist/cli/handlers/lifecycle-health.d.ts +16 -0
- package/dist/cli/handlers/lifecycle-health.d.ts.map +1 -0
- package/dist/cli/handlers/lifecycle-health.js +150 -0
- package/dist/cli/handlers/lifecycle.d.ts +26 -0
- package/dist/cli/handlers/lifecycle.d.ts.map +1 -1
- package/dist/cli/handlers/lifecycle.js +1 -1
- package/dist/cli/handlers/lint.d.ts.map +1 -1
- package/dist/cli/handlers/lint.js +6 -0
- package/dist/cli/handlers/operator.d.ts +2 -2
- package/dist/cli/handlers/operator.js +3 -3
- package/dist/cli/handlers/pr.d.ts +16 -0
- package/dist/cli/handlers/pr.d.ts.map +1 -1
- package/dist/cli/handlers/pr.js +610 -32
- package/dist/cli/handlers/promote.d.ts.map +1 -1
- package/dist/cli/handlers/promote.js +19 -2
- package/dist/cli/handlers/release.d.ts +16 -1
- package/dist/cli/handlers/release.d.ts.map +1 -1
- package/dist/cli/handlers/release.js +83 -11
- package/dist/cli/handlers/run.d.ts +13 -1
- package/dist/cli/handlers/run.d.ts.map +1 -1
- package/dist/cli/handlers/run.js +38 -15
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +121 -33
- package/dist/cli/parse-args.d.ts.map +1 -1
- package/dist/cli/parse-args.js +37 -0
- package/dist/cli/registry.d.ts +29 -6
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/cli/registry.js +6 -2
- package/dist/codegen/generate-post-synth-barrel.js +2 -2
- package/dist/codegen/lexicon-regen.d.ts +4 -0
- package/dist/codegen/lexicon-regen.d.ts.map +1 -1
- package/dist/codegen/lexicon-regen.js +1 -1
- package/dist/codegen/pinned-upgrade.js +2 -2
- package/dist/components/capability.d.ts +44 -3
- package/dist/components/capability.d.ts.map +1 -1
- package/dist/components/capability.js +21 -0
- package/dist/components/changed-files.d.ts +7 -1
- package/dist/components/changed-files.d.ts.map +1 -1
- package/dist/components/changed-files.js +9 -1
- package/dist/components/deploy-inputs.d.ts +91 -0
- package/dist/components/deploy-inputs.d.ts.map +1 -0
- package/dist/components/deploy-inputs.js +184 -0
- package/dist/components/driver.d.ts +38 -0
- package/dist/components/driver.d.ts.map +1 -1
- package/dist/components/driver.js +56 -6
- package/dist/components/fan-out-record.d.ts +6 -1
- package/dist/components/fan-out-record.d.ts.map +1 -1
- package/dist/components/fan-out-record.js +24 -0
- package/dist/components/fan-out-run.d.ts +20 -0
- package/dist/components/fan-out-run.d.ts.map +1 -1
- package/dist/components/fan-out-run.js +21 -1
- package/dist/components/gate-plan.d.ts +8 -0
- package/dist/components/gate-plan.d.ts.map +1 -1
- package/dist/components/gate-plan.js +6 -0
- package/dist/components/pr-pipeline.d.ts +98 -12
- package/dist/components/pr-pipeline.d.ts.map +1 -1
- package/dist/components/pr-pipeline.js +146 -23
- package/dist/components/pr-run.d.ts +128 -30
- package/dist/components/pr-run.d.ts.map +1 -1
- package/dist/components/pr-run.js +290 -70
- package/dist/components/release-compile.d.ts +37 -2
- package/dist/components/release-compile.d.ts.map +1 -1
- package/dist/components/release-compile.js +64 -8
- package/dist/components/release-promote.d.ts +17 -3
- package/dist/components/release-promote.d.ts.map +1 -1
- package/dist/components/release-promote.js +79 -18
- package/dist/components/verbs/bom-writer.d.ts +1 -1
- package/dist/components/verbs/bom-writer.d.ts.map +1 -1
- package/dist/components/verbs/lockfile-sbom-generator.d.ts +20 -0
- package/dist/components/verbs/lockfile-sbom-generator.d.ts.map +1 -1
- package/dist/components/verbs/lockfile-sbom-generator.js +41 -4
- package/dist/components/wave-plan.d.ts +15 -2
- package/dist/components/wave-plan.d.ts.map +1 -1
- package/dist/components/wave-plan.js +44 -5
- package/dist/discovery/fold-import.d.ts.map +1 -1
- package/dist/discovery/fold-import.js +16 -6
- package/dist/discovery/sandbox/bundle.d.ts.map +1 -1
- package/dist/discovery/sandbox/bundle.js +6 -0
- package/dist/discovery/specifier-resolve.d.ts.map +1 -1
- package/dist/discovery/specifier-resolve.js +8 -2
- package/dist/fold/fold.d.ts.map +1 -1
- package/dist/fold/fold.js +68 -1
- package/dist/fold/subset.d.ts +37 -0
- package/dist/fold/subset.d.ts.map +1 -1
- package/dist/fold/subset.js +88 -0
- package/dist/graph-detail.d.ts.map +1 -1
- package/dist/graph-detail.js +32 -7
- package/dist/health.d.ts +110 -0
- package/dist/health.d.ts.map +1 -0
- package/dist/health.js +105 -0
- package/dist/health.schema.json +191 -0
- package/dist/lexicon-module.d.ts +10 -0
- package/dist/lexicon-module.d.ts.map +1 -1
- package/dist/lexicon-module.js +53 -8
- package/dist/lexicon-plugin-helpers.d.ts.map +1 -1
- package/dist/lexicon-plugin-helpers.js +6 -4
- package/dist/lexicon.d.ts +29 -0
- package/dist/lexicon.d.ts.map +1 -1
- package/dist/lifecycle/affected.d.ts.map +1 -1
- package/dist/lifecycle/affected.js +7 -1
- package/dist/lifecycle/merge-record.d.ts +104 -0
- package/dist/lifecycle/merge-record.d.ts.map +1 -0
- package/dist/lifecycle/merge-record.js +102 -0
- package/dist/lifecycle/publish-attachments.d.ts +8 -5
- package/dist/lifecycle/publish-attachments.d.ts.map +1 -1
- package/dist/lifecycle/publish-attachments.js +27 -13
- package/dist/lifecycle/publish-npm.d.ts +3 -2
- package/dist/lifecycle/publish-npm.d.ts.map +1 -1
- package/dist/lifecycle/publish-npm.js +4 -3
- package/dist/lifecycle/release-at.d.ts +40 -0
- package/dist/lifecycle/release-at.d.ts.map +1 -0
- package/dist/lifecycle/release-at.js +83 -0
- package/dist/lifecycle/release-cut.d.ts.map +1 -1
- package/dist/lifecycle/release-cut.js +23 -12
- package/dist/lifecycle/release-ledger.d.ts +21 -0
- package/dist/lifecycle/release-ledger.d.ts.map +1 -1
- package/dist/lifecycle/release-ledger.js +24 -0
- package/dist/lifecycle/release-publish.d.ts +28 -12
- package/dist/lifecycle/release-publish.d.ts.map +1 -1
- package/dist/lifecycle/release-publish.js +29 -17
- package/dist/lifecycle/release-store.d.ts +25 -2
- package/dist/lifecycle/release-store.d.ts.map +1 -1
- package/dist/lifecycle/release-store.js +40 -13
- package/dist/lifecycle/run-ledger.d.ts.map +1 -1
- package/dist/lifecycle/run-ledger.js +1 -0
- package/dist/lifecycle/work-dir.d.ts +45 -0
- package/dist/lifecycle/work-dir.d.ts.map +1 -0
- package/dist/lifecycle/work-dir.js +78 -0
- package/dist/lint/discover.d.ts +17 -9
- package/dist/lint/discover.d.ts.map +1 -1
- package/dist/lint/discover.js +62 -54
- package/dist/lint/rules/op/index.d.ts +2 -1
- package/dist/lint/rules/op/index.d.ts.map +1 -1
- package/dist/lint/rules/op/index.js +4 -2
- package/dist/lint/rules/op/ops018-shell-image-digest.d.ts +10 -0
- package/dist/lint/rules/op/ops018-shell-image-digest.d.ts.map +1 -0
- package/dist/lint/rules/op/ops018-shell-image-digest.js +38 -0
- package/dist/module-source.d.ts +57 -0
- package/dist/module-source.d.ts.map +1 -0
- package/dist/module-source.js +104 -0
- package/dist/op/activities/activity-contracts.d.ts +5 -0
- package/dist/op/activities/activity-contracts.d.ts.map +1 -1
- package/dist/op/activities/activity-contracts.js +3 -0
- package/dist/op/activities/factory.js +1 -1
- package/dist/op/activities/shell.d.ts +38 -0
- package/dist/op/activities/shell.d.ts.map +1 -1
- package/dist/op/activities/shell.js +89 -3
- package/dist/op/builders.d.ts +7 -0
- package/dist/op/builders.d.ts.map +1 -1
- package/dist/op/builders.js +7 -0
- package/dist/op/discover.d.ts.map +1 -1
- package/dist/op/discover.js +13 -3
- package/dist/op/gate.d.ts.map +1 -1
- package/dist/op/gate.js +3 -0
- package/dist/op/op-waves-run.d.ts.map +1 -1
- package/dist/op/op-waves-run.js +20 -5
- package/dist/op/operator.d.ts +2 -2
- package/dist/op/operator.js +2 -2
- package/dist/op/runtime.d.ts +2 -0
- package/dist/op/runtime.d.ts.map +1 -1
- package/dist/op/steward.d.ts +6 -4
- package/dist/op/steward.d.ts.map +1 -1
- package/dist/op/steward.js +5 -3
- package/dist/op/work-lease-run.d.ts +20 -7
- package/dist/op/work-lease-run.d.ts.map +1 -1
- package/dist/op/work-lease-run.js +56 -12
- package/dist/pr-forge.d.ts +10 -0
- package/dist/pr-forge.d.ts.map +1 -1
- package/dist/pr-forge.js +39 -0
- package/dist/pr-loop.d.ts +155 -7
- package/dist/pr-loop.d.ts.map +1 -1
- package/dist/pr-loop.js +137 -11
- package/dist/pr-report-url.d.ts +4 -4
- package/dist/pr-report-url.d.ts.map +1 -1
- package/dist/pr-report-url.js +5 -5
- package/dist/runner-start.d.ts +179 -0
- package/dist/runner-start.d.ts.map +1 -0
- package/dist/runner-start.js +277 -0
- package/dist/ts-loader.d.ts +38 -4
- package/dist/ts-loader.d.ts.map +1 -1
- package/dist/ts-loader.js +190 -16
- package/dist/wave-runtime.mjs +238 -231
- package/dist/workspace/chant-migrations/fountain-retired-kinds.d.ts +34 -0
- package/dist/workspace/chant-migrations/fountain-retired-kinds.d.ts.map +1 -0
- package/dist/workspace/chant-migrations/fountain-retired-kinds.js +176 -0
- package/dist/workspace/chant-migrations.d.ts.map +1 -1
- package/dist/workspace/chant-migrations.js +2 -0
- package/dist/workspace/check.schema.json +70 -2
- package/dist/workspace/checks/boxes.d.ts +6 -6
- package/dist/workspace/checks/boxes.js +9 -9
- package/dist/workspace/checks/security.d.ts +35 -0
- package/dist/workspace/checks/security.d.ts.map +1 -0
- package/dist/workspace/checks/security.js +305 -0
- package/dist/workspace/checks.d.ts +2 -0
- package/dist/workspace/checks.d.ts.map +1 -1
- package/dist/workspace/checks.js +5 -0
- package/dist/workspace/ci-builds.d.ts +163 -0
- package/dist/workspace/ci-builds.d.ts.map +1 -0
- package/dist/workspace/ci-builds.js +315 -0
- package/dist/workspace/ci-green-cli.d.ts +2 -1
- package/dist/workspace/ci-green-cli.d.ts.map +1 -1
- package/dist/workspace/ci-green-cli.js +25 -5
- package/dist/workspace/ci-green-forge.d.ts +18 -4
- package/dist/workspace/ci-green-forge.d.ts.map +1 -1
- package/dist/workspace/ci-green-forge.js +12 -0
- package/dist/workspace/ci-green-workflow.d.ts +55 -1
- package/dist/workspace/ci-green-workflow.d.ts.map +1 -1
- package/dist/workspace/ci-green-workflow.js +128 -1
- package/dist/workspace/ci-green.d.ts +117 -16
- package/dist/workspace/ci-green.d.ts.map +1 -1
- package/dist/workspace/ci-green.js +358 -43
- package/dist/workspace/ci-last-green.schema.json +49 -0
- package/dist/workspace/ci-list.schema.json +47 -7
- package/dist/workspace/ci-report-url.d.ts +18 -0
- package/dist/workspace/ci-report-url.d.ts.map +1 -0
- package/dist/workspace/ci-report-url.js +33 -0
- package/dist/workspace/ci-run-index.d.ts +13 -1
- package/dist/workspace/ci-run-index.d.ts.map +1 -1
- package/dist/workspace/ci-run-index.js +6 -4
- package/dist/workspace/ci-run-index.schema.json +6 -4
- package/dist/workspace/ci-run.d.ts +85 -6
- package/dist/workspace/ci-run.d.ts.map +1 -1
- package/dist/workspace/ci-run.js +262 -64
- package/dist/workspace/ci-runner-key.d.ts +16 -3
- package/dist/workspace/ci-runner-key.d.ts.map +1 -1
- package/dist/workspace/ci-runner-key.js +30 -10
- package/dist/workspace/ci-runner-start.d.ts +77 -0
- package/dist/workspace/ci-runner-start.d.ts.map +1 -0
- package/dist/workspace/ci-runner-start.js +185 -0
- package/dist/workspace/ci-serve.d.ts +130 -11
- package/dist/workspace/ci-serve.d.ts.map +1 -1
- package/dist/workspace/ci-serve.js +323 -40
- package/dist/workspace/declaration.d.ts +25 -0
- package/dist/workspace/declaration.d.ts.map +1 -1
- package/dist/workspace/declaration.js +14 -2
- package/dist/workspace/declaration.schema.json +30 -2
- package/dist/workspace/export.d.ts +1 -1
- package/dist/workspace/export.d.ts.map +1 -1
- package/dist/workspace/export.js +7 -3
- package/dist/workspace/ls.d.ts +8 -1
- package/dist/workspace/ls.d.ts.map +1 -1
- package/dist/workspace/ls.js +2 -1
- package/dist/workspace/ls.schema.json +9 -2
- package/dist/workspace/member-pipeline.d.ts +1 -0
- package/dist/workspace/member-pipeline.d.ts.map +1 -1
- package/dist/workspace/member-pipeline.js +2 -0
- package/dist/workspace/merge-record.schema.json +49 -0
- package/dist/workspace/pin-integrity.d.ts.map +1 -1
- package/dist/workspace/pin-integrity.js +3 -2
- package/dist/workspace/pr-report.schema.json +75 -8
- package/dist/workspace/reason-codes.d.ts +18 -1
- package/dist/workspace/reason-codes.d.ts.map +1 -1
- package/dist/workspace/reason-codes.js +20 -2
- package/dist/workspace/release-candidates.d.ts +129 -0
- package/dist/workspace/release-candidates.d.ts.map +1 -0
- package/dist/workspace/release-candidates.js +233 -0
- package/dist/workspace/release-candidates.schema.json +353 -0
- package/dist/workspace/run-event.schema.json +3 -1
- package/dist/workspace/security.d.ts +40 -0
- package/dist/workspace/security.d.ts.map +1 -0
- package/dist/workspace/security.js +99 -0
- package/dist/workspace/status.schema.json +3 -1
- package/dist/workspace/write-scope.d.ts +9 -0
- package/dist/workspace/write-scope.d.ts.map +1 -1
- package/dist/workspace/write-scope.js +11 -1
- package/package.json +8 -1
- package/src/__fixtures__/pr-loop/pr-apply-wave-waiting.note.golden.md +48 -0
- package/src/__fixtures__/pr-loop/pr-plan.note.golden.md +1 -1
- package/src/ci-jobs.ts +11 -2
- package/src/cli/commands/__fixtures__/init-lexicon-output/package.json +3 -3
- package/src/cli/commands/audit.test.ts +2 -2
- package/src/cli/commands/check-lexicon-plugin.test.ts +9 -0
- package/src/cli/commands/check-lexicon-plugin.ts +11 -8
- package/src/cli/commands/check-lexicon.test.ts +1 -1
- package/src/cli/commands/check-lexicon.ts +16 -11
- package/src/cli/commands/import.ts +40 -0
- package/src/cli/commands/init-lexicon/templates/project.ts +4 -3
- package/src/cli/commands/init-lexicon.test.ts +8 -5
- package/src/cli/commands/onboard.test.ts +45 -0
- package/src/cli/commands/onboard.ts +8 -4
- package/src/cli/commands/update.test.ts +6 -0
- package/src/cli/commands/update.ts +4 -1
- package/src/cli/compiled-cli.e2e.test.ts +76 -11
- package/src/cli/dependencies.e2e.test.ts +101 -0
- package/src/cli/dependencies.test.ts +93 -0
- package/src/cli/dependencies.ts +122 -0
- package/src/cli/handlers/build.test.ts +105 -0
- package/src/cli/handlers/build.ts +35 -4
- package/src/cli/handlers/fan-out.test.ts +73 -0
- package/src/cli/handlers/fan-out.ts +11 -4
- package/src/cli/handlers/graph.test.ts +76 -0
- package/src/cli/handlers/graph.ts +19 -12
- package/src/cli/handlers/lifecycle-health.test.ts +123 -0
- package/src/cli/handlers/lifecycle-health.ts +157 -0
- package/src/cli/handlers/lifecycle.ts +1 -1
- package/src/cli/handlers/lint.test.ts +42 -0
- package/src/cli/handlers/lint.ts +6 -0
- package/src/cli/handlers/operator.ts +3 -3
- package/src/cli/handlers/pr-deploy-inputs.test.ts +209 -0
- package/src/cli/handlers/pr-record.test.ts +201 -0
- package/src/cli/handlers/pr-waves.test.ts +449 -0
- package/src/cli/handlers/pr.test.ts +156 -0
- package/src/cli/handlers/pr.ts +648 -33
- package/src/cli/handlers/promote.test.ts +43 -1
- package/src/cli/handlers/promote.ts +19 -3
- package/src/cli/handlers/release-cut-at.e2e.test.ts +115 -0
- package/src/cli/handlers/release-publish-targets.e2e.test.ts +2 -2
- package/src/cli/handlers/release-verify.e2e.test.ts +12 -10
- package/src/cli/handlers/release.e2e.test.ts +19 -28
- package/src/cli/handlers/release.ts +81 -11
- package/src/cli/handlers/run-components-exit.test.ts +99 -0
- package/src/cli/handlers/run-signer.test.ts +79 -0
- package/src/cli/handlers/run.ts +34 -16
- package/src/cli/main.test.ts +18 -0
- package/src/cli/main.ts +120 -33
- package/src/cli/parse-args.ts +28 -0
- package/src/cli/registry.ts +35 -8
- package/src/codegen/generate-post-synth-barrel.ts +2 -2
- package/src/codegen/lexicon-regen.ts +1 -1
- package/src/codegen/pinned-upgrade.ts +2 -2
- package/src/codegen/post-synth-barrel-guards.test.ts +6 -11
- package/src/components/capability.ts +51 -3
- package/src/components/changed-files.test.ts +16 -1
- package/src/components/changed-files.ts +9 -1
- package/src/components/deploy-inputs.test.ts +108 -0
- package/src/components/deploy-inputs.ts +225 -0
- package/src/components/driver.test.ts +36 -1
- package/src/components/driver.ts +87 -4
- package/src/components/fan-out-record.ts +29 -1
- package/src/components/fan-out-run.test.ts +35 -0
- package/src/components/fan-out-run.ts +40 -1
- package/src/components/gate-plan.ts +9 -0
- package/src/components/pr-pipeline.test.ts +100 -0
- package/src/components/pr-pipeline.ts +184 -28
- package/src/components/pr-run.test.ts +323 -18
- package/src/components/pr-run.ts +355 -76
- package/src/components/release-compile.test.ts +34 -0
- package/src/components/release-compile.ts +89 -8
- package/src/components/release-promote.test.ts +55 -2
- package/src/components/release-promote.ts +93 -23
- package/src/components/verbs/bom-writer.ts +1 -1
- package/src/components/verbs/lockfile-sbom-generator.test.ts +36 -0
- package/src/components/verbs/lockfile-sbom-generator.ts +43 -5
- package/src/components/wave-plan.ts +48 -8
- package/src/discovery/fold-host-method.test.ts +87 -0
- package/src/discovery/fold-import.ts +15 -5
- package/src/discovery/fold-package-composite.test.ts +27 -0
- package/src/discovery/fold-specifiers.test.ts +8 -0
- package/src/discovery/sandbox/bundle.ts +6 -0
- package/src/discovery/specifier-resolve.ts +8 -2
- package/src/fold/fold.test.ts +72 -0
- package/src/fold/fold.ts +71 -0
- package/src/fold/subset.test.ts +31 -0
- package/src/fold/subset.ts +99 -0
- package/src/graph-detail.test.ts +57 -0
- package/src/graph-detail.ts +33 -7
- package/src/health.schema.json +191 -0
- package/src/health.test.ts +62 -0
- package/src/health.ts +178 -0
- package/src/lexicon-dist.e2e.test.ts +254 -0
- package/src/lexicon-module.test.ts +47 -0
- package/src/lexicon-module.ts +49 -7
- package/src/lexicon-plugin-helpers.ts +6 -4
- package/src/lexicon.ts +43 -1
- package/src/lifecycle/affected.test.ts +7 -0
- package/src/lifecycle/affected.ts +6 -1
- package/src/lifecycle/merge-record.test.ts +111 -0
- package/src/lifecycle/merge-record.ts +154 -0
- package/src/lifecycle/publish-attachments.ts +25 -13
- package/src/lifecycle/publish-npm.ts +4 -3
- package/src/lifecycle/publish-targets.test.ts +34 -4
- package/src/lifecycle/release-at.test.ts +48 -0
- package/src/lifecycle/release-at.ts +100 -0
- package/src/lifecycle/release-cut.test.ts +41 -0
- package/src/lifecycle/release-cut.ts +22 -11
- package/src/lifecycle/release-ledger.ts +34 -0
- package/src/lifecycle/release-publish.test.ts +43 -13
- package/src/lifecycle/release-publish.ts +38 -18
- package/src/lifecycle/release-store.ts +57 -13
- package/src/lifecycle/run-ledger.test.ts +13 -0
- package/src/lifecycle/run-ledger.ts +1 -0
- package/src/lifecycle/work-dir.test.ts +77 -0
- package/src/lifecycle/work-dir.ts +82 -0
- package/src/lint/discover.test.ts +46 -2
- package/src/lint/discover.ts +55 -49
- package/src/lint/rules/op/index.ts +4 -2
- package/src/lint/rules/op/ops018-shell-image-digest.test.ts +60 -0
- package/src/lint/rules/op/ops018-shell-image-digest.ts +48 -0
- package/src/module-source.test.ts +85 -0
- package/src/module-source.ts +112 -0
- package/src/op/activities/activity-contracts.ts +3 -0
- package/src/op/activities/factory.ts +1 -1
- package/src/op/activities/shell-container.e2e.test.ts +67 -0
- package/src/op/activities/shell.test.ts +44 -1
- package/src/op/activities/shell.ts +110 -3
- package/src/op/builders.ts +7 -0
- package/src/op/discover-root.test.ts +31 -2
- package/src/op/discover.ts +14 -4
- package/src/op/gate.test.ts +30 -0
- package/src/op/gate.ts +3 -0
- package/src/op/op-waves-run.ts +20 -5
- package/src/op/op-waves.test.ts +49 -0
- package/src/op/operator.ts +2 -2
- package/src/op/runtime.ts +2 -0
- package/src/op/step-console.test.ts +4 -2
- package/src/op/steward.ts +6 -4
- package/src/op/work-lease-run.test.ts +88 -2
- package/src/op/work-lease-run.ts +52 -12
- package/src/pr-forge-bundle.test.ts +2 -2
- package/src/pr-forge.test.ts +42 -0
- package/src/pr-forge.ts +40 -0
- package/src/pr-loop-bundle.test.ts +2 -1
- package/src/pr-loop.test.ts +146 -1
- package/src/pr-loop.ts +278 -17
- package/src/pr-report-url.ts +7 -7
- package/src/runner-start-bundle.test.ts +29 -0
- package/src/runner-start.test.ts +179 -0
- package/src/runner-start.ts +329 -0
- package/src/terraform/__fixtures__/advise.test.ts +21 -2
- package/src/ts-loader.test.ts +89 -1
- package/src/ts-loader.ts +180 -13
- package/src/workspace/changes.test.ts +1 -1
- package/src/workspace/chant-migrations/fountain-retired-kinds.test.ts +33 -0
- package/src/workspace/chant-migrations/fountain-retired-kinds.ts +190 -0
- package/src/workspace/chant-migrations.e2e.test.ts +5 -0
- package/src/workspace/chant-migrations.ts +2 -0
- package/src/workspace/check-contract.test.ts +3 -2
- package/src/workspace/check.schema.json +70 -2
- package/src/workspace/checks/boxes.ts +9 -9
- package/src/workspace/checks/security.test.ts +138 -0
- package/src/workspace/checks/security.ts +305 -0
- package/src/workspace/checks.ts +5 -0
- package/src/workspace/ci-builds.e2e.test.ts +208 -0
- package/src/workspace/ci-builds.test.ts +174 -0
- package/src/workspace/ci-builds.ts +385 -0
- package/src/workspace/ci-green-builds.test.ts +180 -0
- package/src/workspace/ci-green-cli.test.ts +54 -0
- package/src/workspace/ci-green-cli.ts +26 -5
- package/src/workspace/ci-green-forge.ts +30 -4
- package/src/workspace/ci-green-runs.test.ts +53 -11
- package/src/workspace/ci-green-workflow.test.ts +84 -1
- package/src/workspace/ci-green-workflow.ts +139 -2
- package/src/workspace/ci-green.test.ts +6 -3
- package/src/workspace/ci-green.ts +408 -48
- package/src/workspace/ci-last-green.schema.json +49 -0
- package/src/workspace/ci-list.schema.json +47 -7
- package/src/workspace/ci-report-url.test.ts +220 -0
- package/src/workspace/ci-report-url.ts +33 -0
- package/src/workspace/ci-run-index.schema.json +6 -4
- package/src/workspace/ci-run-index.test.ts +42 -3
- package/src/workspace/ci-run-index.ts +19 -5
- package/src/workspace/ci-run.test.ts +203 -8
- package/src/workspace/ci-run.ts +295 -63
- package/src/workspace/ci-runner-key.test.ts +55 -17
- package/src/workspace/ci-runner-key.ts +36 -11
- package/src/workspace/ci-runner-start.test.ts +151 -0
- package/src/workspace/ci-runner-start.ts +193 -0
- package/src/workspace/ci-serve-builds.test.ts +86 -0
- package/src/workspace/ci-serve.test.ts +209 -6
- package/src/workspace/ci-serve.ts +341 -42
- package/src/workspace/declaration.schema.json +30 -2
- package/src/workspace/declaration.test.ts +40 -0
- package/src/workspace/declaration.ts +40 -3
- package/src/workspace/export.ts +6 -3
- package/src/workspace/ls.schema.json +9 -2
- package/src/workspace/ls.ts +10 -4
- package/src/workspace/member-pipeline.ts +2 -1
- package/src/workspace/merge-record.schema.json +49 -0
- package/src/workspace/pin-integrity.test.ts +5 -0
- package/src/workspace/pin-integrity.ts +3 -2
- package/src/workspace/pr-report.schema.json +75 -8
- package/src/workspace/reason-codes.test.ts +2 -0
- package/src/workspace/reason-codes.ts +20 -2
- package/src/workspace/release-candidates.schema.json +353 -0
- package/src/workspace/release-candidates.test.ts +106 -0
- package/src/workspace/release-candidates.ts +315 -0
- package/src/workspace/run-event.schema.json +3 -1
- package/src/workspace/security.test.ts +70 -0
- package/src/workspace/security.ts +118 -0
- package/src/workspace/status.schema.json +3 -1
- package/src/workspace/write-scope.test.ts +29 -1
- package/src/workspace/write-scope.ts +12 -1
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `chant run --components` exits 3 when a step refuses a plan that moved
|
|
3
|
+
* since it was approved (#3997), on the single-component path and on the
|
|
4
|
+
* driver's `all` and list paths. Discovery and the capability registry are
|
|
5
|
+
* fakes; the run is the real `runComponents` on the local runtime.
|
|
6
|
+
*/
|
|
7
|
+
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
|
|
8
|
+
import type { Component } from "../../components/component";
|
|
9
|
+
import type { ParsedArgs } from "../registry";
|
|
10
|
+
|
|
11
|
+
const discoverComponentsMock = vi.fn();
|
|
12
|
+
vi.mock("../../components/discover", () => ({
|
|
13
|
+
discoverComponents: (...args: unknown[]) => discoverComponentsMock(...args),
|
|
14
|
+
}));
|
|
15
|
+
|
|
16
|
+
vi.mock("../../config", async () => {
|
|
17
|
+
const actual = await vi.importActual<typeof import("../../config")>("../../config");
|
|
18
|
+
return { ...actual, loadChantConfig: async () => ({ config: {} }) };
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
/** The error a component's step throws, in place of applying. */
|
|
22
|
+
const refusal = new Map<string, Error>();
|
|
23
|
+
|
|
24
|
+
vi.mock("../../op/runtimes/local", async () => {
|
|
25
|
+
const { CapabilityRegistry } = await import("../../components/capability");
|
|
26
|
+
const { runComponents } = await import("../../components/cli-support");
|
|
27
|
+
const { memoryGateLedgerPort } = await import("../../op/gate");
|
|
28
|
+
const registry = new CapabilityRegistry();
|
|
29
|
+
registry.register({
|
|
30
|
+
kind: "fake-apply",
|
|
31
|
+
async run(ctx: { component: string }) {
|
|
32
|
+
const err = refusal.get(ctx.component);
|
|
33
|
+
if (err) throw err;
|
|
34
|
+
return {};
|
|
35
|
+
},
|
|
36
|
+
} as never);
|
|
37
|
+
return {
|
|
38
|
+
createLocalOpRuntime: () => ({
|
|
39
|
+
name: "local",
|
|
40
|
+
runComponents: (path: string, selector: string, options: object) =>
|
|
41
|
+
runComponents(path, selector, { ...options, registry, config: {}, revision: null, gates: memoryGateLedgerPort() }),
|
|
42
|
+
}),
|
|
43
|
+
};
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const { runOpComponents } = await import("./run");
|
|
47
|
+
|
|
48
|
+
const component = (name: string, dependsOn: string[] = []): Component => ({
|
|
49
|
+
name,
|
|
50
|
+
dependsOn,
|
|
51
|
+
deploy: [{ phase: "Apply", steps: [{ kind: "fake-apply" }] }],
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const ctx = (selector: string) =>
|
|
55
|
+
({
|
|
56
|
+
args: { command: "run", path: selector, components: true, on: "local", format: "", fix: false, watch: false, verbose: false, help: false, live: false } as ParsedArgs,
|
|
57
|
+
plugins: [],
|
|
58
|
+
}) as never;
|
|
59
|
+
|
|
60
|
+
beforeEach(() => {
|
|
61
|
+
refusal.clear();
|
|
62
|
+
const estate = [component("net"), component("app", ["net"])];
|
|
63
|
+
discoverComponentsMock.mockResolvedValue({
|
|
64
|
+
components: new Map(estate.map((c) => [c.name, { component: c, exportName: c.name, filePath: `${c.name}.component.ts` }])),
|
|
65
|
+
sourceFiles: [],
|
|
66
|
+
errors: [],
|
|
67
|
+
});
|
|
68
|
+
vi.spyOn(console, "error").mockImplementation(() => {});
|
|
69
|
+
vi.spyOn(console, "log").mockImplementation(() => {});
|
|
70
|
+
vi.spyOn(process.stderr, "write").mockImplementation(() => true);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
afterEach(() => {
|
|
74
|
+
vi.restoreAllMocks();
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
const marks: Array<[string, number, object]> = [
|
|
78
|
+
["marked planMoved", 3, { planMoved: true }],
|
|
79
|
+
["with exitCode 3", 3, { exitCode: 3 }],
|
|
80
|
+
["with exitCode 7", 1, { exitCode: 7 }],
|
|
81
|
+
["unmarked", 1, {}],
|
|
82
|
+
];
|
|
83
|
+
|
|
84
|
+
describe("chant run --components: a step that refuses a moved plan exits 3 (#3997)", () => {
|
|
85
|
+
test.each(marks)("one component, its step refusing %s: exit %i", async (_label, code, mark) => {
|
|
86
|
+
refusal.set("app", Object.assign(new Error("app: refusing to apply, the plan moved"), mark));
|
|
87
|
+
expect(await runOpComponents(ctx("app"))).toBe(code);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test.each(marks)("all, a step refusing %s: exit %i", async (_label, code, mark) => {
|
|
91
|
+
refusal.set("net", Object.assign(new Error("net: refusing to apply, the plan moved"), mark));
|
|
92
|
+
expect(await runOpComponents(ctx("all"))).toBe(code);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
test("a list that pulls in a dependency whose step refuses a moved plan exits 3", async () => {
|
|
96
|
+
refusal.set("net", Object.assign(new Error("net: refusing to apply, the plan moved"), { planMoved: true }));
|
|
97
|
+
expect(await runOpComponents(ctx("app,net"))).toBe(3);
|
|
98
|
+
});
|
|
99
|
+
});
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* #4156: `chant run`'s runner key is opt-in hardening. A `CHANT_RUNNER_KEY`
|
|
3
|
+
* that `.chant/trust.json` does not list leaves the run unsigned with no
|
|
4
|
+
* warning, unless the declaration sets `ci.green.signedSince`. A key that is
|
|
5
|
+
* not an Ed25519 PEM is an error either way.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { createPublicKey, generateKeyPairSync } from "node:crypto";
|
|
9
|
+
import { afterEach, describe, expect, test, vi } from "vitest";
|
|
10
|
+
import { cleanScratch, declaration, git, scratchDir, writeFiles } from "../../workspace/__fixtures__/contract-repo";
|
|
11
|
+
import { sshFromEd25519 } from "../../workspace/trust/dsse";
|
|
12
|
+
import type { CommandContext } from "../registry";
|
|
13
|
+
import { runSignerFor } from "./run";
|
|
14
|
+
|
|
15
|
+
const home = process.cwd();
|
|
16
|
+
const saved = process.env.CHANT_RUNNER_KEY;
|
|
17
|
+
afterEach(() => {
|
|
18
|
+
process.chdir(home);
|
|
19
|
+
if (saved === undefined) delete process.env.CHANT_RUNNER_KEY;
|
|
20
|
+
else process.env.CHANT_RUNNER_KEY = saved;
|
|
21
|
+
vi.restoreAllMocks();
|
|
22
|
+
cleanScratch();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
function key(): { pem: string; ssh: string } {
|
|
26
|
+
const { privateKey } = generateKeyPairSync("ed25519");
|
|
27
|
+
const jwk = createPublicKey(privateKey).export({ format: "jwk" }) as { x: string };
|
|
28
|
+
return { pem: privateKey.export({ type: "pkcs8", format: "pem" }).toString(), ssh: sshFromEd25519(Buffer.from(jwk.x, "base64url")) };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function repo(green?: Record<string, unknown>): string {
|
|
32
|
+
const root = scratchDir("chant-run-signer-");
|
|
33
|
+
git(root, "init", "-q");
|
|
34
|
+
for (const [k, v] of [["user.name", "t"], ["user.email", "t@example.com"], ["commit.gpgsign", "false"]]) git(root, "config", k!, v!);
|
|
35
|
+
writeFiles(root, {
|
|
36
|
+
"chant.workspace.json": declaration([{ name: "app", dir: "app", kind: "other", because: "the app" }], green ? { ci: { green } } : {}),
|
|
37
|
+
".chant/trust.json": JSON.stringify({ schema: 1, runners: [{ principal: "ci-bot", class: "runner", key: key().ssh }], roles: { runner: ["ci-bot"] } }),
|
|
38
|
+
"app/a.txt": "a\n",
|
|
39
|
+
});
|
|
40
|
+
git(root, "add", "-A");
|
|
41
|
+
git(root, "commit", "-q", "-m", "init");
|
|
42
|
+
return root;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async function signer(root: string, pem: string, verbose = false) {
|
|
46
|
+
process.chdir(root);
|
|
47
|
+
process.env.CHANT_RUNNER_KEY = pem;
|
|
48
|
+
const err: string[] = [];
|
|
49
|
+
vi.spyOn(console, "error").mockImplementation((s: string) => void err.push(String(s)));
|
|
50
|
+
const result = await runSignerFor({ args: { verbose } } as unknown as CommandContext);
|
|
51
|
+
return { result, err: err.join("\n") };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
describe("chant run's runner key from the environment (#4156)", () => {
|
|
55
|
+
test("a key trust.json does not list leaves the run unsigned and quiet, with one line under --verbose", async () => {
|
|
56
|
+
const root = repo();
|
|
57
|
+
const quiet = await signer(root, key().pem);
|
|
58
|
+
expect(quiet.result).toBeUndefined();
|
|
59
|
+
expect(quiet.err).toBe("");
|
|
60
|
+
const verbose = await signer(root, key().pem, true);
|
|
61
|
+
expect(verbose.result).toBeUndefined();
|
|
62
|
+
expect(verbose.err).toContain("CHANT_RUNNER_KEY is set, and the run is not signed");
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
test("with ci.green.signedSince the same key warns", async () => {
|
|
66
|
+
const root = repo();
|
|
67
|
+
const head = git(root, "rev-parse", "HEAD");
|
|
68
|
+
writeFiles(root, { "chant.workspace.json": declaration([{ name: "app", dir: "app", kind: "other", because: "the app" }], { ci: { green: { branch: "main", phases: { test: ["test"] }, require: ["test"], signedSince: head } } }) });
|
|
69
|
+
const r = await signer(root, key().pem);
|
|
70
|
+
expect(r.result).toBeUndefined();
|
|
71
|
+
expect(r.err).toContain(`ci.green.signedSince (${head}) will not count it`);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test("a key that is not an Ed25519 PEM is an error", async () => {
|
|
75
|
+
const r = await signer(repo(), "not a key");
|
|
76
|
+
expect(r.result).toBeNull();
|
|
77
|
+
expect(r.err).toContain("CHANT_RUNNER_KEY is not an Ed25519 private key in PEM");
|
|
78
|
+
});
|
|
79
|
+
});
|
package/src/cli/handlers/run.ts
CHANGED
|
@@ -31,7 +31,7 @@ import type { RunEvent } from "../../run-event";
|
|
|
31
31
|
import { openCliRunEvents, refusesBothStreams, stdoutLine } from "../run-events";
|
|
32
32
|
import { maybeRecordAutoRelease } from "../../components/auto-release";
|
|
33
33
|
import { maybePersistBuildManifest } from "../../components/manifest-persistence";
|
|
34
|
-
import type
|
|
34
|
+
import { failedRunExitCode, type DriverComponentResult } from "../../components/driver";
|
|
35
35
|
import { isComponentList, type ComponentRunPlan, type RunComponentsResult } from "../../components/cli-support";
|
|
36
36
|
import { resolveCiRun, type ReleaseRecord, type RunOrigin } from "../../lifecycle/release-ledger";
|
|
37
37
|
import { gateAdmission, gateApprover } from "../../components/promote";
|
|
@@ -730,9 +730,9 @@ type StewardTurnGate =
|
|
|
730
730
|
* `chant run <op>` for an Op a declared steward lists is one of that
|
|
731
731
|
* steward's turns, not a run beside it (#2750, follow-up to #2731).
|
|
732
732
|
*
|
|
733
|
-
* On fountain, the run belongs
|
|
733
|
+
* On fountain, the run belongs in the steward's conversation: without `--on
|
|
734
734
|
* fountain` this refuses outright, naming the command that posts it there
|
|
735
|
-
* instead (the fountain runtime's own turn already refuses a busy
|
|
735
|
+
* instead (the fountain runtime's own turn already refuses a busy steward,
|
|
736
736
|
* unretried — see chant-fountain-ops).
|
|
737
737
|
*
|
|
738
738
|
* In the local form, the run takes the steward's turn lease
|
|
@@ -771,15 +771,15 @@ async function stewardTurnGate(opName: string, ctx: CommandContext): Promise<Ste
|
|
|
771
771
|
const form = stewardFormFor(owner, env);
|
|
772
772
|
|
|
773
773
|
if (form === "fountain") {
|
|
774
|
-
// `run.on: "fountain"` asks for the steward's
|
|
774
|
+
// `run.on: "fountain"` asks for the steward's conversation as much as the flag
|
|
775
775
|
// does (#2523).
|
|
776
776
|
if ((await chooseOpRuntime(ctx, true))?.on === "fountain") return { ok: true };
|
|
777
777
|
return {
|
|
778
778
|
ok: false,
|
|
779
779
|
message: `Op "${opName}" is one of steward "${owner.name}"'s Ops, which runs on fountain in environment "${env}"`,
|
|
780
780
|
hint:
|
|
781
|
-
`Run \`chant run ${opName} --on fountain\` so it posts to "${owner.name}"'s
|
|
782
|
-
`A plain \`chant run ${opName}\` would run it outside that
|
|
781
|
+
`Run \`chant run ${opName} --on fountain\` so it posts to "${owner.name}"'s conversation. ` +
|
|
782
|
+
`A plain \`chant run ${opName}\` would run it outside that conversation, beside the steward instead of one of its turns.`,
|
|
783
783
|
};
|
|
784
784
|
}
|
|
785
785
|
|
|
@@ -1283,7 +1283,10 @@ async function runComponentSelection(ctx: CommandContext): Promise<number> {
|
|
|
1283
1283
|
}
|
|
1284
1284
|
}
|
|
1285
1285
|
|
|
1286
|
-
|
|
1286
|
+
// A step that refused a plan that moved since it was approved exits 3
|
|
1287
|
+
// (#3997). `--gated-exit` doesn't remap it: the run failed.
|
|
1288
|
+
if (result.success) return 0;
|
|
1289
|
+
return result.run ? failedRunExitCode(result.run.results) : 1;
|
|
1287
1290
|
}
|
|
1288
1291
|
|
|
1289
1292
|
/**
|
|
@@ -1359,9 +1362,10 @@ async function runOpOnResolvedRuntime(ctx: CommandContext): Promise<number> {
|
|
|
1359
1362
|
return 1;
|
|
1360
1363
|
}
|
|
1361
1364
|
|
|
1362
|
-
// #4044: a runner key signs the run's record as it settles, so
|
|
1363
|
-
// can
|
|
1364
|
-
// CHANT_RUNNER_KEY that
|
|
1365
|
+
// #4044: a runner key signs the run's record as it settles, so a reader
|
|
1366
|
+
// can see who ran it. `--key` must be a runner key; the PEM in
|
|
1367
|
+
// CHANT_RUNNER_KEY that trust.json does not list leaves the run unsigned,
|
|
1368
|
+
// with a warning only when ci.green.signedSince asks for signed runs (#4156).
|
|
1365
1369
|
const signRecord = await runSignerFor(ctx);
|
|
1366
1370
|
if (signRecord === null) {
|
|
1367
1371
|
await stewardGate?.release?.();
|
|
@@ -1564,10 +1568,13 @@ const RUNNER_KEY_ENV = "CHANT_RUNNER_KEY";
|
|
|
1564
1568
|
* What signs the run's record (#4044): the runner key `--key` names, or the
|
|
1565
1569
|
* PEM in `CHANT_RUNNER_KEY`, checked against `.chant/trust.json` at `HEAD`.
|
|
1566
1570
|
* Undefined when neither is given. Null, after printing why, when `--key`
|
|
1567
|
-
* is not a runner key
|
|
1568
|
-
*
|
|
1571
|
+
* is not a runner key, or either is not an Ed25519 PEM. A `CHANT_RUNNER_KEY`
|
|
1572
|
+
* that trust.json does not list leaves the run unsigned (#4156): quietly,
|
|
1573
|
+
* with a line under `--verbose`, unless `ci.green.signedSince` asks for
|
|
1574
|
+
* signed runs, which warns. The variable may be set for `ci tick` in a job
|
|
1575
|
+
* that also runs Ops.
|
|
1569
1576
|
*/
|
|
1570
|
-
async function runSignerFor(ctx: CommandContext): Promise<((record: OpRunRecord) => NonNullable<OpRunRecord["statement"]>) | undefined | null> {
|
|
1577
|
+
export async function runSignerFor(ctx: CommandContext): Promise<((record: OpRunRecord) => NonNullable<OpRunRecord["statement"]>) | undefined | null> {
|
|
1571
1578
|
const fromFlag = ctx.args.key !== undefined;
|
|
1572
1579
|
let pem: string | undefined;
|
|
1573
1580
|
try {
|
|
@@ -1577,9 +1584,17 @@ async function runSignerFor(ctx: CommandContext): Promise<((record: OpRunRecord)
|
|
|
1577
1584
|
return null;
|
|
1578
1585
|
}
|
|
1579
1586
|
if (pem === undefined) return undefined;
|
|
1587
|
+
// Loaded only when a key is given, so a run without one loads no workspace code (level 0, #2525).
|
|
1588
|
+
const { opRunSigner, signedRunsRequired } = await import("../../workspace/ci-green");
|
|
1589
|
+
const { loadRunnerKey } = await import("../../workspace/trust/dsse");
|
|
1590
|
+
try {
|
|
1591
|
+
loadRunnerKey(pem);
|
|
1592
|
+
} catch (err) {
|
|
1593
|
+
// A key that is there and is not one is an error either way: the caller asked to sign (#4156).
|
|
1594
|
+
console.error(formatError({ message: `${fromFlag ? `--key ${ctx.args.key}` : RUNNER_KEY_ENV} is not an Ed25519 private key in PEM: ${err instanceof Error ? err.message : String(err)}` }));
|
|
1595
|
+
return null;
|
|
1596
|
+
}
|
|
1580
1597
|
try {
|
|
1581
|
-
// Loaded only when a key is given, so a run without one loads no workspace code (level 0, #2525).
|
|
1582
|
-
const { opRunSigner } = await import("../../workspace/ci-green");
|
|
1583
1598
|
return opRunSigner(process.cwd(), pem);
|
|
1584
1599
|
} catch (err) {
|
|
1585
1600
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -1587,7 +1602,10 @@ async function runSignerFor(ctx: CommandContext): Promise<((record: OpRunRecord)
|
|
|
1587
1602
|
console.error(formatError({ message: `the run would not be signed: ${message}` }));
|
|
1588
1603
|
return null;
|
|
1589
1604
|
}
|
|
1590
|
-
|
|
1605
|
+
// #4156: signing is opt-in, so a key trust.json does not list warns only when ci.green.signedSince asks for signed runs.
|
|
1606
|
+
const required = signedRunsRequired(process.cwd());
|
|
1607
|
+
if (required) console.error(formatWarning({ message: `${RUNNER_KEY_ENV} is set, and the run will not be signed, so ci.green.signedSince (${required}) will not count it: ${message}` }));
|
|
1608
|
+
else if (ctx.args.verbose) console.error(`${RUNNER_KEY_ENV} is set, and the run is not signed: ${message}`);
|
|
1591
1609
|
return undefined;
|
|
1592
1610
|
}
|
|
1593
1611
|
}
|
package/src/cli/main.test.ts
CHANGED
|
@@ -666,6 +666,18 @@ describe("resolveCommand", () => {
|
|
|
666
666
|
expect(result!.compound).toBe(false);
|
|
667
667
|
});
|
|
668
668
|
|
|
669
|
+
test("`sync` is an alias for `update` (#3988)", () => {
|
|
670
|
+
const result = resolveCommand(makeArgs({ command: "sync" }), [...testRegistry, { name: "update", handler: noop }]);
|
|
671
|
+
expect(result!.def.name).toBe("update");
|
|
672
|
+
expect(result!.compound).toBe(false);
|
|
673
|
+
});
|
|
674
|
+
|
|
675
|
+
test("`sync <path>` resolves to `update` with the path kept (#3988)", () => {
|
|
676
|
+
const result = resolveCommand(makeArgs({ command: "sync", path: "./proj" }), [...testRegistry, { name: "update", handler: noop }]);
|
|
677
|
+
expect(result!.def.name).toBe("update");
|
|
678
|
+
expect(result!.compound).toBe(false);
|
|
679
|
+
});
|
|
680
|
+
|
|
669
681
|
test("resolves components status as compound command", () => {
|
|
670
682
|
const result = resolveCommand(makeArgs({ command: "components", path: "status" }), testRegistry);
|
|
671
683
|
expect(result!.def.name).toBe("components status");
|
|
@@ -1021,4 +1033,10 @@ describe("chant --help", () => {
|
|
|
1021
1033
|
const commands = new Set(commandRegistry.map((def) => def.name.split(" ")[0]));
|
|
1022
1034
|
expect([...commands].filter((name) => !listed.has(name))).toEqual([]);
|
|
1023
1035
|
});
|
|
1036
|
+
|
|
1037
|
+
test("names `sync` as the alias of `update` (#3988)", () => {
|
|
1038
|
+
const source = readFileSync(join(import.meta.dirname, "main.ts"), "utf-8");
|
|
1039
|
+
const help = source.slice(source.indexOf("function printHelp("), source.indexOf("Options:", source.indexOf("function printHelp(")));
|
|
1040
|
+
expect(help).toMatch(/^ {2}update \(alias: sync\)/m);
|
|
1041
|
+
});
|
|
1024
1042
|
});
|
package/src/cli/main.ts
CHANGED
|
@@ -238,33 +238,45 @@ CI:
|
|
|
238
238
|
its window, newest first, each green, revoked or
|
|
239
239
|
undecided with its required phases' results. Reads
|
|
240
240
|
local tags; --forge reads check runs for undecided
|
|
241
|
-
commits, and source runs reads the
|
|
242
|
-
|
|
241
|
+
commits, and source runs reads the Op runs on the
|
|
242
|
+
local chant/lifecycle, signed or not. --since replaces the window.
|
|
243
243
|
ci tick [--dry-run] [--forge github] [--source checks|runs] [--key <runner key.pem>]
|
|
244
244
|
Tag each commit within ci.green's window whose
|
|
245
245
|
required phases all passed ci/green/<sha>, and revoke
|
|
246
246
|
a green one that now fails ci/revoked/<sha>. Reads
|
|
247
247
|
check runs from the forge, or with source runs
|
|
248
248
|
(ci.green.source or --source) the Op runs on
|
|
249
|
-
chant/lifecycle
|
|
249
|
+
chant/lifecycle; with ci.green.signedSince, the ones a
|
|
250
|
+
runner key signed. Pushes the
|
|
250
251
|
tags. --key, or the PEM in CHANT_RUNNER_KEY, signs
|
|
251
|
-
each tag with a runner key.
|
|
252
|
+
each tag with a runner key. A cancelled run leaves a
|
|
253
|
+
commit unbuilt, not red, and a failed run is run
|
|
254
|
+
again once. A phase with build: newest leaves the
|
|
255
|
+
commits a newer run superseded unbuilt, and a red
|
|
256
|
+
one starts a bisect: a ci/build/<sha> tag the tick
|
|
257
|
+
starts the phase's workflow at. Each commit judged
|
|
258
|
+
gets a _ci/<sha>.json record on chant/lifecycle.
|
|
252
259
|
ci run plan|apply --env <env> --base <sha> [--pr <n>] [--commit <sha>]
|
|
253
|
-
[--forge github|gitlab|forgejo] [--gate <name>] [--
|
|
254
|
-
[--events-json] [--report-url <url>] [--image <image>]
|
|
260
|
+
[--forge github|gitlab|forgejo] [--gate <name>] [--wave-gate <name>]
|
|
261
|
+
[--branch <name>] [--events-json] [--report-url <url>] [--image <image>]
|
|
255
262
|
[--before-script <line>]... [--pr-build]
|
|
256
263
|
[--pr-build-command <line>] [--chant <command>]
|
|
257
264
|
[--pass-env <NAME>]... [--secrets <file>] [--key <runner key.pem>]
|
|
258
|
-
[-o <dir>]
|
|
265
|
+
[-o <dir>] [--wave <k>] [--require-review]
|
|
259
266
|
[--no-status] [--status-url <url template>]
|
|
260
|
-
|
|
267
|
+
[--in-place | --local] [--no-push] [--require-runner-start] [--verbose]
|
|
268
|
+
Run the pull-request pipeline's plan, record or apply job as
|
|
261
269
|
a pipeline Op in a fresh worktree of --commit (default
|
|
262
270
|
HEAD) with a clean environment. --base and --pr stand
|
|
263
271
|
in for the forge's event values. --pr-build runs
|
|
264
272
|
the job's build and lint lines first. Records the run as
|
|
265
|
-
pr-plan or pr-apply on chant/lifecycle,
|
|
266
|
-
|
|
267
|
-
|
|
273
|
+
pr-plan, pr-record or pr-apply on chant/lifecycle, which ci tick
|
|
274
|
+
from runs counts, signed when --key or CHANT_RUNNER_KEY
|
|
275
|
+
gives a runner key, and copies the report to -o
|
|
276
|
+
(default .chant/pr). --in-place runs in this checkout
|
|
277
|
+
at HEAD, as a generated forge job does, and names the
|
|
278
|
+
forge's run in the record; --no-push keeps the record
|
|
279
|
+
local. Exits with the command's code. With a forge
|
|
268
280
|
token it sets a chant/pr-plan or chant/pr-apply commit
|
|
269
281
|
status (pending, then success or failure); --no-status
|
|
270
282
|
turns that off, and --status-url links it.
|
|
@@ -275,24 +287,55 @@ CI:
|
|
|
275
287
|
With --report-url it also adds the run to
|
|
276
288
|
<url>/runs/index.json, newest first, cut to the
|
|
277
289
|
newest --run-index-limit entries (default 200).
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
290
|
+
Without --report-url, the workspace's ci.reportUrl.
|
|
291
|
+
--local runs the job on this machine: the record is
|
|
292
|
+
kept on the local chant/lifecycle with runOrigin
|
|
293
|
+
local and is never pushed, no status is set, nothing
|
|
294
|
+
goes under a report URL, and ci tick does not count it.
|
|
295
|
+
--require-runner-start refuses the job before its
|
|
296
|
+
first step unless a runner-start statement, signed by
|
|
297
|
+
a runner key .chant/trust.json at --base lists, names
|
|
298
|
+
this forge job.
|
|
299
|
+
ci runner-start sign --key <runner key.pem> --principal <name> --job <json|@file> [-o <file>]
|
|
300
|
+
For the provisioner that starts a runner for one job:
|
|
301
|
+
sign the job's system, repo, run, attempt, job,
|
|
302
|
+
commit and runner name, and print the envelope.
|
|
303
|
+
ci runner-start verify [--base <rev>] [--commit <sha>] [--json]
|
|
304
|
+
In the job: check the statement in CHANT_RUNNER_START,
|
|
305
|
+
or the file CHANT_RUNNER_START_FILE names (default
|
|
306
|
+
/run/chant/runner-start.json), against the forge's
|
|
307
|
+
variables and .chant/trust.json at --base (default
|
|
308
|
+
origin/HEAD). Exits 1 unless it verifies.
|
|
309
|
+
ci run --at <sha> Ask for every required phase at a commit of the
|
|
310
|
+
green branch with a ci/build/<sha> tag, and start the
|
|
311
|
+
workflows holding them there on GitHub when a token
|
|
312
|
+
is set; otherwise the next tick, or ci serve
|
|
313
|
+
--build-command, does.
|
|
314
|
+
ci runs [--report-url <url>] [--json]
|
|
315
|
+
List the runs in the index at the report URL (default
|
|
316
|
+
the workspace's ci.reportUrl), newest first.
|
|
281
317
|
ci serve --forge forgejo|github --repo <owner/repo> --env <env>
|
|
282
318
|
[--interval <s>] [--max-jobs <n>] [--state <dir>]
|
|
283
319
|
[--author <login>]... [--once] [--rerun-failed] [--unsigned]
|
|
284
|
-
[ci run's job flags]
|
|
320
|
+
[--apply-on-merge] [--build-command <line>] [ci run's job flags]
|
|
285
321
|
Poll the forge for open pull requests and the target
|
|
286
322
|
branch's head, and run ci run plan for each new pull
|
|
287
|
-
request head and ci run
|
|
288
|
-
the branch
|
|
323
|
+
request head and ci run record for each new commit on
|
|
324
|
+
the branch, then ci tick from the runs when the
|
|
325
|
+
workspace declares ci.green. A merge deploys nothing;
|
|
326
|
+
--apply-on-merge runs ci run apply in place of the
|
|
327
|
+
record, and --wave-gate needs it. Dedupes on job and commit in a state file
|
|
289
328
|
under --state, takes a lease per apply group, keeps
|
|
290
329
|
each apply's resume record there, and runs at most
|
|
291
330
|
--max-jobs (default 1) jobs at once. --once runs one
|
|
292
331
|
poll and waits for its jobs. --rerun-failed runs a
|
|
293
|
-
failed apply or plan again.
|
|
294
|
-
|
|
295
|
-
|
|
332
|
+
failed apply or plan again. Signs runs with a runner
|
|
333
|
+
key when .chant/trust.json at the target's head lists
|
|
334
|
+
it, and serves unsigned otherwise; with
|
|
335
|
+
ci.green.signedSince it refuses to start without one.
|
|
336
|
+
--build-command runs <line> once per ci/build/<sha>
|
|
337
|
+
tag, in a fresh worktree of the commit, with
|
|
338
|
+
CHANT_BUILD_COMMIT and CHANT_BUILD_PHASES set
|
|
296
339
|
ci serve|run --setup-key [--trust [--principal <name>]] [--state <dir>] [--branch <name>]
|
|
297
340
|
Make the host's runner key (Ed25519, mode 0600) in the
|
|
298
341
|
state directory when there is none and print its public
|
|
@@ -310,10 +353,14 @@ CI:
|
|
|
310
353
|
or a GitHub App's id and key, pushes the tags with a
|
|
311
354
|
token that may tag commits changing workflow files.
|
|
312
355
|
--runner-key-secret hands the tick the runner key it
|
|
313
|
-
signs its tags with.
|
|
356
|
+
signs its tags with. For each phase that sets build,
|
|
357
|
+
it also writes the triggers and concurrency of the
|
|
358
|
+
workflows holding it: newest builds on pushes and by
|
|
359
|
+
hand, one run at a time, and every gives each commit
|
|
360
|
+
a run of its own.
|
|
314
361
|
|
|
315
362
|
Releases:
|
|
316
|
-
release cut [<label>] [--yes] [--build <command>] [--param <k=v>]
|
|
363
|
+
release cut [<label>] [--at <sha>] [--yes] [--build <command>] [--param <k=v>]
|
|
317
364
|
[--params-file <file>] [--src <dir>] [-o <file>] [--lexicon <name>]
|
|
318
365
|
[--actor <name>] [--sign [<key file>]] [--json]
|
|
319
366
|
A dry run of a cut of this member from HEAD, which
|
|
@@ -332,19 +379,29 @@ Releases:
|
|
|
332
379
|
requires it. A project with no components releases
|
|
333
380
|
what chant build --env <env> writes: --src <dir> is
|
|
334
381
|
the build root, -o <file> the output (dist/build.yaml),
|
|
335
|
-
--lexicon narrows it.
|
|
382
|
+
--lexicon narrows it. --at <sha> cuts that commit of
|
|
383
|
+
trunk from a temporary worktree instead of HEAD, so
|
|
384
|
+
the checkout need not be clean. The label reaches
|
|
385
|
+
every compile and build as CHANT_RELEASE_LABEL.
|
|
386
|
+
release candidates [--env <env>] [--json]
|
|
387
|
+
The green commits of trunk a release can be cut from,
|
|
388
|
+
newest first, each with the commits, work items, pull
|
|
389
|
+
requests and flags it would ship, and what each
|
|
390
|
+
environment runs.
|
|
336
391
|
release publish <label|digest> [--yes] [--allow-unsigned]
|
|
337
392
|
[--require-provenance] [--json]
|
|
338
393
|
Publish a cut release to the targets release.publish
|
|
339
394
|
in chant.config.ts declares (npm, OCI registries,
|
|
340
|
-
forge release assets), each with
|
|
341
|
-
|
|
342
|
-
Refuses a revoked release,
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
395
|
+
forge release assets), each with the release's
|
|
396
|
+
provenance and an SBOM when it has a source. A dry
|
|
397
|
+
run without --yes. Refuses a revoked release, and
|
|
398
|
+
with a target a checkout that is not the release's
|
|
399
|
+
commit. Under security verified-releases it refuses
|
|
400
|
+
one whose signature does not verify against
|
|
401
|
+
.chant/allowed_signers unless --allow-unsigned; under
|
|
402
|
+
supply-chain it warns when the run has no OIDC token
|
|
403
|
+
and refuses a target with no SBOM source.
|
|
404
|
+
--require-provenance refuses a run with no OIDC.
|
|
348
405
|
release verify <label|digest> [--json]
|
|
349
406
|
Check, offline, that the release was signed by a key
|
|
350
407
|
.chant/allowed_signers lists at the release's commit.
|
|
@@ -875,6 +932,10 @@ Lifecycle (alias: lc):
|
|
|
875
932
|
estate size rather than stack count (#2405)
|
|
876
933
|
lifecycle affected Stacks a change affects (--base <ref> [--include-dependents])
|
|
877
934
|
--json: emit the ChangeSet as JSON
|
|
935
|
+
lifecycle health <env> Whether each declared service is up, separate from
|
|
936
|
+
drift: ECS running vs desired, Route 53 health
|
|
937
|
+
checks, Container Apps revisions, Cloud Run Ready.
|
|
938
|
+
A failed read is "not read", never unhealthy (--json)
|
|
878
939
|
lifecycle whoami <env> Who chant would act as in each configured lexicon,
|
|
879
940
|
and what that principal is scoped to — read-only,
|
|
880
941
|
before anything acts (--json, --strict)
|
|
@@ -919,7 +980,12 @@ Component release ledger + status:
|
|
|
919
980
|
report and note (--base <ref> --pr <n>
|
|
920
981
|
[--forge github|gitlab|forgejo] posts them);
|
|
921
982
|
applies nothing
|
|
922
|
-
components pr-
|
|
983
|
+
components pr-record On merge (#4168): plan the same members again,
|
|
984
|
+
store the change set and write the merge record
|
|
985
|
+
_merges/<commit>.json; applies and refuses
|
|
986
|
+
nothing, and a plan that differs from the
|
|
987
|
+
approved one sets a failing chant/record status
|
|
988
|
+
components pr-apply With --apply-on-merge: plan the same members again and apply
|
|
923
989
|
them only if an approval stands for that digest
|
|
924
990
|
(chant approve pr-<n> pr-apply --plan <digest>);
|
|
925
991
|
a moved plan refuses with exit 3
|
|
@@ -929,6 +995,10 @@ Component release ledger + status:
|
|
|
929
995
|
member's loop, gate op pr-<n>-<member>;
|
|
930
996
|
--resume <file> finishes an apply that failed
|
|
931
997
|
partway under the same approval;
|
|
998
|
+
--wave-gate <name>: apply a wave at a time, each
|
|
999
|
+
planned after the one before applied, a moved
|
|
1000
|
+
wave waiting at <name>-wave-<k>, with --wave <k>
|
|
1001
|
+
for one wave per CI job;
|
|
932
1002
|
--events-json, both commands: the run-event
|
|
933
1003
|
stream on stdout; --report-url <s3 or file URL>,
|
|
934
1004
|
both commands: copy the report, the change set
|
|
@@ -998,7 +1068,8 @@ Servers:
|
|
|
998
1068
|
serve mcp Start the MCP server (stdio)
|
|
999
1069
|
|
|
1000
1070
|
Project:
|
|
1001
|
-
update
|
|
1071
|
+
update (alias: sync) Sync lexicon types into .chant/types/ (does not install
|
|
1072
|
+
packages: run npm install first)
|
|
1002
1073
|
doctor Check project health and configuration
|
|
1003
1074
|
|
|
1004
1075
|
Options:
|
|
@@ -1217,6 +1288,9 @@ async function loadPluginsOrExit(path: string, lexicon?: string): Promise<import
|
|
|
1217
1288
|
plugins = await loadPlugins(lexiconNames);
|
|
1218
1289
|
} catch (error) {
|
|
1219
1290
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1291
|
+
// #4116: a lexicon package the project has not installed is named as such first.
|
|
1292
|
+
const { reportUninstalledDependencies } = await import("./dependencies");
|
|
1293
|
+
reportUninstalledDependencies([errorMessage], resolve(path));
|
|
1220
1294
|
console.error(formatError({ message: errorMessage }));
|
|
1221
1295
|
process.exit(1);
|
|
1222
1296
|
}
|
|
@@ -1366,6 +1440,8 @@ export const commandRegistry: CommandDef[] = [
|
|
|
1366
1440
|
// #4094: one pull-request job as a pipeline Op in a fresh checkout, the chant runner's first slice.
|
|
1367
1441
|
{ name: "ci run", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/ci-run")).runCiRun(ctx) },
|
|
1368
1442
|
// #4098: the run index at the report URL.
|
|
1443
|
+
// #4147: a provisioner's signed word that it started a runner for one job, signed and checked.
|
|
1444
|
+
{ name: "ci runner-start", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/ci-runner-start")).runCiRunnerStart(ctx) },
|
|
1369
1445
|
{ name: "ci runs", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/ci-run-index")).runCiRuns(ctx) },
|
|
1370
1446
|
{ name: "ci serve", runsNoConfig: true, handler: async (ctx) => (await import("../workspace/ci-serve")).runCiServe(ctx) },
|
|
1371
1447
|
// #4026: the release cut from a green commit (ws-104). Imported on first use.
|
|
@@ -1374,6 +1450,7 @@ export const commandRegistry: CommandDef[] = [
|
|
|
1374
1450
|
{ name: "release publish", runsNoConfig: true, handler: async (ctx) => (await import("./handlers/release")).runReleasePublish(ctx) },
|
|
1375
1451
|
// #4049: check a release's signature offline.
|
|
1376
1452
|
{ name: "release verify", runsNoConfig: true, handler: async (ctx) => (await import("./handlers/release")).runReleaseVerify(ctx) },
|
|
1453
|
+
{ name: "release candidates", runsNoConfig: true, handler: async (ctx) => (await import("./handlers/release")).runReleaseCandidates(ctx) },
|
|
1377
1454
|
{ name: "release list", runsNoConfig: true, handler: async (ctx) => (await import("./handlers/release")).runReleaseList(ctx) },
|
|
1378
1455
|
{ name: "release export", runsNoConfig: true, handler: async (ctx) => (await import("./handlers/release")).runReleaseExport(ctx) },
|
|
1379
1456
|
{ name: "release compile", runsNoConfig: true, handler: async (ctx) => (await import("./handlers/release")).runReleaseCompile(ctx) },
|
|
@@ -1484,6 +1561,8 @@ export const commandRegistry: CommandDef[] = [
|
|
|
1484
1561
|
{ name: "lifecycle plan", requiresPlugins: true, handler: runLifecyclePlan },
|
|
1485
1562
|
{ name: "lifecycle affected", requiresPlugins: true, handler: runLifecycleAffected },
|
|
1486
1563
|
{ name: "lifecycle whoami", requiresPlugins: true, handler: runLifecycleWhoami },
|
|
1564
|
+
// #4177 — runtime health, separate from drift. Imported on first use.
|
|
1565
|
+
{ name: "lifecycle health", requiresPlugins: true, handler: async (ctx) => (await import("./handlers/lifecycle-health")).runLifecycleHealth(ctx) },
|
|
1487
1566
|
{ name: "lifecycle teardown", requiresPlugins: true, handler: runLifecycleTeardown },
|
|
1488
1567
|
{ name: "lifecycle log", handler: runLifecycleLog },
|
|
1489
1568
|
// #4036 — retention's garbage collection. Imported on first use.
|
|
@@ -1499,6 +1578,7 @@ export const commandRegistry: CommandDef[] = [
|
|
|
1499
1578
|
// #3183 — the pull-request loop the generated CI runs. Imported on first use.
|
|
1500
1579
|
{ name: "components pr-plan", requiresPlugins: true, handler: async (ctx) => (await import("./handlers/pr")).runComponentsPrPlan(ctx) },
|
|
1501
1580
|
{ name: "components pr-apply", requiresPlugins: true, handler: async (ctx) => (await import("./handlers/pr")).runComponentsPrApply(ctx) },
|
|
1581
|
+
{ name: "components pr-record", requiresPlugins: true, handler: async (ctx) => (await import("./handlers/pr")).runComponentsPrRecord(ctx) },
|
|
1502
1582
|
{ name: "components status", requiresPlugins: true, handler: runComponentsStatus },
|
|
1503
1583
|
{ name: "components release", handler: runComponentsReleaseRecord },
|
|
1504
1584
|
{ name: "components export", handler: runComponentsExport },
|
|
@@ -1725,6 +1805,13 @@ const isMain = isEntryPoint(process.argv[1], import.meta.url);
|
|
|
1725
1805
|
if (isMain) {
|
|
1726
1806
|
main().catch(async (err) => {
|
|
1727
1807
|
const verbose = process.argv.includes("--verbose") || process.argv.includes("-v");
|
|
1808
|
+
// #4116: a failure to import a package the project has not installed is named as such first.
|
|
1809
|
+
try {
|
|
1810
|
+
const { reportUninstalledDependencies } = await import("./dependencies");
|
|
1811
|
+
reportUninstalledDependencies([err instanceof Error ? err.message : String(err)], process.cwd());
|
|
1812
|
+
} catch {
|
|
1813
|
+
// The original error below is what matters.
|
|
1814
|
+
}
|
|
1728
1815
|
if (verbose && err instanceof Error && err.stack) {
|
|
1729
1816
|
console.error(err.stack);
|
|
1730
1817
|
} else {
|