@intentius/chant 0.124.45 → 0.124.48
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__golden__/wave-loop/op-by-apply-after-fails.json +10 -0
- package/dist/__golden__/wave-loop/op-by-apply-hold.json +10 -0
- package/dist/__golden__/wave-loop/op-by-apply-ignored.json +10 -0
- package/dist/__golden__/wave-loop/op-by-apply-pass.json +10 -0
- package/dist/__golden__/wave-loop/op-by-apply-skip.json +10 -0
- package/dist/__golden__/wave-loop/op-cost-member-clash.json +6 -0
- package/dist/__golden__/wave-loop/op-cost-member.json +13 -0
- package/dist/__golden__/wave-loop/op-denied-source.json +16 -0
- package/dist/__golden__/wave-loop/op-denied.json +16 -0
- package/dist/__golden__/wave-loop/op-discover-rest-short.json +6 -0
- package/dist/__golden__/wave-loop/op-discover-rest-stops.json +13 -0
- package/dist/__golden__/wave-loop/op-discover-rest.json +26 -0
- package/dist/__golden__/wave-loop/op-discover-wide.json +26 -0
- package/dist/__golden__/wave-loop/op-held-on-again.json +16 -0
- package/dist/__golden__/wave-loop/op-held-on-before-apply.json +16 -0
- package/dist/__golden__/wave-loop/op-held-on.json +16 -0
- package/dist/__golden__/wave-loop/op-hooks-apply-fails.json +13 -0
- package/dist/__golden__/wave-loop/op-hooks-fail-after-apply.json +13 -0
- package/dist/__golden__/wave-loop/op-hooks-fail-before-apply.json +13 -0
- package/dist/__golden__/wave-loop/op-hooks-fail-before-plan.json +13 -0
- package/dist/__golden__/wave-loop/op-hooks-held.json +13 -0
- package/dist/__golden__/wave-loop/op-hooks-hold-before-apply.json +13 -0
- package/dist/__golden__/wave-loop/op-hooks-pass.json +13 -0
- package/dist/__golden__/wave-loop/op-hooks-refused-at-base.json +13 -0
- package/dist/__golden__/wave-loop/op-hooks-share.json +33 -0
- package/dist/__golden__/wave-loop/op-outcome-held.json +10 -0
- package/dist/__golden__/wave-loop/op-outcome-replan-approved.json +10 -0
- package/dist/__golden__/wave-loop/op-outcome-replan-forever.json +10 -0
- package/dist/__golden__/wave-loop/op-outcome-replan.json +10 -0
- package/dist/__golden__/wave-loop/op-outcome-stood-down.json +10 -0
- package/dist/__golden__/wave-loop/op-outcome-unreadable.json +10 -0
- package/dist/__golden__/wave-loop/op-overridden.json +16 -0
- package/dist/__golden__/wave-loop/op-per-run.json +20 -0
- package/dist/__golden__/wave-loop/op-point.json +13 -0
- package/dist/__golden__/wave-loop/op-pr-review.json +10 -0
- package/dist/__golden__/wave-loop/op-sealed.json +10 -0
- package/dist/__golden__/wave-loop/op-spend-change-only.json +10 -0
- package/dist/__golden__/wave-loop/op-spend.json +10 -0
- package/dist/__golden__/wave-loop/op-wave-commands.json +55 -0
- package/dist/__golden__/wave-loop/op-wide-refused.json +26 -0
- package/dist/__golden__/wave-loop/op-wide-waiting.json +29 -0
- package/dist/__golden__/wave-loop/op-wide.json +39 -0
- package/dist/action-pins.d.ts +61 -0
- package/dist/action-pins.d.ts.map +1 -0
- package/dist/action-pins.js +77 -0
- package/dist/capabilities/aws.paths +148 -0
- package/dist/capabilities/base-mappings.json +122 -0
- package/dist/capabilities/catalog.d.ts +89 -0
- package/dist/capabilities/catalog.d.ts.map +1 -0
- package/dist/capabilities/catalog.js +204 -0
- package/dist/capabilities/language.d.ts +103 -0
- package/dist/capabilities/language.d.ts.map +1 -0
- package/dist/capabilities/language.js +335 -0
- package/dist/capabilities/matcher.d.ts +65 -0
- package/dist/capabilities/matcher.d.ts.map +1 -0
- package/dist/capabilities/matcher.js +299 -0
- package/dist/capabilities/view.d.ts +207 -0
- package/dist/capabilities/view.d.ts.map +1 -0
- package/dist/capabilities/view.js +484 -0
- package/dist/cli/commands/carve.d.ts +3 -0
- package/dist/cli/commands/carve.d.ts.map +1 -1
- package/dist/cli/commands/carve.js +36 -7
- package/dist/cli/commands/import-report.d.ts +26 -0
- package/dist/cli/commands/import-report.d.ts.map +1 -0
- package/dist/cli/commands/import-report.js +65 -0
- package/dist/cli/commands/import.d.ts +11 -1
- package/dist/cli/commands/import.d.ts.map +1 -1
- package/dist/cli/commands/import.js +22 -3
- package/dist/cli/commands/lint.d.ts.map +1 -1
- package/dist/cli/commands/lint.js +1 -0
- package/dist/cli/commands/migrate.d.ts +13 -1
- package/dist/cli/commands/migrate.d.ts.map +1 -1
- package/dist/cli/commands/migrate.js +134 -10
- package/dist/cli/handlers/approve.d.ts.map +1 -1
- package/dist/cli/handlers/approve.js +21 -2
- package/dist/cli/handlers/build.d.ts.map +1 -1
- package/dist/cli/handlers/build.js +6 -1
- package/dist/cli/handlers/declared-graph.d.ts +44 -0
- package/dist/cli/handlers/declared-graph.d.ts.map +1 -0
- package/dist/cli/handlers/declared-graph.js +87 -0
- package/dist/cli/handlers/graph.d.ts +25 -0
- package/dist/cli/handlers/graph.d.ts.map +1 -1
- package/dist/cli/handlers/graph.js +93 -87
- package/dist/cli/handlers/ledger.d.ts +3 -0
- package/dist/cli/handlers/ledger.d.ts.map +1 -0
- package/dist/cli/handlers/ledger.js +55 -0
- package/dist/cli/handlers/migrate.d.ts.map +1 -1
- package/dist/cli/handlers/migrate.js +18 -11
- package/dist/cli/handlers/misc.d.ts.map +1 -1
- package/dist/cli/handlers/misc.js +12 -1
- package/dist/cli/handlers/pr-env.d.ts.map +1 -1
- package/dist/cli/handlers/pr-env.js +4 -3
- package/dist/cli/handlers/pr.d.ts +15 -1
- package/dist/cli/handlers/pr.d.ts.map +1 -1
- package/dist/cli/handlers/pr.js +143 -39
- package/dist/cli/handlers/query.d.ts +7 -2
- package/dist/cli/handlers/query.d.ts.map +1 -1
- package/dist/cli/handlers/query.js +16 -4
- package/dist/cli/handlers/release.d.ts.map +1 -1
- package/dist/cli/handlers/release.js +6 -3
- package/dist/cli/handlers/search-count.d.ts +89 -0
- package/dist/cli/handlers/search-count.d.ts.map +1 -0
- package/dist/cli/handlers/search-count.js +132 -0
- package/dist/cli/handlers/search.d.ts +356 -6
- package/dist/cli/handlers/search.d.ts.map +1 -1
- package/dist/cli/handlers/search.js +1039 -155
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +88 -17
- package/dist/cli/mcp/server.d.ts.map +1 -1
- package/dist/cli/mcp/server.js +3 -0
- package/dist/cli/mcp/tools/capabilities.d.ts +7 -0
- package/dist/cli/mcp/tools/capabilities.d.ts.map +1 -0
- package/dist/cli/mcp/tools/capabilities.js +27 -0
- package/dist/cli/mcp/workspace-tools.d.ts +3 -1
- package/dist/cli/mcp/workspace-tools.d.ts.map +1 -1
- package/dist/cli/mcp/workspace-tools.js +47 -2
- package/dist/cli/parse-args.d.ts.map +1 -1
- package/dist/cli/parse-args.js +100 -19
- package/dist/cli/registry.d.ts +36 -4
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/components/builders.d.ts +5 -1
- package/dist/components/builders.d.ts.map +1 -1
- package/dist/components/builders.js +5 -0
- package/dist/components/capability-plugin-loader.d.ts.map +1 -1
- package/dist/components/capability-plugin-loader.js +16 -1
- package/dist/components/capability-plugin.d.ts +14 -0
- package/dist/components/capability-plugin.d.ts.map +1 -1
- package/dist/components/pr-env-ports.d.ts +29 -0
- package/dist/components/pr-env-ports.d.ts.map +1 -0
- package/dist/components/pr-env-ports.js +77 -0
- package/dist/components/pr-env-run.d.ts +5 -21
- package/dist/components/pr-env-run.d.ts.map +1 -1
- package/dist/components/pr-env-run.js +6 -70
- package/dist/components/pr-environment.d.ts +2 -1
- package/dist/components/pr-environment.d.ts.map +1 -1
- package/dist/components/pr-environment.js +1 -1
- package/dist/components/pr-hooks.d.ts +21 -1
- package/dist/components/pr-hooks.d.ts.map +1 -1
- package/dist/components/pr-hooks.js +72 -4
- package/dist/components/pr-pipeline.d.ts +45 -10
- package/dist/components/pr-pipeline.d.ts.map +1 -1
- package/dist/components/pr-pipeline.js +47 -14
- package/dist/components/pr-policy.d.ts +36 -0
- package/dist/components/pr-policy.d.ts.map +1 -1
- package/dist/components/pr-policy.js +36 -0
- package/dist/components/starter-plugin.d.ts +1 -0
- package/dist/components/starter-plugin.d.ts.map +1 -1
- package/dist/components/starter-plugin.js +5 -1
- package/dist/components/verbs/index.d.ts +2 -0
- package/dist/components/verbs/index.d.ts.map +1 -1
- package/dist/components/verbs/index.js +2 -0
- package/dist/components/verbs/publish-artifact.d.ts +65 -0
- package/dist/components/verbs/publish-artifact.d.ts.map +1 -0
- package/dist/components/verbs/publish-artifact.js +74 -0
- package/dist/components/verbs/publish-image.d.ts +129 -0
- package/dist/components/verbs/publish-image.d.ts.map +1 -0
- package/dist/components/verbs/publish-image.js +145 -0
- package/dist/config-environments.d.ts +112 -0
- package/dist/config-environments.d.ts.map +1 -0
- package/dist/config-environments.js +114 -0
- package/dist/config.d.ts +32 -84
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +13 -96
- package/dist/gate-decision.d.ts +11 -2
- package/dist/gate-decision.d.ts.map +1 -1
- package/dist/gate-decision.js +15 -3
- package/dist/graph-detail.d.ts.map +1 -1
- package/dist/graph-detail.js +15 -3
- package/dist/graph-effective.d.ts +33 -2
- package/dist/graph-effective.d.ts.map +1 -1
- package/dist/graph-effective.js +215 -68
- package/dist/graph-ir.d.ts +48 -0
- package/dist/graph-ir.d.ts.map +1 -1
- package/dist/graph-ir.js +130 -0
- package/dist/graph-sub-template.d.ts +11 -0
- package/dist/graph-sub-template.d.ts.map +1 -0
- package/dist/graph-sub-template.js +19 -0
- package/dist/graph-walk.d.ts +66 -0
- package/dist/graph-walk.d.ts.map +1 -0
- package/dist/graph-walk.js +70 -0
- package/dist/import/parser.d.ts +19 -0
- package/dist/import/parser.d.ts.map +1 -1
- package/dist/lexicon.d.ts +80 -6
- package/dist/lexicon.d.ts.map +1 -1
- package/dist/lifecycle/gate-ledger.d.ts +11 -0
- package/dist/lifecycle/gate-ledger.d.ts.map +1 -1
- package/dist/lifecycle/git.d.ts +2 -5
- package/dist/lifecycle/git.d.ts.map +1 -1
- package/dist/lifecycle/ledger-read.d.ts +65 -0
- package/dist/lifecycle/ledger-read.d.ts.map +1 -0
- package/dist/lifecycle/ledger-read.js +160 -0
- package/dist/lifecycle/observe.d.ts +28 -0
- package/dist/lifecycle/observe.d.ts.map +1 -1
- package/dist/lifecycle/observe.js +23 -1
- package/dist/lifecycle/release-workstation.d.ts +7 -0
- package/dist/lifecycle/release-workstation.d.ts.map +1 -1
- package/dist/lifecycle/release-workstation.js +25 -0
- package/dist/lifecycle/run-ledger.d.ts +4 -3
- package/dist/lifecycle/run-ledger.d.ts.map +1 -1
- package/dist/lifecycle/run-ledger.js +1 -0
- package/dist/lint/discover.js +3 -1
- package/dist/lint/post-synth.d.ts +127 -1
- package/dist/lint/post-synth.d.ts.map +1 -1
- package/dist/lint/post-synth.js +84 -2
- package/dist/lint/rule.d.ts +6 -0
- package/dist/lint/rule.d.ts.map +1 -1
- package/dist/lint/rules/op/index.d.ts +1 -0
- package/dist/lint/rules/op/index.d.ts.map +1 -1
- package/dist/lint/rules/op/index.js +2 -0
- package/dist/lint/rules/op/ops019-workspace-op-target.d.ts +32 -0
- package/dist/lint/rules/op/ops019-workspace-op-target.d.ts.map +1 -0
- package/dist/lint/rules/op/ops019-workspace-op-target.js +63 -0
- package/dist/live-endpoint.d.ts +1 -1
- package/dist/live-endpoint.d.ts.map +1 -1
- package/dist/live-endpoint.js +1 -1
- package/dist/observation.d.ts +48 -1
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +21 -5
- package/dist/op/activities/activity-contracts.d.ts +9 -6
- package/dist/op/activities/activity-contracts.d.ts.map +1 -1
- package/dist/op/activities/activity-contracts.js +5 -2
- package/dist/op/activities/index.d.ts +2 -2
- package/dist/op/activities/index.d.ts.map +1 -1
- package/dist/op/activities/index.js +1 -1
- package/dist/op/activities/review-agent.d.ts +90 -4
- package/dist/op/activities/review-agent.d.ts.map +1 -1
- package/dist/op/activities/review-agent.js +217 -19
- package/dist/op/activities/work-evidence.d.ts +8 -1
- package/dist/op/activities/work-evidence.d.ts.map +1 -1
- package/dist/op/activities/work-evidence.js +1 -0
- package/dist/op/builders.d.ts +9 -5
- package/dist/op/builders.d.ts.map +1 -1
- package/dist/op/builders.js +9 -5
- package/dist/op/composites/apply-op.d.ts +29 -2
- package/dist/op/composites/apply-op.d.ts.map +1 -1
- package/dist/op/composites/apply-op.js +20 -1
- package/dist/op/gate-approval.d.ts +11 -5
- package/dist/op/gate-approval.d.ts.map +1 -1
- package/dist/op/gate-approval.js +11 -6
- package/dist/op/gate-quorum.d.ts +100 -3
- package/dist/op/gate-quorum.d.ts.map +1 -1
- package/dist/op/gate-quorum.js +108 -6
- package/dist/op/gate-review.d.ts +9 -0
- package/dist/op/gate-review.d.ts.map +1 -1
- package/dist/op/gate-review.js +13 -0
- package/dist/op/gate.d.ts +44 -3
- package/dist/op/gate.d.ts.map +1 -1
- package/dist/op/gate.js +25 -4
- package/dist/op/index.d.ts +3 -3
- package/dist/op/index.d.ts.map +1 -1
- package/dist/op/index.js +1 -1
- package/dist/op/local-executor.d.ts +38 -3
- package/dist/op/local-executor.d.ts.map +1 -1
- package/dist/op/local-executor.js +48 -6
- package/dist/op/op-waves-run.d.ts +26 -1
- package/dist/op/op-waves-run.d.ts.map +1 -1
- package/dist/op/op-waves-run.js +259 -13
- package/dist/op/op-waves.d.ts +72 -5
- package/dist/op/op-waves.d.ts.map +1 -1
- package/dist/op/op-waves.js +110 -15
- package/dist/op/runtime.d.ts +11 -0
- package/dist/op/runtime.d.ts.map +1 -1
- package/dist/op/schedule-overdue.d.ts +16 -0
- package/dist/op/schedule-overdue.d.ts.map +1 -1
- package/dist/op/schedule-overdue.js +36 -0
- package/dist/op/stage-hooks.d.ts +9 -2
- package/dist/op/stage-hooks.d.ts.map +1 -1
- package/dist/op/stage-hooks.js +7 -5
- package/dist/op/workspace-run-env.d.ts +22 -0
- package/dist/op/workspace-run-env.d.ts.map +1 -0
- package/dist/op/workspace-run-env.js +21 -0
- package/dist/pr-forge.d.ts +24 -0
- package/dist/pr-forge.d.ts.map +1 -1
- package/dist/pr-forge.js +47 -0
- package/dist/pr-post.d.ts +42 -0
- package/dist/pr-post.d.ts.map +1 -1
- package/dist/pr-post.js +67 -1
- package/dist/read-filter.d.ts +65 -0
- package/dist/read-filter.d.ts.map +1 -0
- package/dist/read-filter.js +179 -0
- package/dist/run-event.d.ts +1 -1
- package/dist/run-event.d.ts.map +1 -1
- package/dist/terraform/carve.d.ts +24 -3
- package/dist/terraform/carve.d.ts.map +1 -1
- package/dist/terraform/carve.js +32 -14
- package/dist/terraform/cuts.d.ts +97 -0
- package/dist/terraform/cuts.d.ts.map +1 -0
- package/dist/terraform/cuts.js +138 -0
- package/dist/terraform/folds.d.ts +26 -0
- package/dist/terraform/folds.d.ts.map +1 -0
- package/dist/terraform/folds.js +38 -0
- package/dist/terraform/graph.d.ts.map +1 -1
- package/dist/terraform/graph.js +10 -0
- package/dist/terraform/reach.d.ts +140 -0
- package/dist/terraform/reach.d.ts.map +1 -0
- package/dist/terraform/reach.js +170 -0
- package/dist/terraform/score.d.ts +14 -0
- package/dist/terraform/score.d.ts.map +1 -1
- package/dist/terraform/score.js +14 -31
- package/dist/terraform/state.d.ts.map +1 -1
- package/dist/terraform/state.js +4 -2
- package/dist/terraform/types.d.ts +8 -0
- package/dist/terraform/types.d.ts.map +1 -1
- package/dist/wave-blocked.d.ts +10 -1
- package/dist/wave-blocked.d.ts.map +1 -1
- package/dist/wave-blocked.js +31 -3
- package/dist/wave-runtime.mjs +266 -256
- package/dist/workspace/capabilities-contract.d.ts +66 -0
- package/dist/workspace/capabilities-contract.d.ts.map +1 -0
- package/dist/workspace/capabilities-contract.js +107 -0
- package/dist/workspace/capabilities.schema.json +229 -0
- package/dist/workspace/check.schema.json +11 -2
- package/dist/workspace/checks/ci-branch.d.ts +44 -0
- package/dist/workspace/checks/ci-branch.d.ts.map +1 -0
- package/dist/workspace/checks/ci-branch.js +133 -0
- package/dist/workspace/checks/links.d.ts +3 -0
- package/dist/workspace/checks/links.d.ts.map +1 -1
- package/dist/workspace/checks/links.js +12 -1
- package/dist/workspace/checks/org.d.ts +48 -0
- package/dist/workspace/checks/org.d.ts.map +1 -0
- package/dist/workspace/checks/org.js +156 -0
- package/dist/workspace/checks.d.ts +11 -1
- package/dist/workspace/checks.d.ts.map +1 -1
- package/dist/workspace/checks.js +59 -7
- package/dist/workspace/ci-branches.d.ts +16 -0
- package/dist/workspace/ci-branches.d.ts.map +1 -1
- package/dist/workspace/ci-branches.js +27 -0
- package/dist/workspace/ci-green-cli.js +7 -7
- package/dist/workspace/ci-green-workflow.d.ts +1 -1
- package/dist/workspace/ci-green-workflow.d.ts.map +1 -1
- package/dist/workspace/ci-green-workflow.js +13 -8
- package/dist/workspace/ci-green.d.ts +14 -0
- package/dist/workspace/ci-green.d.ts.map +1 -1
- package/dist/workspace/ci-green.js +44 -11
- package/dist/workspace/ci-run.d.ts +9 -1
- package/dist/workspace/ci-run.d.ts.map +1 -1
- package/dist/workspace/ci-run.js +67 -6
- package/dist/workspace/ci-serve.d.ts +9 -0
- package/dist/workspace/ci-serve.d.ts.map +1 -1
- package/dist/workspace/ci-serve.js +114 -76
- package/dist/workspace/compose-graph.d.ts +23 -0
- package/dist/workspace/compose-graph.d.ts.map +1 -1
- package/dist/workspace/compose-graph.js +3 -1
- package/dist/workspace/composites.d.ts +4 -1
- package/dist/workspace/composites.d.ts.map +1 -1
- package/dist/workspace/composites.js +5 -2
- package/dist/workspace/composites.schema.json +22 -0
- package/dist/workspace/conformance/__writer_fixture__/work/work.schema.json +105 -1
- package/dist/workspace/conformance/index.d.ts +1 -1
- package/dist/workspace/conformance/index.d.ts.map +1 -1
- package/dist/workspace/conformance/index.js +39 -2
- package/dist/workspace/cross-root-lint.d.ts +56 -0
- package/dist/workspace/cross-root-lint.d.ts.map +1 -0
- package/dist/workspace/cross-root-lint.js +111 -0
- package/dist/workspace/dbt-models-reader.d.ts +44 -0
- package/dist/workspace/dbt-models-reader.d.ts.map +1 -0
- package/dist/workspace/dbt-models-reader.js +356 -0
- package/dist/workspace/dbt-project-common.d.ts +40 -0
- package/dist/workspace/dbt-project-common.d.ts.map +1 -0
- package/dist/workspace/dbt-project-common.js +106 -0
- package/dist/workspace/dbt-project-reader.d.ts +4 -3
- package/dist/workspace/dbt-project-reader.d.ts.map +1 -1
- package/dist/workspace/dbt-project-reader.js +14 -108
- package/dist/workspace/decision-rank.d.ts +26 -0
- package/dist/workspace/decision-rank.d.ts.map +1 -0
- package/dist/workspace/decision-rank.js +16 -0
- package/dist/workspace/declaration.d.ts +43 -2
- package/dist/workspace/declaration.d.ts.map +1 -1
- package/dist/workspace/declaration.js +45 -11
- package/dist/workspace/declaration.schema.json +133 -24
- package/dist/workspace/environments.d.ts +26 -2
- package/dist/workspace/environments.d.ts.map +1 -1
- package/dist/workspace/environments.js +26 -2
- package/dist/workspace/flyway-dir.d.ts +39 -0
- package/dist/workspace/flyway-dir.d.ts.map +1 -0
- package/dist/workspace/flyway-dir.js +104 -0
- package/dist/workspace/flyway-layout.d.ts +96 -0
- package/dist/workspace/flyway-layout.d.ts.map +1 -0
- package/dist/workspace/flyway-layout.js +308 -0
- package/dist/workspace/graph-cache.d.ts +8 -0
- package/dist/workspace/graph-cache.d.ts.map +1 -1
- package/dist/workspace/graph-cache.js +27 -3
- package/dist/workspace/graph-cli.d.ts +39 -2
- package/dist/workspace/graph-cli.d.ts.map +1 -1
- package/dist/workspace/graph-cli.js +92 -32
- package/dist/workspace/graph.schema.json +182 -0
- package/dist/workspace/intent.d.ts +2 -3
- package/dist/workspace/intent.d.ts.map +1 -1
- package/dist/workspace/intent.js +5 -9
- package/dist/workspace/kind-link-readers.d.ts +59 -2
- package/dist/workspace/kind-link-readers.d.ts.map +1 -1
- package/dist/workspace/kind-link-readers.js +17 -1
- package/dist/workspace/kind-readers.d.ts +3 -0
- package/dist/workspace/kind-readers.d.ts.map +1 -1
- package/dist/workspace/kind-readers.js +7 -1
- package/dist/workspace/kinds.d.ts +66 -2
- package/dist/workspace/kinds.d.ts.map +1 -1
- package/dist/workspace/kinds.js +98 -4
- package/dist/workspace/ledger.schema.json +158 -0
- package/dist/workspace/lexicon-outputs.d.ts +20 -1
- package/dist/workspace/lexicon-outputs.d.ts.map +1 -1
- package/dist/workspace/lexicon-outputs.js +102 -10
- package/dist/workspace/lineage-check.d.ts +3 -0
- package/dist/workspace/lineage-check.d.ts.map +1 -1
- package/dist/workspace/lineage-check.js +23 -4
- package/dist/workspace/links.d.ts +8 -1
- package/dist/workspace/links.d.ts.map +1 -1
- package/dist/workspace/links.js +25 -1
- package/dist/workspace/ls.d.ts +8 -0
- package/dist/workspace/ls.d.ts.map +1 -1
- package/dist/workspace/ls.js +7 -1
- package/dist/workspace/ls.schema.json +7 -0
- package/dist/workspace/member-commands.d.ts +10 -1
- package/dist/workspace/member-commands.d.ts.map +1 -1
- package/dist/workspace/member-commands.js +71 -6
- package/dist/workspace/migrate-links.d.ts +45 -0
- package/dist/workspace/migrate-links.d.ts.map +1 -0
- package/dist/workspace/migrate-links.js +100 -0
- package/dist/workspace/migration-dirs.d.ts +74 -0
- package/dist/workspace/migration-dirs.d.ts.map +1 -0
- package/dist/workspace/migration-dirs.js +254 -0
- package/dist/workspace/nested-graph.d.ts +2 -0
- package/dist/workspace/nested-graph.d.ts.map +1 -1
- package/dist/workspace/nested-graph.js +32 -1
- package/dist/workspace/reason-codes.d.ts +18 -0
- package/dist/workspace/reason-codes.d.ts.map +1 -1
- package/dist/workspace/reason-codes.js +23 -0
- package/dist/workspace/records-cli.d.ts +11 -0
- package/dist/workspace/records-cli.d.ts.map +1 -1
- package/dist/workspace/records-cli.js +57 -5
- package/dist/workspace/records.schema.json +5 -0
- package/dist/workspace/release-candidates.d.ts +2 -0
- package/dist/workspace/release-candidates.d.ts.map +1 -1
- package/dist/workspace/release-candidates.js +5 -2
- package/dist/workspace/release-train.d.ts +53 -0
- package/dist/workspace/release-train.d.ts.map +1 -0
- package/dist/workspace/release-train.js +134 -0
- package/dist/workspace/release-workflow.d.ts.map +1 -1
- package/dist/workspace/release-workflow.js +4 -3
- package/dist/workspace/repo-ref.d.ts +45 -0
- package/dist/workspace/repo-ref.d.ts.map +1 -0
- package/dist/workspace/repo-ref.js +114 -0
- package/dist/workspace/run-event.schema.json +2 -2
- package/dist/workspace/runs-cli.d.ts +9 -0
- package/dist/workspace/runs-cli.d.ts.map +1 -1
- package/dist/workspace/runs-cli.js +48 -3
- package/dist/workspace/runs.schema.json +7 -0
- package/dist/workspace/search-cli.d.ts +204 -0
- package/dist/workspace/search-cli.d.ts.map +1 -0
- package/dist/workspace/search-cli.js +466 -0
- package/dist/workspace/search-contract.d.ts +56 -0
- package/dist/workspace/search-contract.d.ts.map +1 -0
- package/dist/workspace/search-contract.js +70 -0
- package/dist/workspace/search.schema.json +822 -0
- package/dist/workspace/status-decisions.d.ts +37 -0
- package/dist/workspace/status-decisions.d.ts.map +1 -0
- package/dist/workspace/status-decisions.js +147 -0
- package/dist/workspace/status-gates.d.ts +9 -0
- package/dist/workspace/status-gates.d.ts.map +1 -1
- package/dist/workspace/status.d.ts +4 -0
- package/dist/workspace/status.d.ts.map +1 -1
- package/dist/workspace/status.js +14 -2
- package/dist/workspace/status.schema.json +6 -0
- package/dist/workspace/work-cli.d.ts.map +1 -1
- package/dist/workspace/work-cli.js +5 -3
- package/dist/workspace/work-evidence-ops.d.ts +83 -0
- package/dist/workspace/work-evidence-ops.d.ts.map +1 -0
- package/dist/workspace/work-evidence-ops.js +169 -0
- package/dist/workspace/work-evidence.d.ts +12 -2
- package/dist/workspace/work-evidence.d.ts.map +1 -1
- package/dist/workspace/work-evidence.js +21 -3
- package/dist/workspace/work-evidence.schema.json +49 -2
- package/dist/workspace/workspace-gates.d.ts +110 -0
- package/dist/workspace/workspace-gates.d.ts.map +1 -0
- package/dist/workspace/workspace-gates.js +140 -0
- package/dist/workspace/workspace-kinds.schema.json +58 -3
- package/dist/workspace/workspace-ledger.d.ts +76 -0
- package/dist/workspace/workspace-ledger.d.ts.map +1 -0
- package/dist/workspace/workspace-ledger.js +91 -0
- package/dist/workspace/workspace-run.d.ts +112 -0
- package/dist/workspace/workspace-run.d.ts.map +1 -0
- package/dist/workspace/workspace-run.js +432 -0
- package/package.json +1 -1
- package/src/__golden__/wave-loop/op-by-apply-after-fails.json +10 -0
- package/src/__golden__/wave-loop/op-by-apply-hold.json +10 -0
- package/src/__golden__/wave-loop/op-by-apply-ignored.json +10 -0
- package/src/__golden__/wave-loop/op-by-apply-pass.json +10 -0
- package/src/__golden__/wave-loop/op-by-apply-skip.json +10 -0
- package/src/__golden__/wave-loop/op-cost-member-clash.json +6 -0
- package/src/__golden__/wave-loop/op-cost-member.json +13 -0
- package/src/__golden__/wave-loop/op-denied-source.json +16 -0
- package/src/__golden__/wave-loop/op-denied.json +16 -0
- package/src/__golden__/wave-loop/op-discover-rest-short.json +6 -0
- package/src/__golden__/wave-loop/op-discover-rest-stops.json +13 -0
- package/src/__golden__/wave-loop/op-discover-rest.json +26 -0
- package/src/__golden__/wave-loop/op-discover-wide.json +26 -0
- package/src/__golden__/wave-loop/op-held-on-again.json +16 -0
- package/src/__golden__/wave-loop/op-held-on-before-apply.json +16 -0
- package/src/__golden__/wave-loop/op-held-on.json +16 -0
- package/src/__golden__/wave-loop/op-hooks-apply-fails.json +13 -0
- package/src/__golden__/wave-loop/op-hooks-fail-after-apply.json +13 -0
- package/src/__golden__/wave-loop/op-hooks-fail-before-apply.json +13 -0
- package/src/__golden__/wave-loop/op-hooks-fail-before-plan.json +13 -0
- package/src/__golden__/wave-loop/op-hooks-held.json +13 -0
- package/src/__golden__/wave-loop/op-hooks-hold-before-apply.json +13 -0
- package/src/__golden__/wave-loop/op-hooks-pass.json +13 -0
- package/src/__golden__/wave-loop/op-hooks-refused-at-base.json +13 -0
- package/src/__golden__/wave-loop/op-hooks-share.json +33 -0
- package/src/__golden__/wave-loop/op-outcome-held.json +10 -0
- package/src/__golden__/wave-loop/op-outcome-replan-approved.json +10 -0
- package/src/__golden__/wave-loop/op-outcome-replan-forever.json +10 -0
- package/src/__golden__/wave-loop/op-outcome-replan.json +10 -0
- package/src/__golden__/wave-loop/op-outcome-stood-down.json +10 -0
- package/src/__golden__/wave-loop/op-outcome-unreadable.json +10 -0
- package/src/__golden__/wave-loop/op-overridden.json +16 -0
- package/src/__golden__/wave-loop/op-per-run.json +20 -0
- package/src/__golden__/wave-loop/op-point.json +13 -0
- package/src/__golden__/wave-loop/op-pr-review.json +10 -0
- package/src/__golden__/wave-loop/op-sealed.json +10 -0
- package/src/__golden__/wave-loop/op-spend-change-only.json +10 -0
- package/src/__golden__/wave-loop/op-spend.json +10 -0
- package/src/__golden__/wave-loop/op-wave-commands.json +55 -0
- package/src/__golden__/wave-loop/op-wide-refused.json +26 -0
- package/src/__golden__/wave-loop/op-wide-waiting.json +29 -0
- package/src/__golden__/wave-loop/op-wide.json +39 -0
- package/src/__snapshots__/okf.test.ts.snap +10 -0
- package/src/action-pins.test.ts +78 -0
- package/src/action-pins.ts +92 -0
- package/src/capabilities/aws.paths +148 -0
- package/src/capabilities/base-mappings.json +122 -0
- package/src/capabilities/catalog.ts +230 -0
- package/src/capabilities/language.test.ts +191 -0
- package/src/capabilities/language.ts +373 -0
- package/src/capabilities/matcher.ts +315 -0
- package/src/capabilities/view-compose.test.ts +76 -0
- package/src/capabilities/view.ts +631 -0
- package/src/cli/commands/carve-score-once.test.ts +99 -0
- package/src/cli/commands/carve.ts +37 -6
- package/src/cli/commands/check-lexicon.test.ts +2 -2
- package/src/cli/commands/import-report.ts +71 -0
- package/src/cli/commands/import.ts +33 -3
- package/src/cli/commands/lint.ts +1 -0
- package/src/cli/commands/migrate-dialect.test.ts +145 -0
- package/src/cli/commands/migrate.ts +132 -11
- package/src/cli/handlers/__snapshots__/build-member.test.ts.snap +4 -4
- package/src/cli/handlers/approve.ts +23 -2
- package/src/cli/handlers/build.ts +7 -1
- package/src/cli/handlers/declared-graph.ts +99 -0
- package/src/cli/handlers/graph.test.ts +94 -3
- package/src/cli/handlers/graph.ts +123 -96
- package/src/cli/handlers/ledger.ts +54 -0
- package/src/cli/handlers/migrate.ts +21 -12
- package/src/cli/handlers/misc.ts +10 -1
- package/src/cli/handlers/pr-env.ts +3 -4
- package/src/cli/handlers/pr.ts +138 -36
- package/src/cli/handlers/query.ts +16 -4
- package/src/cli/handlers/release.ts +6 -3
- package/src/cli/handlers/search-build-roots.test.ts +144 -0
- package/src/cli/handlers/search-count.test.ts +191 -0
- package/src/cli/handlers/search-count.ts +165 -0
- package/src/cli/handlers/search-json.test.ts +333 -0
- package/src/cli/handlers/search-live.test.ts +387 -0
- package/src/cli/handlers/search-paths.test.ts +235 -0
- package/src/cli/handlers/search.ts +1291 -166
- package/src/cli/main.test.ts +43 -3
- package/src/cli/main.ts +88 -17
- package/src/cli/mcp/server.test.ts +3 -3
- package/src/cli/mcp/server.ts +3 -0
- package/src/cli/mcp/tools/capabilities.ts +32 -0
- package/src/cli/mcp/workspace-tools.e2e.test.ts +21 -1
- package/src/cli/mcp/workspace-tools.ts +47 -2
- package/src/cli/parse-args.ts +79 -15
- package/src/cli/registry.ts +36 -4
- package/src/components/builders.ts +8 -0
- package/src/components/capability-plugin-loader.ts +13 -1
- package/src/components/capability-plugin.ts +16 -0
- package/src/components/pr-env-ports.ts +89 -0
- package/src/components/pr-env-run-bundle.test.ts +54 -0
- package/src/components/pr-env-run.ts +5 -76
- package/src/components/pr-environment.ts +2 -1
- package/src/components/pr-hooks.test.ts +73 -5
- package/src/components/pr-hooks.ts +95 -5
- package/src/components/pr-pipeline.ts +64 -16
- package/src/components/pr-policy.test.ts +64 -1
- package/src/components/pr-policy.ts +53 -0
- package/src/components/registry.test.ts +1 -1
- package/src/components/starter-plugin.ts +6 -0
- package/src/components/verbs/index.ts +2 -0
- package/src/components/verbs/publish-artifact.test.ts +60 -0
- package/src/components/verbs/publish-artifact.ts +122 -0
- package/src/components/verbs/publish-image.test.ts +101 -0
- package/src/components/verbs/publish-image.ts +265 -0
- package/src/config-environments.ts +160 -0
- package/src/config.ts +44 -124
- package/src/gate-decision-bundle.test.ts +1 -0
- package/src/gate-decision-identity.test.ts +9 -0
- package/src/gate-decision.ts +26 -3
- package/src/graph-detail.ts +15 -3
- package/src/graph-effective.ts +226 -75
- package/src/graph-ir.test.ts +163 -0
- package/src/graph-ir.ts +174 -0
- package/src/graph-sub-template.ts +22 -0
- package/src/graph-walk.test.ts +44 -0
- package/src/graph-walk.ts +102 -0
- package/src/import/parser.ts +20 -0
- package/src/lexicon.ts +84 -6
- package/src/lifecycle/gate-ledger.ts +8 -0
- package/src/lifecycle/git.ts +2 -2
- package/src/lifecycle/ledger-read.test.ts +107 -0
- package/src/lifecycle/ledger-read.ts +195 -0
- package/src/lifecycle/observe.test.ts +27 -1
- package/src/lifecycle/observe.ts +43 -1
- package/src/lifecycle/release-workstation.ts +24 -0
- package/src/lifecycle/run-ledger.ts +5 -2
- package/src/lint/cross-root.test.ts +122 -0
- package/src/lint/discover.ts +3 -1
- package/src/lint/post-synth.ts +212 -2
- package/src/lint/rule.ts +6 -0
- package/src/lint/rules/op/index.ts +2 -0
- package/src/lint/rules/op/ops019-workspace-op-target.ts +89 -0
- package/src/live-endpoint.ts +1 -1
- package/src/observation.test.ts +25 -0
- package/src/observation.ts +69 -5
- package/src/op/activities/activity-contracts.ts +5 -2
- package/src/op/activities/index.ts +2 -2
- package/src/op/activities/review-agent.test.ts +221 -4
- package/src/op/activities/review-agent.ts +265 -22
- package/src/op/activities/work-evidence.ts +9 -1
- package/src/op/builders.ts +9 -5
- package/src/op/composites/apply-op.test.ts +108 -0
- package/src/op/composites/apply-op.ts +37 -2
- package/src/op/gate-approval.test.ts +6 -1
- package/src/op/gate-approval.ts +12 -6
- package/src/op/gate-quorum-at-base.test.ts +211 -0
- package/src/op/gate-quorum.ts +156 -8
- package/src/op/gate-review.ts +14 -0
- package/src/op/gate.ts +67 -8
- package/src/op/index.ts +3 -2
- package/src/op/local-executor.ts +69 -9
- package/src/op/op-waves-depends-on.test.ts +81 -0
- package/src/op/op-waves-hook-targets.test.ts +4 -2
- package/src/op/op-waves-quorum-product.test.ts +158 -0
- package/src/op/op-waves-run.ts +288 -14
- package/src/op/op-waves.ts +143 -14
- package/src/op/runtime.ts +8 -0
- package/src/op/schedule-overdue.ts +33 -0
- package/src/op/stage-hooks.ts +13 -5
- package/src/op/workspace-run-env.ts +29 -0
- package/src/pr-forge-bundle.test.ts +2 -2
- package/src/pr-forge.test.ts +47 -0
- package/src/pr-forge.ts +68 -0
- package/src/pr-post-open.e2e.test.ts +36 -0
- package/src/pr-post.test.ts +102 -3
- package/src/pr-post.ts +89 -1
- package/src/read-filter.test.ts +54 -0
- package/src/read-filter.ts +193 -0
- package/src/run-event.ts +1 -1
- package/src/stage-hooks-bundle.test.ts +1 -0
- package/src/terraform/carve.ts +52 -15
- package/src/terraform/cuts.test.ts +173 -0
- package/src/terraform/cuts.ts +188 -0
- package/src/terraform/folds.ts +44 -0
- package/src/terraform/graph.ts +9 -0
- package/src/terraform/radius.test.ts +90 -0
- package/src/terraform/reach.test.ts +146 -0
- package/src/terraform/reach.ts +247 -0
- package/src/terraform/score.ts +27 -29
- package/src/terraform/state.ts +3 -1
- package/src/terraform/types.ts +8 -0
- package/src/wave-blocked.ts +28 -3
- package/src/wave-loop-golden.test.ts +4 -3
- package/src/workspace/behold-kinds.test.ts +1 -1
- package/src/workspace/capabilities-contract.test.ts +88 -0
- package/src/workspace/capabilities-contract.ts +132 -0
- package/src/workspace/capabilities.schema.json +229 -0
- package/src/workspace/check-contract.test.ts +7 -6
- package/src/workspace/check.schema.json +11 -2
- package/src/workspace/checks/ci-branch.test.ts +128 -0
- package/src/workspace/checks/ci-branch.ts +141 -0
- package/src/workspace/checks/links.ts +12 -1
- package/src/workspace/checks/org.ts +169 -0
- package/src/workspace/checks.ts +64 -7
- package/src/workspace/ci-branches.ts +31 -0
- package/src/workspace/ci-green-branches.test.ts +153 -0
- package/src/workspace/ci-green-cli.ts +7 -7
- package/src/workspace/ci-green-workflow.test.ts +4 -3
- package/src/workspace/ci-green-workflow.ts +13 -9
- package/src/workspace/ci-green.ts +49 -12
- package/src/workspace/ci-run.test.ts +72 -1
- package/src/workspace/ci-run.ts +68 -8
- package/src/workspace/ci-serve.test.ts +95 -0
- package/src/workspace/ci-serve.ts +106 -65
- package/src/workspace/component-environments.test.ts +25 -2
- package/src/workspace/compose-graph.ts +19 -3
- package/src/workspace/composites.schema.json +22 -0
- package/src/workspace/composites.test.ts +39 -8
- package/src/workspace/composites.ts +6 -2
- package/src/workspace/conformance/__writer_fixture__/work/work.schema.json +105 -1
- package/src/workspace/conformance/conformance.e2e.test.ts +14 -1
- package/src/workspace/conformance/index.ts +31 -2
- package/src/workspace/cross-root-lint.test.ts +90 -0
- package/src/workspace/cross-root-lint.ts +126 -0
- package/src/workspace/dbt-kind.test.ts +3 -2
- package/src/workspace/dbt-models-reader.ts +362 -0
- package/src/workspace/dbt-models.test.ts +248 -0
- package/src/workspace/dbt-project-common.ts +113 -0
- package/src/workspace/dbt-project-reader.ts +29 -112
- package/src/workspace/decision-rank.ts +40 -0
- package/src/workspace/declaration.schema.json +133 -24
- package/src/workspace/declaration.ts +84 -15
- package/src/workspace/environments.ts +40 -4
- package/src/workspace/flyway-dir.ts +113 -0
- package/src/workspace/flyway-layout.ts +337 -0
- package/src/workspace/graph-cache.ts +27 -3
- package/src/workspace/graph-cli.ts +119 -32
- package/src/workspace/graph-contract.test.ts +4 -2
- package/src/workspace/graph.schema.json +182 -0
- package/src/workspace/identity.test.ts +14 -2
- package/src/workspace/intent.ts +6 -14
- package/src/workspace/kind-link-readers.ts +68 -3
- package/src/workspace/kind-readers.e2e.test.ts +28 -0
- package/src/workspace/kind-readers.test.ts +1 -1
- package/src/workspace/kind-readers.ts +7 -1
- package/src/workspace/kinds.test.ts +12 -7
- package/src/workspace/kinds.ts +132 -7
- package/src/workspace/ledger.schema.json +158 -0
- package/src/workspace/lexicon-outputs.ts +132 -13
- package/src/workspace/lineage-check.ts +30 -7
- package/src/workspace/links.ts +24 -1
- package/src/workspace/ls-contract.test.ts +1 -1
- package/src/workspace/ls.schema.json +7 -0
- package/src/workspace/ls.ts +10 -1
- package/src/workspace/member-commands.ts +82 -3
- package/src/workspace/member-file-schema.test.ts +124 -0
- package/src/workspace/migrate-links.test.ts +99 -0
- package/src/workspace/migrate-links.ts +108 -0
- package/src/workspace/migration-dirs.test.ts +272 -0
- package/src/workspace/migration-dirs.ts +267 -0
- package/src/workspace/nested-graph.ts +32 -1
- package/src/workspace/org-scope.test.ts +238 -0
- package/src/workspace/reason-codes.test.ts +13 -1
- package/src/workspace/reason-codes.ts +23 -0
- package/src/workspace/records-cli.ts +58 -5
- package/src/workspace/records.schema.json +5 -0
- package/src/workspace/release-candidates.ts +7 -2
- package/src/workspace/release-train.ts +157 -0
- package/src/workspace/release-workflow.ts +4 -3
- package/src/workspace/repo-ref.ts +113 -0
- package/src/workspace/run-event.schema.json +2 -2
- package/src/workspace/runs-cli.ts +48 -4
- package/src/workspace/runs.schema.json +7 -0
- package/src/workspace/search-cli.e2e.test.ts +305 -0
- package/src/workspace/search-cli.ts +591 -0
- package/src/workspace/search-contract.ts +95 -0
- package/src/workspace/search.schema.json +822 -0
- package/src/workspace/status-contract.test.ts +46 -1
- package/src/workspace/status-decisions.test.ts +100 -0
- package/src/workspace/status-decisions.ts +151 -0
- package/src/workspace/status-gates.ts +9 -0
- package/src/workspace/status.schema.json +6 -0
- package/src/workspace/status.ts +17 -3
- package/src/workspace/where-filters.test.ts +39 -0
- package/src/workspace/work-cli.ts +5 -3
- package/src/workspace/work-evidence-ops.test.ts +176 -0
- package/src/workspace/work-evidence-ops.ts +189 -0
- package/src/workspace/work-evidence.schema.json +49 -2
- package/src/workspace/work-evidence.ts +22 -3
- package/src/workspace/workspace-gates.ts +200 -0
- package/src/workspace/workspace-kinds.schema.json +58 -3
- package/src/workspace/workspace-ledger.ts +130 -0
- package/src/workspace/workspace-run.test.ts +322 -0
- package/src/workspace/workspace-run.ts +461 -0
package/src/workspace/ci-run.ts
CHANGED
|
@@ -53,7 +53,9 @@
|
|
|
53
53
|
* report with its own token (`postPlanReport`, ../pr-post.ts). In place, a
|
|
54
54
|
* generated job holds no token and its `plan-note` job posts; a job that
|
|
55
55
|
* still holds one was generated before #4295, and the runner posts for it
|
|
56
|
-
* with a warning to regenerate.
|
|
56
|
+
* with a warning to regenerate. Either way the note's overdue check (#4289)
|
|
57
|
+
* reads the scheduled Ops from a fresh checkout of `--base`, as the
|
|
58
|
+
* plan-note job reads them at the target branch's commit (#4328).
|
|
57
59
|
*
|
|
58
60
|
* Signing is opt-in (#4156). With no runner key the record is unsigned, and
|
|
59
61
|
* a reader counts it with no signer. A key `.chant/trust.json` does not list
|
|
@@ -81,14 +83,16 @@
|
|
|
81
83
|
*/
|
|
82
84
|
|
|
83
85
|
import { execFileSync } from "node:child_process";
|
|
84
|
-
import { copyFileSync, cpSync, existsSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, realpathSync, rmSync, writeFileSync } from "node:fs";
|
|
86
|
+
import { copyFileSync, cpSync, existsSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, realpathSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
|
|
85
87
|
import { tmpdir } from "node:os";
|
|
86
|
-
import { dirname, join, relative, resolve, sep } from "node:path";
|
|
88
|
+
import { basename, dirname, join, relative, resolve, sep } from "node:path";
|
|
89
|
+
import { fileURLToPath } from "node:url";
|
|
87
90
|
import { PR_APPLY_RECORD, PR_ENV_POST_JOB, PR_ENV_REPORT_DIR, PR_LOOP_REPORT_DIR, prEnvJobs, prLoopJobs, prLoopSetup, PR_LOOP_IMAGE, type PrEnvJob, type PrLoopJob, type PrLoopPipelineOptions } from "../components/pr-pipeline";
|
|
88
91
|
import { detectForge, ForgeEnvironmentError, forgeFromEnv, FORGE_KINDS, type CommitStatus, type ForgeKind, type PrForge } from "../pr-forge";
|
|
89
92
|
import { holdsForgeToken, withoutForgeTokens } from "../ci-handover";
|
|
90
93
|
import { postPlanReport } from "../pr-post";
|
|
91
|
-
import {
|
|
94
|
+
import { overdueOpsAt } from "../op/schedule-overdue";
|
|
95
|
+
import { PR_APPLY_GATE, type PrOverdue } from "../pr-loop";
|
|
92
96
|
import type { CommandContext } from "../cli/registry";
|
|
93
97
|
import { formatError, formatWarning } from "../cli/format";
|
|
94
98
|
import { CHANT_CI_RUN_FORGE_ENV, CHANT_CI_RUN_ID_ENV, FORGE_RUN_ENV, resolveCiJob, type RunOrigin } from "../lifecycle/release-ledger";
|
|
@@ -738,7 +742,9 @@ export async function ciRun(req: CiRunRequest): Promise<CiRunResult> {
|
|
|
738
742
|
// A generated wave job's command, as prLoopWaveJobs writes it. #4161: a local job's command posts no status or note.
|
|
739
743
|
const forgeCommand = req.noForge ? found.command.replace(` --forge ${req.forge}`, "") : found.command;
|
|
740
744
|
const noStatus = req.local && !/ --no-status(?: |$)/.test(forgeCommand);
|
|
741
|
-
|
|
745
|
+
// #4325: a record or apply on a routed branch is told the branch, as the forge's ref would tell it in a pipeline. `ci serve` has no such ref.
|
|
746
|
+
const branch = req.job !== "plan" && req.loop?.branch !== undefined && !/ --branch(?: |=)/.test(forgeCommand) ? ` --branch ${/^[A-Za-z0-9._\/=:@%+,-]+$/.test(req.loop.branch) ? req.loop.branch : `'${req.loop.branch.replace(/'/g, `'\\''`)}'`}` : "";
|
|
747
|
+
const command = `${forgeCommand}${branch}${req.wave !== undefined ? ` --wave ${req.wave}` : ""}${noStatus ? " --no-status" : ""}`;
|
|
742
748
|
const job = { ...found, command, ...(req.wave !== undefined ? { wave: req.wave } : {}) };
|
|
743
749
|
const own = ciJobEnv(job, {
|
|
744
750
|
forge: req.forge,
|
|
@@ -759,7 +765,7 @@ export async function ciRun(req: CiRunRequest): Promise<CiRunResult> {
|
|
|
759
765
|
const redact = ciRedactor(req.inPlace ? { ...longValues(jobEnv), ...own } : jobEnv, req.secrets);
|
|
760
766
|
try {
|
|
761
767
|
const ran = await runCiJob(req, { cwd, top, commit, place, job, jobEnv, ...(redact ? { redact } : {}) });
|
|
762
|
-
const posted = poster ? await postFromReport(req, poster, ran, { commit, ...(place.member ? { member: place.member } : {}) }) : [];
|
|
768
|
+
const posted = poster ? await postFromReport(req, poster, ran, { top, dir: place.dir, commit, ...(place.member ? { member: place.member } : {}) }) : [];
|
|
763
769
|
const envPost = req.job === "env-up" ? await envPostAfterUp(req, { cwd, top, head: commit, place, jobs, hostEnv, ran }) : undefined;
|
|
764
770
|
const withPost = envPost ? ("result" in envPost ? { ...ran, post: envPost.result } : { ...ran, warnings: [...ran.warnings, envPost.warning] }) : ran;
|
|
765
771
|
const withPosts = posted.length > 0 ? { ...withPost, warnings: [...withPost.warnings, ...posted] } : withPost;
|
|
@@ -831,10 +837,11 @@ async function postFromReport(
|
|
|
831
837
|
req: CiRunRequest,
|
|
832
838
|
poster: NonNullable<ReturnType<typeof planPoster>>,
|
|
833
839
|
ran: CiRunResult,
|
|
834
|
-
at: { commit: string; member?: string },
|
|
840
|
+
at: { top: string; dir: string; commit: string; member?: string },
|
|
835
841
|
): Promise<string[]> {
|
|
836
842
|
if ("error" in poster) return [poster.error];
|
|
837
843
|
const warnings = poster.warning ? [poster.warning] : [];
|
|
844
|
+
const checked: string[] = [];
|
|
838
845
|
const dir = ran.report ?? resolve(req.cwd, req.output ?? PR_LOOP_REPORT_DIR);
|
|
839
846
|
const posted = await postPlanReport({
|
|
840
847
|
forge: poster.forge,
|
|
@@ -844,9 +851,62 @@ async function postFromReport(
|
|
|
844
851
|
env: req.env,
|
|
845
852
|
...(at.member ? { member: at.member } : {}),
|
|
846
853
|
result: ran.status === "ok" ? "success" : "failure",
|
|
854
|
+
// #4328: as pr-post does (#4289), with the Ops read at --base, never from the change's checkout.
|
|
855
|
+
overdue: () => overdueAtBase(req, { forge: poster.forge, top: at.top, dir: at.dir, ...(at.member ? { member: at.member } : {}), log: (line) => checked.push(line) }),
|
|
847
856
|
});
|
|
848
857
|
if (posted.refused) warnings.push(`the plan report was not posted: ${posted.refused}`);
|
|
849
|
-
return [...warnings, ...posted.warnings];
|
|
858
|
+
return [...warnings, ...checked, ...posted.warnings];
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
/**
|
|
862
|
+
* The overdue check for the plan's note (#4289, #4328), at `--base`, as the
|
|
863
|
+
* plan-note job's `pr-post` runs it at the target branch's commit. The Ops
|
|
864
|
+
* are read from a fresh checkout of the base outside the repository, never
|
|
865
|
+
* from the checkout the change's code ran in, in place or not. That checkout
|
|
866
|
+
* resolves packages from the `node_modules` the running chant is installed
|
|
867
|
+
* in ({@link chantNodeModules}), so an Op file's `@intentius/chant` is the
|
|
868
|
+
* chant running the job, not one the change installed. Without `--base`
|
|
869
|
+
* nothing is checked, and `log` says so.
|
|
870
|
+
*/
|
|
871
|
+
async function overdueAtBase(
|
|
872
|
+
req: CiRunRequest,
|
|
873
|
+
at: { forge: PrForge; top: string; dir: string; member?: string; log: (line: string) => void },
|
|
874
|
+
): Promise<PrOverdue[]> {
|
|
875
|
+
if (!at.forge.scheduledRuns) return [];
|
|
876
|
+
if (!req.base) {
|
|
877
|
+
at.log("the scheduled Ops were not checked: the check reads them at the target branch's commit, so pass --base <sha>");
|
|
878
|
+
return [];
|
|
879
|
+
}
|
|
880
|
+
let checkout: { dir: string; remove(): void };
|
|
881
|
+
try {
|
|
882
|
+
checkout = freshCheckout(at.top, resolveJobCommit(at.top, req.base));
|
|
883
|
+
} catch (err) {
|
|
884
|
+
at.log(`the scheduled Ops were not checked: ${message(err)}`);
|
|
885
|
+
return [];
|
|
886
|
+
}
|
|
887
|
+
try {
|
|
888
|
+
const modules = chantNodeModules();
|
|
889
|
+
const link = join(checkout.dir, "node_modules");
|
|
890
|
+
if (modules && !existsSync(link)) symlinkSync(modules, link, "dir");
|
|
891
|
+
return await overdueOpsAt({ forge: at.forge, cwd: at.dir === "." ? checkout.dir : join(checkout.dir, at.dir), ...(at.member ? { member: at.member } : {}), log: at.log });
|
|
892
|
+
} finally {
|
|
893
|
+
checkout.remove();
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
/**
|
|
898
|
+
* The `node_modules` directory the running chant is installed in, or
|
|
899
|
+
* undefined when it runs from a source checkout, where chant's own packages
|
|
900
|
+
* resolve without one (../ts-loader.ts).
|
|
901
|
+
*/
|
|
902
|
+
export function chantNodeModules(from: string = fileURLToPath(import.meta.url)): string | undefined {
|
|
903
|
+
let dir = dirname(from);
|
|
904
|
+
for (;;) {
|
|
905
|
+
if (basename(dir) === "node_modules") return dir;
|
|
906
|
+
const parent = dirname(dir);
|
|
907
|
+
if (parent === dir) return undefined;
|
|
908
|
+
dir = parent;
|
|
909
|
+
}
|
|
850
910
|
}
|
|
851
911
|
|
|
852
912
|
/**
|
|
@@ -602,3 +602,98 @@ describe("ci serve runs fast-forwards only, and honours [skip ci] (#4122)", () =
|
|
|
602
602
|
expect(ofType(events, "not-run")).toHaveLength(1);
|
|
603
603
|
});
|
|
604
604
|
});
|
|
605
|
+
|
|
606
|
+
describe("ci serve follows ci.branches (#4325)", () => {
|
|
607
|
+
/** A forge with a head per branch, and the branches it was asked about. */
|
|
608
|
+
function branchForge(heads: Record<string, string>): CiServeForge & { heads: Record<string, string>; polled: string[] } {
|
|
609
|
+
const f = {
|
|
610
|
+
heads,
|
|
611
|
+
polled: [] as string[],
|
|
612
|
+
async pullRequestFor() {
|
|
613
|
+
return null;
|
|
614
|
+
},
|
|
615
|
+
async openPullRequests(base: string) {
|
|
616
|
+
f.polled.push(base);
|
|
617
|
+
return [];
|
|
618
|
+
},
|
|
619
|
+
async branchHead(branch: string) {
|
|
620
|
+
return f.heads[branch];
|
|
621
|
+
},
|
|
622
|
+
};
|
|
623
|
+
return f;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
/** The workspace with `ci.branches` routing `app` to `release`, and a `release` branch on the forge. */
|
|
627
|
+
function routed(globs: string[] = ["app"]): ReturnType<typeof workspace> & { release: string } {
|
|
628
|
+
const w = workspace();
|
|
629
|
+
writeFiles(w.root, { "chant.workspace.json": declaration([{ name: "app", dir: "app", kind: "other", because: "the app" }], { ci: { branches: { release: globs } } }) });
|
|
630
|
+
commit(w.root, "app/route.txt", "route app to release");
|
|
631
|
+
git(w.root, "push", "-q", "origin", "main");
|
|
632
|
+
git(w.root, "checkout", "-q", "-b", "release");
|
|
633
|
+
const release = commit(w.root, "app/rel.txt");
|
|
634
|
+
git(w.root, "push", "-q", "origin", "release");
|
|
635
|
+
git(w.root, "checkout", "-q", "main");
|
|
636
|
+
return { ...w, main: git(w.root, "rev-parse", "main"), release };
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
test("a routed member polls its route alone, and its record job gets --branch", async () => {
|
|
640
|
+
const { root, app, main, release } = routed();
|
|
641
|
+
const forge = branchForge({ main, release });
|
|
642
|
+
const { opts, events } = serve(app, forge);
|
|
643
|
+
await ciServePass(opts);
|
|
644
|
+
expect(forge.polled).toEqual(["release"]);
|
|
645
|
+
expect(ofType(events, "baseline")).toEqual([{ type: "baseline", commit: release }]);
|
|
646
|
+
|
|
647
|
+
git(root, "checkout", "-q", "release");
|
|
648
|
+
const next = commit(root, "app/rel2.txt");
|
|
649
|
+
git(root, "push", "-q", "origin", "release");
|
|
650
|
+
git(root, "checkout", "-q", "main");
|
|
651
|
+
forge.heads.release = next;
|
|
652
|
+
const pass = await ciServePass(opts);
|
|
653
|
+
expect(pass.jobs).toEqual([expect.objectContaining({ job: "record", commit: next, base: release, status: "ok" })]);
|
|
654
|
+
const argv = argsOf(pass.jobs[0]!.report!, "pr-record");
|
|
655
|
+
expect(argv[argv.indexOf("--branch") + 1]).toBe("release");
|
|
656
|
+
// A push to main is not this member's.
|
|
657
|
+
forge.heads.main = "0".repeat(40);
|
|
658
|
+
expect((await ciServePass(opts)).jobs).toEqual([]);
|
|
659
|
+
});
|
|
660
|
+
|
|
661
|
+
test("a member no glob matches polls main and passes no --branch", async () => {
|
|
662
|
+
const { root, app, main } = routed(["other-*"]);
|
|
663
|
+
const forge = branchForge({ main });
|
|
664
|
+
const { opts } = serve(app, forge);
|
|
665
|
+
await ciServePass(opts);
|
|
666
|
+
expect(forge.polled).toEqual(["main"]);
|
|
667
|
+
const merged = commit(root, "app/merged.txt");
|
|
668
|
+
git(root, "push", "-q", "origin", "main");
|
|
669
|
+
forge.heads.main = merged;
|
|
670
|
+
const pass = await ciServePass(opts);
|
|
671
|
+
expect(pass.jobs).toEqual([expect.objectContaining({ job: "record", commit: merged, base: main })]);
|
|
672
|
+
expect(argsOf(pass.jobs[0]!.report!, "pr-record")).not.toContain("--branch");
|
|
673
|
+
});
|
|
674
|
+
|
|
675
|
+
test("the workspace root polls main and each routed branch, each from its own head", async () => {
|
|
676
|
+
const { root, main, release } = routed();
|
|
677
|
+
const forge = branchForge({ main, release });
|
|
678
|
+
const { opts } = serve(root, forge);
|
|
679
|
+
await ciServePass(opts);
|
|
680
|
+
expect(forge.polled).toEqual(["main", "release"]);
|
|
681
|
+
git(root, "checkout", "-q", "release");
|
|
682
|
+
const next = commit(root, "app/rel2.txt");
|
|
683
|
+
git(root, "push", "-q", "origin", "release");
|
|
684
|
+
git(root, "checkout", "-q", "main");
|
|
685
|
+
forge.heads.release = next;
|
|
686
|
+
const pass = await ciServePass(opts);
|
|
687
|
+
expect(pass.jobs).toEqual([expect.objectContaining({ job: "record", commit: next, base: release })]);
|
|
688
|
+
const state = readCiServeState(join(opts.stateDir!, `${prApplyGroup("prod")}.json`), { forge: "forgejo", repo: "demo/estate", env: "prod", branch: "main" });
|
|
689
|
+
expect(state.target).toBe(main);
|
|
690
|
+
expect(state.targets).toEqual({ release: next });
|
|
691
|
+
expect((await ciServePass(opts)).jobs).toEqual([]);
|
|
692
|
+
});
|
|
693
|
+
|
|
694
|
+
test("a --branch that disagrees with the route is refused", async () => {
|
|
695
|
+
const { app, main, release } = routed();
|
|
696
|
+
const { opts } = serve(app, branchForge({ main, release }), { job: { loop: { branch: "main" } } });
|
|
697
|
+
await expect(ciServePass(opts)).rejects.toThrow(/routes member app to release/);
|
|
698
|
+
});
|
|
699
|
+
});
|
|
@@ -59,6 +59,11 @@
|
|
|
59
59
|
* contains the other. Each is a warning. A local branch ahead of the
|
|
60
60
|
* forge's keeps its facts, and the job's push sends them. Nothing here
|
|
61
61
|
* pushes the ledger.
|
|
62
|
+
* - Routed branches (#4325). `ci.branches` decides the branches one serve
|
|
63
|
+
* polls: a routed member's route alone, an unrouted member's `--branch`
|
|
64
|
+
* (default `main`), and at the workspace root `main` and each routed
|
|
65
|
+
* branch. Jobs on a routed branch get `--branch`. The state file keeps a
|
|
66
|
+
* head per branch (`target`, then `targets`).
|
|
62
67
|
*
|
|
63
68
|
* - Land branches (#4168 4.4). With `land`, each `chant/land/<name>` branch
|
|
64
69
|
* pushed to the remote is a change asking to land without a pull request.
|
|
@@ -104,6 +109,7 @@ import { CI_JOB_OPS, ciJobPlace, ciLoopOptions, ciSecretsOf, ciRun, ciStatusFrom
|
|
|
104
109
|
import { CiGreenError, ciTick, judgePreMerge, lastGreen, RUNNER_KEY_ENV, signedRunsRequired, type CommitVerdict } from "./ci-green";
|
|
105
110
|
import { gitTop } from "./tree";
|
|
106
111
|
import { readDeclaration } from "./declaration";
|
|
112
|
+
import { servedBranches } from "./ci-branches";
|
|
107
113
|
import { locateWorkspace } from "./which-chant";
|
|
108
114
|
import { ciServeRunnerKey, formatRunnerKeySetup, setupRunnerKey } from "./ci-runner-key";
|
|
109
115
|
|
|
@@ -124,8 +130,8 @@ export interface CiServeForge {
|
|
|
124
130
|
* apply of the newest green commit (#4168 step 9).
|
|
125
131
|
*/
|
|
126
132
|
export type CiServeTrigger =
|
|
127
|
-
| { job: "plan"; commit: string; base: string; pr: number; rerun?: boolean }
|
|
128
|
-
| { job: "apply" | "record"; commit: string; base: string; rerun?: boolean };
|
|
133
|
+
| { job: "plan"; commit: string; base: string; pr: number; rerun?: boolean; branch?: string }
|
|
134
|
+
| { job: "apply" | "record"; commit: string; base: string; rerun?: boolean; branch?: string };
|
|
129
135
|
|
|
130
136
|
/**
|
|
131
137
|
* The `git` forge kind (#4016 gap 6): the branch head from `git ls-remote`
|
|
@@ -193,6 +199,8 @@ export interface CiServeState {
|
|
|
193
199
|
member?: string;
|
|
194
200
|
/** The target branch's head the last apply was measured to, or the last head seen and not applied. */
|
|
195
201
|
target?: string;
|
|
202
|
+
/** The same for each further branch `ci.branches` routes (#4325), by branch. `target` is the first served branch's. */
|
|
203
|
+
targets?: Record<string, string>;
|
|
196
204
|
jobs: Record<string, CiServeJobState>;
|
|
197
205
|
/** Plans seen and not run, by state key, with why (#4122). */
|
|
198
206
|
skipped?: Record<string, "skip-ci">;
|
|
@@ -381,7 +389,12 @@ export function defaultCiServeStateDir(cwd: string): string {
|
|
|
381
389
|
interface ServePlace {
|
|
382
390
|
top: string;
|
|
383
391
|
member?: string;
|
|
392
|
+
/** The first branch served: the one the state file's `target` follows. */
|
|
384
393
|
branch: string;
|
|
394
|
+
/** Every branch served (#4325), `branch` first: a routed member's route, or at the workspace root the default and each routed branch. */
|
|
395
|
+
branches: string[];
|
|
396
|
+
/** The served branches a job is told with `--branch`: the ones `ci.branches` names. */
|
|
397
|
+
routed: string[];
|
|
385
398
|
group: string;
|
|
386
399
|
stateDir: string;
|
|
387
400
|
stateFile: string;
|
|
@@ -394,7 +407,21 @@ function servePlace(opts: CiServeOptions): ServePlace {
|
|
|
394
407
|
const { member } = ciJobPlace(cwd, top);
|
|
395
408
|
const group = prApplyGroup(opts.env, member);
|
|
396
409
|
const stateDir = opts.stateDir ? resolve(cwd, opts.stateDir) : defaultCiServeStateDir(cwd);
|
|
397
|
-
|
|
410
|
+
// #4325: ci.branches decides which branches this serve polls. A workspace that can't be read routes nothing.
|
|
411
|
+
let routes: Record<string, string[]> | undefined;
|
|
412
|
+
try {
|
|
413
|
+
routes = readDeclaration(locateWorkspace(cwd).tree).ci?.branches;
|
|
414
|
+
} catch {
|
|
415
|
+
routes = undefined;
|
|
416
|
+
}
|
|
417
|
+
const named = opts.job?.loop?.branch;
|
|
418
|
+
let served: ReturnType<typeof servedBranches>;
|
|
419
|
+
try {
|
|
420
|
+
served = servedBranches(routes, member, named ?? "main", named !== undefined);
|
|
421
|
+
} catch (err) {
|
|
422
|
+
throw new CiRunError(message(err));
|
|
423
|
+
}
|
|
424
|
+
return { top, ...(member ? { member } : {}), branch: served.served[0]!, branches: served.served, routed: served.routed, group, stateDir, stateFile: join(stateDir, `${group}.json`) };
|
|
398
425
|
}
|
|
399
426
|
|
|
400
427
|
/** The state file, or a new one. */
|
|
@@ -439,73 +466,81 @@ export async function ciServeObserve(opts: CiServeOptions, rt: CiServeRuntime =
|
|
|
439
466
|
};
|
|
440
467
|
const triggers: CiServeTrigger[] = [];
|
|
441
468
|
const events: CiServeEvent[] = [];
|
|
442
|
-
const [head, prs] = await Promise.all([opts.client.branchHead(place.branch), opts.client.openPullRequests(place.branch)]);
|
|
443
469
|
// #4168: a new target commit is recorded. With applyOnMerge the newest green commit is applied, below.
|
|
444
470
|
const onMerge = "record" as const;
|
|
471
|
+
const authors = opts.authors?.length ? new Set(opts.authors.map((a) => a.toLowerCase())) : undefined;
|
|
445
472
|
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
const
|
|
457
|
-
const entry = state.jobs[ciServeKey({ job: onMerge, commit: head })];
|
|
458
|
-
if (move === "unknown") {
|
|
459
|
-
events.push({ type: "error", message: `${place.branch} is at ${head.slice(0, 12)} on the forge, and that commit could not be fetched; the next poll tries again` });
|
|
460
|
-
} else if (move === "other" || (!entry && skipsCi(place.top, head))) {
|
|
461
|
-
// #4122: a move that is not a fast-forward, or a head that asks for no run, is seen and not applied.
|
|
462
|
-
update((s) => {
|
|
463
|
-
s.target = head;
|
|
464
|
-
});
|
|
465
|
-
events.push({ type: "not-run", job: onMerge, commit: head, reason: move === "other" ? "not-fast-forward" : "skip-ci", ...(move === "other" ? { branch: place.branch, from } : {}) });
|
|
466
|
-
} else if (!entry) triggers.push({ job: onMerge, commit: head, base: from });
|
|
467
|
-
else if (opts.rerunFailed && failedEntry(entry, ciServeKey(entry), rt)) triggers.push({ job: onMerge, commit: head, base: entry.base, rerun: true });
|
|
468
|
-
} else {
|
|
469
|
-
const key = ciServeKey({ job: onMerge, commit: head });
|
|
470
|
-
const entry = state.jobs[key];
|
|
471
|
-
if (opts.rerunFailed && failedEntry(entry, key, rt)) triggers.push({ job: onMerge, commit: head, base: entry.base, rerun: true });
|
|
472
|
-
}
|
|
473
|
+
// #4325: each served branch is polled on its own, with its own head to measure moves from.
|
|
474
|
+
for (const branch of place.branches) {
|
|
475
|
+
const [head, prs] = await Promise.all([opts.client.branchHead(branch), opts.client.openPullRequests(branch)]);
|
|
476
|
+
const first = branch === place.branch;
|
|
477
|
+
const target = first ? state.target : state.targets?.[branch];
|
|
478
|
+
const setTarget = (s: CiServeState, sha: string): void => {
|
|
479
|
+
if (first) s.target = sha;
|
|
480
|
+
else s.targets = { ...s.targets, [branch]: sha };
|
|
481
|
+
};
|
|
482
|
+
// A job on a routed branch is told which, so its apply routes members as the pushed branch does.
|
|
483
|
+
const routed = place.routed.includes(branch) ? { branch } : {};
|
|
473
484
|
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
if (
|
|
477
|
-
|
|
485
|
+
if (head === undefined) {
|
|
486
|
+
events.push({ type: "no-branch", branch });
|
|
487
|
+
} else if (target === undefined) {
|
|
488
|
+
// What the branch held before this runner watched it was applied by whatever ran then.
|
|
489
|
+
update((s) => setTarget(s, head));
|
|
490
|
+
events.push({ type: "baseline", commit: head });
|
|
491
|
+
} else if (head !== target) {
|
|
492
|
+
const from = target;
|
|
493
|
+
const move = targetMove(place.top, branch, from, head);
|
|
494
|
+
const entry = state.jobs[ciServeKey({ job: onMerge, commit: head })];
|
|
495
|
+
if (move === "unknown") {
|
|
496
|
+
events.push({ type: "error", message: `${branch} is at ${head.slice(0, 12)} on the forge, and that commit could not be fetched; the next poll tries again` });
|
|
497
|
+
} else if (move === "other" || (!entry && skipsCi(place.top, head))) {
|
|
498
|
+
// #4122: a move that is not a fast-forward, or a head that asks for no run, is seen and not applied.
|
|
499
|
+
update((s) => setTarget(s, head));
|
|
500
|
+
events.push({ type: "not-run", job: onMerge, commit: head, reason: move === "other" ? "not-fast-forward" : "skip-ci", ...(move === "other" ? { branch, from } : {}) });
|
|
501
|
+
} else if (!entry) triggers.push({ job: onMerge, commit: head, base: from, ...routed });
|
|
502
|
+
else if (opts.rerunFailed && failedEntry(entry, ciServeKey(entry), rt)) triggers.push({ job: onMerge, commit: head, base: entry.base, rerun: true, ...routed });
|
|
503
|
+
} else {
|
|
504
|
+
const key = ciServeKey({ job: onMerge, commit: head });
|
|
478
505
|
const entry = state.jobs[key];
|
|
479
|
-
if (
|
|
480
|
-
else if (opts.rerunFailed && failedEntry(entry, key, rt)) triggers.push({ job: "apply", commit: green, base: entry.base, rerun: true });
|
|
506
|
+
if (opts.rerunFailed && failedEntry(entry, key, rt)) triggers.push({ job: onMerge, commit: head, base: entry.base, rerun: true, ...routed });
|
|
481
507
|
}
|
|
482
|
-
}
|
|
483
508
|
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
continue;
|
|
509
|
+
if (opts.applyOnMerge && head !== undefined) {
|
|
510
|
+
const green = newestGreen(place.top, opts.cwd, branch, place.routed.includes(branch));
|
|
511
|
+
if (green) {
|
|
512
|
+
const key = ciServeKey({ job: "apply", commit: green });
|
|
513
|
+
const entry = state.jobs[key];
|
|
514
|
+
if (!entry) triggers.push({ job: "apply", commit: green, base: green, ...routed });
|
|
515
|
+
else if (opts.rerunFailed && failedEntry(entry, key, rt)) triggers.push({ job: "apply", commit: green, base: entry.base, rerun: true, ...routed });
|
|
516
|
+
}
|
|
493
517
|
}
|
|
494
|
-
|
|
495
|
-
const
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
if (
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
518
|
+
|
|
519
|
+
for (const pr of prs) {
|
|
520
|
+
if (pr.fork) {
|
|
521
|
+
events.push({ type: "skipped", pr: pr.number, reason: "fork" });
|
|
522
|
+
continue;
|
|
523
|
+
}
|
|
524
|
+
if (authors && !authors.has((pr.author ?? "").toLowerCase())) {
|
|
525
|
+
events.push({ type: "skipped", pr: pr.number, reason: "author", ...(pr.author ? { author: pr.author } : {}) });
|
|
526
|
+
continue;
|
|
527
|
+
}
|
|
528
|
+
const key = ciServeKey({ job: "plan", commit: pr.headSha, pr: pr.number });
|
|
529
|
+
const entry = state.jobs[key];
|
|
530
|
+
const base = pr.baseSha ?? head;
|
|
531
|
+
if (!base || state.skipped?.[key]) continue;
|
|
532
|
+
if (!entry) {
|
|
533
|
+
// #4122: a head whose message asks for no run is seen and not planned.
|
|
534
|
+
if (gitStatus(place.top, ["cat-file", "-e", `${pr.headSha}^{commit}`]).code !== 0) tryGit(place.top, ["fetch", "--quiet", "--no-tags", "origin", `refs/pull/${pr.number}/head`]);
|
|
535
|
+
if (skipsCi(place.top, pr.headSha)) {
|
|
536
|
+
update((s) => {
|
|
537
|
+
s.skipped = { ...s.skipped, [key]: "skip-ci" };
|
|
538
|
+
});
|
|
539
|
+
events.push({ type: "not-run", job: "plan", commit: pr.headSha, pr: pr.number, reason: "skip-ci" });
|
|
540
|
+
} else triggers.push({ job: "plan", commit: pr.headSha, base, pr: pr.number, ...routed });
|
|
541
|
+
}
|
|
542
|
+
else if (opts.rerunFailed && failedEntry(entry, key, rt)) triggers.push({ job: "plan", commit: pr.headSha, base: entry.base, pr: pr.number, rerun: true, ...routed });
|
|
507
543
|
}
|
|
508
|
-
else if (opts.rerunFailed && failedEntry(entry, key, rt)) triggers.push({ job: "plan", commit: pr.headSha, base: entry.base, pr: pr.number, rerun: true });
|
|
509
544
|
}
|
|
510
545
|
return { triggers, events };
|
|
511
546
|
}
|
|
@@ -581,7 +616,10 @@ export async function ciServeSchedule(opts: CiServeOptions, triggers: readonly C
|
|
|
581
616
|
const entry: CiServeJobState = { job: t.job, commit: t.commit, base: t.base, ...pr, status: "running", runId, attempts: attempt, startedAt: now().toISOString() };
|
|
582
617
|
update((s) => {
|
|
583
618
|
s.jobs[key] = entry;
|
|
584
|
-
if (t.job === "record" && !t.rerun)
|
|
619
|
+
if (t.job === "record" && !t.rerun) {
|
|
620
|
+
if (t.branch === undefined || t.branch === place.branch) s.target = t.commit;
|
|
621
|
+
else s.targets = { ...s.targets, [t.branch]: t.commit };
|
|
622
|
+
}
|
|
585
623
|
});
|
|
586
624
|
emit({ type: "started", job: t.job, commit: t.commit, ...pr, base: t.base, runId, attempt, ...(resume && existsSync(resume) ? { resume } : {}) });
|
|
587
625
|
|
|
@@ -621,13 +659,15 @@ async function runJob(
|
|
|
621
659
|
let merged: number | undefined;
|
|
622
660
|
try {
|
|
623
661
|
// The pull request's head is on the forge's refs/pull/<n>/head, the target's on the branch.
|
|
624
|
-
tryGit(place.top, ["fetch", "--quiet", "--no-tags", "origin", t.job === "plan" ? `refs/pull/${t.pr}/head` : place.branch]);
|
|
662
|
+
tryGit(place.top, ["fetch", "--quiet", "--no-tags", "origin", t.job === "plan" ? `refs/pull/${t.pr}/head` : (t.branch ?? place.branch)]);
|
|
625
663
|
const hostEnv = { ...(opts.job?.hostEnv ?? process.env), GITHUB_REPOSITORY: opts.repo };
|
|
626
664
|
// An apply is for a merge: pass the pull request whose merge commit it is, so the commit status link and the run index use `<pr>/<commit>`. None found, or a forge that errs, is today's behaviour.
|
|
627
665
|
if (t.job === "record" && opts.client.pullRequestFor) merged = (await opts.client.pullRequestFor(t.commit).catch(() => null)) ?? undefined;
|
|
628
666
|
const run = opts.run ?? ciRun;
|
|
629
667
|
const r = await run({
|
|
630
668
|
...opts.job,
|
|
669
|
+
// #4325: a job on a routed branch is told the branch, so it routes members as a push to it does.
|
|
670
|
+
...(t.branch !== undefined ? { loop: { ...opts.job?.loop, branch: t.branch } } : {}),
|
|
631
671
|
hostEnv,
|
|
632
672
|
cwd: opts.cwd,
|
|
633
673
|
job: t.job,
|
|
@@ -656,10 +696,11 @@ async function runJob(
|
|
|
656
696
|
* fetching the ci tags, or undefined when none is green or the workspace
|
|
657
697
|
* declares no `ci.green`.
|
|
658
698
|
*/
|
|
659
|
-
function newestGreen(top: string, cwd: string, branch: string): string | undefined {
|
|
699
|
+
function newestGreen(top: string, cwd: string, branch: string, routed = false): string | undefined {
|
|
660
700
|
tryGit(top, ["fetch", "--quiet", "origin", `+refs/heads/${branch}:refs/remotes/origin/${branch}`, "+refs/tags/ci/*:refs/tags/ci/*"]);
|
|
661
701
|
try {
|
|
662
|
-
|
|
702
|
+
// #4325: a routed branch has its own verdict, and none when ci.green does not name it.
|
|
703
|
+
const doc = lastGreen({ cwd, ...(routed ? { branch } : {}) });
|
|
663
704
|
return "commit" in doc && doc.commit ? doc.commit.sha : undefined;
|
|
664
705
|
} catch {
|
|
665
706
|
return undefined;
|
|
@@ -14,9 +14,12 @@ import Ajv2020 from "ajv/dist/2020";
|
|
|
14
14
|
import { afterEach, beforeEach, describe, expect, test } from "vitest";
|
|
15
15
|
import { computeComponentGraph } from "../components/cli-support";
|
|
16
16
|
import componentSchema from "../components/component.schema.json";
|
|
17
|
+
import { ChantConfigSchema, environmentExecutor } from "../config";
|
|
17
18
|
import { componentEnvironments, memberEnvironments, type EnvironmentReason } from "./environments";
|
|
18
19
|
import type { MemberRuntimes } from "./runtimes";
|
|
19
20
|
|
|
21
|
+
const NO_EXECUTOR = { forge: null, workflow: null, reason: { code: "executor-none-declared", message: expect.any(String) } };
|
|
22
|
+
|
|
20
23
|
const runtimes = (environments: MemberRuntimes["environments"], lexicons: string[] = []): MemberRuntimes => ({ lexicons, default: "local", reasons: [], environments });
|
|
21
24
|
|
|
22
25
|
const SITES = [
|
|
@@ -68,13 +71,14 @@ describe("graph --composites lists each environment with the component's site (#
|
|
|
68
71
|
const member = memberEnvironments(runtimes(["prod", "fly"], ["fly"]), { envs: [], reason: null });
|
|
69
72
|
const envs = componentEnvironments("app", member, "local", SITES, ["fly"]);
|
|
70
73
|
expect(envs).toEqual([
|
|
71
|
-
{ name: "local", default: true, source: "builtin", site: null, command: "chant run --components app" },
|
|
72
|
-
{ name: "prod", default: false, source: "config", site: { runtime: "local", url: null, domain: null, lifecycle: null }, command: "chant run --components app --env prod" },
|
|
74
|
+
{ name: "local", default: true, source: "builtin", site: null, executor: NO_EXECUTOR, command: "chant run --components app" },
|
|
75
|
+
{ name: "prod", default: false, source: "config", site: { runtime: "local", url: null, domain: null, lifecycle: null }, executor: NO_EXECUTOR, command: "chant run --components app --env prod" },
|
|
73
76
|
{
|
|
74
77
|
name: "fly",
|
|
75
78
|
default: false,
|
|
76
79
|
source: "config",
|
|
77
80
|
site: { runtime: "fly", url: "https://shop.fly.dev", domain: "shop.example.com", lifecycle: "origin" },
|
|
81
|
+
executor: NO_EXECUTOR,
|
|
78
82
|
command: "chant run --components app --on fly --env fly",
|
|
79
83
|
},
|
|
80
84
|
]);
|
|
@@ -103,3 +107,22 @@ describe("graph --composites lists each environment with the component's site (#
|
|
|
103
107
|
expect(envs.find((e) => e.name === "pr-7")).toMatchObject({ source: "component", site: { url: "https://pr-7.example.com" } });
|
|
104
108
|
});
|
|
105
109
|
});
|
|
110
|
+
|
|
111
|
+
describe("an environment's executor in chant.config.ts (#4402)", () => {
|
|
112
|
+
const prod = { name: "prod", executor: { forge: "github" as const, workflow: "deploy-prod.yml" } };
|
|
113
|
+
|
|
114
|
+
test("is optional on an environment entry, and refuses an unknown forge, an empty workflow and a stray field", () => {
|
|
115
|
+
expect(ChantConfigSchema.safeParse({ environments: ["staging", prod] }).success).toBe(true);
|
|
116
|
+
expect(ChantConfigSchema.safeParse({ environments: [{ name: "prod", executor: { forge: "jenkins", workflow: "x.yml" } }] }).success).toBe(false);
|
|
117
|
+
expect(ChantConfigSchema.safeParse({ environments: [{ name: "prod", executor: { forge: "github", workflow: "" } }] }).success).toBe(false);
|
|
118
|
+
expect(ChantConfigSchema.safeParse({ environments: [{ name: "prod", executor: { forge: "github", workflow: "x.yml", ref: "main" } }] }).success).toBe(false);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
test("resolves a literal entry before a pattern, and a literal without one doesn't take the pattern's", () => {
|
|
122
|
+
const envs = [prod, "pr-special", { name: "pr-*", executor: { forge: "gitlab" as const, workflow: ".gitlab-ci.yml" } }];
|
|
123
|
+
expect(environmentExecutor(envs, "prod")).toEqual(prod.executor);
|
|
124
|
+
expect(environmentExecutor(envs, "pr-7")).toEqual({ forge: "gitlab", workflow: ".gitlab-ci.yml" });
|
|
125
|
+
expect(environmentExecutor(envs, "pr-special")).toBeUndefined();
|
|
126
|
+
expect(environmentExecutor(envs, "staging")).toBeUndefined();
|
|
127
|
+
});
|
|
128
|
+
});
|
|
@@ -41,6 +41,7 @@ import type { KindLinkRead } from "./kind-link-readers";
|
|
|
41
41
|
import type { RecordLinkRow } from "./record-assets";
|
|
42
42
|
import type { ReasonCode } from "./reason-codes";
|
|
43
43
|
import { GRAPH_IR_VERSION, type GraphIR, type IRExport, type IRDanglingRef, type IRGroups, type IRImport, type IREdge, type IRNode } from "../graph-ir";
|
|
44
|
+
import type { ViewDocument } from "../capabilities/view";
|
|
44
45
|
|
|
45
46
|
/** The version of the composed document `chant workspace graph` writes. */
|
|
46
47
|
export const WORKSPACE_GRAPH_VERSION = 1;
|
|
@@ -99,12 +100,24 @@ export interface ComposedMember {
|
|
|
99
100
|
* the outer `nodes` with `outer/inner/id` ids.
|
|
100
101
|
*/
|
|
101
102
|
nested?: NestedWorkspace;
|
|
103
|
+
/**
|
|
104
|
+
* For a member of kind `repo` (#3168): the repository and pinned revision it
|
|
105
|
+
* names, and `read`, the repo identity the other repository's own graph
|
|
106
|
+
* document gave, or null. Its nodes fold in as a nested workspace's do.
|
|
107
|
+
*/
|
|
108
|
+
repo?: { url: string; rev: string; workspace: string; read: string | null };
|
|
102
109
|
/**
|
|
103
110
|
* The factory and listing the member's box block declares (#3146, ws-077),
|
|
104
111
|
* read from the declaration at the revision read. Set by
|
|
105
112
|
* `chant workspace graph` on every member; null when the box declares neither.
|
|
106
113
|
*/
|
|
107
114
|
box?: { factory: FactoryView | null; listing: ListingView | null } | null;
|
|
115
|
+
/**
|
|
116
|
+
* With `--capability-view` (#4378): the lexicon-neutral view the member's
|
|
117
|
+
* own chant mapped through its own lexicons, with `<member>/<id>` ids. null
|
|
118
|
+
* when the member's chant predates the view and printed none.
|
|
119
|
+
*/
|
|
120
|
+
capabilityView?: ViewDocument | null;
|
|
108
121
|
/** Whole-read facts the member's IR carried (`meta`, `pipeline`), kept apart from the composed sections. */
|
|
109
122
|
meta?: Record<string, unknown>;
|
|
110
123
|
pipeline?: unknown;
|
|
@@ -174,7 +187,8 @@ export type ComposedDangling = IRDanglingRef & { member: string; nested?: string
|
|
|
174
187
|
|
|
175
188
|
export interface WorkspaceGraph {
|
|
176
189
|
version: number;
|
|
177
|
-
|
|
190
|
+
/** `repo` (#3168): the repository the document came from, its origin URL redacted, or null; absent from a chant before it. */
|
|
191
|
+
workspace: { name: string; root: string; repo?: string | null };
|
|
178
192
|
members: ComposedMember[];
|
|
179
193
|
nodes: ComposedNode[];
|
|
180
194
|
edges: ComposedEdge[];
|
|
@@ -249,7 +263,9 @@ export interface ComposeInput {
|
|
|
249
263
|
ir?: GraphIR;
|
|
250
264
|
}
|
|
251
265
|
|
|
252
|
-
|
|
266
|
+
/** A member's node id as the composed workspace documents give it: `<member>/<id>`. `workspace search` uses the same rule (#4374). */
|
|
267
|
+
export const composedId = (member: string, id: string): string => `${member}/${id}`;
|
|
268
|
+
const prefix = composedId;
|
|
253
269
|
|
|
254
270
|
const strings = (v: unknown): string[] => (Array.isArray(v) ? v.filter((x): x is string => typeof x === "string") : []);
|
|
255
271
|
const records = (v: unknown): Record<string, unknown>[] =>
|
|
@@ -326,7 +342,7 @@ function sorted(rec: Record<string, string[]>): Record<string, string[]> {
|
|
|
326
342
|
* `read` holds the links each member's kind reader found in its files (#3932).
|
|
327
343
|
*/
|
|
328
344
|
export function composeWorkspaceGraph(
|
|
329
|
-
workspace: { name: string; root: string },
|
|
345
|
+
workspace: { name: string; root: string; repo?: string | null },
|
|
330
346
|
inputs: ComposeInput[],
|
|
331
347
|
links?: { declaration: Declaration; kinds?: KindRegistry; read?: ReadonlyMap<string, KindLinkRead> },
|
|
332
348
|
): WorkspaceGraph {
|
|
@@ -607,6 +607,28 @@
|
|
|
607
607
|
}
|
|
608
608
|
]
|
|
609
609
|
},
|
|
610
|
+
"executor": {
|
|
611
|
+
"description": "The forge and committed workflow that deploys this environment, as the member's chant.config.ts declares on the environment's entry (#4402): a literal entry before a pattern. forge and workflow are null when none is declared, and reason then says why. Never derived from a generated workflow's name. Added by chant 0.124.47; a document from an older chant has no executor.",
|
|
612
|
+
"type": "object",
|
|
613
|
+
"required": ["forge", "workflow", "reason"],
|
|
614
|
+
"properties": {
|
|
615
|
+
"forge": { "enum": ["github", "gitlab", "forgejo", null] },
|
|
616
|
+
"workflow": { "type": ["string", "null"], "description": "The workflow file the forge runs, such as deploy-prod.yml under .github/workflows/, or .gitlab-ci.yml." },
|
|
617
|
+
"reason": {
|
|
618
|
+
"oneOf": [
|
|
619
|
+
{ "type": "null" },
|
|
620
|
+
{
|
|
621
|
+
"type": "object",
|
|
622
|
+
"required": ["code", "message"],
|
|
623
|
+
"properties": {
|
|
624
|
+
"code": { "enum": ["executor-none-declared", "executor-config-unreadable"] },
|
|
625
|
+
"message": { "type": "string" }
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
]
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
},
|
|
610
632
|
"command": {
|
|
611
633
|
"type": "string",
|
|
612
634
|
"description": "The command that deploys the component to this environment on its default runtime, run in the member's directory: chant run --components <name>, with --on <runtime> when the default runtime isn't local, and --env <env> for any environment but the default."
|