@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 @@
|
|
|
1
|
+
{"version":3,"file":"ci-builds.d.ts","sourceRoot":"","sources":["../../src/workspace/ci-builds.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which commits get built, and what each one ends with (#4169).
|
|
3
|
+
*
|
|
4
|
+
* A `ci.green` phase declares `build: "every"` (the default) or
|
|
5
|
+
* `build: "newest"`. Under `newest` the phase's workflow keeps one run
|
|
6
|
+
* waiting and drops the rest, so only the newest commit is built when a
|
|
7
|
+
* runner frees. This module does the tick's part of that, given the
|
|
8
|
+
* verdicts {@link planTick} (./ci-green.ts) judged:
|
|
9
|
+
*
|
|
10
|
+
* - Superseded. A commit with no run of a `newest` phase, below a newer
|
|
11
|
+
* commit that has one, is `unbuilt` for that phase, covered by the newer
|
|
12
|
+
* commit. A cancelled run makes any phase `unbuilt` (`phaseVerdictOf`).
|
|
13
|
+
* - Retry. A failed run with one attempt is run again once before the
|
|
14
|
+
* commit counts red: through the forge's re-run (`CiForge.rerun`) for
|
|
15
|
+
* check runs, or a build request for chant runs. A retry that has not
|
|
16
|
+
* started an hour on counts as the failure it was.
|
|
17
|
+
* - Bisect. When the newest built commit of a `newest` phase is red, the
|
|
18
|
+
* unbuilt commits back to the last one the phase passed on are built, one
|
|
19
|
+
* request per tick: the commit halfway when more than four are left, else
|
|
20
|
+
* the one just below the red. The first red commit found is the culprit,
|
|
21
|
+
* and it and every commit after it name it.
|
|
22
|
+
* - Requests. A build is asked for with an annotated tag,
|
|
23
|
+
* `ci/build/<sha>`, whose record names the phases and why. The tick
|
|
24
|
+
* starts a workflow at that tag on GitHub (`CiForge.dispatch`), and `ci
|
|
25
|
+
* serve --build-command` serves it for chant runs. A phase a request
|
|
26
|
+
* waits on is `pending`. A request no runner served in six hours leaves
|
|
27
|
+
* the phase `unbuilt`, and once its phases are decided the tick deletes
|
|
28
|
+
* the tag.
|
|
29
|
+
* - Records. Every first-parent commit the tick judged gets
|
|
30
|
+
* `_ci/<sha>.json` on `chant/lifecycle`, rewritten only when what it says
|
|
31
|
+
* changes: `green`, `red`, `unbuilt` or `pending`, with each required
|
|
32
|
+
* phase's verdict, runs, reason, the commit that covers it and the culprit.
|
|
33
|
+
* A commit that leaves the window still `pending` is rewritten `unbuilt`,
|
|
34
|
+
* for the reason `aged-out`. The `ci/green` and `ci/revoked` tags stay
|
|
35
|
+
* what decides a release; the records say what happened to the rest.
|
|
36
|
+
*/
|
|
37
|
+
import { execFileSync } from "node:child_process";
|
|
38
|
+
import { commitVerdictOf, phaseVerdictOf } from "./ci-green.js";
|
|
39
|
+
export const CI_BUILD_TAG_PREFIX = "ci/build/";
|
|
40
|
+
/** The directory on `chant/lifecycle` holding one record per commit. */
|
|
41
|
+
export const CI_RECORDS_DIR = "_ci";
|
|
42
|
+
const LEDGER_REF = "refs/heads/chant/lifecycle";
|
|
43
|
+
/** How long a build request may wait for a runner before its phases count as unbuilt. */
|
|
44
|
+
export const BUILD_REQUEST_TTL_MS = 6 * 3600000;
|
|
45
|
+
/** How long a retry may take to start before the failure it was counts. */
|
|
46
|
+
export const RETRY_TTL_MS = 3600000;
|
|
47
|
+
/** Above this many unbuilt commits a bisect halves the range; at or below it, it steps back one commit at a time. */
|
|
48
|
+
export const BISECT_HALVE_ABOVE = 4;
|
|
49
|
+
const iso = (d) => d.toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
50
|
+
const phaseOf = (green, name) => green.phases.find((p) => p.name === name);
|
|
51
|
+
const buildOf = (green, name) => phaseOf(green, name).build ?? "every";
|
|
52
|
+
const decided = (v) => v === "pass" || v === "fail";
|
|
53
|
+
const age = (at, now) => now.getTime() - Date.parse(at);
|
|
54
|
+
function setPhase(c, phase, fn) {
|
|
55
|
+
const v = c.verdict;
|
|
56
|
+
if (!v)
|
|
57
|
+
return;
|
|
58
|
+
c.verdict = commitVerdictOf(v.phases.map((p) => (p.phase === phase ? fn(p) : p)));
|
|
59
|
+
}
|
|
60
|
+
const phaseIn = (c, phase) => c.verdict?.phases.find((p) => p.phase === phase);
|
|
61
|
+
/**
|
|
62
|
+
* Apply supersession, retries, requests and bisection to the judged commits,
|
|
63
|
+
* in place, and say what the tick has to ask for. Pure: it reads and writes
|
|
64
|
+
* nothing but its input.
|
|
65
|
+
*/
|
|
66
|
+
export function planBuilds(input) {
|
|
67
|
+
const { green, commits, now } = input;
|
|
68
|
+
const plan = { requests: [], retries: [], resolved: [] };
|
|
69
|
+
const inWindow = new Set(commits.map((c) => c.sha));
|
|
70
|
+
const live = (sha, phase) => {
|
|
71
|
+
const r = input.requests.get(sha);
|
|
72
|
+
return r && r.phases.includes(phase) && age(r.at, now) < BUILD_REQUEST_TTL_MS ? r : undefined;
|
|
73
|
+
};
|
|
74
|
+
// A request waits on a phase with no run yet; one no runner served in time leaves it unbuilt.
|
|
75
|
+
for (const c of commits) {
|
|
76
|
+
const r = input.requests.get(c.sha);
|
|
77
|
+
if (!r || !c.verdict)
|
|
78
|
+
continue;
|
|
79
|
+
for (const name of r.phases) {
|
|
80
|
+
const p = phaseIn(c, name);
|
|
81
|
+
if (!p || p.runs.length > 0)
|
|
82
|
+
continue;
|
|
83
|
+
setPhase(c, name, (q) => (live(c.sha, name) ? { ...q, verdict: "pending", reason: "requested" } : { ...q, verdict: "unbuilt", reason: "request-unserved" }));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// Superseded: newest first, a newest phase with no run below a commit with one.
|
|
87
|
+
for (const name of green.require) {
|
|
88
|
+
if (buildOf(green, name) !== "newest")
|
|
89
|
+
continue;
|
|
90
|
+
let cover;
|
|
91
|
+
for (const c of commits) {
|
|
92
|
+
const p = phaseIn(c, name);
|
|
93
|
+
if (!p)
|
|
94
|
+
continue;
|
|
95
|
+
if (p.runs.length > 0) {
|
|
96
|
+
cover = c.sha;
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
if (cover && p.reason !== "requested" && p.reason !== "request-unserved")
|
|
100
|
+
setPhase(c, name, (q) => ({ ...q, verdict: "unbuilt", reason: "superseded", coveredBy: cover }));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// Retry once: a commit with no tag whose failed run has one attempt.
|
|
104
|
+
if (input.retryVia) {
|
|
105
|
+
for (const c of commits) {
|
|
106
|
+
if (c.before !== "none" || c.verdict?.verdict !== "fail")
|
|
107
|
+
continue;
|
|
108
|
+
const all = input.runs.get(c.sha) ?? [];
|
|
109
|
+
const retried = input.records.get(c.sha)?.retried ?? {};
|
|
110
|
+
for (const p of c.verdict.phases) {
|
|
111
|
+
for (const run of p.runs.filter((r) => r.verdict === "fail")) {
|
|
112
|
+
if (all.filter((r) => r.name === run.name).length > 1)
|
|
113
|
+
continue;
|
|
114
|
+
const asked = retried[run.name];
|
|
115
|
+
if (asked && asked.run === run.id && age(asked.at, now) >= RETRY_TTL_MS)
|
|
116
|
+
continue;
|
|
117
|
+
if (!asked || asked.run !== run.id) {
|
|
118
|
+
const checkRun = all.find((r) => r.name === run.name && r.id === run.id);
|
|
119
|
+
if (input.retryVia === "forge")
|
|
120
|
+
plan.retries.push({ sha: c.sha, run: checkRun });
|
|
121
|
+
else if (!input.requests.has(c.sha) && !plan.requests.some((q) => q.commit === c.sha))
|
|
122
|
+
plan.requests.push(request(green, c.sha, [p.phase], "retry", now));
|
|
123
|
+
}
|
|
124
|
+
setPhase(c, p.phase, (q) => {
|
|
125
|
+
const runs = q.runs.map((r) => (r.name === run.name && r.id === run.id ? { ...r, verdict: "pending" } : r));
|
|
126
|
+
return { ...q, runs, ...phaseVerdictOf(runs, q.unmatched), reason: "retrying" };
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// Culprits for every phase, and a bisect request for a newest one.
|
|
133
|
+
for (const name of green.require) {
|
|
134
|
+
const verdicts = commits.map((c) => phaseIn(c, name));
|
|
135
|
+
const top = verdicts.findIndex((p) => decided(p?.verdict));
|
|
136
|
+
if (top < 0 || verdicts[top].verdict !== "fail")
|
|
137
|
+
continue;
|
|
138
|
+
let oldestRed = top;
|
|
139
|
+
let between = [];
|
|
140
|
+
let passed = -1;
|
|
141
|
+
for (let i = top + 1; i < commits.length; i++) {
|
|
142
|
+
const v = verdicts[i]?.verdict;
|
|
143
|
+
if (v === "fail") {
|
|
144
|
+
oldestRed = i;
|
|
145
|
+
between = [];
|
|
146
|
+
}
|
|
147
|
+
else if (v === "pass") {
|
|
148
|
+
passed = i;
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
else if (v !== undefined)
|
|
152
|
+
between.push(i);
|
|
153
|
+
}
|
|
154
|
+
if (between.length === 0) {
|
|
155
|
+
if (passed < 0)
|
|
156
|
+
continue;
|
|
157
|
+
const culprit = commits[oldestRed].sha;
|
|
158
|
+
for (let i = oldestRed; i >= 0; i--) {
|
|
159
|
+
if (verdicts[i]?.verdict === "pass")
|
|
160
|
+
break;
|
|
161
|
+
if (verdicts[i])
|
|
162
|
+
setPhase(commits[i], name, (q) => ({ ...q, culprit }));
|
|
163
|
+
}
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
if (buildOf(green, name) !== "newest")
|
|
167
|
+
continue;
|
|
168
|
+
if (between.some((i) => live(commits[i].sha, name)))
|
|
169
|
+
continue;
|
|
170
|
+
const pick = between.length > BISECT_HALVE_ABOVE ? between[Math.floor(between.length / 2)] : between[0];
|
|
171
|
+
const sha = commits[pick].sha;
|
|
172
|
+
if (input.requests.has(sha) || plan.requests.some((q) => q.commit === sha))
|
|
173
|
+
continue;
|
|
174
|
+
plan.requests.push(request(green, sha, [name], "bisect", now));
|
|
175
|
+
setPhase(commits[pick], name, (q) => ({ ...q, verdict: "pending", reason: "requested", coveredBy: undefined }));
|
|
176
|
+
}
|
|
177
|
+
// A request is done once its phases are decided, it has waited too long, or its commit left the window.
|
|
178
|
+
for (const [sha, r] of input.requests) {
|
|
179
|
+
const c = commits.find((x) => x.sha === sha);
|
|
180
|
+
const done = !inWindow.has(sha) || age(r.at, now) >= BUILD_REQUEST_TTL_MS || (c !== undefined && (c.before === "revoked" || r.phases.every((name) => decided(phaseIn(c, name)?.verdict))));
|
|
181
|
+
if (done)
|
|
182
|
+
plan.resolved.push(r.tag);
|
|
183
|
+
}
|
|
184
|
+
return plan;
|
|
185
|
+
}
|
|
186
|
+
function request(green, commit, phases, reason, now) {
|
|
187
|
+
return { schema: 1, tag: `${CI_BUILD_TAG_PREFIX}${commit}`, commit, branch: green.branch, phases, reason, at: iso(now) };
|
|
188
|
+
}
|
|
189
|
+
// ── Records ──────────────────────────────────────────────────────────────────
|
|
190
|
+
const recordRun = (r) => ({ name: r.name, id: r.opRun ? null : r.id, conclusion: r.conclusion, url: r.url });
|
|
191
|
+
/** The record a judged commit gets, carrying the retries asked for before and now. */
|
|
192
|
+
export function recordOf(input) {
|
|
193
|
+
const { green, commit: c, previous, now } = input;
|
|
194
|
+
const retried = { ...(previous?.retried ?? {}) };
|
|
195
|
+
for (const r of input.retries)
|
|
196
|
+
if (r.sha === c.sha)
|
|
197
|
+
retried[r.run.name] = { run: r.run.id, at: iso(now) };
|
|
198
|
+
const req = input.requests.get(c.sha);
|
|
199
|
+
const extras = {
|
|
200
|
+
...(Object.keys(retried).length > 0 ? { retried } : {}),
|
|
201
|
+
...(req ? { request: { tag: req.tag, reason: req.reason, phases: req.phases, at: req.at } } : {}),
|
|
202
|
+
};
|
|
203
|
+
if (c.before === "revoked" || !c.verdict) {
|
|
204
|
+
return { schema: 1, commit: c.sha, branch: green.branch, state: "red", at: iso(now), revoked: true, phases: previous?.phases ?? {}, ...(previous?.failure ? { failure: previous.failure } : {}), ...extras };
|
|
205
|
+
}
|
|
206
|
+
const v = c.verdict;
|
|
207
|
+
// A pass whose tag an ignored tag blocks (#4031) is not green until a person clears the name.
|
|
208
|
+
const state = c.before === "green" ? (v.verdict === "fail" ? "red" : "green") : v.verdict === "pass" ? (c.made ? "green" : "pending") : v.verdict === "fail" ? "red" : v.verdict;
|
|
209
|
+
const phases = {};
|
|
210
|
+
for (const p of v.phases) {
|
|
211
|
+
phases[p.phase] = {
|
|
212
|
+
verdict: p.verdict,
|
|
213
|
+
build: buildOf(green, p.phase),
|
|
214
|
+
runs: p.runs.map(recordRun),
|
|
215
|
+
...(p.reason ? { reason: p.reason } : {}),
|
|
216
|
+
...(p.coveredBy ? { coveredBy: p.coveredBy } : {}),
|
|
217
|
+
...(p.culprit ? { culprit: p.culprit } : {}),
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
return {
|
|
221
|
+
schema: 1,
|
|
222
|
+
commit: c.sha,
|
|
223
|
+
branch: green.branch,
|
|
224
|
+
state,
|
|
225
|
+
at: iso(now),
|
|
226
|
+
phases,
|
|
227
|
+
...(v.failure ? { failure: { phase: v.failure.phase, run: recordRun(v.failure.run) } } : {}),
|
|
228
|
+
...extras,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
/** The record a commit that left the window still pending gets: each pending phase `unbuilt`, `aged-out`. */
|
|
232
|
+
export function agedOut(record, now) {
|
|
233
|
+
const phases = Object.fromEntries(Object.entries(record.phases).map(([k, p]) => [k, p.verdict === "pending" ? { ...p, verdict: "unbuilt", reason: "aged-out" } : p]));
|
|
234
|
+
const { request: _request, ...rest } = record;
|
|
235
|
+
return { ...rest, state: "unbuilt", at: iso(now), phases };
|
|
236
|
+
}
|
|
237
|
+
/** Whether two records say the same thing, the time each was written aside. */
|
|
238
|
+
export function sameRecord(a, b) {
|
|
239
|
+
if (!a)
|
|
240
|
+
return false;
|
|
241
|
+
const { at: _a, ...x } = a;
|
|
242
|
+
const { at: _b, ...y } = b;
|
|
243
|
+
return JSON.stringify(x) === JSON.stringify(y);
|
|
244
|
+
}
|
|
245
|
+
export const recordPath = (sha) => `${CI_RECORDS_DIR}/${sha}.json`;
|
|
246
|
+
function tryGit(top, args) {
|
|
247
|
+
try {
|
|
248
|
+
return execFileSync("git", args, { cwd: top, encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"], maxBuffer: 256 * 1024 * 1024 }).trimEnd();
|
|
249
|
+
}
|
|
250
|
+
catch {
|
|
251
|
+
return null;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
function parseRecord(text) {
|
|
255
|
+
if (!text)
|
|
256
|
+
return undefined;
|
|
257
|
+
try {
|
|
258
|
+
const r = JSON.parse(text);
|
|
259
|
+
return r && r.schema === 1 && typeof r.commit === "string" && typeof r.state === "string" ? r : undefined;
|
|
260
|
+
}
|
|
261
|
+
catch {
|
|
262
|
+
return undefined;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
/** One commit's record, from the local `chant/lifecycle`. */
|
|
266
|
+
export function readCiRecord(top, sha) {
|
|
267
|
+
return parseRecord(tryGit(top, ["show", `${LEDGER_REF}:${recordPath(sha)}`]));
|
|
268
|
+
}
|
|
269
|
+
/** Every record on the local `chant/lifecycle`, by commit. Empty when the branch or the directory is missing. */
|
|
270
|
+
export function readCiRecords(top) {
|
|
271
|
+
const out = new Map();
|
|
272
|
+
const names = tryGit(top, ["ls-tree", "--name-only", `${LEDGER_REF}:${CI_RECORDS_DIR}`]);
|
|
273
|
+
if (!names)
|
|
274
|
+
return out;
|
|
275
|
+
for (const name of names.split("\n")) {
|
|
276
|
+
const m = /^([0-9a-f]{40,64})\.json$/.exec(name);
|
|
277
|
+
if (!m)
|
|
278
|
+
continue;
|
|
279
|
+
const r = readCiRecord(top, m[1]);
|
|
280
|
+
if (r)
|
|
281
|
+
out.set(m[1], r);
|
|
282
|
+
}
|
|
283
|
+
return out;
|
|
284
|
+
}
|
|
285
|
+
// ── Requests ─────────────────────────────────────────────────────────────────
|
|
286
|
+
/** Every `ci/build/<sha>` tag with a record this reads, from local refs, by commit. */
|
|
287
|
+
export function readBuildRequests(top) {
|
|
288
|
+
const out = new Map();
|
|
289
|
+
const raw = tryGit(top, ["for-each-ref", "--format=%(refname:lstrip=2)%00%(objecttype)%00%(contents)%01", `refs/tags/${CI_BUILD_TAG_PREFIX}`]);
|
|
290
|
+
if (!raw)
|
|
291
|
+
return out;
|
|
292
|
+
for (const entry of raw.split("\u0001")) {
|
|
293
|
+
const [tag, type, contents] = entry.replace(/^\n/, "").split("\u0000");
|
|
294
|
+
if (!tag || type !== "tag" || !contents?.includes("{"))
|
|
295
|
+
continue;
|
|
296
|
+
try {
|
|
297
|
+
const r = JSON.parse(contents.slice(contents.indexOf("{")));
|
|
298
|
+
const sha = tag.slice(CI_BUILD_TAG_PREFIX.length);
|
|
299
|
+
if (r.schema === 1 && r.commit === sha && Array.isArray(r.phases) && typeof r.at === "string")
|
|
300
|
+
out.set(sha, { ...r, tag });
|
|
301
|
+
}
|
|
302
|
+
catch {
|
|
303
|
+
// A tag whose record does not parse asks for nothing.
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
return out;
|
|
307
|
+
}
|
|
308
|
+
/** The annotation of a request tag: a subject line, then the record. */
|
|
309
|
+
export function buildRequestAnnotation(r) {
|
|
310
|
+
return `ci: build ${r.phases.join(", ")} at this commit (${r.reason})\n\n${JSON.stringify(r, null, 2)}\n`;
|
|
311
|
+
}
|
|
312
|
+
/** A request for `ci run --at <sha>`: every required phase, asked for by a person. */
|
|
313
|
+
export function requestedBuild(green, commit, phases, now) {
|
|
314
|
+
return request(green, commit, [...phases], "requested", now);
|
|
315
|
+
}
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
* tag the commits that turned green, revoke the ones that turned red
|
|
9
9
|
* ci workflow [--workflow <name>]... [--output <file>] [--chant <command>] [--install <command>]
|
|
10
10
|
* [--token-secret <NAME> | --app-id-var <VAR> --app-key-secret <NAME>] [--runner-key-secret <NAME>]
|
|
11
|
-
* write the root CI file that runs the tick
|
|
11
|
+
* write the root CI file that runs the tick, and the triggers and
|
|
12
|
+
* concurrency of the workflows holding a phase that sets build (#4169)
|
|
12
13
|
*
|
|
13
14
|
* The tick signs its tags with a runner key (#4031) from `--key <file>` or
|
|
14
15
|
* the PEM in `CHANT_RUNNER_KEY`, which the generated workflow sets from the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ci-green-cli.d.ts","sourceRoot":"","sources":["../../src/workspace/ci-green-cli.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"ci-green-cli.d.ts","sourceRoot":"","sources":["../../src/workspace/ci-green-cli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEtD,OAAO,EAAmE,cAAc,EAAE,MAAM,YAAY,CAAC;AAW7G,OAAO,EAAE,cAAc,EAAE,CAAC;AAe1B,wBAAsB,cAAc,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAiBzE;AAED,wBAAsB,SAAS,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAsBpE;AAID,wBAAsB,SAAS,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAoBpE;AAeD,wBAAsB,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA+DxE"}
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
* tag the commits that turned green, revoke the ones that turned red
|
|
9
9
|
* ci workflow [--workflow <name>]... [--output <file>] [--chant <command>] [--install <command>]
|
|
10
10
|
* [--token-secret <NAME> | --app-id-var <VAR> --app-key-secret <NAME>] [--runner-key-secret <NAME>]
|
|
11
|
-
* write the root CI file that runs the tick
|
|
11
|
+
* write the root CI file that runs the tick, and the triggers and
|
|
12
|
+
* concurrency of the workflows holding a phase that sets build (#4169)
|
|
12
13
|
*
|
|
13
14
|
* The tick signs its tags with a runner key (#4031) from `--key <file>` or
|
|
14
15
|
* the PEM in `CHANT_RUNNER_KEY`, which the generated workflow sets from the
|
|
@@ -28,7 +29,7 @@ import { formatError } from "../cli/format.js";
|
|
|
28
29
|
import { findWorkspaceRoot } from "../project-root.js";
|
|
29
30
|
import { ciList, ciTick, CiGreenError, formatList, formatTick, lastGreen, RUNNER_KEY_ENV } from "./ci-green.js";
|
|
30
31
|
import { ciForgeFromEnv } from "./ci-green-forge.js";
|
|
31
|
-
import { ACTIONS_NAME, CI_GREEN_WORKFLOW_FILE, ciGreenHeader, readWorkflowSources, renderCiGreenWorkflow, workflowsHolding, writeWorkflowFile } from "./ci-green-workflow.js";
|
|
32
|
+
import { ACTIONS_NAME, buildTriggerEdits, CI_GREEN_WORKFLOW_FILE, ciGreenHeader, readWorkflowSources, renderCiGreenWorkflow, workflowsHolding, writeWorkflowFile } from "./ci-green-workflow.js";
|
|
32
33
|
import { readDeclaration, readerVersion, WorkspaceReadError } from "./declaration.js";
|
|
33
34
|
import { recordGeneratedFiles, resolveMemberContext, shellArg } from "./member-pipeline.js";
|
|
34
35
|
import { gitTop, workingTree } from "./tree.js";
|
|
@@ -99,6 +100,13 @@ export async function runCiTick(ctx) {
|
|
|
99
100
|
// The forge is made only when the source is check runs, so a tick from chant runs needs no forge token.
|
|
100
101
|
const forge = () => ciForgeFromEnv(ctx.args.forge ?? "github");
|
|
101
102
|
const runnerKey = ctx.args.key !== undefined ? readFileSync(resolve(ctx.args.key), "utf-8") : process.env[RUNNER_KEY_ENV] || undefined;
|
|
103
|
+
// #4168: under who-ran-it every tag the tick makes is signed, so a tick without a key makes none.
|
|
104
|
+
if (runnerKey === undefined && ctx.args.dryRun !== true) {
|
|
105
|
+
const { securityGroupsAt } = await import("./security.js");
|
|
106
|
+
if (securityGroupsAt(process.cwd()).has("who-ran-it")) {
|
|
107
|
+
throw new Error(`the workspace opts into who-ran-it, so the tick signs every tag it makes and needs a runner key; pass --key <runner key.pem> or set ${RUNNER_KEY_ENV}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
102
110
|
const result = await ciTick({ cwd: process.cwd(), forge, dryRun: ctx.args.dryRun === true, ...(source ? { source } : {}), ...(runnerKey !== undefined ? { runnerKey } : {}) });
|
|
103
111
|
console.log(formatTick(result, ctx.args.dryRun === true));
|
|
104
112
|
return 0;
|
|
@@ -142,7 +150,10 @@ export async function runCiWorkflow(ctx) {
|
|
|
142
150
|
const member = resolveMemberContext(cwd, found);
|
|
143
151
|
const target = ctx.args.output ? resolve(realpathSync(cwd), ctx.args.output) : join(repoRoot, CI_GREEN_WORKFLOW_FILE);
|
|
144
152
|
const fromRepo = relative(repoRoot, target).split(sep).join("/");
|
|
145
|
-
const
|
|
153
|
+
const sources = readWorkflowSources(repoRoot, fromRepo);
|
|
154
|
+
const scan = workflowsHolding(green, sources);
|
|
155
|
+
// #4169: the triggers and concurrency of the workflows holding a phase that sets build. Refused before anything is written.
|
|
156
|
+
const edits = buildTriggerEdits(green, sources);
|
|
146
157
|
const extra = ctx.args.ciWorkflows ?? [];
|
|
147
158
|
const workflows = [...new Set([...scan.workflows, ...extra])].sort();
|
|
148
159
|
for (const f of scan.unreadable)
|
|
@@ -167,8 +178,9 @@ export async function runCiWorkflow(ctx) {
|
|
|
167
178
|
const runnerKeySecret = ctx.args.ciRunnerKeySecret;
|
|
168
179
|
if (runnerKeySecret)
|
|
169
180
|
parts.push("--runner-key-secret", runnerKeySecret);
|
|
170
|
-
|
|
171
|
-
|
|
181
|
+
const { securityGroupsAt } = await import("./security.js");
|
|
182
|
+
if ((green.signedSince || securityGroupsAt(root).has("who-ran-it")) && !runnerKeySecret) {
|
|
183
|
+
console.error(`warning: ci.green.signedSince is set or the workspace opts into who-ran-it, so the tick needs a runner key; pass --runner-key-secret <NAME> naming the repository secret that holds it, or every tick will fail`);
|
|
172
184
|
}
|
|
173
185
|
const command = parts.map(shellArg).join(" ");
|
|
174
186
|
const workspaceRoot = relative(repoRoot, root).split(sep).join("/") || ".";
|
|
@@ -179,6 +191,14 @@ export async function runCiWorkflow(ctx) {
|
|
|
179
191
|
if (member)
|
|
180
192
|
recordGeneratedFiles(member.memberRoot, [{ path: fromRepo, command }]);
|
|
181
193
|
console.log(`Wrote ${written}: ticks when ${workflows.join(", ")} complete${workflows.length === 1 ? "s" : ""} on ${green.branch}, and every 15 minutes.`);
|
|
194
|
+
for (const e of edits) {
|
|
195
|
+
if (!e.changed)
|
|
196
|
+
continue;
|
|
197
|
+
const path = writeWorkflowFile(join(repoRoot, e.path), e.text);
|
|
198
|
+
console.log(e.build === "newest"
|
|
199
|
+
? `Wrote ${path}'s triggers and concurrency: ${e.phases.join(", ")} build${e.phases.length === 1 ? "s" : ""} the newest commit on ${green.branch} when a run ends, and a ci/build/<sha> tag by hand.`
|
|
200
|
+
: `Wrote ${path}'s concurrency: ${e.phases.join(", ")} build${e.phases.length === 1 ? "s" : ""} every commit on ${green.branch}, none cancelled.`);
|
|
201
|
+
}
|
|
182
202
|
return 0;
|
|
183
203
|
}
|
|
184
204
|
catch (err) {
|
|
@@ -51,6 +51,18 @@ export interface CiForge {
|
|
|
51
51
|
kind: ForgeKind;
|
|
52
52
|
/** Every check run on `sha`, every attempt. */
|
|
53
53
|
checkRuns(sha: string): Promise<CheckRun[]>;
|
|
54
|
+
/**
|
|
55
|
+
* Run a failed check run's job again (#4169), so a flake costs one more
|
|
56
|
+
* run before the commit counts red. Absent on a forge chant can't ask.
|
|
57
|
+
*/
|
|
58
|
+
rerun?(run: CheckRun): Promise<void>;
|
|
59
|
+
/**
|
|
60
|
+
* Start a workflow at a ref (#4169), for a build the tick asks for: a
|
|
61
|
+
* bisect step, or `chant ci run --at`. `workflow` is the file's name in
|
|
62
|
+
* `.github/workflows/`, and `ref` a branch or tag. Absent on a forge chant
|
|
63
|
+
* can't ask.
|
|
64
|
+
*/
|
|
65
|
+
dispatch?(workflow: string, ref: string): Promise<void>;
|
|
54
66
|
}
|
|
55
67
|
export interface GithubCiForgeOptions {
|
|
56
68
|
/** `$GITHUB_API_URL`: `https://api.github.com` or `<host>/api/v3`. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ci-green-forge.d.ts","sourceRoot":"","sources":["../../src/workspace/ci-green-forge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAwC,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AACpG,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,gDAAgD;AAChD,MAAM,WAAW,QAAQ;IACvB,0EAA0E;IAC1E,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,6GAA6G;IAC7G,MAAM,EAAE,MAAM,CAAC;IACf,8HAA8H;IAC9H,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,6GAA6G;IAC7G,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wDAAwD;AACxD,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,gJAAgJ;IAChJ,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,4CAA4C;IAC5C,SAAS,CAAC,EAAE,WAAW,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,CAAC;CACnD;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,SAAS,CAAC;IAChB,+CAA+C;IAC/C,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"ci-green-forge.d.ts","sourceRoot":"","sources":["../../src/workspace/ci-green-forge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAwC,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,aAAa,CAAC;AACpG,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAEjD,gDAAgD;AAChD,MAAM,WAAW,QAAQ;IACvB,0EAA0E;IAC1E,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,6GAA6G;IAC7G,MAAM,EAAE,MAAM,CAAC;IACf,8HAA8H;IAC9H,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,6GAA6G;IAC7G,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,wDAAwD;AACxD,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,gJAAgJ;IAChJ,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,4CAA4C;IAC5C,SAAS,CAAC,EAAE,WAAW,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,CAAC;CACnD;AAED,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,SAAS,CAAC;IAChB,+CAA+C;IAC/C,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC;IAC5C;;;OAGG;IACH,KAAK,CAAC,CAAC,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC;;;;;OAKG;IACH,QAAQ,CAAC,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACzD;AAED,MAAM,WAAW,oBAAoB;IACnC,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;IAChB,oBAAoB;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,UAAU,CAAC;CACpB;AAKD,+GAA+G;AAC/G,wBAAgB,aAAa,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CA8CjE;AAED,0EAA0E;AAC1E,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,YAAY,IAAI,EAAE,MAAM,EAKvB;CACF;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,GAAE,MAAiB,EAAE,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,EAAE,SAAS,CAAC,EAAE,UAAU,GAAG,OAAO,CAW9I"}
|
|
@@ -55,7 +55,19 @@ export function githubCiForge(opts) {
|
|
|
55
55
|
}
|
|
56
56
|
return out;
|
|
57
57
|
},
|
|
58
|
+
// An Actions job's check run has the job's id, so the job is re-run by it. Both need `actions: write`.
|
|
59
|
+
async rerun(run) {
|
|
60
|
+
await post(`${root}/repos/${opts.repo}/actions/jobs/${run.id}/rerun`, {});
|
|
61
|
+
},
|
|
62
|
+
async dispatch(workflow, ref) {
|
|
63
|
+
await post(`${root}/repos/${opts.repo}/actions/workflows/${encodeURIComponent(workflow)}/dispatches`, { ref });
|
|
64
|
+
},
|
|
58
65
|
};
|
|
66
|
+
async function post(url, body) {
|
|
67
|
+
const res = await fetchImpl(url, { method: "POST", headers: { ...headers, "Content-Type": "application/json" }, body: JSON.stringify(body) });
|
|
68
|
+
if (!res.ok)
|
|
69
|
+
throw new ForgeApiError("POST", url, res.status, await res.text());
|
|
70
|
+
}
|
|
59
71
|
}
|
|
60
72
|
/** Thrown for a forge `chant ci tick` has no check-run client for yet. */
|
|
61
73
|
export class CiForgeUnsupportedError extends Error {
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
* the command runs in records it in its generated-file record, so `WSP081`
|
|
45
45
|
* allows one declarer.
|
|
46
46
|
*/
|
|
47
|
-
import type { CiGreen } from "./declaration.js";
|
|
47
|
+
import type { CiBuild, CiGreen } from "./declaration.js";
|
|
48
48
|
/** Where the workflow goes, relative to the repository root. */
|
|
49
49
|
export declare const CI_GREEN_WORKFLOW_FILE = ".github/workflows/chant-ci-green.yml";
|
|
50
50
|
export declare const CI_GREEN_WORKFLOW_NAME = "chant-ci-green";
|
|
@@ -69,6 +69,15 @@ export interface WorkflowScan {
|
|
|
69
69
|
}
|
|
70
70
|
/** Find the workflows that hold the required phases' check runs. */
|
|
71
71
|
export declare function workflowsHolding(green: CiGreen, sources: readonly WorkflowSource[]): WorkflowScan;
|
|
72
|
+
/**
|
|
73
|
+
* The workflow files that hold a check run of one of `phases` and can be
|
|
74
|
+
* started by hand (`workflow_dispatch`), by file name, for a build the tick
|
|
75
|
+
* asks for (#4169). Files that can't be parsed are left out.
|
|
76
|
+
*/
|
|
77
|
+
export declare function dispatchableWorkflows(green: CiGreen, phases: readonly string[], sources: readonly WorkflowSource[]): {
|
|
78
|
+
dispatchable: string[];
|
|
79
|
+
without: string[];
|
|
80
|
+
};
|
|
72
81
|
/** The repository's GitHub workflow files, other than `skip`. */
|
|
73
82
|
export declare function readWorkflowSources(repoRoot: string, skip: string): WorkflowSource[];
|
|
74
83
|
export interface WorkflowInput {
|
|
@@ -113,6 +122,51 @@ export type PushToken = {
|
|
|
113
122
|
export declare const ACTIONS_NAME: RegExp;
|
|
114
123
|
/** The workflow's YAML, without the generated-file header. Deterministic: the same input writes the same bytes. */
|
|
115
124
|
export declare function renderCiGreenWorkflow(input: WorkflowInput): string;
|
|
125
|
+
/** Whether any phase sets `build` (#4169): then the tick may re-run jobs and start workflows. */
|
|
126
|
+
export declare const declaresBuild: (green: CiGreen) => boolean;
|
|
127
|
+
/** Whether a required phase builds only the newest commit (#4169). */
|
|
128
|
+
export declare const newestPhases: (green: CiGreen) => boolean;
|
|
129
|
+
/** The comment line above each top-level block `ci workflow` writes into a phase's workflow. */
|
|
130
|
+
export declare const BUILD_BLOCK_MARKER = "# Written by chant ci workflow from ci.green's build (#4169); edit ci.green and run it again.";
|
|
131
|
+
/** What `ci workflow` writes into one workflow holding a phase that sets `build`. */
|
|
132
|
+
export interface BuildTriggerEdit {
|
|
133
|
+
/** Relative to the repository root. */
|
|
134
|
+
path: string;
|
|
135
|
+
build: CiBuild;
|
|
136
|
+
phases: string[];
|
|
137
|
+
/** The file with its triggers and concurrency written. */
|
|
138
|
+
text: string;
|
|
139
|
+
changed: boolean;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* The workflows holding the check runs of phases that set `build`, each with
|
|
143
|
+
* its triggers and concurrency written for that build (#4169):
|
|
144
|
+
*
|
|
145
|
+
* - `newest`: on pushes to the branch, and by hand (`workflow_dispatch`),
|
|
146
|
+
* which is how the tick starts a bisect step or a requested build at a
|
|
147
|
+
* `ci/build/<sha>` tag. A `schedule` goes: a runner freeing up, not a
|
|
148
|
+
* clock, picks the commit. Other triggers stay. One concurrency group per
|
|
149
|
+
* ref that never cancels a run in progress, so GitHub keeps the newest
|
|
150
|
+
* push waiting and drops the ones between, and each tag's build runs in a
|
|
151
|
+
* group of its own.
|
|
152
|
+
* - `every`: the triggers stay, and the group is the commit itself on the
|
|
153
|
+
* branch, so no push cancels or replaces another's run; elsewhere, such as
|
|
154
|
+
* a pull request, a new push cancels the run it supersedes.
|
|
155
|
+
*
|
|
156
|
+
* Only the top-level `on:` (for `newest`) and `concurrency:` blocks change,
|
|
157
|
+
* each under {@link BUILD_BLOCK_MARKER}; the rest of the file is kept as it
|
|
158
|
+
* is. Throws when one workflow holds a phase of each build, which no one
|
|
159
|
+
* concurrency group can serve.
|
|
160
|
+
*/
|
|
161
|
+
export declare function buildTriggerEdits(green: CiGreen, sources: readonly WorkflowSource[]): BuildTriggerEdit[];
|
|
162
|
+
/**
|
|
163
|
+
* Replace the top-level `key:` block of a YAML file with `value` (or with
|
|
164
|
+
* `value`'s lines, the key's own line first), under
|
|
165
|
+
* {@link BUILD_BLOCK_MARKER}, or add it before `permissions:` or `jobs:`
|
|
166
|
+
* when the file has none. The block runs from its key's line to the next
|
|
167
|
+
* line at column 0 that is not blank; comments above the key stay.
|
|
168
|
+
*/
|
|
169
|
+
export declare function writeTopLevel(text: string, key: string, value: Record<string, unknown> | string[]): string;
|
|
116
170
|
/** The header line naming the command that regenerates the file, and where to run it. */
|
|
117
171
|
export declare function ciGreenHeader(command: string, where: "member" | "root"): string;
|
|
118
172
|
/** Write the file, creating its directory. Returns the path relative to the current directory. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ci-green-workflow.d.ts","sourceRoot":"","sources":["../../src/workspace/ci-green-workflow.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAMH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"ci-green-workflow.d.ts","sourceRoot":"","sources":["../../src/workspace/ci-green-workflow.ts"],"names":[],"mappings":"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"}
|