@intentius/chant 0.124.32 → 0.124.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ci-jobs.d.ts +4 -0
- package/dist/ci-jobs.d.ts.map +1 -1
- package/dist/ci-jobs.js +9 -2
- package/dist/cli/handlers/build.d.ts.map +1 -1
- package/dist/cli/handlers/build.js +18 -3
- package/dist/cli/handlers/lifecycle-health.d.ts +16 -0
- package/dist/cli/handlers/lifecycle-health.d.ts.map +1 -0
- package/dist/cli/handlers/lifecycle-health.js +150 -0
- package/dist/cli/handlers/lifecycle.d.ts +26 -0
- package/dist/cli/handlers/lifecycle.d.ts.map +1 -1
- package/dist/cli/handlers/lifecycle.js +1 -1
- package/dist/cli/handlers/pr.d.ts +2 -0
- package/dist/cli/handlers/pr.d.ts.map +1 -1
- package/dist/cli/handlers/pr.js +124 -2
- package/dist/cli/handlers/promote.d.ts.map +1 -1
- package/dist/cli/handlers/promote.js +16 -1
- package/dist/cli/handlers/release.d.ts +16 -1
- package/dist/cli/handlers/release.d.ts.map +1 -1
- package/dist/cli/handlers/release.js +83 -11
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +81 -21
- package/dist/cli/parse-args.d.ts.map +1 -1
- package/dist/cli/parse-args.js +23 -1
- package/dist/cli/registry.d.ts +18 -4
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/components/deploy-inputs.d.ts +91 -0
- package/dist/components/deploy-inputs.d.ts.map +1 -0
- package/dist/components/deploy-inputs.js +184 -0
- package/dist/components/driver.d.ts.map +1 -1
- package/dist/components/driver.js +9 -0
- package/dist/components/gate-plan.d.ts +8 -0
- package/dist/components/gate-plan.d.ts.map +1 -1
- package/dist/components/gate-plan.js +6 -0
- package/dist/components/pr-pipeline.d.ts +33 -10
- package/dist/components/pr-pipeline.d.ts.map +1 -1
- package/dist/components/pr-pipeline.js +42 -11
- package/dist/components/pr-run.d.ts +1 -1
- package/dist/components/pr-run.d.ts.map +1 -1
- package/dist/components/release-compile.d.ts +37 -2
- package/dist/components/release-compile.d.ts.map +1 -1
- package/dist/components/release-compile.js +64 -8
- package/dist/components/release-promote.d.ts +17 -3
- package/dist/components/release-promote.d.ts.map +1 -1
- package/dist/components/release-promote.js +79 -18
- package/dist/components/verbs/bom-writer.d.ts +1 -1
- package/dist/components/verbs/bom-writer.d.ts.map +1 -1
- package/dist/components/verbs/lockfile-sbom-generator.d.ts +20 -0
- package/dist/components/verbs/lockfile-sbom-generator.d.ts.map +1 -1
- package/dist/components/verbs/lockfile-sbom-generator.js +41 -4
- package/dist/components/wave-plan.d.ts +10 -0
- package/dist/components/wave-plan.d.ts.map +1 -1
- package/dist/components/wave-plan.js +32 -4
- package/dist/graph-detail.d.ts.map +1 -1
- package/dist/graph-detail.js +32 -7
- package/dist/health.d.ts +110 -0
- package/dist/health.d.ts.map +1 -0
- package/dist/health.js +105 -0
- package/dist/health.schema.json +191 -0
- package/dist/lexicon.d.ts +27 -0
- package/dist/lexicon.d.ts.map +1 -1
- package/dist/lifecycle/merge-record.d.ts +104 -0
- package/dist/lifecycle/merge-record.d.ts.map +1 -0
- package/dist/lifecycle/merge-record.js +102 -0
- package/dist/lifecycle/publish-attachments.d.ts +8 -5
- package/dist/lifecycle/publish-attachments.d.ts.map +1 -1
- package/dist/lifecycle/publish-attachments.js +27 -13
- package/dist/lifecycle/publish-npm.d.ts +3 -2
- package/dist/lifecycle/publish-npm.d.ts.map +1 -1
- package/dist/lifecycle/publish-npm.js +4 -3
- package/dist/lifecycle/release-at.d.ts +40 -0
- package/dist/lifecycle/release-at.d.ts.map +1 -0
- package/dist/lifecycle/release-at.js +83 -0
- package/dist/lifecycle/release-cut.d.ts.map +1 -1
- package/dist/lifecycle/release-cut.js +23 -12
- package/dist/lifecycle/release-publish.d.ts +28 -12
- package/dist/lifecycle/release-publish.d.ts.map +1 -1
- package/dist/lifecycle/release-publish.js +29 -17
- package/dist/lifecycle/release-store.d.ts +25 -2
- package/dist/lifecycle/release-store.d.ts.map +1 -1
- package/dist/lifecycle/release-store.js +40 -13
- package/dist/lifecycle/run-ledger.d.ts.map +1 -1
- package/dist/lifecycle/run-ledger.js +1 -0
- package/dist/lint/rules/op/index.d.ts +2 -1
- package/dist/lint/rules/op/index.d.ts.map +1 -1
- package/dist/lint/rules/op/index.js +4 -2
- package/dist/lint/rules/op/ops018-shell-image-digest.d.ts +10 -0
- package/dist/lint/rules/op/ops018-shell-image-digest.d.ts.map +1 -0
- package/dist/lint/rules/op/ops018-shell-image-digest.js +38 -0
- package/dist/op/activities/activity-contracts.d.ts +5 -0
- package/dist/op/activities/activity-contracts.d.ts.map +1 -1
- package/dist/op/activities/activity-contracts.js +3 -0
- package/dist/op/activities/shell.d.ts +38 -0
- package/dist/op/activities/shell.d.ts.map +1 -1
- package/dist/op/activities/shell.js +89 -3
- package/dist/op/builders.d.ts +7 -0
- package/dist/op/builders.d.ts.map +1 -1
- package/dist/op/builders.js +7 -0
- package/dist/op/runtime.d.ts +2 -0
- package/dist/op/runtime.d.ts.map +1 -1
- package/dist/pr-loop.d.ts +14 -3
- package/dist/pr-loop.d.ts.map +1 -1
- package/dist/pr-loop.js +15 -5
- package/dist/pr-report-url.d.ts +2 -2
- package/dist/pr-report-url.d.ts.map +1 -1
- package/dist/runner-start.d.ts +179 -0
- package/dist/runner-start.d.ts.map +1 -0
- package/dist/runner-start.js +277 -0
- package/dist/wave-runtime.mjs +235 -228
- package/dist/workspace/check.schema.json +70 -2
- package/dist/workspace/checks/security.d.ts +35 -0
- package/dist/workspace/checks/security.d.ts.map +1 -0
- package/dist/workspace/checks/security.js +305 -0
- package/dist/workspace/checks.d.ts +2 -0
- package/dist/workspace/checks.d.ts.map +1 -1
- package/dist/workspace/checks.js +5 -0
- package/dist/workspace/ci-builds.d.ts +163 -0
- package/dist/workspace/ci-builds.d.ts.map +1 -0
- package/dist/workspace/ci-builds.js +315 -0
- package/dist/workspace/ci-green-cli.d.ts +2 -1
- package/dist/workspace/ci-green-cli.d.ts.map +1 -1
- package/dist/workspace/ci-green-cli.js +25 -5
- package/dist/workspace/ci-green-forge.d.ts +12 -0
- package/dist/workspace/ci-green-forge.d.ts.map +1 -1
- package/dist/workspace/ci-green-forge.js +12 -0
- package/dist/workspace/ci-green-workflow.d.ts +55 -1
- package/dist/workspace/ci-green-workflow.d.ts.map +1 -1
- package/dist/workspace/ci-green-workflow.js +128 -1
- package/dist/workspace/ci-green.d.ts +89 -4
- package/dist/workspace/ci-green.d.ts.map +1 -1
- package/dist/workspace/ci-green.js +310 -23
- package/dist/workspace/ci-last-green.schema.json +49 -0
- package/dist/workspace/ci-list.schema.json +35 -1
- package/dist/workspace/ci-run-index.d.ts +1 -1
- package/dist/workspace/ci-run-index.d.ts.map +1 -1
- package/dist/workspace/ci-run-index.schema.json +1 -1
- package/dist/workspace/ci-run.d.ts +12 -6
- package/dist/workspace/ci-run.d.ts.map +1 -1
- package/dist/workspace/ci-run.js +72 -16
- package/dist/workspace/ci-runner-start.d.ts +77 -0
- package/dist/workspace/ci-runner-start.d.ts.map +1 -0
- package/dist/workspace/ci-runner-start.js +185 -0
- package/dist/workspace/ci-serve.d.ts +76 -7
- package/dist/workspace/ci-serve.d.ts.map +1 -1
- package/dist/workspace/ci-serve.js +153 -19
- package/dist/workspace/declaration.d.ts +17 -0
- package/dist/workspace/declaration.d.ts.map +1 -1
- package/dist/workspace/declaration.js +3 -0
- package/dist/workspace/declaration.schema.json +23 -0
- package/dist/workspace/ls.d.ts +2 -0
- package/dist/workspace/ls.d.ts.map +1 -1
- package/dist/workspace/ls.js +1 -1
- package/dist/workspace/ls.schema.json +2 -1
- package/dist/workspace/member-pipeline.d.ts +1 -0
- package/dist/workspace/member-pipeline.d.ts.map +1 -1
- package/dist/workspace/member-pipeline.js +2 -0
- package/dist/workspace/merge-record.schema.json +49 -0
- package/dist/workspace/pr-report.schema.json +3 -3
- package/dist/workspace/reason-codes.d.ts +17 -0
- package/dist/workspace/reason-codes.d.ts.map +1 -1
- package/dist/workspace/reason-codes.js +18 -0
- package/dist/workspace/release-candidates.d.ts +129 -0
- package/dist/workspace/release-candidates.d.ts.map +1 -0
- package/dist/workspace/release-candidates.js +233 -0
- package/dist/workspace/release-candidates.schema.json +353 -0
- package/dist/workspace/security.d.ts +40 -0
- package/dist/workspace/security.d.ts.map +1 -0
- package/dist/workspace/security.js +99 -0
- package/package.json +8 -1
- package/src/__fixtures__/pr-loop/pr-plan.note.golden.md +1 -1
- package/src/ci-jobs.ts +11 -2
- package/src/cli/handlers/build.test.ts +36 -0
- package/src/cli/handlers/build.ts +18 -3
- package/src/cli/handlers/lifecycle-health.test.ts +123 -0
- package/src/cli/handlers/lifecycle-health.ts +157 -0
- package/src/cli/handlers/lifecycle.ts +1 -1
- package/src/cli/handlers/pr-deploy-inputs.test.ts +209 -0
- package/src/cli/handlers/pr-record.test.ts +201 -0
- package/src/cli/handlers/pr.test.ts +22 -0
- package/src/cli/handlers/pr.ts +127 -4
- package/src/cli/handlers/promote.test.ts +17 -0
- package/src/cli/handlers/promote.ts +16 -1
- package/src/cli/handlers/release-cut-at.e2e.test.ts +115 -0
- package/src/cli/handlers/release-publish-targets.e2e.test.ts +2 -2
- package/src/cli/handlers/release-verify.e2e.test.ts +12 -10
- package/src/cli/handlers/release.e2e.test.ts +19 -28
- package/src/cli/handlers/release.ts +81 -11
- package/src/cli/main.ts +81 -21
- package/src/cli/parse-args.ts +17 -1
- package/src/cli/registry.ts +18 -4
- package/src/components/deploy-inputs.test.ts +108 -0
- package/src/components/deploy-inputs.ts +225 -0
- package/src/components/driver.ts +11 -0
- package/src/components/gate-plan.ts +9 -0
- package/src/components/pr-pipeline.ts +56 -15
- package/src/components/pr-run.ts +1 -1
- package/src/components/release-compile.test.ts +34 -0
- package/src/components/release-compile.ts +89 -8
- package/src/components/release-promote.test.ts +55 -2
- package/src/components/release-promote.ts +93 -23
- package/src/components/verbs/bom-writer.ts +1 -1
- package/src/components/verbs/lockfile-sbom-generator.test.ts +36 -0
- package/src/components/verbs/lockfile-sbom-generator.ts +43 -5
- package/src/components/wave-plan.ts +32 -4
- package/src/graph-detail.test.ts +57 -0
- package/src/graph-detail.ts +33 -7
- package/src/health.schema.json +191 -0
- package/src/health.test.ts +62 -0
- package/src/health.ts +178 -0
- package/src/lexicon.ts +41 -1
- package/src/lifecycle/merge-record.test.ts +111 -0
- package/src/lifecycle/merge-record.ts +154 -0
- package/src/lifecycle/publish-attachments.ts +25 -13
- package/src/lifecycle/publish-npm.ts +4 -3
- package/src/lifecycle/publish-targets.test.ts +34 -4
- package/src/lifecycle/release-at.test.ts +48 -0
- package/src/lifecycle/release-at.ts +100 -0
- package/src/lifecycle/release-cut.test.ts +41 -0
- package/src/lifecycle/release-cut.ts +22 -11
- package/src/lifecycle/release-publish.test.ts +43 -13
- package/src/lifecycle/release-publish.ts +38 -18
- package/src/lifecycle/release-store.ts +57 -13
- package/src/lifecycle/run-ledger.test.ts +13 -0
- package/src/lifecycle/run-ledger.ts +1 -0
- package/src/lint/rules/op/index.ts +4 -2
- package/src/lint/rules/op/ops018-shell-image-digest.test.ts +60 -0
- package/src/lint/rules/op/ops018-shell-image-digest.ts +48 -0
- package/src/op/activities/activity-contracts.ts +3 -0
- package/src/op/activities/shell-container.e2e.test.ts +67 -0
- package/src/op/activities/shell.test.ts +44 -1
- package/src/op/activities/shell.ts +110 -3
- package/src/op/builders.ts +7 -0
- package/src/op/runtime.ts +2 -0
- package/src/op/step-console.test.ts +4 -2
- package/src/pr-loop.test.ts +29 -0
- package/src/pr-loop.ts +26 -7
- package/src/pr-report-url.ts +2 -2
- package/src/runner-start-bundle.test.ts +29 -0
- package/src/runner-start.test.ts +179 -0
- package/src/runner-start.ts +329 -0
- package/src/workspace/check-contract.test.ts +3 -2
- package/src/workspace/check.schema.json +70 -2
- package/src/workspace/checks/security.test.ts +138 -0
- package/src/workspace/checks/security.ts +305 -0
- package/src/workspace/checks.ts +5 -0
- package/src/workspace/ci-builds.e2e.test.ts +208 -0
- package/src/workspace/ci-builds.test.ts +174 -0
- package/src/workspace/ci-builds.ts +385 -0
- package/src/workspace/ci-green-builds.test.ts +180 -0
- package/src/workspace/ci-green-cli.test.ts +54 -0
- package/src/workspace/ci-green-cli.ts +26 -5
- package/src/workspace/ci-green-forge.ts +24 -0
- package/src/workspace/ci-green-workflow.test.ts +84 -1
- package/src/workspace/ci-green-workflow.ts +139 -2
- package/src/workspace/ci-green.test.ts +5 -2
- package/src/workspace/ci-green.ts +359 -27
- package/src/workspace/ci-last-green.schema.json +49 -0
- package/src/workspace/ci-list.schema.json +35 -1
- package/src/workspace/ci-run-index.schema.json +1 -1
- package/src/workspace/ci-run-index.ts +1 -1
- package/src/workspace/ci-run.test.ts +24 -7
- package/src/workspace/ci-run.ts +78 -16
- package/src/workspace/ci-runner-start.test.ts +151 -0
- package/src/workspace/ci-runner-start.ts +193 -0
- package/src/workspace/ci-serve-builds.test.ts +86 -0
- package/src/workspace/ci-serve.test.ts +59 -0
- package/src/workspace/ci-serve.ts +177 -22
- package/src/workspace/declaration.schema.json +23 -0
- package/src/workspace/declaration.test.ts +17 -0
- package/src/workspace/declaration.ts +22 -1
- package/src/workspace/ls.schema.json +2 -1
- package/src/workspace/ls.ts +3 -2
- package/src/workspace/member-pipeline.ts +2 -1
- package/src/workspace/merge-record.schema.json +49 -0
- package/src/workspace/pr-report.schema.json +3 -3
- package/src/workspace/reason-codes.test.ts +2 -0
- package/src/workspace/reason-codes.ts +18 -0
- package/src/workspace/release-candidates.schema.json +353 -0
- package/src/workspace/release-candidates.test.ts +106 -0
- package/src/workspace/release-candidates.ts +315 -0
- package/src/workspace/security.test.ts +70 -0
- package/src/workspace/security.ts +118 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The local files a component's steps deploy from, and their content digests
|
|
3
|
+
* (#4155).
|
|
4
|
+
*
|
|
5
|
+
* A component gate approves `componentPlanDigest` (./gate-plan.ts). A step
|
|
6
|
+
* whose capability has a `plan` is bound by what it plans. Every other step
|
|
7
|
+
* was bound only by its input as written, so a Helm chart, a kustomize
|
|
8
|
+
* directory or a static site's tree could change after review without moving
|
|
9
|
+
* the digest. This module names those files and hashes them, so the digest
|
|
10
|
+
* moves when they do.
|
|
11
|
+
*
|
|
12
|
+
* Which fields name a path is data, as the template fields are in
|
|
13
|
+
* ./release-compile.ts and the unit fields in ./deploy-units.ts: a kind's
|
|
14
|
+
* fields in {@link DEPLOY_INPUT_FIELDS}, plus `template`, `manifest` and
|
|
15
|
+
* `values` on any step ({@link TEMPLATE_FIELDS}). Only a literal path counts:
|
|
16
|
+
* a value wired from another step (`@Build.uri`) or an `archive:` path is a
|
|
17
|
+
* build output, and binding it would make an approval unusable by a build
|
|
18
|
+
* that is not reproducible. The build steps' own sources are bound instead.
|
|
19
|
+
*
|
|
20
|
+
* - A file is hashed by its bytes.
|
|
21
|
+
* - A directory is hashed over the files under it that git does not ignore
|
|
22
|
+
* (`git ls-files --cached --others --exclude-standard`), each by its path
|
|
23
|
+
* and bytes, so `node_modules` and a build's `dist` inside a Docker context
|
|
24
|
+
* are left out. Outside a git repository every file is hashed except under
|
|
25
|
+
* `.git` and `node_modules`.
|
|
26
|
+
* - A directory git ignores as a whole is a build output. It is not hashed;
|
|
27
|
+
* the step is listed as unbound, with that reason.
|
|
28
|
+
* - A path that does not exist is left out. One that appears later moves the
|
|
29
|
+
* digest.
|
|
30
|
+
*
|
|
31
|
+
* A step whose kind runs content chant can't name, such as `shell`, is listed
|
|
32
|
+
* as unbound ({@link UNBOUND_KINDS}), so the plan note can show a reviewer
|
|
33
|
+
* what the approval does not cover.
|
|
34
|
+
*/
|
|
35
|
+
import type { DriverPhase, DriverStep } from "./driver.js";
|
|
36
|
+
/** The fields that name every step's deployed file, whatever its kind (as ./release-compile.ts reads them). */
|
|
37
|
+
export declare const TEMPLATE_FIELDS: readonly string[];
|
|
38
|
+
/** Per kind, the fields beyond {@link TEMPLATE_FIELDS} that name a local file or directory the step deploys or builds from. */
|
|
39
|
+
export declare const DEPLOY_INPUT_FIELDS: Readonly<Record<string, readonly string[]>>;
|
|
40
|
+
/** Kinds that deploy content chant can't name from their input: a command, an agent's work. */
|
|
41
|
+
export declare const UNBOUND_KINDS: readonly string[];
|
|
42
|
+
/** One path a step names. */
|
|
43
|
+
export interface DeployInputRef {
|
|
44
|
+
phase: string;
|
|
45
|
+
kind: string;
|
|
46
|
+
field: string;
|
|
47
|
+
/** Relative to the member's directory, as written. */
|
|
48
|
+
path: string;
|
|
49
|
+
}
|
|
50
|
+
/** A named path and the digest of what is there. */
|
|
51
|
+
export interface DeployInputDigest {
|
|
52
|
+
path: string;
|
|
53
|
+
/** `sha256:<hex>` of a file's bytes, or a plan digest over a directory's files. */
|
|
54
|
+
digest: string;
|
|
55
|
+
}
|
|
56
|
+
/** A step the digest does not cover, and why. */
|
|
57
|
+
export interface UnboundStep {
|
|
58
|
+
phase: string;
|
|
59
|
+
kind: string;
|
|
60
|
+
reason: string;
|
|
61
|
+
}
|
|
62
|
+
/** What a component's steps deploy from: the digests, and the steps they can't cover. */
|
|
63
|
+
export interface ComponentDeployInputs {
|
|
64
|
+
inputs: DeployInputDigest[];
|
|
65
|
+
unbound: UnboundStep[];
|
|
66
|
+
}
|
|
67
|
+
/** Every capability step of a composition with its phase, nested phases included, gates left out. */
|
|
68
|
+
export declare function stepsWithPhase(phases: readonly DriverPhase[]): Array<{
|
|
69
|
+
phase: string;
|
|
70
|
+
step: DriverStep;
|
|
71
|
+
}>;
|
|
72
|
+
/** The literal paths one step names, in field order. A Docker build's Dockerfile is named under its context. */
|
|
73
|
+
export declare function stepInputRefs(phase: string, step: DriverStep): DeployInputRef[];
|
|
74
|
+
/** The files under `dir` (relative to `root`) a directory digest covers, relative to `root`, sorted. */
|
|
75
|
+
export declare function directoryFiles(root: string, dir: string): string[];
|
|
76
|
+
/** Every file under `dir`, relative to `root`, sorted, leaving out `.git` and `node_modules`. What a cut records of a directory git ignores. */
|
|
77
|
+
export declare function walkFiles(root: string, dir: string): string[];
|
|
78
|
+
/** Whether git ignores `path` (relative to `root`). False outside a git repository. */
|
|
79
|
+
export declare function ignoredByGit(root: string, path: string): boolean;
|
|
80
|
+
/** `sha256:<hex>` of a file's bytes. */
|
|
81
|
+
export declare function fileDigest(file: string): string;
|
|
82
|
+
/** The digest of the files under `dir`: a plan digest over each file's path (from `dir`) and bytes. */
|
|
83
|
+
export declare function directoryDigest(root: string, dir: string): string;
|
|
84
|
+
/**
|
|
85
|
+
* What a component's steps deploy from, read under `root` (the member's
|
|
86
|
+
* directory). `include` picks the steps to read, all of them by default; the
|
|
87
|
+
* wave planner passes the steps without a `plan`, which their plan does not
|
|
88
|
+
* already cover.
|
|
89
|
+
*/
|
|
90
|
+
export declare function componentDeployInputs(phases: readonly DriverPhase[], root: string, include?: (step: DriverStep) => boolean): ComponentDeployInputs;
|
|
91
|
+
//# sourceMappingURL=deploy-inputs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deploy-inputs.d.ts","sourceRoot":"","sources":["../../src/components/deploy-inputs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAOH,OAAO,KAAK,EAAc,WAAW,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEpE,+GAA+G;AAC/G,eAAO,MAAM,eAAe,EAAE,SAAS,MAAM,EAAuC,CAAC;AAErF,+HAA+H;AAC/H,eAAO,MAAM,mBAAmB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAa3E,CAAC;AAEF,+FAA+F;AAC/F,eAAO,MAAM,aAAa,EAAE,SAAS,MAAM,EAA2B,CAAC;AAEvE,6BAA6B;AAC7B,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,oDAAoD;AACpD,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,mFAAmF;IACnF,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,iDAAiD;AACjD,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,yFAAyF;AACzF,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAC5B,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB;AAaD,qGAAqG;AACrG,wBAAgB,cAAc,CAAC,MAAM,EAAE,SAAS,WAAW,EAAE,GAAG,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC,CAUzG;AAED,gHAAgH;AAChH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,cAAc,EAAE,CAY/E;AAOD,wGAAwG;AACxG,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAWlE;AAED,gJAAgJ;AAChJ,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAY7D;AAED,uFAAuF;AACvF,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAEhE;AAED,wCAAwC;AACxC,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED,uGAAuG;AACvG,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAOjE;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,SAAS,WAAW,EAAE,EAC9B,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,CAAC,IAAI,EAAE,UAAU,KAAK,OAAoB,GAClD,qBAAqB,CA4BvB"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The local files a component's steps deploy from, and their content digests
|
|
3
|
+
* (#4155).
|
|
4
|
+
*
|
|
5
|
+
* A component gate approves `componentPlanDigest` (./gate-plan.ts). A step
|
|
6
|
+
* whose capability has a `plan` is bound by what it plans. Every other step
|
|
7
|
+
* was bound only by its input as written, so a Helm chart, a kustomize
|
|
8
|
+
* directory or a static site's tree could change after review without moving
|
|
9
|
+
* the digest. This module names those files and hashes them, so the digest
|
|
10
|
+
* moves when they do.
|
|
11
|
+
*
|
|
12
|
+
* Which fields name a path is data, as the template fields are in
|
|
13
|
+
* ./release-compile.ts and the unit fields in ./deploy-units.ts: a kind's
|
|
14
|
+
* fields in {@link DEPLOY_INPUT_FIELDS}, plus `template`, `manifest` and
|
|
15
|
+
* `values` on any step ({@link TEMPLATE_FIELDS}). Only a literal path counts:
|
|
16
|
+
* a value wired from another step (`@Build.uri`) or an `archive:` path is a
|
|
17
|
+
* build output, and binding it would make an approval unusable by a build
|
|
18
|
+
* that is not reproducible. The build steps' own sources are bound instead.
|
|
19
|
+
*
|
|
20
|
+
* - A file is hashed by its bytes.
|
|
21
|
+
* - A directory is hashed over the files under it that git does not ignore
|
|
22
|
+
* (`git ls-files --cached --others --exclude-standard`), each by its path
|
|
23
|
+
* and bytes, so `node_modules` and a build's `dist` inside a Docker context
|
|
24
|
+
* are left out. Outside a git repository every file is hashed except under
|
|
25
|
+
* `.git` and `node_modules`.
|
|
26
|
+
* - A directory git ignores as a whole is a build output. It is not hashed;
|
|
27
|
+
* the step is listed as unbound, with that reason.
|
|
28
|
+
* - A path that does not exist is left out. One that appears later moves the
|
|
29
|
+
* digest.
|
|
30
|
+
*
|
|
31
|
+
* A step whose kind runs content chant can't name, such as `shell`, is listed
|
|
32
|
+
* as unbound ({@link UNBOUND_KINDS}), so the plan note can show a reviewer
|
|
33
|
+
* what the approval does not cover.
|
|
34
|
+
*/
|
|
35
|
+
import { spawnSync } from "node:child_process";
|
|
36
|
+
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
37
|
+
import { join, relative, resolve, sep } from "node:path";
|
|
38
|
+
import { sha256Hex } from "../content-digest.js";
|
|
39
|
+
import { computePlanDigest } from "../lifecycle/plan-digest.js";
|
|
40
|
+
/** The fields that name every step's deployed file, whatever its kind (as ./release-compile.ts reads them). */
|
|
41
|
+
export const TEMPLATE_FIELDS = ["template", "manifest", "values"];
|
|
42
|
+
/** Per kind, the fields beyond {@link TEMPLATE_FIELDS} that name a local file or directory the step deploys or builds from. */
|
|
43
|
+
export const DEPLOY_INPUT_FIELDS = {
|
|
44
|
+
"helm-upgrade": ["chart"],
|
|
45
|
+
"kustomize-apply": ["dir"],
|
|
46
|
+
"fly-release": ["plan"],
|
|
47
|
+
"fly-rollback": ["plan"],
|
|
48
|
+
"s3-sync": ["from"],
|
|
49
|
+
"r2-sync": ["from"],
|
|
50
|
+
"copy-to-host": ["from"],
|
|
51
|
+
"wrangler-deploy": ["config"],
|
|
52
|
+
"wrangler-versions-promote": ["config"],
|
|
53
|
+
"docker-build": ["context"],
|
|
54
|
+
"zip-package": ["source"],
|
|
55
|
+
"jvm-build": ["path"],
|
|
56
|
+
};
|
|
57
|
+
/** Kinds that deploy content chant can't name from their input: a command, an agent's work. */
|
|
58
|
+
export const UNBOUND_KINDS = ["shell", "run-agent"];
|
|
59
|
+
function isGate(step) {
|
|
60
|
+
return step.kind === "gate";
|
|
61
|
+
}
|
|
62
|
+
function isPhase(step) {
|
|
63
|
+
return typeof step.phase === "string" && Array.isArray(step.steps);
|
|
64
|
+
}
|
|
65
|
+
const isLiteralPath = (v) => typeof v === "string" && v !== "" && !v.startsWith("@") && !v.startsWith("$") && !v.startsWith("archive:");
|
|
66
|
+
/** Every capability step of a composition with its phase, nested phases included, gates left out. */
|
|
67
|
+
export function stepsWithPhase(phases) {
|
|
68
|
+
const out = [];
|
|
69
|
+
const walk = (phase) => {
|
|
70
|
+
for (const step of phase.steps) {
|
|
71
|
+
if (isPhase(step))
|
|
72
|
+
walk(step);
|
|
73
|
+
else if (!isGate(step))
|
|
74
|
+
out.push({ phase: phase.phase, step });
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
phases.forEach(walk);
|
|
78
|
+
return out;
|
|
79
|
+
}
|
|
80
|
+
/** The literal paths one step names, in field order. A Docker build's Dockerfile is named under its context. */
|
|
81
|
+
export function stepInputRefs(phase, step) {
|
|
82
|
+
const out = [];
|
|
83
|
+
for (const field of [...TEMPLATE_FIELDS, ...(DEPLOY_INPUT_FIELDS[step.kind] ?? [])]) {
|
|
84
|
+
const raw = step[field];
|
|
85
|
+
for (const value of Array.isArray(raw) ? raw : [raw]) {
|
|
86
|
+
if (isLiteralPath(value))
|
|
87
|
+
out.push({ phase, kind: step.kind, field, path: value });
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (step.kind === "docker-build" && isLiteralPath(step.context) && isLiteralPath(step.dockerfile)) {
|
|
91
|
+
out.push({ phase, kind: step.kind, field: "dockerfile", path: join(step.context, step.dockerfile) });
|
|
92
|
+
}
|
|
93
|
+
return out;
|
|
94
|
+
}
|
|
95
|
+
function git(root, args) {
|
|
96
|
+
const r = spawnSync("git", ["-C", root, ...args], { encoding: "utf-8", maxBuffer: 256 * 1024 * 1024 });
|
|
97
|
+
return { ok: r.status === 0, out: r.stdout ?? "" };
|
|
98
|
+
}
|
|
99
|
+
/** The files under `dir` (relative to `root`) a directory digest covers, relative to `root`, sorted. */
|
|
100
|
+
export function directoryFiles(root, dir) {
|
|
101
|
+
const listed = git(root, ["ls-files", "-z", "--cached", "--others", "--exclude-standard", "--", dir]);
|
|
102
|
+
if (listed.ok) {
|
|
103
|
+
return [...new Set(listed.out.split("\0").filter((p) => p !== ""))]
|
|
104
|
+
.filter((p) => {
|
|
105
|
+
const full = resolve(root, p);
|
|
106
|
+
return existsSync(full) && statSync(full).isFile();
|
|
107
|
+
})
|
|
108
|
+
.sort();
|
|
109
|
+
}
|
|
110
|
+
return walkFiles(root, dir);
|
|
111
|
+
}
|
|
112
|
+
/** Every file under `dir`, relative to `root`, sorted, leaving out `.git` and `node_modules`. What a cut records of a directory git ignores. */
|
|
113
|
+
export function walkFiles(root, dir) {
|
|
114
|
+
const out = [];
|
|
115
|
+
const walk = (abs) => {
|
|
116
|
+
for (const entry of readdirSync(abs, { withFileTypes: true })) {
|
|
117
|
+
if (entry.name === ".git" || entry.name === "node_modules")
|
|
118
|
+
continue;
|
|
119
|
+
const full = join(abs, entry.name);
|
|
120
|
+
if (entry.isDirectory())
|
|
121
|
+
walk(full);
|
|
122
|
+
else if (entry.isFile())
|
|
123
|
+
out.push(relative(root, full).split(sep).join("/"));
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
walk(resolve(root, dir));
|
|
127
|
+
return out.sort();
|
|
128
|
+
}
|
|
129
|
+
/** Whether git ignores `path` (relative to `root`). False outside a git repository. */
|
|
130
|
+
export function ignoredByGit(root, path) {
|
|
131
|
+
return git(root, ["check-ignore", "-q", "--", path]).ok;
|
|
132
|
+
}
|
|
133
|
+
/** `sha256:<hex>` of a file's bytes. */
|
|
134
|
+
export function fileDigest(file) {
|
|
135
|
+
return `sha256:${sha256Hex(readFileSync(file))}`;
|
|
136
|
+
}
|
|
137
|
+
/** The digest of the files under `dir`: a plan digest over each file's path (from `dir`) and bytes. */
|
|
138
|
+
export function directoryDigest(root, dir) {
|
|
139
|
+
const base = resolve(root, dir);
|
|
140
|
+
const files = directoryFiles(root, dir).map((p) => ({
|
|
141
|
+
path: relative(base, resolve(root, p)).split(sep).join("/"),
|
|
142
|
+
digest: fileDigest(resolve(root, p)),
|
|
143
|
+
}));
|
|
144
|
+
return computePlanDigest("directory", files);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* What a component's steps deploy from, read under `root` (the member's
|
|
148
|
+
* directory). `include` picks the steps to read, all of them by default; the
|
|
149
|
+
* wave planner passes the steps without a `plan`, which their plan does not
|
|
150
|
+
* already cover.
|
|
151
|
+
*/
|
|
152
|
+
export function componentDeployInputs(phases, root, include = () => true) {
|
|
153
|
+
const inputs = new Map();
|
|
154
|
+
const unbound = [];
|
|
155
|
+
for (const { phase, step } of stepsWithPhase(phases)) {
|
|
156
|
+
if (!include(step))
|
|
157
|
+
continue;
|
|
158
|
+
if (UNBOUND_KINDS.includes(step.kind)) {
|
|
159
|
+
unbound.push({ phase, kind: step.kind, reason: `a ${step.kind} step runs content chant can't name from its input` });
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
for (const ref of stepInputRefs(phase, step)) {
|
|
163
|
+
if (inputs.has(ref.path))
|
|
164
|
+
continue;
|
|
165
|
+
const full = resolve(root, ref.path);
|
|
166
|
+
if (!existsSync(full))
|
|
167
|
+
continue;
|
|
168
|
+
if (statSync(full).isDirectory()) {
|
|
169
|
+
if (ignoredByGit(root, ref.path)) {
|
|
170
|
+
unbound.push({ phase, kind: step.kind, reason: `its ${ref.field} "${ref.path}" is a directory git ignores, so a build output; bind its sources through the step that builds it` });
|
|
171
|
+
continue;
|
|
172
|
+
}
|
|
173
|
+
inputs.set(ref.path, directoryDigest(root, ref.path));
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
inputs.set(ref.path, fileDigest(full));
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return {
|
|
181
|
+
inputs: [...inputs].map(([path, digest]) => ({ path, digest })).sort((a, b) => (a.path < b.path ? -1 : a.path > b.path ? 1 : 0)),
|
|
182
|
+
unbound,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../../src/components/driver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AAIH,OAAO,EAAmC,KAAK,kBAAkB,EAAE,KAAK,cAAc,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"driver.d.ts","sourceRoot":"","sources":["../../src/components/driver.ts"],"names":[],"mappings":"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"}
|
|
@@ -51,6 +51,7 @@ import { evaluateGate, gitGateLedgerPort } from "../op/gate.js";
|
|
|
51
51
|
import { gateName } from "../op/gate-name.js";
|
|
52
52
|
import { GateNotRecordableError } from "../lifecycle/no-record.js";
|
|
53
53
|
import { componentPlanDigest } from "./gate-plan.js";
|
|
54
|
+
import { componentDeployInputs } from "./deploy-inputs.js";
|
|
54
55
|
import { isPlanMovedError, PLAN_MOVED_EXIT_CODE } from "./capability.js";
|
|
55
56
|
import { isPromotedArtifact } from "./auto-release.js";
|
|
56
57
|
import { gateEventsOf, joinRunEventSinks, progressSinkOf } from "../run-event-stream.js";
|
|
@@ -570,6 +571,11 @@ async function rollbackExecuted(executed, ctx, registry) {
|
|
|
570
571
|
return records;
|
|
571
572
|
}
|
|
572
573
|
// ── Per-component deploy ─────────────────────────────────────────────────
|
|
574
|
+
/** Whether a component's composition has a gate step anywhere, nested phases and `rollback` included. */
|
|
575
|
+
function hasGateStep(component) {
|
|
576
|
+
const walk = (steps) => steps.some((step) => isGateStep(step) || (Array.isArray(step.steps) && walk(step.steps)));
|
|
577
|
+
return [...component.deploy, ...(component.rollback ?? [])].some((p) => walk(p.steps));
|
|
578
|
+
}
|
|
573
579
|
/**
|
|
574
580
|
* Run one component's `deploy` composition. On terminal failure: unwind every
|
|
575
581
|
* executed step in reverse via its capability's `rollback` (saga
|
|
@@ -610,6 +616,9 @@ export async function runComponentDeploy(component, ctx, registry, componentOutp
|
|
|
610
616
|
component,
|
|
611
617
|
...(ctx.vars ? { vars: ctx.vars } : {}),
|
|
612
618
|
...(release !== undefined ? { release } : {}),
|
|
619
|
+
// #4155: the files the steps deploy from, read where the steps read
|
|
620
|
+
// them. Only a gate reads the digest, so a run with none skips the hashing.
|
|
621
|
+
...(hasGateStep(component) ? { inputs: componentDeployInputs(component.deploy, process.cwd()).inputs } : {}),
|
|
613
622
|
}),
|
|
614
623
|
};
|
|
615
624
|
const records = [];
|
|
@@ -17,6 +17,11 @@
|
|
|
17
17
|
* its publish output against a recorded digest that is not in the
|
|
18
18
|
* composition, so it passes that digest here.
|
|
19
19
|
* - `vars`, the environment config the caller resolved ahead of the run.
|
|
20
|
+
* - The content digests of the local files the steps deploy from (#4155,
|
|
21
|
+
* ./deploy-inputs.ts): a chart, a manifest, a site's tree, a build step's
|
|
22
|
+
* sources. A file changed after review moves the digest. The key is left
|
|
23
|
+
* out when no step names an existing file, so a composition that deploys
|
|
24
|
+
* none keeps the digest it had before #4155.
|
|
20
25
|
*
|
|
21
26
|
* ## What it leaves out
|
|
22
27
|
*
|
|
@@ -26,6 +31,7 @@
|
|
|
26
31
|
* upstream components. The run id and the time are left out for the reasons
|
|
27
32
|
* `../lifecycle/plan-digest.ts` gives.
|
|
28
33
|
*/
|
|
34
|
+
import type { DeployInputDigest } from "./deploy-inputs.js";
|
|
29
35
|
import type { DriverComponent } from "./driver.js";
|
|
30
36
|
/** What a component gate's plan digest is taken over. */
|
|
31
37
|
export interface ComponentGatePlan {
|
|
@@ -34,6 +40,8 @@ export interface ComponentGatePlan {
|
|
|
34
40
|
vars?: Record<string, unknown>;
|
|
35
41
|
/** The recorded digest a promote or rollback deploys, when the caller has one. */
|
|
36
42
|
release?: string;
|
|
43
|
+
/** What the steps deploy from (`componentDeployInputs`), when the caller read it. */
|
|
44
|
+
inputs?: readonly DeployInputDigest[];
|
|
37
45
|
}
|
|
38
46
|
/** The plan digest a component gate records and approves. */
|
|
39
47
|
export declare function componentPlanDigest(plan: ComponentGatePlan): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gate-plan.d.ts","sourceRoot":"","sources":["../../src/components/gate-plan.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"gate-plan.d.ts","sourceRoot":"","sources":["../../src/components/gate-plan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAEhD,yDAAyD;AACzD,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,eAAe,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,kFAAkF;IAClF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qFAAqF;IACrF,MAAM,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;CACvC;AAED,6DAA6D;AAC7D,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CAWnE"}
|
|
@@ -17,6 +17,11 @@
|
|
|
17
17
|
* its publish output against a recorded digest that is not in the
|
|
18
18
|
* composition, so it passes that digest here.
|
|
19
19
|
* - `vars`, the environment config the caller resolved ahead of the run.
|
|
20
|
+
* - The content digests of the local files the steps deploy from (#4155,
|
|
21
|
+
* ./deploy-inputs.ts): a chart, a manifest, a site's tree, a build step's
|
|
22
|
+
* sources. A file changed after review moves the digest. The key is left
|
|
23
|
+
* out when no step names an existing file, so a composition that deploys
|
|
24
|
+
* none keeps the digest it had before #4155.
|
|
20
25
|
*
|
|
21
26
|
* ## What it leaves out
|
|
22
27
|
*
|
|
@@ -37,5 +42,6 @@ export function componentPlanDigest(plan) {
|
|
|
37
42
|
rollback: component.rollback ?? null,
|
|
38
43
|
vars: plan.vars ?? null,
|
|
39
44
|
release: plan.release ?? null,
|
|
45
|
+
...(plan.inputs && plan.inputs.length > 0 ? { inputs: plan.inputs } : {}),
|
|
40
46
|
});
|
|
41
47
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The jobs of a generated pull-request pipeline (#3183): a plan job on every
|
|
3
|
-
* pull request and
|
|
3
|
+
* pull request and, on every push to the target branch, a record job, or an
|
|
4
|
+
* apply job when the pipeline opts into apply on merge (#4168).
|
|
4
5
|
*
|
|
5
6
|
* Each forge's generator (the github, gitlab and forgejo lexicons) adds its
|
|
6
7
|
* own triggers, permissions and artifact handling; the commands and the
|
|
@@ -9,11 +10,19 @@
|
|
|
9
10
|
* - The plan job runs `chant components pr-plan` against the pull request's
|
|
10
11
|
* target commit. It posts the note and the `chant/plan` status and writes
|
|
11
12
|
* nothing to `chant/lifecycle`, since it runs the pull request's code.
|
|
12
|
-
* - The
|
|
13
|
+
* - The record job (#4168 step 1, the default) runs `chant components
|
|
14
|
+
* pr-record` against the commit the push replaced. It plans the same
|
|
15
|
+
* members on the merged commit, stores the change set and writes the merge
|
|
16
|
+
* record, `_merges/<commit>.json` on `chant/lifecycle`. It applies nothing:
|
|
17
|
+
* a release that carries the commit deploys it. It needs write access to
|
|
18
|
+
* `chant/lifecycle`. One record runs at a time per environment.
|
|
19
|
+
* - With `applyOnMerge` the apply job takes the record job's place. It runs
|
|
20
|
+
* `chant components pr-apply` against the commit the
|
|
13
21
|
* push replaced, finds the pull request that merged the pushed commit
|
|
14
22
|
* through the forge, and applies only when an approval stands for the
|
|
15
|
-
* digest it plans. With `requireReview` (
|
|
16
|
-
*
|
|
23
|
+
* digest it plans. With `requireReview` (off by default since #4168, on
|
|
24
|
+
* under the `review-rules` security group) the approver must also have
|
|
25
|
+
* approved the pull request on the forge. It needs write access
|
|
17
26
|
* to `chant/lifecycle`, to record the pending fact when the gate stops it.
|
|
18
27
|
* One apply runs at a time per environment.
|
|
19
28
|
*
|
|
@@ -35,6 +44,7 @@
|
|
|
35
44
|
* it too. With `reportUrl` both pass `--report-url`, which copies the report,
|
|
36
45
|
* the change set and the events where a reader outside CI can fetch them;
|
|
37
46
|
* the job's own environment brings the credentials an `s3://` URL needs.
|
|
47
|
+
* The record job passes the same flags as the apply.
|
|
38
48
|
*
|
|
39
49
|
* With `build` (#4088) both jobs run the project's build and `chant lint`
|
|
40
50
|
* before their command, and fail on an error. A `cfn-deploy` member's plan
|
|
@@ -104,8 +114,16 @@ export interface PrLoopPipelineOptions {
|
|
|
104
114
|
* GitHub and Forgejo; on GitLab, the project's default branch.
|
|
105
115
|
*/
|
|
106
116
|
branch?: string;
|
|
107
|
-
/** Count an approval only from someone who approved the pull request on the forge. Default
|
|
117
|
+
/** Count an approval only from someone who approved the pull request on the forge. Default false (#4168): review rules are opt-in. */
|
|
108
118
|
requireReview?: boolean;
|
|
119
|
+
/** The job on merge (apply, or record since #4168) has `chant ci run` refuse to start without a runner-start statement for it (`--require-runner-start`, #4147), as under the `isolated-runners` security group (#4168). Default false. */
|
|
120
|
+
requireRunnerStart?: boolean;
|
|
121
|
+
/**
|
|
122
|
+
* Apply the approved plan on merge (#4168), as every pull-request pipeline
|
|
123
|
+
* did before #4168: the apply job in place of the record job. Default
|
|
124
|
+
* false, so a merge deploys nothing. `waveGate` needs it.
|
|
125
|
+
*/
|
|
126
|
+
applyOnMerge?: boolean;
|
|
109
127
|
/**
|
|
110
128
|
* Stream each job's run events (#4007): `--events-json` on both commands,
|
|
111
129
|
* and `CHANT_RUN_EVENTS_DIR` set to {@link PR_LOOP_EVENTS_DIR}. Default false.
|
|
@@ -146,8 +164,8 @@ export interface PrLoopPipelineOptions {
|
|
|
146
164
|
}
|
|
147
165
|
/** One job's command and the forge values it reads, as environment variables for its step. */
|
|
148
166
|
export interface PrLoopJob {
|
|
149
|
-
/** `plan` or `
|
|
150
|
-
jobName: "plan" | "apply";
|
|
167
|
+
/** `plan`, `apply` or `record` (#4168). */
|
|
168
|
+
jobName: "plan" | "apply" | "record";
|
|
151
169
|
/** The command line. Reads `$BASE_SHA` and, for the plan, `$PR_NUMBER`. */
|
|
152
170
|
command: string;
|
|
153
171
|
/**
|
|
@@ -178,11 +196,14 @@ export interface PrLoopJob {
|
|
|
178
196
|
/** The lines `build` (#4088) runs before a job's command: the build, then the lint. Empty without the option. */
|
|
179
197
|
export declare function prLoopBuildLines(env: string, options?: PrLoopPipelineOptions): string[];
|
|
180
198
|
/**
|
|
181
|
-
* The
|
|
182
|
-
*
|
|
183
|
-
*
|
|
199
|
+
* The jobs for `forge`: plan, apply and record, in that order. A generator
|
|
200
|
+
* writes the plan and, on merge, {@link prLoopMergeJob}'s choice of the
|
|
201
|
+
* other two. `member` is the workspace member the pipeline is generated for;
|
|
202
|
+
* the commands then run in its directory, so `--output` is relative to it.
|
|
184
203
|
*/
|
|
185
204
|
export declare function prLoopJobs(forge: ForgeKind, env: string, options?: PrLoopPipelineOptions, member?: string): PrLoopJob[];
|
|
205
|
+
/** The job a push to the target branch runs (#4168): `record`, or `apply` when the pipeline opts into apply on merge. */
|
|
206
|
+
export declare function prLoopMergeJob(jobs: readonly PrLoopJob[], options?: PrLoopPipelineOptions): PrLoopJob;
|
|
186
207
|
/**
|
|
187
208
|
* The pull-request options with `--wave-gate` beside `--pr-loop` (#4003):
|
|
188
209
|
* the apply gets a gate per wave. A canary or a fixed base is refused, since
|
|
@@ -211,6 +232,8 @@ export declare function prLoopWaveJobs(components: DriverComponent[], apply: PrL
|
|
|
211
232
|
* apart from a single project's `chant-apply-<env>`.
|
|
212
233
|
*/
|
|
213
234
|
export declare function prApplyGroup(env: string, member?: string): string;
|
|
235
|
+
/** The group that keeps one record job at a time per environment and member (#4168), named as {@link prApplyGroup} names the apply's. */
|
|
236
|
+
export declare function prRecordGroup(env: string, member?: string): string;
|
|
214
237
|
/**
|
|
215
238
|
* The cache key the apply job keeps its attempt record under (#3543), with
|
|
216
239
|
* `commit` the forge's expression for the pushed commit. A push of another
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pr-pipeline.d.ts","sourceRoot":"","sources":["../../src/components/pr-pipeline.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"pr-pipeline.d.ts","sourceRoot":"","sources":["../../src/components/pr-pipeline.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The jobs of a generated pull-request pipeline (#3183): a plan job on every
|
|
3
|
-
* pull request and
|
|
3
|
+
* pull request and, on every push to the target branch, a record job, or an
|
|
4
|
+
* apply job when the pipeline opts into apply on merge (#4168).
|
|
4
5
|
*
|
|
5
6
|
* Each forge's generator (the github, gitlab and forgejo lexicons) adds its
|
|
6
7
|
* own triggers, permissions and artifact handling; the commands and the
|
|
@@ -9,11 +10,19 @@
|
|
|
9
10
|
* - The plan job runs `chant components pr-plan` against the pull request's
|
|
10
11
|
* target commit. It posts the note and the `chant/plan` status and writes
|
|
11
12
|
* nothing to `chant/lifecycle`, since it runs the pull request's code.
|
|
12
|
-
* - The
|
|
13
|
+
* - The record job (#4168 step 1, the default) runs `chant components
|
|
14
|
+
* pr-record` against the commit the push replaced. It plans the same
|
|
15
|
+
* members on the merged commit, stores the change set and writes the merge
|
|
16
|
+
* record, `_merges/<commit>.json` on `chant/lifecycle`. It applies nothing:
|
|
17
|
+
* a release that carries the commit deploys it. It needs write access to
|
|
18
|
+
* `chant/lifecycle`. One record runs at a time per environment.
|
|
19
|
+
* - With `applyOnMerge` the apply job takes the record job's place. It runs
|
|
20
|
+
* `chant components pr-apply` against the commit the
|
|
13
21
|
* push replaced, finds the pull request that merged the pushed commit
|
|
14
22
|
* through the forge, and applies only when an approval stands for the
|
|
15
|
-
* digest it plans. With `requireReview` (
|
|
16
|
-
*
|
|
23
|
+
* digest it plans. With `requireReview` (off by default since #4168, on
|
|
24
|
+
* under the `review-rules` security group) the approver must also have
|
|
25
|
+
* approved the pull request on the forge. It needs write access
|
|
17
26
|
* to `chant/lifecycle`, to record the pending fact when the gate stops it.
|
|
18
27
|
* One apply runs at a time per environment.
|
|
19
28
|
*
|
|
@@ -35,6 +44,7 @@
|
|
|
35
44
|
* it too. With `reportUrl` both pass `--report-url`, which copies the report,
|
|
36
45
|
* the change set and the events where a reader outside CI can fetch them;
|
|
37
46
|
* the job's own environment brings the credentials an `s3://` URL needs.
|
|
47
|
+
* The record job passes the same flags as the apply.
|
|
38
48
|
*
|
|
39
49
|
* With `build` (#4088) both jobs run the project's build and `chant lint`
|
|
40
50
|
* before their command, and fail on an error. A `cfn-deploy` member's plan
|
|
@@ -109,9 +119,10 @@ export function prLoopBuildLines(env, options = {}) {
|
|
|
109
119
|
return [options.buildCommand ?? `chant build --env ${env}`, "chant lint"];
|
|
110
120
|
}
|
|
111
121
|
/**
|
|
112
|
-
* The
|
|
113
|
-
*
|
|
114
|
-
*
|
|
122
|
+
* The jobs for `forge`: plan, apply and record, in that order. A generator
|
|
123
|
+
* writes the plan and, on merge, {@link prLoopMergeJob}'s choice of the
|
|
124
|
+
* other two. `member` is the workspace member the pipeline is generated for;
|
|
125
|
+
* the commands then run in its directory, so `--output` is relative to it.
|
|
115
126
|
*/
|
|
116
127
|
export function prLoopJobs(forge, env, options = {}, member) {
|
|
117
128
|
const gate = options.gate ?? PR_APPLY_GATE;
|
|
@@ -133,9 +144,10 @@ export function prLoopJobs(forge, env, options = {}, member) {
|
|
|
133
144
|
"chant", "ci", "run", job, "--in-place", ...(job === "plan" ? ["--no-push"] : []),
|
|
134
145
|
"--base", '"$BASE_SHA"', ...(job === "plan" ? ["--pr", '"$PR_NUMBER"'] : []),
|
|
135
146
|
"--env", env, "--gate", gate, "--forge", forge,
|
|
136
|
-
...(options.waveGate ? ["--wave-gate", options.waveGate] : []),
|
|
137
|
-
...(job
|
|
138
|
-
...(job === "apply" && options.requireReview ===
|
|
147
|
+
...(job !== "record" && options.waveGate ? ["--wave-gate", options.waveGate] : []),
|
|
148
|
+
...(job !== "plan" && options.branch ? ["--branch", JSON.stringify(options.branch)] : []),
|
|
149
|
+
...(job === "apply" && options.requireReview === true ? ["--require-review"] : []),
|
|
150
|
+
...(job !== "plan" && options.requireRunnerStart === true ? ["--require-runner-start"] : []),
|
|
139
151
|
...(options.events ? ["--events-json"] : []),
|
|
140
152
|
...(options.reportUrl ? ["--report-url", JSON.stringify(options.reportUrl)] : []),
|
|
141
153
|
];
|
|
@@ -157,7 +169,7 @@ export function prLoopJobs(forge, env, options = {}, member) {
|
|
|
157
169
|
jobName: "apply",
|
|
158
170
|
command: [
|
|
159
171
|
"chant", "components", "pr-apply", "--base", '"$BASE_SHA"', ...common,
|
|
160
|
-
...(options.requireReview ===
|
|
172
|
+
...(options.requireReview === true ? ["--require-review"] : []),
|
|
161
173
|
...(options.waveGate ? ["--wave-gate", options.waveGate] : []),
|
|
162
174
|
"--resume", PR_APPLY_RECORD,
|
|
163
175
|
].join(" "),
|
|
@@ -166,8 +178,20 @@ export function prLoopJobs(forge, env, options = {}, member) {
|
|
|
166
178
|
...build,
|
|
167
179
|
run: { command: ciRun("apply").join(" "), env: runEnv(applyEnv) },
|
|
168
180
|
},
|
|
181
|
+
{
|
|
182
|
+
jobName: "record",
|
|
183
|
+
command: ["chant", "components", "pr-record", "--base", '"$BASE_SHA"', ...common].join(" "),
|
|
184
|
+
env: applyEnv,
|
|
185
|
+
setup: [github ? githubBaseFallback(options.branch) : gitlabBaseFallback(options.branch)],
|
|
186
|
+
...build,
|
|
187
|
+
run: { command: ciRun("record").join(" "), env: runEnv(applyEnv) },
|
|
188
|
+
},
|
|
169
189
|
];
|
|
170
190
|
}
|
|
191
|
+
/** The job a push to the target branch runs (#4168): `record`, or `apply` when the pipeline opts into apply on merge. */
|
|
192
|
+
export function prLoopMergeJob(jobs, options = {}) {
|
|
193
|
+
return jobs.find((j) => j.jobName === (options.applyOnMerge ? "apply" : "record"));
|
|
194
|
+
}
|
|
171
195
|
/**
|
|
172
196
|
* The pull-request options with `--wave-gate` beside `--pr-loop` (#4003):
|
|
173
197
|
* the apply gets a gate per wave. A canary or a fixed base is refused, since
|
|
@@ -177,6 +201,9 @@ export function prLoopJobs(forge, env, options = {}, member) {
|
|
|
177
201
|
export function prLoopWithWaves(prLoop, gatedWaves) {
|
|
178
202
|
if (!gatedWaves)
|
|
179
203
|
return prLoop;
|
|
204
|
+
if (!prLoop.applyOnMerge) {
|
|
205
|
+
throw new Error("--wave-gate beside --pr-loop gates the apply on merge, so it needs --apply-on-merge (#4168); without it a merge records the plan and a release deploys it");
|
|
206
|
+
}
|
|
180
207
|
if (gatedWaves.canary?.length)
|
|
181
208
|
throw new Error("a pull-request pipeline's waves are the change's derivation, so it takes no --canary; drop --canary");
|
|
182
209
|
if (gatedWaves.base !== undefined)
|
|
@@ -217,6 +244,10 @@ export function prLoopWaveJobs(components, apply) {
|
|
|
217
244
|
export function prApplyGroup(env, member) {
|
|
218
245
|
return member ? `chant-apply.${member}.${env}` : `chant-apply-${env}`;
|
|
219
246
|
}
|
|
247
|
+
/** The group that keeps one record job at a time per environment and member (#4168), named as {@link prApplyGroup} names the apply's. */
|
|
248
|
+
export function prRecordGroup(env, member) {
|
|
249
|
+
return member ? `chant-record.${member}.${env}` : `chant-record-${env}`;
|
|
250
|
+
}
|
|
220
251
|
/**
|
|
221
252
|
* The cache key the apply job keeps its attempt record under (#3543), with
|
|
222
253
|
* `commit` the forge's expression for the pushed commit. A push of another
|
|
@@ -307,7 +307,7 @@ export declare function prWavePlan(plan: FanOutPlan, components: DriverComponent
|
|
|
307
307
|
*/
|
|
308
308
|
export declare function waveNotCovered(approved: ChangeSetDocument, fresh: ChangeSetDocument, approvedMembers?: readonly PrMember[]): string[];
|
|
309
309
|
export interface PrReportInput {
|
|
310
|
-
stage: "plan" | "apply";
|
|
310
|
+
stage: "plan" | "apply" | "record";
|
|
311
311
|
pr: number | null;
|
|
312
312
|
env: string;
|
|
313
313
|
/** The workspace member whose pipeline runs the stage (#3465). */
|