@intentius/chant 0.124.51 → 0.124.54
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/audit/discover.d.ts.map +1 -1
- package/dist/audit/discover.js +3 -1
- package/dist/behaviour.d.ts +1 -1
- package/dist/behaviour.d.ts.map +1 -1
- package/dist/capabilities/templates.d.ts +65 -0
- package/dist/capabilities/templates.d.ts.map +1 -0
- package/dist/capabilities/templates.js +193 -0
- package/dist/capabilities/templates.json +145 -0
- package/dist/change-set-graph.d.ts +35 -3
- package/dist/change-set-graph.d.ts.map +1 -1
- package/dist/change-set-graph.js +60 -9
- package/dist/change-set.d.ts +65 -7
- package/dist/change-set.d.ts.map +1 -1
- package/dist/change-set.js +23 -12
- package/dist/ci-identity.d.ts +7 -2
- package/dist/ci-identity.d.ts.map +1 -1
- package/dist/ci-identity.js +4 -1
- package/dist/cli/commands/import-index.d.ts +52 -0
- package/dist/cli/commands/import-index.d.ts.map +1 -0
- package/dist/cli/commands/import-index.js +226 -0
- package/dist/cli/commands/lint.d.ts.map +1 -1
- package/dist/cli/commands/lint.js +4 -2
- package/dist/cli/handlers/components.d.ts.map +1 -1
- package/dist/cli/handlers/components.js +11 -2
- package/dist/cli/handlers/fan-out.d.ts.map +1 -1
- package/dist/cli/handlers/fan-out.js +16 -3
- package/dist/cli/handlers/graph.d.ts.map +1 -1
- package/dist/cli/handlers/graph.js +22 -4
- package/dist/cli/handlers/index-cloud.d.ts +14 -0
- package/dist/cli/handlers/index-cloud.d.ts.map +1 -0
- package/dist/cli/handlers/index-cloud.js +22 -0
- package/dist/cli/handlers/index-diff.d.ts +18 -0
- package/dist/cli/handlers/index-diff.d.ts.map +1 -0
- package/dist/cli/handlers/index-diff.js +142 -0
- package/dist/cli/handlers/lifecycle-drift.d.ts +25 -0
- package/dist/cli/handlers/lifecycle-drift.d.ts.map +1 -0
- package/dist/cli/handlers/lifecycle-drift.js +64 -0
- package/dist/cli/handlers/lifecycle.d.ts.map +1 -1
- package/dist/cli/handlers/lifecycle.js +188 -28
- package/dist/cli/handlers/misc.d.ts +9 -0
- package/dist/cli/handlers/misc.d.ts.map +1 -1
- package/dist/cli/handlers/misc.js +77 -0
- package/dist/cli/handlers/pr.d.ts.map +1 -1
- package/dist/cli/handlers/pr.js +17 -3
- package/dist/cli/handlers/promote.d.ts.map +1 -1
- package/dist/cli/handlers/promote.js +89 -15
- package/dist/cli/handlers/query.d.ts.map +1 -1
- package/dist/cli/handlers/query.js +28 -4
- package/dist/cli/handlers/scenario.d.ts.map +1 -1
- package/dist/cli/handlers/scenario.js +8 -7
- package/dist/cli/handlers/search.d.ts +34 -4
- package/dist/cli/handlers/search.d.ts.map +1 -1
- package/dist/cli/handlers/search.js +216 -36
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +55 -1
- package/dist/cli/mcp/lifecycle-tools.d.ts.map +1 -1
- package/dist/cli/mcp/lifecycle-tools.js +3 -2
- package/dist/cli/mcp/resource-handlers.d.ts.map +1 -1
- package/dist/cli/mcp/resource-handlers.js +4 -3
- package/dist/cli/mcp/workspace-tools.js +1 -1
- package/dist/cli/parse-args.d.ts.map +1 -1
- package/dist/cli/parse-args.js +55 -2
- package/dist/cli/registry.d.ts +19 -1
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/cloud-lister/aws.d.ts +35 -0
- package/dist/cloud-lister/aws.d.ts.map +1 -0
- package/dist/cloud-lister/aws.js +203 -0
- package/dist/cloud-lister/azure.d.ts +34 -0
- package/dist/cloud-lister/azure.d.ts.map +1 -0
- package/dist/cloud-lister/azure.js +129 -0
- package/dist/cloud-lister/common.d.ts +40 -0
- package/dist/cloud-lister/common.d.ts.map +1 -0
- package/dist/cloud-lister/common.js +83 -0
- package/dist/cloud-lister/credentials.d.ts +50 -0
- package/dist/cloud-lister/credentials.d.ts.map +1 -0
- package/dist/cloud-lister/credentials.js +86 -0
- package/dist/cloud-lister/fakes.d.ts +27 -0
- package/dist/cloud-lister/fakes.d.ts.map +1 -0
- package/dist/cloud-lister/fakes.js +50 -0
- package/dist/cloud-lister/gcp.d.ts +42 -0
- package/dist/cloud-lister/gcp.d.ts.map +1 -0
- package/dist/cloud-lister/gcp.js +143 -0
- package/dist/cloud-lister/guard.d.ts +49 -0
- package/dist/cloud-lister/guard.d.ts.map +1 -0
- package/dist/cloud-lister/guard.js +103 -0
- package/dist/cloud-lister/ids.d.ts +23 -0
- package/dist/cloud-lister/ids.d.ts.map +1 -0
- package/dist/cloud-lister/ids.js +42 -0
- package/dist/cloud-lister/index.d.ts +67 -0
- package/dist/cloud-lister/index.d.ts.map +1 -0
- package/dist/cloud-lister/index.js +102 -0
- package/dist/cloud-lister/kubernetes.d.ts +64 -0
- package/dist/cloud-lister/kubernetes.d.ts.map +1 -0
- package/dist/cloud-lister/kubernetes.js +276 -0
- package/dist/cloud-lister/markers.d.ts +31 -0
- package/dist/cloud-lister/markers.d.ts.map +1 -0
- package/dist/cloud-lister/markers.js +73 -0
- package/dist/cloud-lister/mask.d.ts +31 -0
- package/dist/cloud-lister/mask.d.ts.map +1 -0
- package/dist/cloud-lister/mask.js +74 -0
- package/dist/cloud-lister/sigv4.d.ts +29 -0
- package/dist/cloud-lister/sigv4.d.ts.map +1 -0
- package/dist/cloud-lister/sigv4.js +54 -0
- package/dist/cloud-lister/transport.d.ts +55 -0
- package/dist/cloud-lister/transport.d.ts.map +1 -0
- package/dist/cloud-lister/transport.js +86 -0
- package/dist/cloud-lister/types.d.ts +121 -0
- package/dist/cloud-lister/types.d.ts.map +1 -0
- package/dist/cloud-lister/types.js +24 -0
- package/dist/components/capability-plugin-loader.d.ts.map +1 -1
- package/dist/components/capability-plugin-loader.js +6 -0
- package/dist/components/capability-plugin.d.ts +9 -0
- package/dist/components/capability-plugin.d.ts.map +1 -1
- package/dist/components/capability.d.ts +224 -0
- package/dist/components/capability.d.ts.map +1 -1
- package/dist/components/cli-support.d.ts +21 -0
- package/dist/components/cli-support.d.ts.map +1 -1
- package/dist/components/cli-support.js +58 -14
- package/dist/components/covered-round.d.ts +173 -0
- package/dist/components/covered-round.d.ts.map +1 -0
- package/dist/components/covered-round.js +200 -0
- package/dist/components/declared-reads.d.ts +38 -0
- package/dist/components/declared-reads.d.ts.map +1 -0
- package/dist/components/declared-reads.js +131 -0
- package/dist/components/deploy-units.d.ts.map +1 -1
- package/dist/components/deploy-units.js +4 -0
- package/dist/components/driver.d.ts +42 -1
- package/dist/components/driver.d.ts.map +1 -1
- package/dist/components/driver.js +74 -3
- package/dist/components/fan-out-run.d.ts +23 -1
- package/dist/components/fan-out-run.d.ts.map +1 -1
- package/dist/components/fan-out-run.js +82 -14
- package/dist/components/fan-out-support.d.ts +6 -0
- package/dist/components/fan-out-support.d.ts.map +1 -1
- package/dist/components/fan-out-support.js +4 -1
- package/dist/components/fan-out.d.ts +28 -0
- package/dist/components/fan-out.d.ts.map +1 -1
- package/dist/components/groups.d.ts +229 -0
- package/dist/components/groups.d.ts.map +1 -0
- package/dist/components/groups.js +760 -0
- package/dist/components/index.d.ts +7 -2
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +5 -0
- package/dist/components/plan-shape-conformance.d.ts +48 -0
- package/dist/components/plan-shape-conformance.d.ts.map +1 -0
- package/dist/components/plan-shape-conformance.js +122 -0
- package/dist/components/pr-run.d.ts +62 -7
- package/dist/components/pr-run.d.ts.map +1 -1
- package/dist/components/pr-run.js +354 -53
- package/dist/components/promote-rounds.d.ts +9 -0
- package/dist/components/promote-rounds.d.ts.map +1 -1
- package/dist/components/promote-rounds.js +23 -2
- package/dist/components/promote.d.ts +17 -0
- package/dist/components/promote.d.ts.map +1 -1
- package/dist/components/promote.js +36 -6
- package/dist/components/release-gate.d.ts +23 -1
- package/dist/components/release-gate.d.ts.map +1 -1
- package/dist/components/release-gate.js +97 -33
- package/dist/components/run-groups.d.ts +58 -0
- package/dist/components/run-groups.d.ts.map +1 -0
- package/dist/components/run-groups.js +78 -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 +6 -1
- package/dist/components/verbs/index.d.ts +1 -0
- package/dist/components/verbs/index.d.ts.map +1 -1
- package/dist/components/verbs/index.js +1 -0
- package/dist/components/verbs/member-outputs.d.ts +187 -0
- package/dist/components/verbs/member-outputs.d.ts.map +1 -0
- package/dist/components/verbs/member-outputs.js +218 -0
- package/dist/components/wave-plan.d.ts +2 -0
- package/dist/components/wave-plan.d.ts.map +1 -1
- package/dist/components/wave-plan.js +4 -1
- package/dist/config.d.ts +60 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +27 -0
- package/dist/deep-observation.d.ts +1 -13
- package/dist/deep-observation.d.ts.map +1 -1
- package/dist/deep-observation.js +5 -22
- package/dist/drift-record.d.ts +542 -0
- package/dist/drift-record.d.ts.map +1 -0
- package/dist/drift-record.js +886 -0
- package/dist/engine-facts.d.ts +144 -0
- package/dist/engine-facts.d.ts.map +1 -0
- package/dist/engine-facts.js +14 -0
- package/dist/graph-ir.d.ts +153 -2
- package/dist/graph-ir.d.ts.map +1 -1
- package/dist/graph-ir.js +224 -6
- package/dist/graph-refs.d.ts +145 -0
- package/dist/graph-refs.d.ts.map +1 -1
- package/dist/graph-refs.js +305 -0
- package/dist/graph-schema/fixtures/adopt.json +15 -0
- package/dist/graph-schema/fixtures/choudoufu.engine-graph.json +169 -0
- package/dist/graph-schema/fixtures/index.json +68 -0
- package/dist/graph-schema/fixtures/plunge.engine-graph.json +158 -0
- package/dist/graph-schema/fixtures.d.ts +23 -0
- package/dist/graph-schema/fixtures.d.ts.map +1 -0
- package/dist/graph-schema/fixtures.js +246 -0
- package/dist/graph-schema/generate.d.ts +15 -0
- package/dist/graph-schema/generate.d.ts.map +1 -0
- package/dist/graph-schema/generate.js +267 -0
- package/dist/graph-schema/graph.schema.json +1387 -0
- package/dist/health.schema.json +2 -1
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +2 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/instance-nodes.d.ts +159 -0
- package/dist/instance-nodes.d.ts.map +1 -0
- package/dist/instance-nodes.js +231 -0
- package/dist/lexicon.d.ts +72 -0
- package/dist/lexicon.d.ts.map +1 -1
- package/dist/lifecycle/adoption-file.d.ts +56 -0
- package/dist/lifecycle/adoption-file.d.ts.map +1 -0
- package/dist/lifecycle/adoption-file.js +123 -0
- package/dist/lifecycle/cloud-index.d.ts +186 -0
- package/dist/lifecycle/cloud-index.d.ts.map +1 -0
- package/dist/lifecycle/cloud-index.js +618 -0
- package/dist/lifecycle/derive-edges.d.ts +59 -0
- package/dist/lifecycle/derive-edges.d.ts.map +1 -0
- package/dist/lifecycle/derive-edges.js +126 -0
- package/dist/lifecycle/git.d.ts +10 -9
- package/dist/lifecycle/git.d.ts.map +1 -1
- package/dist/lifecycle/git.js +7 -1
- package/dist/lifecycle/identity-match.d.ts +133 -0
- package/dist/lifecycle/identity-match.d.ts.map +1 -0
- package/dist/lifecycle/identity-match.js +147 -0
- package/dist/lifecycle/index-diff.d.ts +224 -0
- package/dist/lifecycle/index-diff.d.ts.map +1 -0
- package/dist/lifecycle/index-diff.js +327 -0
- package/dist/lifecycle/index-document.d.ts +130 -0
- package/dist/lifecycle/index-document.d.ts.map +1 -0
- package/dist/lifecycle/index-document.js +189 -0
- package/dist/lifecycle/index-drift.d.ts +121 -0
- package/dist/lifecycle/index-drift.d.ts.map +1 -0
- package/dist/lifecycle/index-drift.js +178 -0
- package/dist/lifecycle/index-import.d.ts +168 -0
- package/dist/lifecycle/index-import.d.ts.map +1 -0
- package/dist/lifecycle/index-import.js +515 -0
- package/dist/lifecycle/index-join.d.ts +129 -0
- package/dist/lifecycle/index-join.d.ts.map +1 -0
- package/dist/lifecycle/index-join.js +248 -0
- package/dist/lifecycle/index.d.ts +4 -0
- package/dist/lifecycle/index.d.ts.map +1 -1
- package/dist/lifecycle/index.js +4 -0
- package/dist/lifecycle/observation-baseline.d.ts +61 -21
- package/dist/lifecycle/observation-baseline.d.ts.map +1 -1
- package/dist/lifecycle/observation-baseline.js +144 -19
- package/dist/lifecycle/observe.d.ts.map +1 -1
- package/dist/lifecycle/observe.js +6 -1
- package/dist/lifecycle/query.d.ts +45 -4
- package/dist/lifecycle/query.d.ts.map +1 -1
- package/dist/lifecycle/query.js +89 -7
- package/dist/lifecycle/replay.d.ts +10 -3
- package/dist/lifecycle/replay.d.ts.map +1 -1
- package/dist/lifecycle/replay.js +10 -6
- package/dist/lifecycle/scenario.d.ts +4 -3
- package/dist/lifecycle/scenario.d.ts.map +1 -1
- package/dist/lifecycle/snapshot-store-fake.d.ts +9 -0
- package/dist/lifecycle/snapshot-store-fake.d.ts.map +1 -0
- package/dist/lifecycle/snapshot-store-fake.js +21 -0
- package/dist/lifecycle/snapshot-store-s3.d.ts +102 -0
- package/dist/lifecycle/snapshot-store-s3.d.ts.map +1 -0
- package/dist/lifecycle/snapshot-store-s3.js +254 -0
- package/dist/lifecycle/snapshot-store.d.ts +170 -0
- package/dist/lifecycle/snapshot-store.d.ts.map +1 -0
- package/dist/lifecycle/snapshot-store.js +832 -0
- package/dist/lifecycle/snapshot.d.ts +11 -0
- package/dist/lifecycle/snapshot.d.ts.map +1 -1
- package/dist/lifecycle/snapshot.js +18 -5
- package/dist/lifecycle/type-listing.d.ts +148 -0
- package/dist/lifecycle/type-listing.d.ts.map +1 -0
- package/dist/lifecycle/type-listing.js +166 -0
- package/dist/lint/component-checks.d.ts +15 -1
- package/dist/lint/component-checks.d.ts.map +1 -1
- package/dist/lint/component-checks.js +1 -0
- package/dist/lint/presets/relaxed.json +2 -1
- package/dist/lint/presets/strict.json +2 -1
- package/dist/lint/rules/__fixtures__/comp/comp008/fail/dns.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp008/fail/dns.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp008/fail/dns.component.js +13 -0
- package/dist/lint/rules/__fixtures__/comp/comp008/pass/dns.component.d.ts +4 -0
- package/dist/lint/rules/__fixtures__/comp/comp008/pass/dns.component.d.ts.map +1 -0
- package/dist/lint/rules/__fixtures__/comp/comp008/pass/dns.component.js +8 -0
- package/dist/lint/rules/comp/comp008-applies-signal-only-root.d.ts +33 -0
- package/dist/lint/rules/comp/comp008-applies-signal-only-root.d.ts.map +1 -0
- package/dist/lint/rules/comp/comp008-applies-signal-only-root.js +123 -0
- package/dist/lint/rules/comp/index.d.ts +2 -1
- package/dist/lint/rules/comp/index.d.ts.map +1 -1
- package/dist/lint/rules/comp/index.js +4 -1
- package/dist/observation.d.ts +19 -2
- package/dist/observation.d.ts.map +1 -1
- package/dist/observation.js +18 -1
- package/dist/op/activities/activity-contracts.d.ts +1 -1
- package/dist/op/activities/activity-contracts.js +1 -1
- package/dist/op/activities/change-set.d.ts +6 -4
- package/dist/op/activities/change-set.d.ts.map +1 -1
- package/dist/op/activities/change-set.js +4 -2
- package/dist/op/activity-failure.d.ts +27 -0
- package/dist/op/activity-failure.d.ts.map +1 -1
- package/dist/op/activity-failure.js +31 -0
- package/dist/op/index.d.ts +2 -1
- package/dist/op/index.d.ts.map +1 -1
- package/dist/op/index.js +1 -1
- package/dist/op/local-executor.d.ts +5 -1
- package/dist/op/local-executor.d.ts.map +1 -1
- package/dist/op/local-executor.js +22 -8
- package/dist/pr-loop.d.ts +92 -3
- package/dist/pr-loop.d.ts.map +1 -1
- package/dist/pr-loop.js +62 -3
- package/dist/pulumi-urn.d.ts +101 -0
- package/dist/pulumi-urn.d.ts.map +1 -0
- package/dist/pulumi-urn.js +131 -0
- package/dist/release-floors.d.ts +23 -0
- package/dist/release-floors.d.ts.map +1 -0
- package/dist/release-floors.js +22 -0
- package/dist/sensitive-key.d.ts +23 -0
- package/dist/sensitive-key.d.ts.map +1 -0
- package/dist/sensitive-key.js +31 -0
- package/dist/wave-runtime.mjs +234 -234
- package/dist/workspace/adoption-report.d.ts +53 -0
- package/dist/workspace/adoption-report.d.ts.map +1 -0
- package/dist/workspace/adoption-report.js +76 -0
- package/dist/workspace/capabilities-contract.d.ts +7 -0
- package/dist/workspace/capabilities-contract.d.ts.map +1 -1
- package/dist/workspace/capabilities-contract.js +2 -1
- package/dist/workspace/capabilities.schema.json +98 -0
- package/dist/workspace/change-set.schema.json +42 -3
- package/dist/workspace/ci-cloud-identity.d.ts +13 -1
- package/dist/workspace/ci-cloud-identity.d.ts.map +1 -1
- package/dist/workspace/ci-cloud-identity.js +30 -1
- package/dist/workspace/compose-graph.d.ts +10 -1
- package/dist/workspace/compose-graph.d.ts.map +1 -1
- package/dist/workspace/compose-graph.js +6 -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 +6 -1
- package/dist/workspace/drift-cli.d.ts +81 -0
- package/dist/workspace/drift-cli.d.ts.map +1 -0
- package/dist/workspace/drift-cli.js +317 -0
- package/dist/workspace/drift.schema.json +672 -0
- package/dist/workspace/graph-cli.d.ts +2 -0
- package/dist/workspace/graph-cli.d.ts.map +1 -1
- package/dist/workspace/graph-cli.js +3 -0
- package/dist/workspace/graph.schema.json +72 -0
- package/dist/workspace/init.d.ts +5 -1
- package/dist/workspace/init.d.ts.map +1 -1
- package/dist/workspace/init.js +55 -9
- package/dist/workspace/ledger.schema.json +1 -1
- package/dist/workspace/nested-graph.d.ts.map +1 -1
- package/dist/workspace/nested-graph.js +2 -0
- package/dist/workspace/pr-report.schema.json +76 -3
- package/dist/workspace/promote-waves.d.ts +112 -0
- package/dist/workspace/promote-waves.d.ts.map +1 -0
- package/dist/workspace/promote-waves.js +290 -0
- package/dist/workspace/promote.d.ts +84 -2
- package/dist/workspace/promote.d.ts.map +1 -1
- package/dist/workspace/promote.js +347 -61
- package/dist/workspace/reason-codes.d.ts +12 -0
- package/dist/workspace/reason-codes.d.ts.map +1 -1
- package/dist/workspace/reason-codes.js +14 -0
- package/dist/workspace/search-contract.d.ts +3 -3
- package/dist/workspace/search-contract.d.ts.map +1 -1
- package/dist/workspace/search-contract.js +2 -0
- package/dist/workspace/search.schema.json +103 -5
- package/package.json +14 -1
- package/src/__fixtures__/drift-record/README.md +58 -0
- package/src/__fixtures__/drift-record/choudoufu-cone.ndjson +4 -0
- package/src/__fixtures__/drift-record/choudoufu-resource.ndjson +3 -0
- package/src/__fixtures__/drift-record/component-status-ledger.json +65 -0
- package/src/__fixtures__/drift-record/component-status.json +91 -0
- package/src/__fixtures__/drift-record/deep-diff.json +259 -0
- package/src/__fixtures__/drift-record/lifecycle-diff-live.json +825 -0
- package/src/__fixtures__/drift-record/live-diff.json +125 -0
- package/src/audit/discover.e2e.test.ts +14 -0
- package/src/audit/discover.ts +3 -1
- package/src/behaviour.ts +1 -1
- package/src/capabilities/templates.json +145 -0
- package/src/capabilities/templates.test.ts +212 -0
- package/src/capabilities/templates.ts +204 -0
- package/src/change-set-bundle.test.ts +83 -0
- package/src/change-set-graph.ts +80 -9
- package/src/change-set.test.ts +24 -0
- package/src/change-set.ts +77 -14
- package/src/ci-identity-targets.test.ts +23 -0
- package/src/ci-identity.ts +10 -4
- package/src/cli/commands/import-index.test.ts +117 -0
- package/src/cli/commands/import-index.ts +265 -0
- package/src/cli/commands/lint.ts +4 -2
- package/src/cli/handlers/components.test.ts +9 -0
- package/src/cli/handlers/components.ts +12 -2
- package/src/cli/handlers/fan-out.ts +17 -3
- package/src/cli/handlers/graph.test.ts +42 -0
- package/src/cli/handlers/graph.ts +26 -4
- package/src/cli/handlers/index-cloud.ts +32 -0
- package/src/cli/handlers/index-diff.test.ts +68 -0
- package/src/cli/handlers/index-diff.ts +146 -0
- package/src/cli/handlers/ledger-root-member.test.ts +161 -0
- package/src/cli/handlers/lifecycle-drift.ts +68 -0
- package/src/cli/handlers/lifecycle.test.ts +33 -11
- package/src/cli/handlers/lifecycle.ts +205 -30
- package/src/cli/handlers/misc.ts +73 -0
- package/src/cli/handlers/pr-waves-blocked.test.ts +37 -2
- package/src/cli/handlers/pr.ts +16 -3
- package/src/cli/handlers/promote.test.ts +64 -0
- package/src/cli/handlers/promote.ts +81 -6
- package/src/cli/handlers/query.ts +27 -4
- package/src/cli/handlers/run-declared-reads-cli.test.ts +187 -0
- package/src/cli/handlers/run-groups-cli.test.ts +229 -0
- package/src/cli/handlers/scenario.test.ts +13 -0
- package/src/cli/handlers/scenario.ts +8 -7
- package/src/cli/handlers/search-index.test.ts +255 -0
- package/src/cli/handlers/search-json.test.ts +1 -1
- package/src/cli/handlers/search-ownership.test.ts +194 -0
- package/src/cli/handlers/search.ts +271 -38
- package/src/cli/main.test.ts +7 -0
- package/src/cli/main.ts +56 -1
- package/src/cli/mcp/lifecycle-tools.ts +3 -2
- package/src/cli/mcp/resource-handlers.ts +4 -3
- package/src/cli/mcp/workspace-tools.ts +1 -1
- package/src/cli/parse-args.ts +40 -2
- package/src/cli/registry.ts +19 -1
- package/src/cloud-lister/aws.test.ts +202 -0
- package/src/cloud-lister/aws.ts +226 -0
- package/src/cloud-lister/azure.test.ts +132 -0
- package/src/cloud-lister/azure.ts +142 -0
- package/src/cloud-lister/common.ts +115 -0
- package/src/cloud-lister/credentials.ts +110 -0
- package/src/cloud-lister/fakes.ts +66 -0
- package/src/cloud-lister/gcp.test.ts +121 -0
- package/src/cloud-lister/gcp.ts +159 -0
- package/src/cloud-lister/guard.test.ts +198 -0
- package/src/cloud-lister/guard.ts +111 -0
- package/src/cloud-lister/ids.ts +54 -0
- package/src/cloud-lister/index.ts +134 -0
- package/src/cloud-lister/kubernetes.test.ts +160 -0
- package/src/cloud-lister/kubernetes.ts +284 -0
- package/src/cloud-lister/markers.ts +74 -0
- package/src/cloud-lister/mask.ts +77 -0
- package/src/cloud-lister/shape.test.ts +81 -0
- package/src/cloud-lister/sigv4.ts +70 -0
- package/src/cloud-lister/transport.ts +118 -0
- package/src/cloud-lister/types.ts +135 -0
- package/src/components/capability-plugin-loader.ts +4 -0
- package/src/components/capability-plugin.ts +10 -0
- package/src/components/capability.ts +238 -0
- package/src/components/cli-support.ts +70 -14
- package/src/components/covered-round.test.ts +166 -0
- package/src/components/covered-round.ts +293 -0
- package/src/components/declared-reads.test.ts +103 -0
- package/src/components/declared-reads.ts +134 -0
- package/src/components/deploy-units.ts +4 -0
- package/src/components/driver.ts +101 -4
- package/src/components/fan-out-run.ts +95 -15
- package/src/components/fan-out-support.ts +10 -1
- package/src/components/fan-out.ts +30 -0
- package/src/components/groups.test.ts +320 -0
- package/src/components/groups.ts +880 -0
- package/src/components/index.ts +59 -0
- package/src/components/plan-shape-conformance.ts +130 -0
- package/src/components/pr-env-run-bundle.test.ts +2 -0
- package/src/components/pr-run.test.ts +728 -4
- package/src/components/pr-run.ts +395 -55
- package/src/components/promote-rounds.ts +25 -2
- package/src/components/promote.ts +55 -5
- package/src/components/registry.test.ts +1 -1
- package/src/components/release-gate.ts +115 -30
- package/src/components/release-groups.test.ts +362 -0
- package/src/components/run-groups.ts +113 -0
- package/src/components/starter-plugin.ts +6 -0
- package/src/components/verbs/index.ts +1 -0
- package/src/components/verbs/member-outputs.test.ts +205 -0
- package/src/components/verbs/member-outputs.ts +308 -0
- package/src/components/wave-plan.ts +5 -2
- package/src/config.ts +44 -0
- package/src/deep-observation.ts +5 -23
- package/src/drift-record.test.ts +596 -0
- package/src/drift-record.ts +1206 -0
- package/src/engine-facts.guard.test.ts +111 -0
- package/src/engine-facts.test.ts +178 -0
- package/src/engine-facts.ts +154 -0
- package/src/gated-waves-bundle.test.ts +2 -0
- package/src/graph-ir-live.test.ts +92 -0
- package/src/graph-ir.ts +317 -7
- package/src/graph-refs.ts +416 -0
- package/src/graph-schema/fixtures/adopt.json +15 -0
- package/src/graph-schema/fixtures/choudoufu.engine-graph.json +169 -0
- package/src/graph-schema/fixtures/index.json +68 -0
- package/src/graph-schema/fixtures/plunge.engine-graph.json +158 -0
- package/src/graph-schema/fixtures.ts +267 -0
- package/src/graph-schema/generate.ts +263 -0
- package/src/graph-schema/graph-schema.test.ts +153 -0
- package/src/graph-schema/graph.schema.json +1387 -0
- package/src/health.schema.json +2 -1
- package/src/identity.ts +2 -0
- package/src/index.ts +2 -0
- package/src/instance-nodes.ts +288 -0
- package/src/lexicon.ts +76 -0
- package/src/lifecycle/__fixtures__/index-diff/20261026T120000Z-aaaaaaaaaaaa.json +149 -0
- package/src/lifecycle/__fixtures__/index-diff/20261026T130000Z-bbbbbbbbbbbb.json +127 -0
- package/src/lifecycle/adoption-file.test.ts +100 -0
- package/src/lifecycle/adoption-file.ts +154 -0
- package/src/lifecycle/cloud-index.test.ts +517 -0
- package/src/lifecycle/cloud-index.ts +736 -0
- package/src/lifecycle/derive-edges.test.ts +193 -0
- package/src/lifecycle/derive-edges.ts +182 -0
- package/src/lifecycle/git.ts +10 -4
- package/src/lifecycle/identity-match.test.ts +308 -0
- package/src/lifecycle/identity-match.ts +257 -0
- package/src/lifecycle/index-diff.test.ts +198 -0
- package/src/lifecycle/index-diff.ts +476 -0
- package/src/lifecycle/index-document.test.ts +64 -0
- package/src/lifecycle/index-document.ts +299 -0
- package/src/lifecycle/index-drift.test.ts +191 -0
- package/src/lifecycle/index-drift.ts +304 -0
- package/src/lifecycle/index-import.test.ts +255 -0
- package/src/lifecycle/index-import.ts +634 -0
- package/src/lifecycle/index-join.test.ts +250 -0
- package/src/lifecycle/index-join.ts +304 -0
- package/src/lifecycle/index-store-load-bearing.test.ts +187 -0
- package/src/lifecycle/index.ts +4 -0
- package/src/lifecycle/member-ledger.test.ts +25 -7
- package/src/lifecycle/observation-baseline.test.ts +72 -1
- package/src/lifecycle/observation-baseline.ts +190 -27
- package/src/lifecycle/observe.ts +6 -1
- package/src/lifecycle/query.test.ts +69 -1
- package/src/lifecycle/query.ts +103 -10
- package/src/lifecycle/replay.test.ts +9 -5
- package/src/lifecycle/replay.ts +9 -5
- package/src/lifecycle/scenario.ts +4 -3
- package/src/lifecycle/snapshot-store-fake.ts +29 -0
- package/src/lifecycle/snapshot-store-s3.ts +316 -0
- package/src/lifecycle/snapshot-store.test.ts +385 -0
- package/src/lifecycle/snapshot-store.ts +981 -0
- package/src/lifecycle/snapshot.test.ts +13 -0
- package/src/lifecycle/snapshot.ts +23 -6
- package/src/lifecycle/type-listing.test.ts +166 -0
- package/src/lifecycle/type-listing.ts +309 -0
- package/src/lint/component-checks.ts +17 -1
- package/src/lint/config.test.ts +3 -0
- package/src/lint/presets/relaxed.json +2 -1
- package/src/lint/presets/strict.json +2 -1
- package/src/lint/rules/__fixtures__/comp/comp008/fail/dns.component.ts +15 -0
- package/src/lint/rules/__fixtures__/comp/comp008/pass/dns.component.ts +10 -0
- package/src/lint/rules/comp/comp.test.ts +2 -1
- package/src/lint/rules/comp/comp008-applies-signal-only-root.ts +121 -0
- package/src/lint/rules/comp/comp008.test.ts +77 -0
- package/src/lint/rules/comp/index.ts +4 -1
- package/src/observation-edges.test.ts +33 -0
- package/src/observation.ts +36 -1
- package/src/op/activities/activity-contracts.ts +1 -1
- package/src/op/activities/change-set.ts +8 -5
- package/src/op/activity-failure.ts +36 -0
- package/src/op/index.ts +2 -1
- package/src/op/local-executor.test.ts +80 -0
- package/src/op/local-executor.ts +27 -9
- package/src/pr-loop-bundle.test.ts +5 -2
- package/src/pr-loop.test.ts +57 -1
- package/src/pr-loop.ts +154 -6
- package/src/pulumi-urn.ts +151 -0
- package/src/release-floors.ts +22 -0
- package/src/sensitive-key.ts +34 -0
- package/src/workspace/adoption-report.test.ts +61 -0
- package/src/workspace/adoption-report.ts +103 -0
- package/src/workspace/capabilities-contract.test.ts +4 -0
- package/src/workspace/capabilities-contract.ts +9 -1
- package/src/workspace/capabilities.schema.json +98 -0
- package/src/workspace/change-set.schema.json +42 -3
- package/src/workspace/ci-cloud-identity.ts +31 -1
- package/src/workspace/compose-graph.test.ts +12 -0
- package/src/workspace/compose-graph.ts +12 -1
- package/src/workspace/conformance/conformance.e2e.test.ts +2 -1
- package/src/workspace/conformance/index.ts +6 -1
- package/src/workspace/drift-cli.test.ts +65 -0
- package/src/workspace/drift-cli.ts +365 -0
- package/src/workspace/drift.schema.json +672 -0
- package/src/workspace/graph-cli.ts +5 -0
- package/src/workspace/graph.schema.json +72 -0
- package/src/workspace/init.test.ts +38 -1
- package/src/workspace/init.ts +50 -8
- package/src/workspace/intent-gaps.test.ts +18 -2
- package/src/workspace/ledger.schema.json +1 -1
- package/src/workspace/nested-graph.ts +1 -0
- package/src/workspace/pr-report.schema.json +76 -3
- package/src/workspace/promote-waves.test.ts +296 -0
- package/src/workspace/promote-waves.ts +340 -0
- package/src/workspace/promote.test.ts +158 -4
- package/src/workspace/promote.ts +398 -57
- package/src/workspace/reason-codes.test.ts +4 -1
- package/src/workspace/reason-codes.ts +14 -0
- package/src/workspace/search-contract.ts +2 -0
- package/src/workspace/search.schema.json +103 -5
|
@@ -37,6 +37,7 @@ import { resolveComponentGraph, type DriverComponent } from "./driver";
|
|
|
37
37
|
import { deployUnits } from "./deploy-units";
|
|
38
38
|
import { computePlanDigest } from "../lifecycle/plan-digest";
|
|
39
39
|
import { layerWaves } from "../gated-waves";
|
|
40
|
+
import type { ReportedGroupRead } from "./capability";
|
|
40
41
|
|
|
41
42
|
/** Thrown when `changed` or `indeterminate` names a component the project does not have. */
|
|
42
43
|
export class UnknownComponentError extends Error {
|
|
@@ -124,6 +125,35 @@ export interface FanOutPlan {
|
|
|
124
125
|
indeterminate: string[];
|
|
125
126
|
/** Identity of this derivation, for binding one approval to the whole fan-out (#2300's pattern). */
|
|
126
127
|
digest: string;
|
|
128
|
+
/**
|
|
129
|
+
* The groups a pull request plans and applies as one (ws-107), each in
|
|
130
|
+
* one wave, set by `groupFanOut` (./groups.ts). `waves` are then the
|
|
131
|
+
* grouped waves. `digest` stays the derivation's. Absent when none formed.
|
|
132
|
+
*/
|
|
133
|
+
groups?: FanOutGroup[];
|
|
134
|
+
/** The components that could have grouped and did not, each with why (ws-107, ruling 1). Absent when none. */
|
|
135
|
+
fallbacks?: FanOutGroupFallback[];
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** Components one capability plans and applies in one call (ws-107). */
|
|
139
|
+
export interface FanOutGroup {
|
|
140
|
+
/** The kind of the capability every member's one step names. */
|
|
141
|
+
capability: string;
|
|
142
|
+
/** The members, upstreams first. */
|
|
143
|
+
components: string[];
|
|
144
|
+
/**
|
|
145
|
+
* The reads between members the capability reported through `groupReads`
|
|
146
|
+
* (#4447), which no member's step input shows. Absent when none.
|
|
147
|
+
*/
|
|
148
|
+
reads?: ReportedGroupRead[];
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/** A component that did not join a group (ws-107): its capability's `kind`, and the fallback's `kind` and `reason`. */
|
|
152
|
+
export interface FanOutGroupFallback {
|
|
153
|
+
component: string;
|
|
154
|
+
capability: string;
|
|
155
|
+
kind: string;
|
|
156
|
+
reason: string;
|
|
127
157
|
}
|
|
128
158
|
|
|
129
159
|
/** Reverse the `dependsOn` edges: who has to re-run when this one moves. */
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which components form a group and where it sits (ws-107, #4440), against
|
|
3
|
+
* fake capabilities: `fake-group` declares `planGroup` and `runGroup`,
|
|
4
|
+
* `fake-plain` does not. Planning and applying a group in a pull request is
|
|
5
|
+
* in `pr-run.test.ts`.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { readFileSync } from "node:fs";
|
|
9
|
+
import { join } from "node:path";
|
|
10
|
+
import { describe, expect, test } from "vitest";
|
|
11
|
+
import { CapabilityRegistry, type GroupFallback, type GroupMember, type ReportedGroupRead } from "./capability";
|
|
12
|
+
import { planFanOut } from "./fan-out";
|
|
13
|
+
import { findComponentGroups, groupFanOut, narrowGroups, planComponentGroup } from "./groups";
|
|
14
|
+
import { prWavePlan } from "./pr-run";
|
|
15
|
+
import type { DriverComponent } from "./driver";
|
|
16
|
+
|
|
17
|
+
const so = (stack: string, name: string) => ({ stackOutput: { stack, name } });
|
|
18
|
+
|
|
19
|
+
const component = (kind: string, name: string, dependsOn: string[] = [], vars?: Record<string, unknown>, extra: Array<Record<string, unknown>> = []): DriverComponent => ({
|
|
20
|
+
name,
|
|
21
|
+
dependsOn,
|
|
22
|
+
deploy: [{ phase: "Apply", steps: [{ kind, root: name, ...(vars ? { vars } : {}) }, ...(extra as never[])] }],
|
|
23
|
+
});
|
|
24
|
+
const grouped = (name: string, dependsOn: string[] = [], vars?: Record<string, unknown>) => component("fake-group", name, dependsOn, vars);
|
|
25
|
+
const plain = (name: string, dependsOn: string[] = [], vars?: Record<string, unknown>) => component("fake-plain", name, dependsOn, vars);
|
|
26
|
+
|
|
27
|
+
function registry(fallback?: (members: readonly GroupMember[]) => GroupFallback | undefined) {
|
|
28
|
+
const asked: GroupMember[][] = [];
|
|
29
|
+
const r = new CapabilityRegistry();
|
|
30
|
+
const unused = async (): Promise<never> => {
|
|
31
|
+
throw new Error("not called here");
|
|
32
|
+
};
|
|
33
|
+
r.register({
|
|
34
|
+
kind: "fake-group",
|
|
35
|
+
run: unused,
|
|
36
|
+
plan: unused,
|
|
37
|
+
planGroup: unused,
|
|
38
|
+
runGroup: unused,
|
|
39
|
+
...(fallback
|
|
40
|
+
? {
|
|
41
|
+
async groupFallback(_ctx: unknown, members: readonly GroupMember[]) {
|
|
42
|
+
asked.push([...members]);
|
|
43
|
+
return fallback(members);
|
|
44
|
+
},
|
|
45
|
+
}
|
|
46
|
+
: {}),
|
|
47
|
+
} as never);
|
|
48
|
+
r.register({ kind: "fake-plain", run: unused, plan: unused } as never);
|
|
49
|
+
return { registry: r, asked };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async function groupsOf(components: DriverComponent[], changed: string[], r = registry().registry) {
|
|
53
|
+
const plan = planFanOut({ components, changed });
|
|
54
|
+
const found = await findComponentGroups({ components, plan, registry: r, env: "prod" });
|
|
55
|
+
return { plan, found, grouped: groupFanOut(plan, components, found) };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
describe("which components form a group (ws-107)", () => {
|
|
59
|
+
/** a; b reads a; c reads b. */
|
|
60
|
+
const CHAIN = [grouped("a"), grouped("b", ["a"], { upstream: so("a", "id") }), grouped("c", ["b"], { upstream: so("b", "arn") })];
|
|
61
|
+
|
|
62
|
+
test("one-step components of a group capability joined by reads form one group, upstreams first", async () => {
|
|
63
|
+
const { found } = await groupsOf(CHAIN, ["a"]);
|
|
64
|
+
expect(found).toEqual({ groups: [{ capability: "fake-group", components: ["a", "b", "c"] }], fallbacks: [] });
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test("a component that reads none of the others, or is of another capability, joins nothing and is not listed", async () => {
|
|
68
|
+
const components = [...CHAIN, grouped("lone", ["a"]), plain("p", ["a"], { upstream: so("a", "id") })];
|
|
69
|
+
const { found } = await groupsOf(components, ["a"]);
|
|
70
|
+
expect(found.groups).toEqual([{ capability: "fake-group", components: ["a", "b", "c"] }]);
|
|
71
|
+
expect(found.fallbacks).toEqual([]);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test("a component outside the set on a dependency path between two members splits it (ruling 2)", async () => {
|
|
75
|
+
// c reads a too, but m sits between them.
|
|
76
|
+
const components = [grouped("a"), plain("m", ["a"], { upstream: so("a", "id") }), grouped("c", ["m"], { upstream: so("m", "x"), first: so("a", "id") })];
|
|
77
|
+
const { found } = await groupsOf(components, ["a"]);
|
|
78
|
+
expect(found.groups).toEqual([]);
|
|
79
|
+
expect(found.fallbacks.map((f) => [f.component, f.capability, f.kind])).toEqual([
|
|
80
|
+
["a", "fake-group", "split"],
|
|
81
|
+
["c", "fake-group", "split"],
|
|
82
|
+
]);
|
|
83
|
+
expect(found.fallbacks[0]!.reason).toMatch(/^m lies on a dependency path between a/);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
test("a component whose group step is one of several does not join (ruling 3), and is listed as steps", async () => {
|
|
87
|
+
const components = [grouped("a"), component("fake-group", "s", ["a"], { upstream: so("a", "id") }, [{ kind: "gate", gate: "ok" }])];
|
|
88
|
+
const { found } = await groupsOf(components, ["a"]);
|
|
89
|
+
expect(found.groups).toEqual([]);
|
|
90
|
+
expect(found.fallbacks).toEqual([
|
|
91
|
+
{ component: "s", capability: "fake-group", kind: "steps", reason: "s deploys in 2 steps, and only a component whose deploy is one fake-group step joins a group" },
|
|
92
|
+
]);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
test("the capability's groupFallback is asked before anything plans, with each member's reads and no input, and dissolves the group", async () => {
|
|
96
|
+
const r = registry(() => ({ kind: "off", reason: "grouping is turned off" }));
|
|
97
|
+
const { found, grouped: plan, plan: derived } = await groupsOf(CHAIN, ["a"], r.registry);
|
|
98
|
+
expect(r.asked).toHaveLength(1);
|
|
99
|
+
expect(r.asked[0]!.map((m) => m.component)).toEqual(["a", "b", "c"]);
|
|
100
|
+
expect(r.asked[0]![1]).toMatchObject({ component: "b", step: { root: "b", vars: { upstream: so("a", "id") } }, reads: [{ at: "/vars/upstream", ref: "a.id", component: "a", output: "id" }] });
|
|
101
|
+
expect(r.asked[0]![1]!.input).toBeUndefined();
|
|
102
|
+
expect(found.groups).toEqual([]);
|
|
103
|
+
expect(found.fallbacks.map((f) => [f.component, f.kind, f.reason])).toEqual([
|
|
104
|
+
["a", "off", "grouping is turned off"],
|
|
105
|
+
["b", "off", "grouping is turned off"],
|
|
106
|
+
["c", "off", "grouping is turned off"],
|
|
107
|
+
]);
|
|
108
|
+
// No group: the waves are the derivation's.
|
|
109
|
+
expect(plan.waves).toEqual(derived.waves);
|
|
110
|
+
expect(plan.groups).toBeUndefined();
|
|
111
|
+
expect(plan.fallbacks).toEqual(found.fallbacks);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
describe("a groupFallback that drops members (#4419 ruling 1)", () => {
|
|
116
|
+
/** A fallback that drops `names` while any of them is still in the group, and takes the group once none is. */
|
|
117
|
+
const dropping = (names: string[]) => (members: readonly GroupMember[]): GroupFallback | undefined => {
|
|
118
|
+
const hit = members.filter((m) => names.includes(m.component)).map((m) => m.component);
|
|
119
|
+
return hit.length === 0 ? undefined : { kind: "lock", reason: "holds no lock", drop: hit.map((component) => ({ component, reason: `${component} holds no lock` })) };
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
test("dropping one of three leaves the other two grouped; core asks again with the two, and the report names the one", async () => {
|
|
123
|
+
const components = [grouped("a"), grouped("b", ["a"], { upstream: so("a", "id") }), grouped("c", ["b"], { upstream: so("b", "id") })];
|
|
124
|
+
const r = registry(dropping(["c"]));
|
|
125
|
+
const { found, grouped: plan } = await groupsOf(components, ["a"], r.registry);
|
|
126
|
+
expect(r.asked.map((ms) => ms.map((m) => m.component))).toEqual([
|
|
127
|
+
["a", "b", "c"],
|
|
128
|
+
["a", "b"],
|
|
129
|
+
]);
|
|
130
|
+
expect(found.groups).toEqual([{ capability: "fake-group", components: ["a", "b"] }]);
|
|
131
|
+
expect(found.fallbacks).toEqual([{ component: "c", capability: "fake-group", kind: "lock", reason: "c holds no lock" }]);
|
|
132
|
+
expect(plan.fallbacks).toEqual(found.fallbacks);
|
|
133
|
+
// c keeps its wave after the group; b's emptied wave stays so wave numbers keep their meaning (ws-107).
|
|
134
|
+
expect(plan.waves).toEqual([["a", "b"], [], ["c"]]);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
test("a dropped member on a dependency path between the rest splits them, each as split", async () => {
|
|
138
|
+
// c reads a and b; b reads a. Without b, a and c still read each other, but b applies between them.
|
|
139
|
+
const components = [grouped("a"), grouped("b", ["a"], { upstream: so("a", "id") }), grouped("c", ["a", "b"], { first: so("a", "id"), second: so("b", "id") })];
|
|
140
|
+
const r = registry(dropping(["b"]));
|
|
141
|
+
const { found } = await groupsOf(components, ["a"], r.registry);
|
|
142
|
+
expect(r.asked).toHaveLength(1);
|
|
143
|
+
expect(found.groups).toEqual([]);
|
|
144
|
+
expect(found.fallbacks.map((f) => [f.component, f.kind])).toEqual([
|
|
145
|
+
["a", "split"],
|
|
146
|
+
["b", "lock"],
|
|
147
|
+
["c", "split"],
|
|
148
|
+
]);
|
|
149
|
+
expect(found.fallbacks[0]!.reason).toMatch(/^b lies on a dependency path between a/);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
test("a drop that leaves one member is no group, and that member falls back as alone", async () => {
|
|
153
|
+
const components = [grouped("a"), grouped("b", ["a"], { upstream: so("a", "id") })];
|
|
154
|
+
const r = registry(dropping(["a"]));
|
|
155
|
+
const { found, grouped: plan, plan: derived } = await groupsOf(components, ["a"], r.registry);
|
|
156
|
+
expect(r.asked).toHaveLength(1);
|
|
157
|
+
expect(found.groups).toEqual([]);
|
|
158
|
+
expect(found.fallbacks).toEqual([
|
|
159
|
+
{ component: "a", capability: "fake-group", kind: "lock", reason: "a holds no lock" },
|
|
160
|
+
{ component: "b", capability: "fake-group", kind: "alone", reason: "b is the only member of its group left once a fell back, and a group of one is no group" },
|
|
161
|
+
]);
|
|
162
|
+
expect(plan.waves).toEqual(derived.waves);
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
test("a drop that names no member of the group dissolves it with the fallback's kind", async () => {
|
|
166
|
+
const r = registry(() => ({ kind: "lock", reason: "holds no lock", drop: [{ component: "elsewhere" }] }));
|
|
167
|
+
const components = [grouped("a"), grouped("b", ["a"], { upstream: so("a", "id") })];
|
|
168
|
+
const { found } = await groupsOf(components, ["a"], r.registry);
|
|
169
|
+
expect(found.groups).toEqual([]);
|
|
170
|
+
expect(found.fallbacks.map((f) => [f.component, f.kind, f.reason])).toEqual([
|
|
171
|
+
["a", "lock", "holds no lock"],
|
|
172
|
+
["b", "lock", "holds no lock"],
|
|
173
|
+
]);
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
describe("where a group sits (ws-107)", () => {
|
|
178
|
+
test("in the earliest wave any member is in; the waves it left stay, empty, and the digest is the derivation's", async () => {
|
|
179
|
+
const components = [grouped("a"), grouped("b", ["a"], { upstream: so("a", "id") }), grouped("c", ["b"], { upstream: so("b", "id") })];
|
|
180
|
+
const { plan, grouped: g } = await groupsOf(components, ["a"]);
|
|
181
|
+
expect(plan.waves).toEqual([["a"], ["b"], ["c"]]);
|
|
182
|
+
expect(g.waves).toEqual([["a", "b", "c"], [], []]);
|
|
183
|
+
expect(g.order).toEqual(["a", "b", "c"]);
|
|
184
|
+
expect(g.digest).toBe(plan.digest);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
test("after everything its members depend on outside it; what depends on a member moves after the group", async () => {
|
|
188
|
+
// b reads a and depends on u too; z depends on a.
|
|
189
|
+
const components = [plain("u"), grouped("a"), grouped("b", ["a", "u"], { upstream: so("a", "id") }), plain("z", ["a"])];
|
|
190
|
+
const { plan, grouped: g } = await groupsOf(components, ["a", "u"]);
|
|
191
|
+
expect(plan.waves).toEqual([["a", "u"], ["b", "z"]]);
|
|
192
|
+
expect(g.groups).toEqual([{ capability: "fake-group", components: ["a", "b"] }]);
|
|
193
|
+
expect(g.waves).toEqual([["u"], ["a", "b"], ["z"]]);
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
test("a round's narrowing keeps what is left of a group as one; a wave gate's wave carries the group (ws-107)", async () => {
|
|
197
|
+
const components = [plain("x"), grouped("a", ["x"], { upstream: so("x", "id") }), grouped("b", ["a"], { upstream: so("a", "id") })];
|
|
198
|
+
const { grouped: g } = await groupsOf(components, ["x"]);
|
|
199
|
+
expect(g.waves).toEqual([["x"], ["a", "b"], []]);
|
|
200
|
+
const left = narrowGroups({ ...g, order: ["a", "b"], waves: [["a"], ["b"]], groups: undefined }, components, g.groups);
|
|
201
|
+
expect(left.groups).toEqual(g.groups);
|
|
202
|
+
expect(left.waves).toEqual([["a", "b"], []]);
|
|
203
|
+
const wave = prWavePlan(g, components, 2, ["x"]);
|
|
204
|
+
expect(wave).toMatchObject({ order: ["a", "b"], waves: [["a", "b"]], groups: g.groups, seeds: ["x"], digest: g.digest });
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
describe("reads a capability reports through groupReads (#4447)", () => {
|
|
209
|
+
/** A registry whose `fake-group` reports `reads` and records what it was asked. */
|
|
210
|
+
function reporting(reads: ReportedGroupRead[]) {
|
|
211
|
+
const asked: Array<{ components: string[]; members: string[] }> = [];
|
|
212
|
+
const r = new CapabilityRegistry();
|
|
213
|
+
const unused = async (): Promise<never> => {
|
|
214
|
+
throw new Error("not called here");
|
|
215
|
+
};
|
|
216
|
+
r.register({
|
|
217
|
+
kind: "fake-group",
|
|
218
|
+
run: unused,
|
|
219
|
+
plan: unused,
|
|
220
|
+
runGroup: unused,
|
|
221
|
+
async planGroup(_ctx: unknown, members: readonly GroupMember[]) {
|
|
222
|
+
// a knows nothing at plan; b's outputs are all known.
|
|
223
|
+
const plans = Object.fromEntries(
|
|
224
|
+
members.map((m) => [m.component, { member: m.component, planDigest: `d-${m.component}`, outputs: m.component === "a" ? { known: {}, unknown: ["id"] } : { known: { arn: "x" }, unknown: [] } }]),
|
|
225
|
+
);
|
|
226
|
+
return { members: plans, digest: "g" };
|
|
227
|
+
},
|
|
228
|
+
async groupReads(ctx: { components: string[] }, members: readonly GroupMember[]) {
|
|
229
|
+
asked.push({ components: [...ctx.components], members: members.map((m) => m.component) });
|
|
230
|
+
return reads;
|
|
231
|
+
},
|
|
232
|
+
} as never);
|
|
233
|
+
r.register({ kind: "fake-plain", run: unused, plan: unused } as never);
|
|
234
|
+
return { registry: r, asked };
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
test("a reported read joins two components with no stackOutput read, upstream first, and is kept as the group's reads", async () => {
|
|
238
|
+
// a reads b only in a file core cannot see, and declares no dependsOn.
|
|
239
|
+
const components = [grouped("a"), grouped("b")];
|
|
240
|
+
const r = reporting([
|
|
241
|
+
{ reader: "a", upstream: "b", ref: "data.remote.b" },
|
|
242
|
+
{ reader: "a", upstream: "a", ref: "self" },
|
|
243
|
+
{ reader: "a", upstream: "elsewhere", ref: "not.a.component" },
|
|
244
|
+
]);
|
|
245
|
+
const { found } = await groupsOf(components, ["a", "b"], r.registry);
|
|
246
|
+
expect(r.asked).toHaveLength(1);
|
|
247
|
+
expect([...r.asked[0]!.members].sort()).toEqual(["a", "b"]);
|
|
248
|
+
expect(found).toEqual({
|
|
249
|
+
groups: [{ capability: "fake-group", components: ["b", "a"], reads: [{ reader: "a", upstream: "b", ref: "data.remote.b" }] }],
|
|
250
|
+
fallbacks: [],
|
|
251
|
+
});
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
test("a reported read the upstream's plan does not know is one of the reader's group reads in its change-set part", async () => {
|
|
255
|
+
const components = [grouped("a"), grouped("b")];
|
|
256
|
+
const r = reporting([{ reader: "b", upstream: "a", ref: "data.remote.a" }]);
|
|
257
|
+
const planned = await planComponentGroup({
|
|
258
|
+
group: { capability: "fake-group", components: ["a", "b"], reads: [{ reader: "b", upstream: "a", ref: "data.remote.a" }] },
|
|
259
|
+
components: new Map(components.map((c) => [c.name, c])),
|
|
260
|
+
registry: r.registry,
|
|
261
|
+
env: "prod",
|
|
262
|
+
ctxOf: (component) => ({ env: "prod", component }),
|
|
263
|
+
outputs: {},
|
|
264
|
+
});
|
|
265
|
+
const reads = Object.fromEntries(planned.plans.map((p) => [p.component, "error" in p ? p.error : p.parts?.[0]?.member.group?.reads]));
|
|
266
|
+
expect(reads).toEqual({ a: [], b: ["data.remote.a"] });
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
test("a reported read on a dependency path through a component of another kind splits the group (ruling 2)", async () => {
|
|
270
|
+
// b reads a in a file; m, of another kind, depends on a and b depends on m.
|
|
271
|
+
const components = [grouped("a"), plain("m", ["a"]), grouped("b", ["m"])];
|
|
272
|
+
const r = reporting([{ reader: "b", upstream: "a", ref: "data.remote.a" }]);
|
|
273
|
+
const { found } = await groupsOf(components, ["a"], r.registry);
|
|
274
|
+
expect(found.groups).toEqual([]);
|
|
275
|
+
expect(found.fallbacks.map((f) => [f.component, f.kind])).toEqual([
|
|
276
|
+
["a", "split"],
|
|
277
|
+
["b", "split"],
|
|
278
|
+
]);
|
|
279
|
+
expect(found.fallbacks[0]!.reason).toMatch(/^m lies on a dependency path between a/);
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
test("a capability whose groupReads throws reports no reads", async () => {
|
|
283
|
+
const r = new CapabilityRegistry();
|
|
284
|
+
const unused = async (): Promise<never> => {
|
|
285
|
+
throw new Error("not called here");
|
|
286
|
+
};
|
|
287
|
+
r.register({ kind: "fake-group", run: unused, plan: unused, planGroup: unused, runGroup: unused, groupReads: unused } as never);
|
|
288
|
+
const { found } = await groupsOf([grouped("a"), grouped("b")], ["a", "b"], r);
|
|
289
|
+
expect(found).toEqual({ groups: [], fallbacks: [] });
|
|
290
|
+
});
|
|
291
|
+
|
|
292
|
+
test("narrowing a group keeps only the reported reads between members left", async () => {
|
|
293
|
+
const components = [grouped("a"), grouped("b"), grouped("c")];
|
|
294
|
+
const r = reporting([
|
|
295
|
+
{ reader: "b", upstream: "a", ref: "data.remote.a" },
|
|
296
|
+
{ reader: "c", upstream: "b", ref: "data.remote.b" },
|
|
297
|
+
]);
|
|
298
|
+
const { grouped: g } = await groupsOf(components, ["a", "b", "c"], r.registry);
|
|
299
|
+
expect(g.groups).toEqual([{ capability: "fake-group", components: ["a", "b", "c"], reads: [
|
|
300
|
+
{ reader: "b", upstream: "a", ref: "data.remote.a" },
|
|
301
|
+
{ reader: "c", upstream: "b", ref: "data.remote.b" },
|
|
302
|
+
] }]);
|
|
303
|
+
const left = narrowGroups({ ...g, order: ["b", "c"], waves: [["b", "c"]], groups: undefined }, components, g.groups);
|
|
304
|
+
expect(left.groups).toEqual([{ capability: "fake-group", components: ["b", "c"], reads: [{ reader: "c", upstream: "b", ref: "data.remote.b" }] }]);
|
|
305
|
+
});
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
describe("core stays lexicon-free here (ws-107)", () => {
|
|
309
|
+
const read = (file: string) => readFileSync(join(import.meta.dirname, file), "utf-8");
|
|
310
|
+
const imports = (source: string) => [...source.matchAll(/^import[^;]*?from\s+"([^"]+)"/gms)].map((m) => m[1]!);
|
|
311
|
+
|
|
312
|
+
test("the group modules import no lexicon, and groups.ts names none", () => {
|
|
313
|
+
for (const file of ["groups.ts", "capability.ts", "pr-run.ts", "fan-out-run.ts", "fan-out.ts"]) {
|
|
314
|
+
const from = imports(read(file));
|
|
315
|
+
expect(from.length, file).toBeGreaterThan(0);
|
|
316
|
+
expect(from.filter((m) => /lexicon|^@intentius\/chant-lexicon|lexicons\//.test(m)), file).toEqual([]);
|
|
317
|
+
}
|
|
318
|
+
expect(read("groups.ts")).not.toMatch(/terraform|tofu|choudoufu|cloudformation|\bcfn\b|kubernetes|\baws\b|\bazure\b|\bgcp\b/i);
|
|
319
|
+
});
|
|
320
|
+
});
|