@intentius/chant-lexicon-forgejo 0.124.46 → 0.124.49
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/actions.d.ts.map +1 -1
- package/dist/actions.js +16 -1
- package/dist/components/ci-jobs.d.ts.map +1 -1
- package/dist/components/ci-jobs.js +1 -0
- package/dist/components/generate-pipeline.d.ts +1 -1
- package/dist/components/generate-pipeline.js +1 -1
- package/dist/dialect.d.ts.map +1 -1
- package/dist/dialect.js +5 -1
- package/dist/integrity.json +2 -2
- package/dist/manifest.json +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +2 -1
- package/package.json +3 -3
- package/src/actions.ts +18 -1
- package/src/components/__fixtures__/pr-loop-build.forgejo.golden.yml +8 -9
- package/src/components/__fixtures__/pr-loop-record.forgejo.golden.yml +4 -5
- package/src/components/__fixtures__/pr-loop-waves.forgejo.golden.yml +12 -13
- package/src/components/__fixtures__/pr-loop.forgejo.golden.yml +8 -9
- package/src/components/__golden__/op-waves-jobs.yml +48 -7
- package/src/components/action-pins.test.ts +54 -0
- package/src/components/ci-jobs.ts +1 -0
- package/src/components/generate-op-pipeline.review.test.ts +63 -0
- package/src/components/generate-op-pipeline.test.ts +3 -2
- package/src/components/generate-pipeline.test.ts +2 -1
- package/src/components/generate-pipeline.ts +1 -1
- package/src/components/generate-pr-pipeline.locks.test.ts +30 -0
- package/src/components/generate-pr-pipeline.test.ts +9 -7
- package/src/components/generate-pr-waves-pipeline.test.ts +2 -1
- package/src/dialect.ts +4 -1
- package/src/mcp/context-tools.test.ts +2 -1
- package/src/plugin.ts +2 -1
- package/src/serializer.test.ts +4 -3
package/dist/actions.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;
|
|
1
|
+
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,6BAA6B,CAAC;AAE/D;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GACpB;IACE,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GACD;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjC;;;;;;GAMG;AACH,eAAO,MAAM,wBAAwB,OAAO,CAAC;AAE7C,kFAAkF;AAClF,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAkBtD,CAAC;AAEF,MAAM,WAAW,oBAAoB;IACnC,2EAA2E;IAC3E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+DAA+D;IAC/D,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,mBAAmB;IAClC,gDAAgD;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAaD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,oBAAyB,GAAG,mBAAmB,CA4BrG"}
|
package/dist/actions.js
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* The resolver rewrites a built-in set of common actions and reports anything it
|
|
10
10
|
* can't place as a diagnostic (never dropping or silently passing it through).
|
|
11
11
|
*/
|
|
12
|
+
import { pinAtMajor, pinMajor } from "@intentius/chant/action-pins";
|
|
12
13
|
/**
|
|
13
14
|
* Default actions root. `code.forgejo.org` hosts the Forgejo `actions/*` mirror
|
|
14
15
|
* (checkout, setup-*, cache, upload/download-artifact, …). Override per project
|
|
@@ -75,10 +76,24 @@ export function resolveActionRef(ref, options = {}) {
|
|
|
75
76
|
}
|
|
76
77
|
const base = target.kind === "mirror" ? `${root}/${target.repo}` : target.url;
|
|
77
78
|
const withSubpath = subpath ? `${base}/${subpath}` : base;
|
|
78
|
-
const pinned = target.kind === "mirror" && target.newest
|
|
79
|
+
const pinned = target.kind === "mirror" && target.newest ? olderPin(version, target.newest) : version;
|
|
79
80
|
const rewritten = pinned ? `${withSubpath}@${pinned}` : withSubpath;
|
|
80
81
|
return { rewritten };
|
|
81
82
|
}
|
|
83
|
+
/**
|
|
84
|
+
* `version` held to `newest`: a tag of a later major becomes `newest`, and a
|
|
85
|
+
* pinned commit of a later major becomes the commit of `newest` in chant's pin
|
|
86
|
+
* table (the mirror carries the same commits as GitHub's). Anything else,
|
|
87
|
+
* including a commit the table does not know, passes through.
|
|
88
|
+
*/
|
|
89
|
+
function olderPin(version, newest) {
|
|
90
|
+
if (/^[0-9a-f]{40}$/.test(version)) {
|
|
91
|
+
const major = pinMajor(version);
|
|
92
|
+
const target = Number(newest.replace(/^v/, ""));
|
|
93
|
+
return major !== undefined && major > target ? (pinAtMajor(version, newest)?.sha ?? version) : version;
|
|
94
|
+
}
|
|
95
|
+
return laterMajor(version, newest) ? newest : version;
|
|
96
|
+
}
|
|
82
97
|
/** Whether `version` (`v4`, `v4.1.0`) names a later major than `newest` (`v3`). A SHA or branch never does. */
|
|
83
98
|
function laterMajor(version, newest) {
|
|
84
99
|
const major = (v) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ci-jobs.d.ts","sourceRoot":"","sources":["../../src/components/ci-jobs.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iEAAiE,CAAC;AAC3G,OAAO,EAA2B,KAAK,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAEjF,kEAAkE;AAClE,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,qBAAqB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAElH;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQ5F;AAED,0FAA0F;AAC1F,wBAAgB,wBAAwB,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,EAAE,CAQ1E;AAED,mHAAmH;AACnH,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAOlF;AAED;;;;GAIG;AACH,eAAO,MAAM,eAAe;IAAK,iBAAiB;CAAqC,CAAC;AAExF;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,mBAAmB,EAAE,OAAO,EAAE,qBAAqB,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,mBAAmB,
|
|
1
|
+
{"version":3,"file":"ci-jobs.d.ts","sourceRoot":"","sources":["../../src/components/ci-jobs.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iEAAiE,CAAC;AAC3G,OAAO,EAA2B,KAAK,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAEjF,kEAAkE;AAClE,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,qBAAqB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAElH;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAQ5F;AAED,0FAA0F;AAC1F,wBAAgB,wBAAwB,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,EAAE,CAQ1E;AAED,mHAAmH;AACnH,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAOlF;AAED;;;;GAIG;AACH,eAAO,MAAM,eAAe;IAAK,iBAAiB;CAAqC,CAAC;AAExF;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,mBAAmB,EAAE,OAAO,EAAE,qBAAqB,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,mBAAmB,CAanI"}
|
|
@@ -67,5 +67,6 @@ export function forgejoWorkflowDoc(doc, dialect, header) {
|
|
|
67
67
|
permissions: {},
|
|
68
68
|
jobsDoc: forgejoize(withoutEnvironment(doc.jobsDoc), dialect),
|
|
69
69
|
...(doc.gatedNoticeDoc ? { gatedNoticeDoc: forgejoize(doc.gatedNoticeDoc, dialect) } : {}),
|
|
70
|
+
...(doc.reviewNoteDoc ? { reviewNoteDoc: forgejoize(doc.reviewNoteDoc, dialect) } : {}),
|
|
70
71
|
};
|
|
71
72
|
}
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
*
|
|
15
15
|
* - runner labels: `runs-on: ubuntu-latest` → the project's Forgejo label
|
|
16
16
|
* (default `docker`, the label a fresh `act_runner` exposes);
|
|
17
|
-
* - `uses:` refs (`actions/checkout
|
|
17
|
+
* - `uses:` refs (`actions/checkout`, `actions/upload-artifact`, ...), each pinned by commit SHA,
|
|
18
18
|
* rewritten to a Forgejo-resolvable form;
|
|
19
19
|
* - keys the Forgejo runner ignores (`continue-on-error`, and `permissions` bar `id-token`)
|
|
20
20
|
* dropped (`permissions` keeps only `id-token`, which OIDC needs).
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
*
|
|
15
15
|
* - runner labels: `runs-on: ubuntu-latest` → the project's Forgejo label
|
|
16
16
|
* (default `docker`, the label a fresh `act_runner` exposes);
|
|
17
|
-
* - `uses:` refs (`actions/checkout
|
|
17
|
+
* - `uses:` refs (`actions/checkout`, `actions/upload-artifact`, ...), each pinned by commit SHA,
|
|
18
18
|
* rewritten to a Forgejo-resolvable form;
|
|
19
19
|
* - keys the Forgejo runner ignores (`continue-on-error`, and `permissions` bar `id-token`)
|
|
20
20
|
* dropped (`permissions` keeps only `id-token`, which OIDC needs).
|
package/dist/dialect.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dialect.d.ts","sourceRoot":"","sources":["../src/dialect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAMH,OAAO,EAAsC,KAAK,UAAU,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"dialect.d.ts","sourceRoot":"","sources":["../src/dialect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAMH,OAAO,EAAsC,KAAK,UAAU,EAAE,MAAM,6BAA6B,CAAC;AA6ClG;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAKxD,CAAC;AAEF,MAAM,WAAW,qBAAqB;IACpC,mFAAmF;IACnF,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,uEAAuE;IACvE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACnC,sEAAsE;IACtE,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAClC,iEAAiE;IACjE,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AA8GD,MAAM,WAAW,qBAAqB;IACpC,qEAAqE;IACrE,KAAK,EAAE,OAAO,CAAC;IACf,8EAA8E;IAC9E,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,OAAO,EACZ,OAAO,GAAE,qBAA0B,GAClC,qBAAqB,CAKvB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,EACjC,OAAO,GAAE,qBAA0B,GAClC,oBAAoB,CAWtB"}
|
package/dist/dialect.js
CHANGED
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
// be `true`, so the two disagreed about a value carrying `false`. Core's also
|
|
28
28
|
// accepts an entity a host built, which a local identity check cannot.
|
|
29
29
|
import { isDeclarable, isResourceDeclarable } from "@intentius/chant/declarable";
|
|
30
|
+
import { ACTION_PINS } from "@intentius/chant/action-pins";
|
|
30
31
|
import { resolveActionRef } from "./actions.js";
|
|
31
32
|
/**
|
|
32
33
|
* Keys the Forgejo runner ignores. Emitting them is misleading (they look
|
|
@@ -149,7 +150,10 @@ const V4_ONLY_UPLOAD_INPUTS = new Set(["include-hidden-files", "overwrite"]);
|
|
|
149
150
|
function dropV4OnlyArtifactInputs(step) {
|
|
150
151
|
const uses = step.uses;
|
|
151
152
|
const withs = step.with;
|
|
152
|
-
if (typeof uses !== "string" || !/\/actions\/upload-artifact@v3$/.test(uses))
|
|
153
|
+
if (typeof uses !== "string" || !/\/actions\/upload-artifact@(v3|[0-9a-f]{40})$/.test(uses))
|
|
154
|
+
return;
|
|
155
|
+
const at = uses.slice(uses.lastIndexOf("@") + 1);
|
|
156
|
+
if (at !== "v3" && at !== ACTION_PINS.uploadArtifact3.sha)
|
|
153
157
|
return;
|
|
154
158
|
if (withs === null || typeof withs !== "object" || Array.isArray(withs))
|
|
155
159
|
return;
|
package/dist/integrity.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"algorithm": "sha256",
|
|
3
3
|
"artifacts": {
|
|
4
|
-
"manifest.json": "
|
|
4
|
+
"manifest.json": "22ec7e6cc36b408bc0d3ffce150bf60e5fa580fc599e1010f234a5de5677f9f1",
|
|
5
5
|
"meta.json": "44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a",
|
|
6
6
|
"types/index.d.ts": "66204549b2a864ab5489e3f02c1878e73ab4b3c9d938cfb480b66f71543a43de",
|
|
7
7
|
"rules/delegate-to-github.ts": "1060cda40f4b73d6cca3ba3fa13b80b4886147d4034c88584c2d80c5510dbe5e",
|
|
@@ -9,5 +9,5 @@
|
|
|
9
9
|
"rules/wfj011.ts": "fcb8bf6685d744af20ad804ce929488257995c74b9a3353b2eacae3768d1c83e",
|
|
10
10
|
"skills/chant-forgejo.md": "f28d7fb69fb1cfd992496ef41fda0ea5ccd54a29b84ea1c501a44f6a3992c4d5"
|
|
11
11
|
},
|
|
12
|
-
"composite": "
|
|
12
|
+
"composite": "f0eed9dedc8ec24f2fef6cc57150caa5a875a0cb1240027477dcde28ea5552d9"
|
|
13
13
|
}
|
package/dist/manifest.json
CHANGED
package/dist/plugin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAoC,MAAM,0BAA0B,CAAC;AAqBhG,eAAO,MAAM,aAAa,EAAE,
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAoC,MAAM,0BAA0B,CAAC;AAqBhG,eAAO,MAAM,aAAa,EAAE,aAuM3B,CAAC"}
|
package/dist/plugin.js
CHANGED
|
@@ -118,7 +118,8 @@ export const build = new Job({
|
|
|
118
118
|
async transform(content, opts) {
|
|
119
119
|
const { transform } = await import("./migrate/from-github/index.js");
|
|
120
120
|
const result = await transform(content, {
|
|
121
|
-
|
|
121
|
+
// "sql" is for sql targets (#4399); chant migrate refuses it for this pair.
|
|
122
|
+
emit: opts.emit === "sql" ? undefined : opts.emit,
|
|
122
123
|
sourceFile: opts.sourceFile,
|
|
123
124
|
strict: opts.strict,
|
|
124
125
|
security: opts.security,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intentius/chant-lexicon-forgejo",
|
|
3
|
-
"version": "0.124.
|
|
3
|
+
"version": "0.124.49",
|
|
4
4
|
"description": "Forgejo / Codeberg / Gitea Actions lexicon for chant — a thin GitHub Actions dialect",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://intentius.io/chant",
|
|
@@ -54,8 +54,8 @@
|
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
56
|
"zod": "^4.3.6",
|
|
57
|
-
"@intentius/chant": "^0.124.
|
|
58
|
-
"@intentius/chant-lexicon-github": "^0.124.
|
|
57
|
+
"@intentius/chant": "^0.124.49",
|
|
58
|
+
"@intentius/chant-lexicon-github": "^0.124.49"
|
|
59
59
|
},
|
|
60
60
|
"scripts": {
|
|
61
61
|
"generate": "tsx src/codegen/generate-cli.ts",
|
package/src/actions.ts
CHANGED
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
* can't place as a diagnostic (never dropping or silently passing it through).
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
+
import { pinAtMajor, pinMajor } from "@intentius/chant/action-pins";
|
|
14
|
+
|
|
13
15
|
/**
|
|
14
16
|
* Default actions root. `code.forgejo.org` hosts the Forgejo `actions/*` mirror
|
|
15
17
|
* (checkout, setup-*, cache, upload/download-artifact, …). Override per project
|
|
@@ -118,11 +120,26 @@ export function resolveActionRef(ref: string, options: ActionResolveOptions = {}
|
|
|
118
120
|
|
|
119
121
|
const base = target.kind === "mirror" ? `${root}/${target.repo}` : target.url;
|
|
120
122
|
const withSubpath = subpath ? `${base}/${subpath}` : base;
|
|
121
|
-
const pinned = target.kind === "mirror" && target.newest
|
|
123
|
+
const pinned = target.kind === "mirror" && target.newest ? olderPin(version, target.newest) : version;
|
|
122
124
|
const rewritten = pinned ? `${withSubpath}@${pinned}` : withSubpath;
|
|
123
125
|
return { rewritten };
|
|
124
126
|
}
|
|
125
127
|
|
|
128
|
+
/**
|
|
129
|
+
* `version` held to `newest`: a tag of a later major becomes `newest`, and a
|
|
130
|
+
* pinned commit of a later major becomes the commit of `newest` in chant's pin
|
|
131
|
+
* table (the mirror carries the same commits as GitHub's). Anything else,
|
|
132
|
+
* including a commit the table does not know, passes through.
|
|
133
|
+
*/
|
|
134
|
+
function olderPin(version: string, newest: string): string {
|
|
135
|
+
if (/^[0-9a-f]{40}$/.test(version)) {
|
|
136
|
+
const major = pinMajor(version);
|
|
137
|
+
const target = Number(newest.replace(/^v/, ""));
|
|
138
|
+
return major !== undefined && major > target ? (pinAtMajor(version, newest)?.sha ?? version) : version;
|
|
139
|
+
}
|
|
140
|
+
return laterMajor(version, newest) ? newest : version;
|
|
141
|
+
}
|
|
142
|
+
|
|
126
143
|
/** Whether `version` (`v4`, `v4.1.0`) names a later major than `newest` (`v3`). A SHA or branch never does. */
|
|
127
144
|
function laterMajor(version: string, newest: string): boolean {
|
|
128
145
|
const major = (v: string): number | undefined => {
|
|
@@ -68,7 +68,6 @@ jobs:
|
|
|
68
68
|
env:
|
|
69
69
|
BASE_SHA: '${{ github.event.pull_request.base.sha }}'
|
|
70
70
|
PR_NUMBER: '${{ github.event.pull_request.number }}'
|
|
71
|
-
CHANT_RUNNER_KEY: '${{ secrets.CHANT_RUNNER_KEY }}'
|
|
72
71
|
run: |
|
|
73
72
|
if [ -z "${CHANT_NO_FORGE_TOKEN:-}" ] && [ "${0#*/}" != "$0" ] && [ -f "$0" ] && ! { [ "${0##*/}" = sh ] || [ "${0##*/}" = bash ] || [ "${0##*/}" = dash ]; } && command -v env >/dev/null 2>&1 && command -v sh >/dev/null 2>&1; then exec env -u CHANT_FORGE_TOKEN -u CHANT_GITHUB_TOKEN -u CHANT_FORGEJO_TOKEN -u CHANT_GITLAB_TOKEN -u CHANT_CHECKOUT_TOKEN -u GITHUB_TOKEN -u GH_TOKEN -u FORGEJO_TOKEN -u GITEA_TOKEN -u GITLAB_TOKEN -u CI_JOB_TOKEN -u ACTIONS_RUNTIME_TOKEN CHANT_NO_FORGE_TOKEN=1 sh -e "$0"; fi; unset CHANT_FORGE_TOKEN CHANT_GITHUB_TOKEN CHANT_FORGEJO_TOKEN CHANT_GITLAB_TOKEN CHANT_CHECKOUT_TOKEN GITHUB_TOKEN GH_TOKEN FORGEJO_TOKEN GITEA_TOKEN GITLAB_TOKEN CI_JOB_TOKEN ACTIONS_RUNTIME_TOKEN
|
|
74
73
|
chant_report="$PWD/.chant/pr"
|
|
@@ -83,7 +82,7 @@ jobs:
|
|
|
83
82
|
container: node:22
|
|
84
83
|
steps:
|
|
85
84
|
- name: Check out the target branch's commit
|
|
86
|
-
uses: https://code.forgejo.org/actions/checkout@v7
|
|
85
|
+
uses: https://code.forgejo.org/actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
87
86
|
with:
|
|
88
87
|
ref: '${{ github.event.pull_request.base.sha }}'
|
|
89
88
|
- name: Take the plan report from the plan job
|
|
@@ -97,7 +96,7 @@ jobs:
|
|
|
97
96
|
END_OF_REPORT
|
|
98
97
|
- name: Keep the plan report
|
|
99
98
|
if: always()
|
|
100
|
-
uses: https://code.forgejo.org/actions/upload-artifact@v3
|
|
99
|
+
uses: https://code.forgejo.org/actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3.2.1
|
|
101
100
|
with:
|
|
102
101
|
name: chant-pr-plan
|
|
103
102
|
path: .chant/pr
|
|
@@ -118,7 +117,7 @@ jobs:
|
|
|
118
117
|
group: chant-record-prod
|
|
119
118
|
cancel-in-progress: false
|
|
120
119
|
steps:
|
|
121
|
-
- uses: https://code.forgejo.org/actions/checkout@v7
|
|
120
|
+
- uses: https://code.forgejo.org/actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
122
121
|
with:
|
|
123
122
|
fetch-depth: 0
|
|
124
123
|
- run: command -v tofu >/dev/null 2>&1 || (curl -fsSL https://get.opentofu.org/install-opentofu.sh -o /tmp/install-opentofu.sh && sh /tmp/install-opentofu.sh --install-method standalone)
|
|
@@ -136,7 +135,7 @@ jobs:
|
|
|
136
135
|
chant ci run record --in-place --base "$BASE_SHA" --env prod --gate pr-apply --forge forgejo
|
|
137
136
|
- name: Keep the record report
|
|
138
137
|
if: always()
|
|
139
|
-
uses: https://code.forgejo.org/actions/upload-artifact@v3
|
|
138
|
+
uses: https://code.forgejo.org/actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3.2.1
|
|
140
139
|
with:
|
|
141
140
|
name: chant-pr-record
|
|
142
141
|
path: .chant/pr
|
|
@@ -149,7 +148,7 @@ jobs:
|
|
|
149
148
|
group: chant-apply-prod
|
|
150
149
|
cancel-in-progress: false
|
|
151
150
|
steps:
|
|
152
|
-
- uses: https://code.forgejo.org/actions/checkout@v7
|
|
151
|
+
- uses: https://code.forgejo.org/actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
153
152
|
with:
|
|
154
153
|
fetch-depth: 0
|
|
155
154
|
- run: command -v tofu >/dev/null 2>&1 || (curl -fsSL https://get.opentofu.org/install-opentofu.sh -o /tmp/install-opentofu.sh && sh /tmp/install-opentofu.sh --install-method standalone)
|
|
@@ -158,7 +157,7 @@ jobs:
|
|
|
158
157
|
- name: Lint the project
|
|
159
158
|
run: chant lint
|
|
160
159
|
- name: Restore the record of an earlier attempt at this commit
|
|
161
|
-
uses: https://code.forgejo.org/actions/cache/restore@v4
|
|
160
|
+
uses: https://code.forgejo.org/actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
|
162
161
|
with:
|
|
163
162
|
path: .chant/pr-resume/pr-apply.json
|
|
164
163
|
key: chant-apply-prod-${{ github.sha }}-${{ github.run_id }}-${{ github.run_attempt }}
|
|
@@ -172,13 +171,13 @@ jobs:
|
|
|
172
171
|
chant ci run apply --in-place --env prod --gate pr-apply --forge forgejo
|
|
173
172
|
- name: Keep the record for a re-run
|
|
174
173
|
if: always()
|
|
175
|
-
uses: https://code.forgejo.org/actions/cache/save@v4
|
|
174
|
+
uses: https://code.forgejo.org/actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
|
176
175
|
with:
|
|
177
176
|
path: .chant/pr-resume/pr-apply.json
|
|
178
177
|
key: chant-apply-prod-${{ github.sha }}-${{ github.run_id }}-${{ github.run_attempt }}
|
|
179
178
|
- name: Keep the apply report
|
|
180
179
|
if: always()
|
|
181
|
-
uses: https://code.forgejo.org/actions/upload-artifact@v3
|
|
180
|
+
uses: https://code.forgejo.org/actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3.2.1
|
|
182
181
|
with:
|
|
183
182
|
name: chant-pr-apply
|
|
184
183
|
path: .chant/pr
|
|
@@ -58,7 +58,6 @@ jobs:
|
|
|
58
58
|
env:
|
|
59
59
|
BASE_SHA: '${{ github.event.pull_request.base.sha }}'
|
|
60
60
|
PR_NUMBER: '${{ github.event.pull_request.number }}'
|
|
61
|
-
CHANT_RUNNER_KEY: '${{ secrets.CHANT_RUNNER_KEY }}'
|
|
62
61
|
run: |
|
|
63
62
|
if [ -z "${CHANT_NO_FORGE_TOKEN:-}" ] && [ "${0#*/}" != "$0" ] && [ -f "$0" ] && ! { [ "${0##*/}" = sh ] || [ "${0##*/}" = bash ] || [ "${0##*/}" = dash ]; } && command -v env >/dev/null 2>&1 && command -v sh >/dev/null 2>&1; then exec env -u CHANT_FORGE_TOKEN -u CHANT_GITHUB_TOKEN -u CHANT_FORGEJO_TOKEN -u CHANT_GITLAB_TOKEN -u CHANT_CHECKOUT_TOKEN -u GITHUB_TOKEN -u GH_TOKEN -u FORGEJO_TOKEN -u GITEA_TOKEN -u GITLAB_TOKEN -u CI_JOB_TOKEN -u ACTIONS_RUNTIME_TOKEN CHANT_NO_FORGE_TOKEN=1 sh -e "$0"; fi; unset CHANT_FORGE_TOKEN CHANT_GITHUB_TOKEN CHANT_FORGEJO_TOKEN CHANT_GITLAB_TOKEN CHANT_CHECKOUT_TOKEN GITHUB_TOKEN GH_TOKEN FORGEJO_TOKEN GITEA_TOKEN GITLAB_TOKEN CI_JOB_TOKEN ACTIONS_RUNTIME_TOKEN
|
|
64
63
|
chant_report="$PWD/.chant/pr"
|
|
@@ -73,7 +72,7 @@ jobs:
|
|
|
73
72
|
container: node:22
|
|
74
73
|
steps:
|
|
75
74
|
- name: Check out the target branch's commit
|
|
76
|
-
uses: https://code.forgejo.org/actions/checkout@v7
|
|
75
|
+
uses: https://code.forgejo.org/actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
77
76
|
with:
|
|
78
77
|
ref: '${{ github.event.pull_request.base.sha }}'
|
|
79
78
|
- name: Take the plan report from the plan job
|
|
@@ -87,7 +86,7 @@ jobs:
|
|
|
87
86
|
END_OF_REPORT
|
|
88
87
|
- name: Keep the plan report
|
|
89
88
|
if: always()
|
|
90
|
-
uses: https://code.forgejo.org/actions/upload-artifact@v3
|
|
89
|
+
uses: https://code.forgejo.org/actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3.2.1
|
|
91
90
|
with:
|
|
92
91
|
name: chant-pr-plan
|
|
93
92
|
path: .chant/pr
|
|
@@ -108,7 +107,7 @@ jobs:
|
|
|
108
107
|
group: chant-record-prod
|
|
109
108
|
cancel-in-progress: false
|
|
110
109
|
steps:
|
|
111
|
-
- uses: https://code.forgejo.org/actions/checkout@v7
|
|
110
|
+
- uses: https://code.forgejo.org/actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
112
111
|
with:
|
|
113
112
|
fetch-depth: 0
|
|
114
113
|
- run: command -v tofu >/dev/null 2>&1 || (curl -fsSL https://get.opentofu.org/install-opentofu.sh -o /tmp/install-opentofu.sh && sh /tmp/install-opentofu.sh --install-method standalone)
|
|
@@ -122,7 +121,7 @@ jobs:
|
|
|
122
121
|
chant ci run record --in-place --base "$BASE_SHA" --env prod --gate pr-apply --forge forgejo
|
|
123
122
|
- name: Keep the record report
|
|
124
123
|
if: always()
|
|
125
|
-
uses: https://code.forgejo.org/actions/upload-artifact@v3
|
|
124
|
+
uses: https://code.forgejo.org/actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3.2.1
|
|
126
125
|
with:
|
|
127
126
|
name: chant-pr-record
|
|
128
127
|
path: .chant/pr
|
|
@@ -60,7 +60,6 @@ jobs:
|
|
|
60
60
|
env:
|
|
61
61
|
BASE_SHA: '${{ github.event.pull_request.base.sha }}'
|
|
62
62
|
PR_NUMBER: '${{ github.event.pull_request.number }}'
|
|
63
|
-
CHANT_RUNNER_KEY: '${{ secrets.CHANT_RUNNER_KEY }}'
|
|
64
63
|
run: |
|
|
65
64
|
if [ -z "${CHANT_NO_FORGE_TOKEN:-}" ] && [ "${0#*/}" != "$0" ] && [ -f "$0" ] && ! { [ "${0##*/}" = sh ] || [ "${0##*/}" = bash ] || [ "${0##*/}" = dash ]; } && command -v env >/dev/null 2>&1 && command -v sh >/dev/null 2>&1; then exec env -u CHANT_FORGE_TOKEN -u CHANT_GITHUB_TOKEN -u CHANT_FORGEJO_TOKEN -u CHANT_GITLAB_TOKEN -u CHANT_CHECKOUT_TOKEN -u GITHUB_TOKEN -u GH_TOKEN -u FORGEJO_TOKEN -u GITEA_TOKEN -u GITLAB_TOKEN -u CI_JOB_TOKEN -u ACTIONS_RUNTIME_TOKEN CHANT_NO_FORGE_TOKEN=1 sh -e "$0"; fi; unset CHANT_FORGE_TOKEN CHANT_GITHUB_TOKEN CHANT_FORGEJO_TOKEN CHANT_GITLAB_TOKEN CHANT_CHECKOUT_TOKEN GITHUB_TOKEN GH_TOKEN FORGEJO_TOKEN GITEA_TOKEN GITLAB_TOKEN CI_JOB_TOKEN ACTIONS_RUNTIME_TOKEN
|
|
66
65
|
chant_report="$PWD/.chant/pr"
|
|
@@ -75,7 +74,7 @@ jobs:
|
|
|
75
74
|
container: node:22
|
|
76
75
|
steps:
|
|
77
76
|
- name: Check out the target branch's commit
|
|
78
|
-
uses: https://code.forgejo.org/actions/checkout@v7
|
|
77
|
+
uses: https://code.forgejo.org/actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
79
78
|
with:
|
|
80
79
|
ref: '${{ github.event.pull_request.base.sha }}'
|
|
81
80
|
- name: Take the plan report from the plan job
|
|
@@ -89,7 +88,7 @@ jobs:
|
|
|
89
88
|
END_OF_REPORT
|
|
90
89
|
- name: Keep the plan report
|
|
91
90
|
if: always()
|
|
92
|
-
uses: https://code.forgejo.org/actions/upload-artifact@v3
|
|
91
|
+
uses: https://code.forgejo.org/actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3.2.1
|
|
93
92
|
with:
|
|
94
93
|
name: chant-pr-plan
|
|
95
94
|
path: .chant/pr
|
|
@@ -110,7 +109,7 @@ jobs:
|
|
|
110
109
|
group: chant-record-prod
|
|
111
110
|
cancel-in-progress: false
|
|
112
111
|
steps:
|
|
113
|
-
- uses: https://code.forgejo.org/actions/checkout@v7
|
|
112
|
+
- uses: https://code.forgejo.org/actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
114
113
|
with:
|
|
115
114
|
fetch-depth: 0
|
|
116
115
|
- run: command -v tofu >/dev/null 2>&1 || (curl -fsSL https://get.opentofu.org/install-opentofu.sh -o /tmp/install-opentofu.sh && sh /tmp/install-opentofu.sh --install-method standalone)
|
|
@@ -124,7 +123,7 @@ jobs:
|
|
|
124
123
|
chant ci run record --in-place --base "$BASE_SHA" --env prod --gate pr-apply --forge forgejo
|
|
125
124
|
- name: Keep the record report
|
|
126
125
|
if: always()
|
|
127
|
-
uses: https://code.forgejo.org/actions/upload-artifact@v3
|
|
126
|
+
uses: https://code.forgejo.org/actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3.2.1
|
|
128
127
|
with:
|
|
129
128
|
name: chant-pr-record
|
|
130
129
|
path: .chant/pr
|
|
@@ -139,12 +138,12 @@ jobs:
|
|
|
139
138
|
outputs:
|
|
140
139
|
green-sha: '${{ steps.apply.outputs.green-sha }}'
|
|
141
140
|
steps:
|
|
142
|
-
- uses: https://code.forgejo.org/actions/checkout@v7
|
|
141
|
+
- uses: https://code.forgejo.org/actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
143
142
|
with:
|
|
144
143
|
fetch-depth: 0
|
|
145
144
|
- run: command -v tofu >/dev/null 2>&1 || (curl -fsSL https://get.opentofu.org/install-opentofu.sh -o /tmp/install-opentofu.sh && sh /tmp/install-opentofu.sh --install-method standalone)
|
|
146
145
|
- name: Restore the newest record of this commit's apply
|
|
147
|
-
uses: https://code.forgejo.org/actions/cache/restore@v4
|
|
146
|
+
uses: https://code.forgejo.org/actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
|
148
147
|
with:
|
|
149
148
|
path: .chant/pr-resume/pr-apply.json
|
|
150
149
|
key: chant-apply-prod-${{ github.sha }}-${{ github.run_id }}-${{ github.run_attempt }}-wave-1
|
|
@@ -160,13 +159,13 @@ jobs:
|
|
|
160
159
|
chant ci run apply --in-place --env prod --gate pr-apply --forge forgejo --wave-gate release --wave 1
|
|
161
160
|
- name: Keep the record for the next wave and a re-run
|
|
162
161
|
if: always()
|
|
163
|
-
uses: https://code.forgejo.org/actions/cache/save@v4
|
|
162
|
+
uses: https://code.forgejo.org/actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
|
164
163
|
with:
|
|
165
164
|
path: .chant/pr-resume/pr-apply.json
|
|
166
165
|
key: chant-apply-prod-${{ github.sha }}-${{ github.run_id }}-${{ github.run_attempt }}-wave-1
|
|
167
166
|
- name: Keep the wave 1 apply report
|
|
168
167
|
if: always()
|
|
169
|
-
uses: https://code.forgejo.org/actions/upload-artifact@v3
|
|
168
|
+
uses: https://code.forgejo.org/actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3.2.1
|
|
170
169
|
with:
|
|
171
170
|
name: chant-pr-apply-wave-1
|
|
172
171
|
path: .chant/pr
|
|
@@ -183,12 +182,12 @@ jobs:
|
|
|
183
182
|
outputs:
|
|
184
183
|
green-sha: '${{ steps.apply.outputs.green-sha }}'
|
|
185
184
|
steps:
|
|
186
|
-
- uses: https://code.forgejo.org/actions/checkout@v7
|
|
185
|
+
- uses: https://code.forgejo.org/actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
187
186
|
with:
|
|
188
187
|
fetch-depth: 0
|
|
189
188
|
- run: command -v tofu >/dev/null 2>&1 || (curl -fsSL https://get.opentofu.org/install-opentofu.sh -o /tmp/install-opentofu.sh && sh /tmp/install-opentofu.sh --install-method standalone)
|
|
190
189
|
- name: Restore the newest record of this commit's apply
|
|
191
|
-
uses: https://code.forgejo.org/actions/cache/restore@v4
|
|
190
|
+
uses: https://code.forgejo.org/actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
|
192
191
|
with:
|
|
193
192
|
path: .chant/pr-resume/pr-apply.json
|
|
194
193
|
key: chant-apply-prod-${{ github.sha }}-${{ github.run_id }}-${{ github.run_attempt }}-wave-2
|
|
@@ -205,13 +204,13 @@ jobs:
|
|
|
205
204
|
chant ci run apply --in-place --env prod --gate pr-apply --forge forgejo --wave-gate release --wave 2
|
|
206
205
|
- name: Keep the record for the next wave and a re-run
|
|
207
206
|
if: always()
|
|
208
|
-
uses: https://code.forgejo.org/actions/cache/save@v4
|
|
207
|
+
uses: https://code.forgejo.org/actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
|
209
208
|
with:
|
|
210
209
|
path: .chant/pr-resume/pr-apply.json
|
|
211
210
|
key: chant-apply-prod-${{ github.sha }}-${{ github.run_id }}-${{ github.run_attempt }}-wave-2
|
|
212
211
|
- name: Keep the wave 2 apply report
|
|
213
212
|
if: always()
|
|
214
|
-
uses: https://code.forgejo.org/actions/upload-artifact@v3
|
|
213
|
+
uses: https://code.forgejo.org/actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3.2.1
|
|
215
214
|
with:
|
|
216
215
|
name: chant-pr-apply-wave-2
|
|
217
216
|
path: .chant/pr
|
|
@@ -60,7 +60,6 @@ jobs:
|
|
|
60
60
|
env:
|
|
61
61
|
BASE_SHA: '${{ github.event.pull_request.base.sha }}'
|
|
62
62
|
PR_NUMBER: '${{ github.event.pull_request.number }}'
|
|
63
|
-
CHANT_RUNNER_KEY: '${{ secrets.CHANT_RUNNER_KEY }}'
|
|
64
63
|
run: |
|
|
65
64
|
if [ -z "${CHANT_NO_FORGE_TOKEN:-}" ] && [ "${0#*/}" != "$0" ] && [ -f "$0" ] && ! { [ "${0##*/}" = sh ] || [ "${0##*/}" = bash ] || [ "${0##*/}" = dash ]; } && command -v env >/dev/null 2>&1 && command -v sh >/dev/null 2>&1; then exec env -u CHANT_FORGE_TOKEN -u CHANT_GITHUB_TOKEN -u CHANT_FORGEJO_TOKEN -u CHANT_GITLAB_TOKEN -u CHANT_CHECKOUT_TOKEN -u GITHUB_TOKEN -u GH_TOKEN -u FORGEJO_TOKEN -u GITEA_TOKEN -u GITLAB_TOKEN -u CI_JOB_TOKEN -u ACTIONS_RUNTIME_TOKEN CHANT_NO_FORGE_TOKEN=1 sh -e "$0"; fi; unset CHANT_FORGE_TOKEN CHANT_GITHUB_TOKEN CHANT_FORGEJO_TOKEN CHANT_GITLAB_TOKEN CHANT_CHECKOUT_TOKEN GITHUB_TOKEN GH_TOKEN FORGEJO_TOKEN GITEA_TOKEN GITLAB_TOKEN CI_JOB_TOKEN ACTIONS_RUNTIME_TOKEN
|
|
66
65
|
chant_report="$PWD/.chant/pr"
|
|
@@ -75,7 +74,7 @@ jobs:
|
|
|
75
74
|
container: node:22
|
|
76
75
|
steps:
|
|
77
76
|
- name: Check out the target branch's commit
|
|
78
|
-
uses: https://code.forgejo.org/actions/checkout@v7
|
|
77
|
+
uses: https://code.forgejo.org/actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
79
78
|
with:
|
|
80
79
|
ref: '${{ github.event.pull_request.base.sha }}'
|
|
81
80
|
- name: Take the plan report from the plan job
|
|
@@ -89,7 +88,7 @@ jobs:
|
|
|
89
88
|
END_OF_REPORT
|
|
90
89
|
- name: Keep the plan report
|
|
91
90
|
if: always()
|
|
92
|
-
uses: https://code.forgejo.org/actions/upload-artifact@v3
|
|
91
|
+
uses: https://code.forgejo.org/actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3.2.1
|
|
93
92
|
with:
|
|
94
93
|
name: chant-pr-plan
|
|
95
94
|
path: .chant/pr
|
|
@@ -110,7 +109,7 @@ jobs:
|
|
|
110
109
|
group: chant-record-prod
|
|
111
110
|
cancel-in-progress: false
|
|
112
111
|
steps:
|
|
113
|
-
- uses: https://code.forgejo.org/actions/checkout@v7
|
|
112
|
+
- uses: https://code.forgejo.org/actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
114
113
|
with:
|
|
115
114
|
fetch-depth: 0
|
|
116
115
|
- run: command -v tofu >/dev/null 2>&1 || (curl -fsSL https://get.opentofu.org/install-opentofu.sh -o /tmp/install-opentofu.sh && sh /tmp/install-opentofu.sh --install-method standalone)
|
|
@@ -124,7 +123,7 @@ jobs:
|
|
|
124
123
|
chant ci run record --in-place --base "$BASE_SHA" --env prod --gate pr-apply --forge forgejo
|
|
125
124
|
- name: Keep the record report
|
|
126
125
|
if: always()
|
|
127
|
-
uses: https://code.forgejo.org/actions/upload-artifact@v3
|
|
126
|
+
uses: https://code.forgejo.org/actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3.2.1
|
|
128
127
|
with:
|
|
129
128
|
name: chant-pr-record
|
|
130
129
|
path: .chant/pr
|
|
@@ -137,12 +136,12 @@ jobs:
|
|
|
137
136
|
group: chant-apply-prod
|
|
138
137
|
cancel-in-progress: false
|
|
139
138
|
steps:
|
|
140
|
-
- uses: https://code.forgejo.org/actions/checkout@v7
|
|
139
|
+
- uses: https://code.forgejo.org/actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
141
140
|
with:
|
|
142
141
|
fetch-depth: 0
|
|
143
142
|
- run: command -v tofu >/dev/null 2>&1 || (curl -fsSL https://get.opentofu.org/install-opentofu.sh -o /tmp/install-opentofu.sh && sh /tmp/install-opentofu.sh --install-method standalone)
|
|
144
143
|
- name: Restore the record of an earlier attempt at this commit
|
|
145
|
-
uses: https://code.forgejo.org/actions/cache/restore@v4
|
|
144
|
+
uses: https://code.forgejo.org/actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
|
146
145
|
with:
|
|
147
146
|
path: .chant/pr-resume/pr-apply.json
|
|
148
147
|
key: chant-apply-prod-${{ github.sha }}-${{ github.run_id }}-${{ github.run_attempt }}
|
|
@@ -156,13 +155,13 @@ jobs:
|
|
|
156
155
|
chant ci run apply --in-place --env prod --gate pr-apply --forge forgejo
|
|
157
156
|
- name: Keep the record for a re-run
|
|
158
157
|
if: always()
|
|
159
|
-
uses: https://code.forgejo.org/actions/cache/save@v4
|
|
158
|
+
uses: https://code.forgejo.org/actions/cache/save@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
|
|
160
159
|
with:
|
|
161
160
|
path: .chant/pr-resume/pr-apply.json
|
|
162
161
|
key: chant-apply-prod-${{ github.sha }}-${{ github.run_id }}-${{ github.run_attempt }}
|
|
163
162
|
- name: Keep the apply report
|
|
164
163
|
if: always()
|
|
165
|
-
uses: https://code.forgejo.org/actions/upload-artifact@v3
|
|
164
|
+
uses: https://code.forgejo.org/actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3.2.1
|
|
166
165
|
with:
|
|
167
166
|
name: chant-pr-apply
|
|
168
167
|
path: .chant/pr
|
|
@@ -15,29 +15,48 @@ jobs:
|
|
|
15
15
|
runs-on: plan
|
|
16
16
|
container: node:22
|
|
17
17
|
steps:
|
|
18
|
-
- uses: https://code.forgejo.org/actions/checkout@v7
|
|
18
|
+
- uses: https://code.forgejo.org/actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
19
19
|
with:
|
|
20
20
|
fetch-depth: 0
|
|
21
21
|
- name: Plan, gate and apply wave 1 (dev)
|
|
22
22
|
run: chant run wave --spec waves.json --wave 1
|
|
23
|
+
- name: Keep the job's outcome
|
|
24
|
+
if: always()
|
|
25
|
+
uses: https://code.forgejo.org/actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3.2.1
|
|
26
|
+
with:
|
|
27
|
+
name: migrations-wave-1-dev-outcome
|
|
28
|
+
path: .chant/op-waves/migrations/outcomes/outcome-wave-1.json
|
|
29
|
+
if-no-files-found: ignore
|
|
23
30
|
wave-2-prod-decide:
|
|
24
31
|
runs-on: plan
|
|
25
32
|
needs:
|
|
26
33
|
- wave-1-dev
|
|
34
|
+
if: '!cancelled()'
|
|
27
35
|
container: node:22
|
|
28
36
|
steps:
|
|
29
|
-
- uses: https://code.forgejo.org/actions/checkout@v7
|
|
37
|
+
- uses: https://code.forgejo.org/actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
30
38
|
with:
|
|
31
39
|
fetch-depth: 0
|
|
40
|
+
- name: Download the earlier jobs' outcomes
|
|
41
|
+
uses: https://code.forgejo.org/actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
|
42
|
+
with:
|
|
43
|
+
path: .chant/op-waves/migrations/outcomes
|
|
32
44
|
- name: Plan wave 2 (prod) and decide its gate
|
|
33
45
|
run: chant run wave --spec waves.json --wave 2 --decide
|
|
34
46
|
- name: Keep wave 2's decision
|
|
35
47
|
if: always()
|
|
36
|
-
uses: https://code.forgejo.org/actions/upload-artifact@v3
|
|
48
|
+
uses: https://code.forgejo.org/actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3.2.1
|
|
37
49
|
with:
|
|
38
50
|
name: migrations-wave-2-decision
|
|
39
51
|
path: .chant/op-waves/migrations/wave-2.json
|
|
40
52
|
if-no-files-found: ignore
|
|
53
|
+
- name: Keep the job's outcome
|
|
54
|
+
if: always()
|
|
55
|
+
uses: https://code.forgejo.org/actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3.2.1
|
|
56
|
+
with:
|
|
57
|
+
name: migrations-wave-2-prod-decide-outcome
|
|
58
|
+
path: .chant/op-waves/migrations/outcomes/outcome-wave-2.json
|
|
59
|
+
if-no-files-found: ignore
|
|
41
60
|
wave-2-prod-us:
|
|
42
61
|
runs-on:
|
|
43
62
|
- self-hosted
|
|
@@ -51,29 +70,51 @@ jobs:
|
|
|
51
70
|
REGION: us
|
|
52
71
|
CLOUD_TOKEN_AUDIENCE: us.example
|
|
53
72
|
steps:
|
|
54
|
-
- uses: https://code.forgejo.org/actions/checkout@v7
|
|
73
|
+
- uses: https://code.forgejo.org/actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
55
74
|
with:
|
|
56
75
|
fetch-depth: 0
|
|
57
76
|
- name: Download wave 2's decision
|
|
58
|
-
uses: https://code.forgejo.org/actions/download-artifact@v3
|
|
77
|
+
uses: https://code.forgejo.org/actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
|
59
78
|
with:
|
|
60
79
|
name: migrations-wave-2-decision
|
|
61
80
|
path: .chant/op-waves/migrations
|
|
81
|
+
- name: Download the earlier jobs' outcomes
|
|
82
|
+
uses: https://code.forgejo.org/actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
|
83
|
+
with:
|
|
84
|
+
path: .chant/op-waves/migrations/outcomes
|
|
62
85
|
- name: Apply job group us of wave 2 (prod)
|
|
63
86
|
run: chant run wave --spec waves.json --wave 2 --group us
|
|
87
|
+
- name: Keep the job's outcome
|
|
88
|
+
if: always()
|
|
89
|
+
uses: https://code.forgejo.org/actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3.2.1
|
|
90
|
+
with:
|
|
91
|
+
name: migrations-wave-2-prod-us-outcome
|
|
92
|
+
path: .chant/op-waves/migrations/outcomes/outcome-wave-2-group-us.json
|
|
93
|
+
if-no-files-found: ignore
|
|
64
94
|
wave-2-prod-eu:
|
|
65
95
|
runs-on: eu-apply
|
|
66
96
|
needs:
|
|
67
97
|
- wave-2-prod-decide
|
|
68
98
|
container: node:22
|
|
69
99
|
steps:
|
|
70
|
-
- uses: https://code.forgejo.org/actions/checkout@v7
|
|
100
|
+
- uses: https://code.forgejo.org/actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
71
101
|
with:
|
|
72
102
|
fetch-depth: 0
|
|
73
103
|
- name: Download wave 2's decision
|
|
74
|
-
uses: https://code.forgejo.org/actions/download-artifact@v3
|
|
104
|
+
uses: https://code.forgejo.org/actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
|
75
105
|
with:
|
|
76
106
|
name: migrations-wave-2-decision
|
|
77
107
|
path: .chant/op-waves/migrations
|
|
108
|
+
- name: Download the earlier jobs' outcomes
|
|
109
|
+
uses: https://code.forgejo.org/actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2
|
|
110
|
+
with:
|
|
111
|
+
path: .chant/op-waves/migrations/outcomes
|
|
78
112
|
- name: Apply job group eu of wave 2 (prod)
|
|
79
113
|
run: chant run wave --spec waves.json --wave 2 --group eu
|
|
114
|
+
- name: Keep the job's outcome
|
|
115
|
+
if: always()
|
|
116
|
+
uses: https://code.forgejo.org/actions/upload-artifact@ff15f0306b3f739f7b6fd43fb5d26cd321bd4de5 # v3.2.1
|
|
117
|
+
with:
|
|
118
|
+
name: migrations-wave-2-prod-eu-outcome
|
|
119
|
+
path: .chant/op-waves/migrations/outcomes/outcome-wave-2-group-eu.json
|
|
120
|
+
if-no-files-found: ignore
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* #4403: no workflow chant generates names an action by tag or branch, and no
|
|
3
|
+
* generator's source does either outside the pin table.
|
|
4
|
+
*/
|
|
5
|
+
import { readFileSync, readdirSync } from "node:fs";
|
|
6
|
+
import { join } from "node:path";
|
|
7
|
+
import { describe, expect, it } from "vitest";
|
|
8
|
+
import type { DriverComponent } from "@intentius/chant/components/driver";
|
|
9
|
+
import { ACTION_PINS, unpinnedActions } from "@intentius/chant/action-pins";
|
|
10
|
+
import { generateGithubPipeline } from "@intentius/chant-lexicon-github/components/generate-pipeline";
|
|
11
|
+
import { generateForgejoPipeline } from "./generate-pipeline";
|
|
12
|
+
|
|
13
|
+
const ESTATE: DriverComponent[] = [
|
|
14
|
+
{ name: "net", dependsOn: [], deploy: [{ phase: "Apply", steps: [{ kind: "terraform-apply", root: "net" }] }] },
|
|
15
|
+
{ name: "app", dependsOn: ["net"], deploy: [{ phase: "Apply", steps: [{ kind: "terraform-apply", root: "app" }] }] },
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
const root = join(import.meta.dirname, "../../../..");
|
|
19
|
+
|
|
20
|
+
describe("the actions a generated workflow uses", () => {
|
|
21
|
+
const variants = [{ env: "prod" }, { env: "prod", prLoop: { applyOnMerge: true } }, { env: "prod", prLoop: {} }] as const;
|
|
22
|
+
for (const [forge, gen] of [["github", generateGithubPipeline], ["forgejo", generateForgejoPipeline]] as const) {
|
|
23
|
+
it(`are each pinned by commit SHA, with the release beside it, on ${forge}`, () => {
|
|
24
|
+
for (const options of variants) {
|
|
25
|
+
const yaml = gen(ESTATE, options as never).yaml;
|
|
26
|
+
expect(unpinnedActions(yaml)).toEqual([]);
|
|
27
|
+
expect(yaml).toMatch(new RegExp(`uses: \\S*actions/checkout@${ACTION_PINS.checkout7.sha} # ${ACTION_PINS.checkout7.tag}$`, "m"));
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
it("are pinned in the committed workflow chant ci workflow wrote", () => {
|
|
33
|
+
const committed = readFileSync(join(root, ".github/workflows/chant-ci-green.yml"), "utf8");
|
|
34
|
+
expect(unpinnedActions(committed)).toEqual([]);
|
|
35
|
+
expect(committed).toMatch(new RegExp(`uses: actions/checkout@${ACTION_PINS.checkout6.sha} # ${ACTION_PINS.checkout6.tag}$`, "m"));
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("name no action by tag or branch in a generator's source, outside the pin table", () => {
|
|
39
|
+
const dirs = ["lexicons/github/src/components", "lexicons/forgejo/src/components", "packages/core/src/components"].map((d) => join(root, d));
|
|
40
|
+
const files = [
|
|
41
|
+
...dirs.flatMap((d) => readdirSync(d).filter((n) => n.endsWith(".ts") && !n.endsWith(".test.ts")).map((n) => join(d, n))),
|
|
42
|
+
join(root, "packages/core/src/workspace/ci-green-workflow.ts"),
|
|
43
|
+
join(root, "packages/core/src/workspace/release-workflow.ts"),
|
|
44
|
+
];
|
|
45
|
+
const found: string[] = [];
|
|
46
|
+
for (const f of files) {
|
|
47
|
+
for (const m of readFileSync(f, "utf8").matchAll(/["'`]((?:https:\/\/[\w.]+\/)?[\w-]+\/[\w./-]+@[\w.-]+)["'`]/g)) {
|
|
48
|
+
if (!/@[0-9a-f]{40}$/.test(m[1])) found.push(`${f.slice(root.length + 1)}: ${m[1]}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
expect(files.length).toBeGreaterThan(10);
|
|
52
|
+
expect(found).toEqual([]);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
@@ -76,5 +76,6 @@ export function forgejoWorkflowDoc(doc: GithubOpPipelineDoc, dialect: ForgejoDia
|
|
|
76
76
|
permissions: {},
|
|
77
77
|
jobsDoc: forgejoize(withoutEnvironment(doc.jobsDoc), dialect),
|
|
78
78
|
...(doc.gatedNoticeDoc ? { gatedNoticeDoc: forgejoize(doc.gatedNoticeDoc, dialect) } : {}),
|
|
79
|
+
...(doc.reviewNoteDoc ? { reviewNoteDoc: forgejoize(doc.reviewNoteDoc, dialect) } : {}),
|
|
79
80
|
};
|
|
80
81
|
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The split review on Forgejo (#4326): the github shape under the Forgejo
|
|
3
|
+
* dialect. Forgejo ignores `permissions:`, so the review job's safety is the
|
|
4
|
+
* token variables the step drops and the note job that holds the token alone.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { describe, expect, test } from "vitest";
|
|
8
|
+
import { parseYAML } from "@intentius/chant/yaml";
|
|
9
|
+
import { CHECKOUT_TOKEN_ENV, checkoutScript, FORGE_TOKEN_VARS } from "@intentius/chant/ci-handover";
|
|
10
|
+
import type { ScheduledOpSpec } from "@intentius/chant/lexicon";
|
|
11
|
+
import { generateForgejoOpPipeline } from "./generate-op-pipeline";
|
|
12
|
+
|
|
13
|
+
interface Step {
|
|
14
|
+
id?: string;
|
|
15
|
+
uses?: string;
|
|
16
|
+
run?: string;
|
|
17
|
+
env?: Record<string, string>;
|
|
18
|
+
}
|
|
19
|
+
interface Job {
|
|
20
|
+
needs?: string;
|
|
21
|
+
if?: string;
|
|
22
|
+
permissions?: unknown;
|
|
23
|
+
outputs?: Record<string, string>;
|
|
24
|
+
steps: Step[];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const SPEC: ScheduledOpSpec = { name: "pr-review", trigger: { kind: "pull_request" }, reviewAgent: true };
|
|
28
|
+
|
|
29
|
+
describe("generateForgejoOpPipeline: reviewAgent", () => {
|
|
30
|
+
const out = generateForgejoOpPipeline([SPEC]);
|
|
31
|
+
const doc = parseYAML(out.files[0]!.yaml) as { jobs: Record<string, Job> };
|
|
32
|
+
|
|
33
|
+
test("a review job and a note job, with the handoff between them", () => {
|
|
34
|
+
expect(Object.keys(doc.jobs)).toEqual(["pr-review", "pr-review-note"]);
|
|
35
|
+
expect(doc.jobs["pr-review"]!.outputs).toEqual({ report_0: "${{ steps.chant-review.outputs.report_0 }}" });
|
|
36
|
+
expect(doc.jobs["pr-review-note"]!.needs).toBe("pr-review");
|
|
37
|
+
expect(doc.jobs["pr-review-note"]!.if).toBe("needs.pr-review.result == 'success'");
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test("no step of the review job but the checkout's fetches names a forge token, and the Op's step drops them", () => {
|
|
41
|
+
for (const step of doc.jobs["pr-review"]!.steps) {
|
|
42
|
+
const named = Object.keys(step.env ?? {}).filter((n) => (FORGE_TOKEN_VARS as readonly string[]).includes(n));
|
|
43
|
+
expect(named).toEqual(step.run?.trimEnd() === checkoutScript(true).trimEnd() ? [CHECKOUT_TOKEN_ENV] : []);
|
|
44
|
+
expect(step.uses ?? "").not.toMatch(/^actions\/checkout/);
|
|
45
|
+
}
|
|
46
|
+
expect(doc.jobs["pr-review"]!.steps.at(-1)!.run).toContain("exec env -u CHANT_FORGE_TOKEN");
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test("the note job checks nothing out and takes the token from the job", () => {
|
|
50
|
+
const note = doc.jobs["pr-review-note"]!;
|
|
51
|
+
expect(note.steps.some((s) => (s.uses ?? "").includes("checkout"))).toBe(false);
|
|
52
|
+
expect(note.steps[1]!.env).toEqual({ GITHUB_TOKEN: "${{ github.token }}", CHANT_OP: "pr-review" });
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test("the dialect drops permissions: from both jobs, as it does for every Op", () => {
|
|
56
|
+
expect(doc.jobs["pr-review"]!.permissions).toBeUndefined();
|
|
57
|
+
expect(doc.jobs["pr-review-note"]!.permissions).toBeUndefined();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test("the same refusals as github's", () => {
|
|
61
|
+
expect(() => generateForgejoOpPipeline([{ ...SPEC, trigger: { kind: "push" } }])).toThrow(/reviewAgent/);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
@@ -11,6 +11,7 @@ import { parseYAML } from "@intentius/chant/yaml";
|
|
|
11
11
|
import { generateForgejoOpPipeline } from "./generate-op-pipeline";
|
|
12
12
|
import { generateGithubOpPipeline } from "@intentius/chant-lexicon-github/components/generate-op-pipeline";
|
|
13
13
|
import type { ScheduledOpSpec } from "@intentius/chant/lexicon";
|
|
14
|
+
import { ACTION_PINS, usesRef } from "@intentius/chant/action-pins";
|
|
14
15
|
|
|
15
16
|
interface ParsedJob {
|
|
16
17
|
needs?: string;
|
|
@@ -214,7 +215,7 @@ describe("generateForgejoOpPipeline: setup steps and additive permissions (#2242
|
|
|
214
215
|
const steps = doc.jobs!["app-apply"].steps;
|
|
215
216
|
// The checkout is rewritten to the Forgejo mirror; an action with no
|
|
216
217
|
// mapping in ../actions.ts passes through verbatim.
|
|
217
|
-
expect(steps[0].uses).toContain(
|
|
218
|
+
expect(steps[0].uses).toContain(`${usesRef(ACTION_PINS.checkout7)}`);
|
|
218
219
|
expect(steps[1].uses).toBe("aws-actions/configure-aws-credentials@v6");
|
|
219
220
|
expect((steps[1] as { with?: Record<string, string> }).with).toEqual({
|
|
220
221
|
"role-to-assume": "${{ vars.AWS_ROLE_ARN }}",
|
|
@@ -336,7 +337,7 @@ describe("generateForgejoOpPipeline: a dropped deployment environment (#2257)",
|
|
|
336
337
|
" runs-on: docker",
|
|
337
338
|
" container: node:22",
|
|
338
339
|
" steps:",
|
|
339
|
-
|
|
340
|
+
` - uses: https://code.forgejo.org/${usesRef(ACTION_PINS.checkout7)} # ${ACTION_PINS.checkout7.tag}`,
|
|
340
341
|
" - run: chant run actions-audit",
|
|
341
342
|
" env:",
|
|
342
343
|
" GITHUB_TOKEN: '${{ github.token }}'",
|
|
@@ -16,6 +16,7 @@ import { generateGithubPipeline } from "@intentius/chant-lexicon-github/componen
|
|
|
16
16
|
import { type DriverComponent } from "@intentius/chant/components/driver";
|
|
17
17
|
import { searchService } from "@intentius/chant/components/pilots/alb-ecs.pilot";
|
|
18
18
|
import { ordersTable } from "@intentius/chant/components/pilots/dynamodb.pilot";
|
|
19
|
+
import { ACTION_PINS, usesRef } from "@intentius/chant/action-pins";
|
|
19
20
|
|
|
20
21
|
function pilotComponents(): DriverComponent[] {
|
|
21
22
|
return [
|
|
@@ -110,7 +111,7 @@ describe("generateForgejoPipeline: dialect applied", () => {
|
|
|
110
111
|
expect(ref).toContain("code.forgejo.org/actions/");
|
|
111
112
|
}
|
|
112
113
|
// checkout is present and mirrored.
|
|
113
|
-
expect(all.some((r) => r ===
|
|
114
|
+
expect(all.some((r) => r === `https://code.forgejo.org/${usesRef(ACTION_PINS.checkout7)}`)).toBe(true);
|
|
114
115
|
});
|
|
115
116
|
});
|
|
116
117
|
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
*
|
|
15
15
|
* - runner labels: `runs-on: ubuntu-latest` → the project's Forgejo label
|
|
16
16
|
* (default `docker`, the label a fresh `act_runner` exposes);
|
|
17
|
-
* - `uses:` refs (`actions/checkout
|
|
17
|
+
* - `uses:` refs (`actions/checkout`, `actions/upload-artifact`, ...), each pinned by commit SHA,
|
|
18
18
|
* rewritten to a Forgejo-resolvable form;
|
|
19
19
|
* - keys the Forgejo runner ignores (`continue-on-error`, and `permissions` bar `id-token`)
|
|
20
20
|
* dropped (`permissions` keeps only `id-token`, which OIDC needs).
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/** The Forgejo pull-request workflow with `ci.locks: plan` (#4327): the GitHub generator's lock and unlock jobs, in the Forgejo dialect. */
|
|
2
|
+
|
|
3
|
+
import { describe, expect, test } from "vitest";
|
|
4
|
+
import { parseYAML } from "@intentius/chant/yaml";
|
|
5
|
+
import type { DriverComponent } from "@intentius/chant/components/driver";
|
|
6
|
+
import { generateForgejoPipeline } from "./generate-pipeline";
|
|
7
|
+
|
|
8
|
+
const ESTATE: DriverComponent[] = [
|
|
9
|
+
{ name: "net", dependsOn: [], deploy: [{ phase: "Apply", steps: [{ kind: "terraform-apply", root: "net" }] }] },
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
interface Step { run?: string }
|
|
13
|
+
type Doc = { jobs: Record<string, { if?: string; needs?: string[]; steps: Step[] }> };
|
|
14
|
+
|
|
15
|
+
describe("the Forgejo workflow with ci.locks: plan", () => {
|
|
16
|
+
const doc = parseYAML(generateForgejoPipeline(ESTATE, { env: "prod", prLoop: { locks: "plan" } }).yaml) as Doc;
|
|
17
|
+
|
|
18
|
+
test("writes the lock and unlock jobs for forgejo", () => {
|
|
19
|
+
expect(doc.jobs.lock!.needs).toEqual(["plan"]);
|
|
20
|
+
expect(doc.jobs.lock!.steps.find((s) => s.run?.startsWith("chant lock"))!.run).toContain("--forge forgejo");
|
|
21
|
+
expect(doc.jobs.unlock!.if).toContain("github.event.action == 'closed'");
|
|
22
|
+
expect(doc.jobs.unlock!.steps.some((s) => s.run === 'chant unlock --pr "$PR_NUMBER"')).toBe(true);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
test("without ci.locks neither job is written", () => {
|
|
26
|
+
const plain = parseYAML(generateForgejoPipeline(ESTATE, { env: "prod", prLoop: {} }).yaml) as Doc;
|
|
27
|
+
expect(Object.keys(plain.jobs)).not.toContain("lock");
|
|
28
|
+
expect(Object.keys(plain.jobs)).not.toContain("unlock");
|
|
29
|
+
});
|
|
30
|
+
});
|
|
@@ -17,6 +17,7 @@ import { generateGithubPipeline } from "@intentius/chant-lexicon-github/componen
|
|
|
17
17
|
import { githubBaseFallback, greenCheckout } from "@intentius/chant/components/pr-pipeline";
|
|
18
18
|
import { dropForgeTokens } from "@intentius/chant/ci-handover";
|
|
19
19
|
import { generateForgejoPipeline } from "./generate-pipeline";
|
|
20
|
+
import { ACTION_PINS, usesRef } from "@intentius/chant/action-pins";
|
|
20
21
|
|
|
21
22
|
const ESTATE: DriverComponent[] = [
|
|
22
23
|
{ name: "net", dependsOn: [], deploy: [{ phase: "Apply", steps: [{ kind: "terraform-apply", root: "net" }] }] },
|
|
@@ -42,9 +43,9 @@ describe("the Forgejo pull-request workflow", () => {
|
|
|
42
43
|
expect(result.yaml).toBe(readFileSync(GOLDEN, "utf-8"));
|
|
43
44
|
});
|
|
44
45
|
|
|
45
|
-
test("
|
|
46
|
+
test("the jobs run chant ci run, with the runner key secret on every job but the plan, as on GitHub (#4156, #4328)", () => {
|
|
46
47
|
expect(result.yaml).toContain("chant ci run plan --in-place --no-push");
|
|
47
|
-
expect(result.yaml.match(/CHANT_RUNNER_KEY: '\$\{\{ secrets\.CHANT_RUNNER_KEY \}\}'/g)).toHaveLength(
|
|
48
|
+
expect(result.yaml.match(/CHANT_RUNNER_KEY: '\$\{\{ secrets\.CHANT_RUNNER_KEY \}\}'/g)).toHaveLength(2);
|
|
48
49
|
expect(result.yaml).not.toContain("chant components pr-plan");
|
|
49
50
|
expect(result.yaml).not.toContain("chant components pr-apply");
|
|
50
51
|
// #4295: the plan-note job posts with pr-post, to Forgejo.
|
|
@@ -84,21 +85,22 @@ describe("the Forgejo pull-request workflow", () => {
|
|
|
84
85
|
});
|
|
85
86
|
|
|
86
87
|
test("the apply keeps its resume record in the runner's cache, through the Forgejo mirror of actions/cache (#3543)", () => {
|
|
87
|
-
expect(result.yaml).toContain(
|
|
88
|
-
expect(result.yaml).toContain(
|
|
88
|
+
expect(result.yaml).toContain(`uses: https://code.forgejo.org/${usesRef(ACTION_PINS.cacheRestore4)}`);
|
|
89
|
+
expect(result.yaml).toContain(`uses: https://code.forgejo.org/${usesRef(ACTION_PINS.cacheSave4)}`);
|
|
89
90
|
// ci run's inner pr-apply resumes from it (#4156): the job runs in place, where the cache restored it.
|
|
90
91
|
expect(result.yaml).toContain("chant ci run apply --in-place --env prod");
|
|
91
92
|
});
|
|
92
93
|
|
|
93
94
|
test("keeps its reports with upload-artifact v3, the version a Forgejo runner runs, while GitHub keeps v4 (#4008)", () => {
|
|
94
95
|
// v4 refuses a runner that reads as GitHub Enterprise Server, as Forgejo's does.
|
|
95
|
-
expect(result.yaml.match(
|
|
96
|
-
expect(result.yaml).not.
|
|
96
|
+
expect(result.yaml.match(new RegExp(`uses: https://code\\.forgejo\\.org/actions/upload-artifact@${ACTION_PINS.uploadArtifact3.sha} # ${ACTION_PINS.uploadArtifact3.tag}$`, "gm"))).toHaveLength(3);
|
|
97
|
+
expect(result.yaml).not.toContain(ACTION_PINS.uploadArtifact4.sha);
|
|
98
|
+
expect(result.yaml).not.toContain(ACTION_PINS.downloadArtifact4.sha);
|
|
97
99
|
// v3 uploads hidden files with no input asking for it, so .chant/pr is still kept.
|
|
98
100
|
expect(result.yaml).not.toContain("include-hidden-files");
|
|
99
101
|
expect(result.yaml).toContain("path: .chant/pr");
|
|
100
102
|
const github = generateGithubPipeline(ESTATE, { env: "prod", prLoop: { applyOnMerge: true } }).yaml;
|
|
101
|
-
expect(github.match(
|
|
103
|
+
expect(github.match(new RegExp(`uses: actions/upload-artifact@${ACTION_PINS.uploadArtifact4.sha} # ${ACTION_PINS.uploadArtifact4.tag}$`, "gm"))).toHaveLength(3);
|
|
102
104
|
expect(github).toContain("include-hidden-files: true");
|
|
103
105
|
});
|
|
104
106
|
|
|
@@ -10,6 +10,7 @@ import { describe, expect, test } from "vitest";
|
|
|
10
10
|
import { parseYAML } from "@intentius/chant/yaml";
|
|
11
11
|
import type { DriverComponent } from "@intentius/chant/components/driver";
|
|
12
12
|
import { generateForgejoPipeline } from "./generate-pipeline";
|
|
13
|
+
import { ACTION_PINS, usesRef } from "@intentius/chant/action-pins";
|
|
13
14
|
|
|
14
15
|
const root = (name: string, dependsOn: string[] = []): DriverComponent => ({
|
|
15
16
|
name,
|
|
@@ -56,7 +57,7 @@ describe("the Forgejo pull-request workflow with a gate per wave (#4003)", () =>
|
|
|
56
57
|
const job = doc.jobs[`apply-wave-${k}`]!;
|
|
57
58
|
expect(job["runs-on"]).toBe("docker");
|
|
58
59
|
expect(job.steps.find((s) => s.run?.includes("ci run apply"))!.run).toContain(`--forge forgejo --wave-gate release --wave ${k}`);
|
|
59
|
-
expect(job.steps.some((s) => s.uses ===
|
|
60
|
+
expect(job.steps.some((s) => s.uses === `https://code.forgejo.org/${usesRef(ACTION_PINS.cacheRestore4)}`)).toBe(true);
|
|
60
61
|
}
|
|
61
62
|
});
|
|
62
63
|
});
|
package/src/dialect.ts
CHANGED
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
// be `true`, so the two disagreed about a value carrying `false`. Core's also
|
|
29
29
|
// accepts an entity a host built, which a local identity check cannot.
|
|
30
30
|
import { isDeclarable, isResourceDeclarable, type Declarable } from "@intentius/chant/declarable";
|
|
31
|
+
import { ACTION_PINS } from "@intentius/chant/action-pins";
|
|
31
32
|
import { resolveActionRef } from "./actions";
|
|
32
33
|
|
|
33
34
|
/**
|
|
@@ -183,7 +184,9 @@ const V4_ONLY_UPLOAD_INPUTS = new Set(["include-hidden-files", "overwrite"]);
|
|
|
183
184
|
function dropV4OnlyArtifactInputs(step: Record<string, unknown>): void {
|
|
184
185
|
const uses = step.uses;
|
|
185
186
|
const withs = step.with;
|
|
186
|
-
if (typeof uses !== "string" || !/\/actions\/upload-artifact@v3$/.test(uses)) return;
|
|
187
|
+
if (typeof uses !== "string" || !/\/actions\/upload-artifact@(v3|[0-9a-f]{40})$/.test(uses)) return;
|
|
188
|
+
const at = uses.slice(uses.lastIndexOf("@") + 1);
|
|
189
|
+
if (at !== "v3" && at !== ACTION_PINS.uploadArtifact3.sha) return;
|
|
187
190
|
if (withs === null || typeof withs !== "object" || Array.isArray(withs)) return;
|
|
188
191
|
const kept = Object.fromEntries(Object.entries(withs as Record<string, unknown>).filter(([k]) => !V4_ONLY_UPLOAD_INPUTS.has(toKebabCase(k))));
|
|
189
192
|
step.with = kept;
|
|
@@ -80,7 +80,8 @@ describe("forgejo context tools", () => {
|
|
|
80
80
|
test("forgejo:references reports the rewritten + unmapped refs", async () => {
|
|
81
81
|
const refs = (await tool("forgejo:references").handler({ path: join(dir, "src") })) as Array<{ source: string }>;
|
|
82
82
|
const sources = refs.map((r) => r.source);
|
|
83
|
-
|
|
83
|
+
// Composites pin by commit SHA since #4410.
|
|
84
|
+
expect(sources.some((s: string) => /^https:\/\/code\.forgejo\.org\/actions\/checkout@[0-9a-f]{40}$/.test(s))).toBe(true);
|
|
84
85
|
expect(sources).toContain("some-org/custom-action@v1");
|
|
85
86
|
});
|
|
86
87
|
|
package/src/plugin.ts
CHANGED
|
@@ -131,7 +131,8 @@ export const build = new Job({
|
|
|
131
131
|
async transform(content: string, opts) {
|
|
132
132
|
const { transform } = await import("./migrate/from-github");
|
|
133
133
|
const result = await transform(content, {
|
|
134
|
-
|
|
134
|
+
// "sql" is for sql targets (#4399); chant migrate refuses it for this pair.
|
|
135
|
+
emit: opts.emit === "sql" ? undefined : opts.emit,
|
|
135
136
|
sourceFile: opts.sourceFile,
|
|
136
137
|
strict: opts.strict,
|
|
137
138
|
security: opts.security,
|
package/src/serializer.test.ts
CHANGED
|
@@ -88,15 +88,16 @@ describe("forgejoSerializer — uses: action resolution", () => {
|
|
|
88
88
|
const { primary } = asResult(
|
|
89
89
|
forgejoSerializer.serialize(withSteps(Checkout({}).step, SetupNode({ nodeVersion: "22" }).step)),
|
|
90
90
|
);
|
|
91
|
-
|
|
92
|
-
expect(primary).
|
|
91
|
+
// Composites pin by commit SHA since #4410; the rewrite still puts them under the actions root.
|
|
92
|
+
expect(primary).toMatch(new RegExp(`uses: ${DEFAULT_ACTIONS_ROOT}/actions/checkout@[0-9a-f]{40}`));
|
|
93
|
+
expect(primary).toMatch(new RegExp(`uses: ${DEFAULT_ACTIONS_ROOT}/actions/setup-node@[0-9a-f]{40}`));
|
|
93
94
|
});
|
|
94
95
|
|
|
95
96
|
test("forgejo.actionsRoot override changes the rewritten base", () => {
|
|
96
97
|
const out = forgejoSerializer.serialize(withSteps(Checkout({}).step), undefined, {
|
|
97
98
|
config: { forgejo: { actionsRoot: "https://codeberg.org" } },
|
|
98
99
|
});
|
|
99
|
-
expect(asResult(out).primary).
|
|
100
|
+
expect(asResult(out).primary).toMatch(/uses: https:\/\/codeberg\.org\/actions\/checkout@[0-9a-f]{40}/);
|
|
100
101
|
});
|
|
101
102
|
|
|
102
103
|
test("an unmapped action ref is passed through (WFJ010 reports it post-synth)", () => {
|