@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
|
@@ -17,9 +17,9 @@ import { join } from "node:path";
|
|
|
17
17
|
import { afterAll, beforeAll, describe, expect, test } from "vitest";
|
|
18
18
|
import { cleanScratch, declaration, git, repoFixture, scratchDir, writeFiles } from "./__fixtures__/contract-repo";
|
|
19
19
|
import { checkRunEventLines } from "./__fixtures__/run-event-check";
|
|
20
|
-
import { ciJobCommand, ciJobEnv, ciJobFailure, ciJobOp, ciRun, CiRunError, ciStatusContext, ciStatusFromEnv, ciStatusUrl, formatCiRun } from "./ci-run";
|
|
20
|
+
import { ciJobCommand, ciJobEnv, ciJobFailure, ciJobOp, ciLoopOptions, ciRun, CiRunError, ciStatusContext, ciStatusFromEnv, ciStatusUrl, formatCiRun } from "./ci-run";
|
|
21
21
|
import type { CommitStatus } from "../pr-forge";
|
|
22
|
-
import { ciTick, evaluateCommit, readOpRunSource, revokedAnnotation } from "./ci-green";
|
|
22
|
+
import { ciList, ciTick, evaluateCommit, readOpRunSource, revokedAnnotation } from "./ci-green";
|
|
23
23
|
import type { StepRecord } from "../op/local-executor";
|
|
24
24
|
import { sshFromEd25519 } from "./trust/dsse";
|
|
25
25
|
import { verifyOpRunStatement } from "./trust/op-run-statement";
|
|
@@ -199,6 +199,24 @@ describe("the job as an Op (#4094)", () => {
|
|
|
199
199
|
expect(args).toMatchObject({ command: "ci", path: "run", extraPositional: "apply", env: "prod", base: "abc", commit: "def", passEnv: ["AWS_PROFILE", "AWS_REGION"], ciChant: "npx chant", key: "k.pem" });
|
|
200
200
|
expect(() => parseArgs(["ci", "run", "plan", "--commit"])).toThrow(/--commit needs/);
|
|
201
201
|
});
|
|
202
|
+
|
|
203
|
+
test("--wave-gate (#4003): the apply job runs pr-apply --wave-gate, the waves in order with no --wave, and the plan passes the gate for its note", () => {
|
|
204
|
+
for (const path of ["run", "serve"]) {
|
|
205
|
+
const args = parseArgs(["ci", path, ...(path === "run" ? ["apply"] : []), "--env", "prod", "--gate", "infra", "--wave-gate", "release"]);
|
|
206
|
+
expect(ciLoopOptions(args)).toEqual({ gate: "infra", waveGate: "release" });
|
|
207
|
+
}
|
|
208
|
+
const [plan, apply] = prLoopJobs("forgejo", "prod", ciLoopOptions(parseArgs(["ci", "run", "apply", "--env", "prod", "--wave-gate", "release"])));
|
|
209
|
+
// #4168: no --require-review unless asked for.
|
|
210
|
+
expect(apply!.command).toContain(" --wave-gate release --resume .chant/pr-resume/pr-apply.json");
|
|
211
|
+
expect(apply!.command).not.toContain("--require-review");
|
|
212
|
+
const reviewed = prLoopJobs("forgejo", "prod", ciLoopOptions(parseArgs(["ci", "run", "apply", "--env", "prod", "--wave-gate", "release", "--require-review"])))[1]!;
|
|
213
|
+
expect(reviewed.command).toContain("--require-review --wave-gate release --resume .chant/pr-resume/pr-apply.json");
|
|
214
|
+
expect(apply!.command).not.toContain("--wave ");
|
|
215
|
+
expect(plan!.command).toContain("--wave-gate release");
|
|
216
|
+
expect(plan!.command).not.toContain("--wave ");
|
|
217
|
+
const op = ciJobOp({ job: apply!, env: "prod", cwd: "/w", jobEnv: {}, setup: [], build: [] });
|
|
218
|
+
expect(op.phases.map((p) => p.name)).toEqual(["apply"]);
|
|
219
|
+
});
|
|
202
220
|
});
|
|
203
221
|
|
|
204
222
|
describe("chant ci run, then ci tick from runs (#4094)", () => {
|
|
@@ -280,7 +298,7 @@ describe("chant ci run, then ci tick from runs (#4094)", () => {
|
|
|
280
298
|
|
|
281
299
|
expect(apply.status).toBe("ok");
|
|
282
300
|
const applyArgs = readFileSync(join(reports, "apply", "pr-apply.args"), "utf-8").trimEnd().split("\n");
|
|
283
|
-
expect(applyArgs).toEqual(["components", "pr-apply", "--base", base, "--env", "prod", "--gate", "pr-apply", "--output", ".chant/pr", "--forge", "forgejo", "--member", "app", "--
|
|
301
|
+
expect(applyArgs).toEqual(["components", "pr-apply", "--base", base, "--env", "prod", "--gate", "pr-apply", "--output", ".chant/pr", "--forge", "forgejo", "--member", "app", "--resume", ".chant/pr-resume/pr-apply.json"]);
|
|
284
302
|
expect(formatCiRun(apply)).toContain("signed by chant-runner");
|
|
285
303
|
});
|
|
286
304
|
|
|
@@ -296,8 +314,19 @@ describe("chant ci run, then ci tick from runs (#4094)", () => {
|
|
|
296
314
|
expect(record.phases.apply![0]).toMatchObject({ name: "pr-apply", opRun: { id: apply.record.id, signer: "chant-runner" } });
|
|
297
315
|
});
|
|
298
316
|
|
|
299
|
-
test("
|
|
300
|
-
const { app, base } = workspace();
|
|
317
|
+
test("under the isolated-runners security group an apply job requires a runner-start statement, and a plan job does not (#4168)", async () => {
|
|
318
|
+
const { root, app, base } = workspace();
|
|
319
|
+
writeFiles(root, { "chant.workspace.json": declaration([{ name: "app", dir: "app", kind: "other", because: "the app", security: ["isolated-runners"] }], { ci: { green: GREEN } }) });
|
|
320
|
+
git(root, "commit", "-qam", "isolated-runners");
|
|
321
|
+
git(root, "push", "-q", "origin", "main");
|
|
322
|
+
const job = (j: "plan" | "apply") =>
|
|
323
|
+
ciRun({ image: JOB_IMAGE, cwd: app, job: j, env: "prod", forge: "github", base, ...(j === "plan" ? { pr: 7 } : {}), chant: fakeChant(), hostEnv: HOST, output: join(scratchDir("chant-ci-run-out-"), "pr"), push: false });
|
|
324
|
+
await expect(job("apply")).rejects.toThrow(/--require-runner-start needs a forge job to check/);
|
|
325
|
+
expect((await job("plan")).status).toBe("ok");
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
test("a failing job is recorded failed, and a key from the environment that trust.json does not list leaves it unsigned, quietly", async () => {
|
|
329
|
+
const { root, app, base } = workspace();
|
|
301
330
|
const stranger = runnerKey();
|
|
302
331
|
const lines: string[] = [];
|
|
303
332
|
const r = await ciRun({ image: JOB_IMAGE,
|
|
@@ -319,17 +348,30 @@ describe("chant ci run, then ci tick from runs (#4094)", () => {
|
|
|
319
348
|
expect(r.record.status).toBe("fail");
|
|
320
349
|
expect(r.record.statement).toBeUndefined();
|
|
321
350
|
expect(r.signer).toBeNull();
|
|
322
|
-
|
|
351
|
+
// #4156: signing is opt-in, so an unlisted key is a note for --verbose, not a warning.
|
|
352
|
+
expect(r.warnings).toEqual([]);
|
|
353
|
+
expect(r.notes[0]).toMatch(/CHANT_RUNNER_KEY is set, and the run will not be signed: .*lists no runner with this key/);
|
|
354
|
+
// The command's exit code is the job's, as a forge job's was before it ran through ci run.
|
|
355
|
+
expect(r.exitCode).toBe(3);
|
|
323
356
|
expect(r.failure).toMatchObject({ phase: "apply", error: expect.stringContaining("command exited 3") });
|
|
324
357
|
// The report says nothing about a failure, so the record names the command.
|
|
325
358
|
expect(r.record.failure).toMatchObject({ code: "command-failed", phase: "apply", exitCode: 3, reason: expect.stringContaining("command exited 3") });
|
|
326
359
|
expect(lines.some((l) => l.includes("fake pr-apply ran"))).toBe(true);
|
|
327
360
|
expect(r.report).not.toBeNull();
|
|
328
|
-
expect(formatCiRun(r)).toContain("
|
|
361
|
+
expect(formatCiRun(r)).toContain("on chant/lifecycle, unsigned");
|
|
329
362
|
|
|
330
|
-
// The same key given with --key refuses the run before anything runs.
|
|
363
|
+
// The same key given with --key refuses the run before anything runs, and so does a key that is not one.
|
|
331
364
|
await expect(ciRun({ image: JOB_IMAGE, cwd: app, job: "apply", env: "prod", forge: "github", base, chant: fakeChant(), hostEnv: HOST, runnerKey: stranger.pem, push: false })).rejects.toThrow(/would not be signed/);
|
|
365
|
+
await expect(ciRun({ image: JOB_IMAGE, cwd: app, job: "apply", env: "prod", forge: "github", base, chant: fakeChant(), hostEnv: HOST, runnerKey: "not a key", runnerKeyFromEnv: true, push: false })).rejects.toThrow(/in CHANT_RUNNER_KEY is not an Ed25519 private key in PEM/);
|
|
332
366
|
expect((await readRunLedger("prod", "pr-apply", { cwd: app })).records).toHaveLength(1);
|
|
367
|
+
|
|
368
|
+
// With ci.green.signedSince the same run warns, and so does one with no key.
|
|
369
|
+
writeFiles(root, { "chant.workspace.json": declaration([{ name: "app", dir: "app", kind: "other", because: "the app" }], { ci: { green: { ...GREEN, signedSince: base } } }) });
|
|
370
|
+
const opted = { image: JOB_IMAGE, cwd: app, job: "apply" as const, env: "prod", forge: "github" as const, base, chant: fakeChant(), hostEnv: HOST, push: false, output: join(scratchDir("chant-ci-run-out-"), "pr") };
|
|
371
|
+
const warned = await ciRun({ ...opted, runnerKey: stranger.pem, runnerKeyFromEnv: true });
|
|
372
|
+
expect(warned.warnings[0]).toMatch(/CHANT_RUNNER_KEY is set, and the run will not be signed: [\s\S]*, and ci.green.signedSince is [0-9a-f]{40}, so it will not count/);
|
|
373
|
+
const keyless = await ciRun(opted);
|
|
374
|
+
expect(keyless.warnings).toEqual([expect.stringMatching(/^there is no runner key, so the run's record is unsigned, and ci.green.signedSince is/)]);
|
|
333
375
|
});
|
|
334
376
|
|
|
335
377
|
test("--pr-build runs the job's build and lint lines after --before-script and before the command, and a failing build fails the job", async () => {
|
|
@@ -714,3 +756,156 @@ describe("the job's secrets from the host (#4096)", () => {
|
|
|
714
756
|
expect(formatCiRun(r)).toContain("not-approved in apply, exit 3: the deploy failed with ***");
|
|
715
757
|
});
|
|
716
758
|
});
|
|
759
|
+
|
|
760
|
+
describe("a generated forge job runs ci run --in-place (#4156)", () => {
|
|
761
|
+
// What a GitHub or Forgejo job has in its environment: the forge's run, job and attempt, and the secret.
|
|
762
|
+
const FORGE = { GITHUB_RUN_ID: "4242", GITHUB_RUN_ATTEMPT: "2", GITHUB_JOB: "apply", GITHUB_REPOSITORY: "acme/estate", GITHUB_SERVER_URL: "http://forgejo.localhost" };
|
|
763
|
+
|
|
764
|
+
test("the generated job's line parses to the same job, and --in-place, --no-push, --require-review and --wave reach it", () => {
|
|
765
|
+
const [plan, apply] = prLoopJobs("forgejo", "prod", { events: true, reportUrl: "s3://b/p", requireReview: true, waveGate: "release", branch: "trunk" });
|
|
766
|
+
expect(plan!.run.command).toBe('chant ci run plan --in-place --no-push --base "$BASE_SHA" --pr "$PR_NUMBER" --env prod --gate pr-apply --forge forgejo --wave-gate release --events-json --report-url "s3://b/p"');
|
|
767
|
+
const args = parseArgs(apply!.run.command.replace(/"\$BASE_SHA"/, "b".repeat(40)).replace(/"/g, "").split(" ").slice(1).concat(["--wave", "2"]));
|
|
768
|
+
expect(args).toMatchObject({ ciInPlace: true, requireReview: true, wave: 2, waveGate: "release", branch: "trunk", eventsJson: true, reportUrl: "s3://b/p" });
|
|
769
|
+
expect(ciLoopOptions(args)).toEqual({ gate: "pr-apply", branch: "trunk", events: true, reportUrl: "s3://b/p", waveGate: "release", requireReview: true });
|
|
770
|
+
// --no-require-review, which pipelines generated before #4168 pass, is the default now.
|
|
771
|
+
expect(ciLoopOptions(parseArgs(["ci", "run", "apply", "--no-require-review"]))).toEqual({});
|
|
772
|
+
expect(parseArgs(["ci", "run", "plan", "--no-push"]).noPush).toBe(true);
|
|
773
|
+
// ci run rebuilds pr-apply from those options: the very command the job ran before #4156.
|
|
774
|
+
expect(prLoopJobs("forgejo", "prod", ciLoopOptions(args))[1]!.command).toBe(apply!.command);
|
|
775
|
+
expect(apply!.run.env.CHANT_RUNNER_KEY).toBe("${{ secrets.CHANT_RUNNER_KEY }}");
|
|
776
|
+
});
|
|
777
|
+
|
|
778
|
+
test("in the job's own checkout, with its environment less the key, a signed record names the forge's run and verifies, and ci list sees it", async () => {
|
|
779
|
+
const { root, app, base, sha } = workspace();
|
|
780
|
+
const chant = fakeChant();
|
|
781
|
+
const before = git(root, "worktree", "list", "--porcelain");
|
|
782
|
+
const r = await ciRun({ cwd: app, job: "apply", env: "prod", forge: "forgejo", base, chant, hostEnv: { ...HOST, ...FORGE }, runnerKey: BOT.pem, runnerKeyFromEnv: true, inPlace: true, runId: "forge-apply-1" });
|
|
783
|
+
expect(r.status).toBe("ok");
|
|
784
|
+
expect(r.warnings).toEqual([]);
|
|
785
|
+
expect(r.signer).toBe("chant-runner");
|
|
786
|
+
expect(r.pushed).toBe(true);
|
|
787
|
+
|
|
788
|
+
// In place: no worktree, the report where the forge keeps it, and no setup phase.
|
|
789
|
+
expect(git(root, "worktree", "list", "--porcelain")).toBe(before);
|
|
790
|
+
expect(readFileSync(join(app, ".chant/pr/pr-apply.pwd"), "utf-8").trim()).toBe(realpathSync(app));
|
|
791
|
+
expect(r.report).toBe(join(realpathSync(app), ".chant/pr"));
|
|
792
|
+
expect(r.record.phases.map((p) => p.name)).toEqual(["apply"]);
|
|
793
|
+
const argv = readFileSync(join(app, ".chant/pr/pr-apply.args"), "utf-8").trimEnd().split("\n");
|
|
794
|
+
expect(argv).toEqual(["components", "pr-apply", "--base", base, "--env", "prod", "--gate", "pr-apply", "--output", ".chant/pr", "--forge", "forgejo", "--member", "app", "--resume", ".chant/pr-resume/pr-apply.json"]);
|
|
795
|
+
// The forge job's whole environment reaches the step, but never the runner key.
|
|
796
|
+
const env = envFile(join(app, ".chant/pr"), "pr-apply");
|
|
797
|
+
expect(env).toMatchObject({ NOT_FOR_JOBS: "leak", GITHUB_RUN_ID: "4242", BASE_SHA: base, GITHUB_SHA: sha });
|
|
798
|
+
expect(env).not.toHaveProperty("CHANT_RUNNER_KEY");
|
|
799
|
+
|
|
800
|
+
// The record: the forge's run, job and attempt as runOrigin, signed, and it verifies against trust.json.
|
|
801
|
+
const origin = { forge: "github", repo: "acme/estate", url: "http://forgejo.localhost/acme/estate/actions/runs/4242", jobId: "apply", attempt: 2 };
|
|
802
|
+
expect(r.record).toMatchObject({ op: "pr-apply", gitSha: sha, id: "forge-apply-1", runOrigin: origin });
|
|
803
|
+
const stored = (await readRunLedger("prod", "pr-apply", { cwd: app })).records.at(-1)!;
|
|
804
|
+
expect(verifyOpRunStatement(stored, RUNNERS, { runner: ["chant-runner"] })).toMatchObject({ status: "signed", signer: "chant-runner" });
|
|
805
|
+
expect(git(root, "ls-remote", "origin", "chant/lifecycle")).toContain(git(root, "rev-parse", "chant/lifecycle"));
|
|
806
|
+
|
|
807
|
+
const list = (await ciList({ cwd: app, now: NOW })) as Extract<Awaited<ReturnType<typeof ciList>>, { commits: unknown }>;
|
|
808
|
+
const listed = list.commits.find((c) => c.sha === sha)!;
|
|
809
|
+
expect(listed.phases.find((p) => p.phase === "apply")!.runs).toEqual([expect.objectContaining({ name: "pr-apply", opRun: { id: "forge-apply-1", env: "prod", signer: "chant-runner" } })]);
|
|
810
|
+
});
|
|
811
|
+
|
|
812
|
+
test("with no key the job runs, warns of nothing, and its unsigned record counts in ci list and the run index", async () => {
|
|
813
|
+
const { app, base, sha } = workspace();
|
|
814
|
+
const reports = scratchDir("chant-ci-run-index-");
|
|
815
|
+
const { CHANT_RUNNER_KEY: _key, ...keyless } = HOST;
|
|
816
|
+
const r = await ciRun({ cwd: app, job: "plan", env: "prod", forge: "forgejo", base, pr: 7, chant: fakeChant(), hostEnv: { ...keyless, ...FORGE, GITHUB_JOB: "plan" }, inPlace: true, push: false, runId: "forge-plan-1", loop: { reportUrl: `file://${reports}` } });
|
|
817
|
+
expect(r.status).toBe("ok");
|
|
818
|
+
expect(r.warnings).toEqual([]);
|
|
819
|
+
expect(r.notes).toEqual(["there is no runner key, so the run's record is unsigned"]);
|
|
820
|
+
expect(r.signer).toBeNull();
|
|
821
|
+
expect(r.record.statement).toBeUndefined();
|
|
822
|
+
expect(r.record.runOrigin).toMatchObject({ forge: "github", jobId: "plan", attempt: 2 });
|
|
823
|
+
// --no-push: the plan's record stays on this checkout's chant/lifecycle.
|
|
824
|
+
expect(r.pushed).toBe(false);
|
|
825
|
+
|
|
826
|
+
const list = (await ciList({ cwd: app, now: NOW })) as Extract<Awaited<ReturnType<typeof ciList>>, { commits: unknown }>;
|
|
827
|
+
const plan = list.commits.find((c) => c.sha === sha)!.phases.find((p) => p.phase === "plan")!;
|
|
828
|
+
expect(plan.result).toBe("pass");
|
|
829
|
+
expect(plan.runs[0]).toMatchObject({ name: "pr-plan", opRun: { id: "forge-plan-1", signer: null } });
|
|
830
|
+
|
|
831
|
+
const index = JSON.parse(readFileSync(join(reports, "runs", "index.json"), "utf-8")) as { runs: Record<string, unknown>[] };
|
|
832
|
+
expect(index.runs[0]).toMatchObject({ job: "plan", runId: "forge-plan-1", signer: null, runOrigin: { forge: "github", jobId: "plan", attempt: 2 } });
|
|
833
|
+
});
|
|
834
|
+
|
|
835
|
+
test("a failed command's exit code is the job's, and --wave reaches pr-apply", async () => {
|
|
836
|
+
const { app, base } = workspace();
|
|
837
|
+
const r = await ciRun({ cwd: app, job: "apply", env: "prod", forge: "github", base, chant: fakeChant(), hostEnv: { ...HOST, ...FORGE, FAKE_EXIT: "3" }, inPlace: true, push: false, loop: { waveGate: "release" }, wave: 2 });
|
|
838
|
+
expect(r.status).toBe("fail");
|
|
839
|
+
expect(r.exitCode).toBe(3);
|
|
840
|
+
const argv = readFileSync(join(app, ".chant/pr/pr-apply.args"), "utf-8").trimEnd().split("\n");
|
|
841
|
+
expect(argv.slice(-4)).toEqual(["--resume", ".chant/pr-resume/pr-apply.json", "--wave", "2"]);
|
|
842
|
+
await expect(ciRun({ cwd: app, job: "plan", env: "prod", forge: "github", base, pr: 1, chant: fakeChant(), hostEnv: HOST, inPlace: true, push: false, wave: 2 })).rejects.toThrow(/--wave names the one wave an apply runs/);
|
|
843
|
+
// In place runs HEAD only.
|
|
844
|
+
await expect(ciRun({ cwd: app, job: "apply", env: "prod", forge: "github", base, commit: base, chant: fakeChant(), hostEnv: HOST, inPlace: true, push: false })).rejects.toThrow(/--in-place runs the checkout's HEAD/);
|
|
845
|
+
});
|
|
846
|
+
});
|
|
847
|
+
|
|
848
|
+
describe("ci run --local (#4161)", () => {
|
|
849
|
+
test("the job runs on this machine: no push, no status, no report upload or run index, a local record ci tick ignores, and events that say local", async () => {
|
|
850
|
+
const { root, app, base, sha } = workspace();
|
|
851
|
+
const reports = scratchDir("chant-ci-run-local-");
|
|
852
|
+
const remoteBefore = git(root, "ls-remote", "origin");
|
|
853
|
+
const posts: CommitStatus[] = [];
|
|
854
|
+
const events: string[] = [];
|
|
855
|
+
const r = await ciRun({
|
|
856
|
+
image: JOB_IMAGE,
|
|
857
|
+
cwd: app,
|
|
858
|
+
job: "plan",
|
|
859
|
+
env: "prod",
|
|
860
|
+
forge: "forgejo",
|
|
861
|
+
base,
|
|
862
|
+
pr: 7,
|
|
863
|
+
chant: fakeChant(),
|
|
864
|
+
hostEnv: HOST,
|
|
865
|
+
runnerKey: BOT.pem,
|
|
866
|
+
runnerKeyFromEnv: true,
|
|
867
|
+
local: true,
|
|
868
|
+
runId: "local-plan-1",
|
|
869
|
+
output: join(scratchDir("chant-ci-run-local-out-"), "pr"),
|
|
870
|
+
loop: { reportUrl: `file://${reports}`, events: true },
|
|
871
|
+
status: { client: { async setCommitStatus(_sha, status) { posts.push(status); } } },
|
|
872
|
+
runEvents: (line) => events.push(line),
|
|
873
|
+
});
|
|
874
|
+
expect(r.status).toBe("ok");
|
|
875
|
+
expect(r.warnings).toEqual([]);
|
|
876
|
+
expect(r.local).toBe(true);
|
|
877
|
+
|
|
878
|
+
// Nothing left this machine: origin is as it was, the fake forge saw no status, and the report URL holds nothing.
|
|
879
|
+
expect(r.pushed).toBe(false);
|
|
880
|
+
expect(git(root, "ls-remote", "origin")).toBe(remoteBefore);
|
|
881
|
+
expect(posts).toEqual([]);
|
|
882
|
+
expect(readdirSync(reports)).toEqual([]);
|
|
883
|
+
// The command got --no-status and no --report-url, so pr-plan posts and uploads nothing either.
|
|
884
|
+
const argv = readFileSync(join(r.report!, "pr-plan.args"), "utf-8").trimEnd().split("\n");
|
|
885
|
+
expect(argv).toContain("--no-status");
|
|
886
|
+
expect(argv).not.toContain("--report-url");
|
|
887
|
+
expect(argv).toContain("--events-json");
|
|
888
|
+
|
|
889
|
+
// The record is on this checkout's chant/lifecycle, and says local.
|
|
890
|
+
expect(r.record).toMatchObject({ op: "pr-plan", gitSha: sha, id: "local-plan-1", runOrigin: { forge: "local" } });
|
|
891
|
+
const stored = (await readRunLedger("prod", "pr-plan", { cwd: app })).records.at(-1)!;
|
|
892
|
+
expect(stored).toMatchObject({ id: "local-plan-1", runOrigin: { forge: "local" } });
|
|
893
|
+
expect(formatCiRun(r)).toContain("local run: the record stays on this machine");
|
|
894
|
+
|
|
895
|
+
// The events stream as the job runs, and say where it ran.
|
|
896
|
+
const stream = checkRunEventLines(events);
|
|
897
|
+
expect(stream[0]).toMatchObject({ type: "run-start", kind: "pipeline", runtime: "local", runId: "local-plan-1", gitSha: sha, runOrigin: { forge: "local" } });
|
|
898
|
+
expect(stream.at(-1)).toMatchObject({ type: "run-settle", status: "ok" });
|
|
899
|
+
|
|
900
|
+
// A local run is never CI's verdict, signed or not.
|
|
901
|
+
const runs = await readOpRunSource(app, root, git(root, "rev-parse", "HEAD"));
|
|
902
|
+
expect(runs.checkRuns(sha)).toEqual([]);
|
|
903
|
+
expect(runs.ignored.get(sha)).toBeUndefined();
|
|
904
|
+
});
|
|
905
|
+
|
|
906
|
+
test("--local with --in-place is refused before anything runs, and the flag parses", async () => {
|
|
907
|
+
const { app, base } = workspace();
|
|
908
|
+
await expect(ciRun({ cwd: app, job: "plan", env: "prod", forge: "github", base, pr: 1, chant: fakeChant(), hostEnv: HOST, inPlace: true, local: true })).rejects.toThrow(/--in-place .* --local/);
|
|
909
|
+
expect(parseArgs(["ci", "run", "plan", "--local"]).local).toBe(true);
|
|
910
|
+
});
|
|
911
|
+
});
|