@intentius/chant-lexicon-github 0.116.0 → 0.117.0
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/components/generate-op-waves-pipeline.d.ts +6 -0
- package/dist/components/generate-op-waves-pipeline.d.ts.map +1 -1
- package/dist/integrity.json +2 -2
- package/dist/manifest.json +1 -1
- package/package.json +2 -2
- package/src/components/generate-op-waves-pipeline.test.ts +11 -0
- package/src/components/generate-op-waves-pipeline.ts +31 -5
|
@@ -13,6 +13,11 @@
|
|
|
13
13
|
* deciding job uploads its decision, even when it waits, and each share job
|
|
14
14
|
* downloads it. The forgejo generator reuses {@link buildGithubOpWavesDoc}
|
|
15
15
|
* and applies its dialect.
|
|
16
|
+
*
|
|
17
|
+
* With `resume` on the spec (#3683), a second workflow, `<name>-resume.yml`,
|
|
18
|
+
* runs `chant run resume --op <name>` on that schedule: it re-runs the failed
|
|
19
|
+
* jobs of a run whose waiting wave has been approved since, with the job's
|
|
20
|
+
* token and `actions: write`.
|
|
16
21
|
*/
|
|
17
22
|
import { type OpWavesSpec } from "@intentius/chant/op/op-waves";
|
|
18
23
|
import type { OpWavesPipelineOptions, OpWavesPipelineResult } from "@intentius/chant/lexicon";
|
|
@@ -25,6 +30,7 @@ export declare function opWaveRecordArtifact(spec: Pick<OpWavesSpec, "name">, wa
|
|
|
25
30
|
export declare function buildGithubOpWavesDoc(spec: OpWavesSpec, options: OpWavesPipelineOptions): {
|
|
26
31
|
doc: GithubOpPipelineDoc;
|
|
27
32
|
jobs: OpWavesPipelineResult["jobs"];
|
|
33
|
+
resumeDoc?: GithubOpPipelineDoc;
|
|
28
34
|
};
|
|
29
35
|
/** Render an Op waves spec as one GitHub Actions workflow, `<name>.yml`. */
|
|
30
36
|
export declare function generateGithubOpWavesPipeline(spec: OpWavesSpec, options: OpWavesPipelineOptions): OpWavesPipelineResult;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate-op-waves-pipeline.d.ts","sourceRoot":"","sources":["../../src/components/generate-op-waves-pipeline.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"generate-op-waves-pipeline.d.ts","sourceRoot":"","sources":["../../src/components/generate-op-waves-pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAoC,KAAK,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAClG,OAAO,KAAK,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAE9F,OAAO,EAIL,KAAK,mBAAmB,EACzB,MAAM,wBAAwB,CAAC;AAEhC,yFAAyF;AACzF,eAAO,MAAM,cAAc,YAAY,CAAC;AAExC,oEAAoE;AACpE,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE1F;AAOD,qEAAqE;AACrE,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,WAAW,EACjB,OAAO,EAAE,sBAAsB,GAC9B;IAAE,GAAG,EAAE,mBAAmB,CAAC;IAAC,IAAI,EAAE,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAAC,SAAS,CAAC,EAAE,mBAAmB,CAAA;CAAE,CA0DpG;AA2BD,4EAA4E;AAC5E,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,sBAAsB,GAAG,qBAAqB,CAKvH"}
|
package/dist/integrity.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"algorithm": "sha256",
|
|
3
3
|
"artifacts": {
|
|
4
|
-
"manifest.json": "
|
|
4
|
+
"manifest.json": "80cd8fc60162a6b30fc79202a8992ab61d34b4d245c93553194e489340c32abd",
|
|
5
5
|
"meta.json": "c50e0ef3845c370c3ad2210b8bba455980417c0f818aa6ed46e06d4fb8b1b9f9",
|
|
6
6
|
"types/index.d.ts": "bdd54a4145a39a9dd4f7bbc8c500191acb6bc9057a87da0040475afac84db397",
|
|
7
7
|
"rules/deprecated-action-version.ts": "d41e6e532ab7f623af1bee4ac5279fcb2baada7defa1c5d022a5bc71983e8797",
|
|
@@ -78,5 +78,5 @@
|
|
|
78
78
|
"skills/chant-github-patterns.md": "bb3abef289a8fdfcf07d6bb2d7289dcb2f38bc0cb0321ea320b78b45a6f548c0",
|
|
79
79
|
"skills/chant-github-security.md": "aab111cb0871cad30281ce48d7da23663689619351029219e2be019a1a61e394"
|
|
80
80
|
},
|
|
81
|
-
"composite": "
|
|
81
|
+
"composite": "56d98c73201dd7cf4c5a2ca9153dfd1324ae6cc21adf35f9a956e389f98f51b8"
|
|
82
82
|
}
|
package/dist/manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intentius/chant-lexicon-github",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.117.0",
|
|
4
4
|
"description": "GitHub Actions lexicon for chant — declarative IaC in TypeScript",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://intentius.io/chant",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"typescript": "^5.9.3"
|
|
62
62
|
},
|
|
63
63
|
"peerDependencies": {
|
|
64
|
-
"@intentius/chant": "^0.
|
|
64
|
+
"@intentius/chant": "^0.117.0",
|
|
65
65
|
"typescript": "^5.9.3"
|
|
66
66
|
}
|
|
67
67
|
}
|
|
@@ -30,4 +30,15 @@ describe("generateGithubOpWavesPipeline", () => {
|
|
|
30
30
|
expect(yaml).toContain("name: migrations-wave-2-decision");
|
|
31
31
|
expect(yaml).toContain("environment:\n name: production");
|
|
32
32
|
});
|
|
33
|
+
|
|
34
|
+
test("resume renders a scheduled workflow that re-runs approved waves with actions: write (#3683)", () => {
|
|
35
|
+
const { files } = generateGithubOpWavesPipeline({ ...spec, resume: { schedule: "*/10 * * * *" } }, { specFile: "waves.json" });
|
|
36
|
+
expect(files.map((f) => f.name)).toEqual([`${spec.name}.yml`, `${spec.name}-resume.yml`]);
|
|
37
|
+
const yaml = files[1]!.yaml;
|
|
38
|
+
expect(yaml).toContain("- cron: '*/10 * * * *'");
|
|
39
|
+
expect(yaml).toMatch(/permissions:\n\s+contents: read\n\s+actions: write/);
|
|
40
|
+
expect(yaml).toContain(`run: chant run resume --op ${spec.name}`);
|
|
41
|
+
expect(yaml).toContain("GITHUB_TOKEN: '${{ github.token }}'");
|
|
42
|
+
expect(generateGithubOpWavesPipeline(spec, { specFile: "waves.json" }).files).toHaveLength(1);
|
|
43
|
+
});
|
|
33
44
|
});
|
|
@@ -13,9 +13,14 @@
|
|
|
13
13
|
* deciding job uploads its decision, even when it waits, and each share job
|
|
14
14
|
* downloads it. The forgejo generator reuses {@link buildGithubOpWavesDoc}
|
|
15
15
|
* and applies its dialect.
|
|
16
|
+
*
|
|
17
|
+
* With `resume` on the spec (#3683), a second workflow, `<name>-resume.yml`,
|
|
18
|
+
* runs `chant run resume --op <name>` on that schedule: it re-runs the failed
|
|
19
|
+
* jobs of a run whose waiting wave has been approved since, with the job's
|
|
20
|
+
* token and `actions: write`.
|
|
16
21
|
*/
|
|
17
22
|
|
|
18
|
-
import { opWaveJobs, type OpWavesSpec } from "@intentius/chant/op/op-waves";
|
|
23
|
+
import { opWaveJobs, opWavesResumeCommand, type OpWavesSpec } from "@intentius/chant/op/op-waves";
|
|
19
24
|
import type { OpWavesPipelineOptions, OpWavesPipelineResult } from "@intentius/chant/lexicon";
|
|
20
25
|
import { actionRef } from "../action-pins";
|
|
21
26
|
import {
|
|
@@ -42,7 +47,7 @@ function dirOf(path: string): string {
|
|
|
42
47
|
export function buildGithubOpWavesDoc(
|
|
43
48
|
spec: OpWavesSpec,
|
|
44
49
|
options: OpWavesPipelineOptions,
|
|
45
|
-
): { doc: GithubOpPipelineDoc; jobs: OpWavesPipelineResult["jobs"] } {
|
|
50
|
+
): { doc: GithubOpPipelineDoc; jobs: OpWavesPipelineResult["jobs"]; resumeDoc?: GithubOpPipelineDoc } {
|
|
46
51
|
const jobs = opWaveJobs(spec, options.specFile);
|
|
47
52
|
const image = options.image ?? OP_WAVES_IMAGE;
|
|
48
53
|
for (const wave of spec.waves) {
|
|
@@ -99,7 +104,26 @@ export function buildGithubOpWavesDoc(
|
|
|
99
104
|
permissions: { contents: "write" },
|
|
100
105
|
jobsDoc,
|
|
101
106
|
};
|
|
102
|
-
return { doc, jobs };
|
|
107
|
+
return { doc, jobs, ...(spec.resume ? { resumeDoc: buildResumeDoc(spec, options) } : {}) };
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** The scheduled resume workflow (#3683). */
|
|
111
|
+
function buildResumeDoc(spec: OpWavesSpec, options: OpWavesPipelineOptions): GithubOpPipelineDoc {
|
|
112
|
+
const steps: Array<Record<string, unknown>> = [{ uses: actionRef("actions/checkout") }];
|
|
113
|
+
for (const line of options.beforeScript ?? []) steps.push({ run: line });
|
|
114
|
+
steps.push({
|
|
115
|
+
name: `Resume the waves of ${spec.name} whose approval arrived`,
|
|
116
|
+
run: opWavesResumeCommand(spec).join(" "),
|
|
117
|
+
env: { GITHUB_TOKEN: "${{ github.token }}" },
|
|
118
|
+
});
|
|
119
|
+
return {
|
|
120
|
+
name: `${spec.name}-resume`,
|
|
121
|
+
on: { schedule: [{ cron: spec.resume!.schedule }], workflow_dispatch: {} },
|
|
122
|
+
concurrency: { group: `${spec.name}-resume`, "cancel-in-progress": true },
|
|
123
|
+
// contents: read fetches chant/lifecycle; actions: write re-runs a waiting run.
|
|
124
|
+
permissions: { contents: "read", actions: "write" },
|
|
125
|
+
jobsDoc: { resume: { "runs-on": "ubuntu-latest", container: options.image ?? OP_WAVES_IMAGE, steps } },
|
|
126
|
+
};
|
|
103
127
|
}
|
|
104
128
|
|
|
105
129
|
function describeJob(kind: "wave" | "decide" | "share", wave: number, name: string, share?: number): string {
|
|
@@ -110,6 +134,8 @@ function describeJob(kind: "wave" | "decide" | "share", wave: number, name: stri
|
|
|
110
134
|
|
|
111
135
|
/** Render an Op waves spec as one GitHub Actions workflow, `<name>.yml`. */
|
|
112
136
|
export function generateGithubOpWavesPipeline(spec: OpWavesSpec, options: OpWavesPipelineOptions): OpWavesPipelineResult {
|
|
113
|
-
const { doc, jobs } = buildGithubOpWavesDoc(spec, options);
|
|
114
|
-
|
|
137
|
+
const { doc, jobs, resumeDoc } = buildGithubOpWavesDoc(spec, options);
|
|
138
|
+
const files = [{ name: `${spec.name}.yml`, yaml: emitOpPipelineYAML(doc) }];
|
|
139
|
+
if (resumeDoc) files.push({ name: `${spec.name}-resume.yml`, yaml: emitOpPipelineYAML(resumeDoc) });
|
|
140
|
+
return { files, jobs };
|
|
115
141
|
}
|