@intentius/chant-lexicon-forgejo 0.124.56 → 0.124.57

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.
@@ -63,7 +63,7 @@ export function forgejoWorkflowDoc(doc, dialect, header) {
63
63
  ...(doc.name ? { name: doc.name } : {}),
64
64
  on: forgejoize(doc.on, dialect),
65
65
  ...(doc.env ? { env: forgejoize(doc.env, dialect) } : {}),
66
- concurrency: forgejoize(doc.concurrency, dialect),
66
+ ...(doc.concurrency ? { concurrency: forgejoize(doc.concurrency, dialect) } : {}),
67
67
  permissions: {},
68
68
  jobsDoc: forgejoize(withoutEnvironment(doc.jobsDoc), dialect),
69
69
  ...(doc.gatedNoticeDoc ? { gatedNoticeDoc: forgejoize(doc.gatedNoticeDoc, dialect) } : {}),
@@ -25,6 +25,14 @@
25
25
  * The apply-job guard (#4624) starts each wave job as on GitHub, with the
26
26
  * forge set to Forgejo: it checks the ref and, for a `self-hosted` label,
27
27
  * the runner, and no forge environment, since Forgejo has none.
28
+ *
29
+ * Like GitHub's, the workflow carries no concurrency group (ruling for
30
+ * ci-products 2026-10-28, "Ledger lock"; Forgejo 16.0.5 has no job-level
31
+ * concurrency either). Two pushes run their waves side by side: a stock
32
+ * Pulumi stack or a Terraform root waits for its row on chant's ledger,
33
+ * oldest commit first, up to the job's `timeout-minutes`, and a plunge stack
34
+ * on the resource grain leases its resource rows and never waits on another
35
+ * stack.
28
36
  */
29
37
  import type { OpWavesSpec } from "@intentius/chant/op/op-waves";
30
38
  import type { OpWavesPipelineOptions, OpWavesPipelineResult } from "@intentius/chant/lexicon";
@@ -1 +1 @@
1
- {"version":3,"file":"generate-op-waves-pipeline.d.ts","sourceRoot":"","sources":["../../src/components/generate-op-waves-pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAEhE,OAAO,KAAK,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAC9F,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAGxD,6EAA6E;AAC7E,wBAAgB,8BAA8B,CAC5C,IAAI,EAAE,WAAW,EACjB,OAAO,EAAE,sBAAsB,EAC/B,cAAc,GAAE,qBAA0B,GACzC,qBAAqB,CAiBvB"}
1
+ {"version":3,"file":"generate-op-waves-pipeline.d.ts","sourceRoot":"","sources":["../../src/components/generate-op-waves-pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAEhE,OAAO,KAAK,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,0BAA0B,CAAC;AAC9F,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAGxD,6EAA6E;AAC7E,wBAAgB,8BAA8B,CAC5C,IAAI,EAAE,WAAW,EACjB,OAAO,EAAE,sBAAsB,EAC/B,cAAc,GAAE,qBAA0B,GACzC,qBAAqB,CAiBvB"}
@@ -25,6 +25,14 @@
25
25
  * The apply-job guard (#4624) starts each wave job as on GitHub, with the
26
26
  * forge set to Forgejo: it checks the ref and, for a `self-hosted` label,
27
27
  * the runner, and no forge environment, since Forgejo has none.
28
+ *
29
+ * Like GitHub's, the workflow carries no concurrency group (ruling for
30
+ * ci-products 2026-10-28, "Ledger lock"; Forgejo 16.0.5 has no job-level
31
+ * concurrency either). Two pushes run their waves side by side: a stock
32
+ * Pulumi stack or a Terraform root waits for its row on chant's ledger,
33
+ * oldest commit first, up to the job's `timeout-minutes`, and a plunge stack
34
+ * on the resource grain leases its resource rows and never waits on another
35
+ * stack.
28
36
  */
29
37
  import { buildGithubOpWavesDoc } from "@intentius/chant-lexicon-github/components/generate-op-waves-pipeline";
30
38
  import { emitOpPipelineYAML } from "@intentius/chant-lexicon-github/components/generate-op-pipeline";
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "algorithm": "sha256",
3
3
  "artifacts": {
4
- "manifest.json": "d8927356783df4ae21c431e0a016299273a031fecc05ead9df07f900b57ed4c7",
4
+ "manifest.json": "4c4c5e8764f6844c5a23d70e6afa86d905c6627e01d04a2463e9a6f40d857e2c",
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": "7b0449ca0d3675a7e8c15a30fc85f3de807f6eb7eb538536867e77edd16ee133"
12
+ "composite": "4226c270f3ec6aed2feaee4293a384febb3a87163e9c1256fd58813717a46592"
13
13
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "forgejo",
3
- "version": "0.124.56",
3
+ "version": "0.124.57",
4
4
  "chantVersion": ">=0.1.0",
5
5
  "namespace": "Forgejo",
6
6
  "intrinsics": [],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intentius/chant-lexicon-forgejo",
3
- "version": "0.124.56",
3
+ "version": "0.124.57",
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.56",
58
- "@intentius/chant-lexicon-github": "^0.124.56"
57
+ "@intentius/chant": "^0.124.57",
58
+ "@intentius/chant-lexicon-github": "^0.124.57"
59
59
  },
60
60
  "scripts": {
61
61
  "generate": "tsx src/codegen/generate-cli.ts",
@@ -6,14 +6,13 @@ on:
6
6
  - main
7
7
  workflow_dispatch: {}
8
8
 
9
- concurrency:
10
- group: migrations
11
- cancel-in-progress: false
12
-
13
9
  jobs:
14
10
  wave-1-dev:
15
11
  runs-on: plan
16
12
  container: node:22
13
+ timeout-minutes: 180
14
+ env:
15
+ CHANT_LOCK_WAIT: '10500'
17
16
  steps:
18
17
  - name: Check the job runs where the spec set it to run
19
18
  env:
@@ -37,6 +36,9 @@ jobs:
37
36
  - wave-1-dev
38
37
  if: '!cancelled()'
39
38
  container: node:22
39
+ timeout-minutes: 180
40
+ env:
41
+ CHANT_LOCK_WAIT: '10500'
40
42
  steps:
41
43
  - name: Check the job runs where the spec set it to run
42
44
  env:
@@ -74,7 +76,9 @@ jobs:
74
76
  container: node:22
75
77
  permissions:
76
78
  id-token: write
79
+ timeout-minutes: 180
77
80
  env:
81
+ CHANT_LOCK_WAIT: '10500'
78
82
  REGION: us
79
83
  CLOUD_TOKEN_AUDIENCE: us.example
80
84
  steps:
@@ -108,6 +112,9 @@ jobs:
108
112
  needs:
109
113
  - wave-2-prod-decide
110
114
  container: node:22
115
+ timeout-minutes: 180
116
+ env:
117
+ CHANT_LOCK_WAIT: '10500'
111
118
  steps:
112
119
  - name: Check the job runs where the spec set it to run
113
120
  env:
@@ -72,7 +72,7 @@ export function forgejoWorkflowDoc(doc: GithubOpPipelineDoc, dialect: ForgejoDia
72
72
  ...(doc.name ? { name: doc.name } : {}),
73
73
  on: forgejoize(doc.on, dialect),
74
74
  ...(doc.env ? { env: forgejoize(doc.env, dialect) } : {}),
75
- concurrency: forgejoize(doc.concurrency, dialect),
75
+ ...(doc.concurrency ? { concurrency: forgejoize(doc.concurrency, dialect) } : {}),
76
76
  permissions: {},
77
77
  jobsDoc: forgejoize(withoutEnvironment(doc.jobsDoc), dialect),
78
78
  ...(doc.gatedNoticeDoc ? { gatedNoticeDoc: forgejoize(doc.gatedNoticeDoc, dialect) } : {}),
@@ -90,8 +90,8 @@ describe("a runner per wave and job groups per wave (#3914)", () => {
90
90
  expect(jobs.map((j) => j.jobName)).toEqual(["wave-1-dev", "wave-2-prod-decide", "wave-2-prod-us", "wave-2-prod-eu"]);
91
91
  const yaml = files[0]!.yaml;
92
92
  expect(yaml).toMatch(/wave-1-dev:\n\s+runs-on: plan\n/);
93
- expect(yaml).toMatch(/wave-2-prod-us:\n\s+runs-on:\n\s+- self-hosted\n\s+- us\n[\s\S]*?permissions:\n\s+id-token: write\n\s+env:\n\s+REGION: us\n\s+CLOUD_TOKEN_AUDIENCE: us.example\n/);
94
- expect(yaml).toMatch(/wave-2-prod-eu:\n\s+runs-on: eu-apply\n\s+needs:\n\s+- wave-2-prod-decide\n\s+container: node:22\n\s+steps:/);
93
+ expect(yaml).toMatch(/wave-2-prod-us:\n\s+runs-on:\n\s+- self-hosted\n\s+- us\n[\s\S]*?permissions:\n\s+id-token: write\n\s+timeout-minutes: 180\n\s+env:\n\s+CHANT_LOCK_WAIT: '10500'\n\s+REGION: us\n\s+CLOUD_TOKEN_AUDIENCE: us.example\n/);
94
+ expect(yaml).toMatch(/wave-2-prod-eu:\n\s+runs-on: eu-apply\n\s+needs:\n\s+- wave-2-prod-decide\n\s+container: node:22\n\s+timeout-minutes: 180\n\s+env:\n\s+CHANT_LOCK_WAIT: '10500'\n\s+steps:/);
95
95
  expect(yaml).not.toContain("contents: write");
96
96
  });
97
97
 
@@ -138,3 +138,12 @@ describe("an Op wave's jobs by cloud identity (#4332)", () => {
138
138
  expect(jobs.every((j) => j.command[0] === "chant")).toBe(true);
139
139
  });
140
140
  });
141
+
142
+ describe("the ledger lock (ruling for ci-products 2026-10-28)", () => {
143
+ test("the waves workflow carries no concurrency group, workflow or job; each wave job carries its timeout and the lock wait", () => {
144
+ const yaml = generateForgejoOpWavesPipeline(spec, { specFile: "waves.json" }).files[0]!.yaml;
145
+ expect(yaml).not.toContain("concurrency:");
146
+ expect(yaml.match(/timeout-minutes: 180\n/g)).toHaveLength(3);
147
+ expect(yaml.match(/CHANT_LOCK_WAIT: '10500'\n/g)).toHaveLength(3);
148
+ });
149
+ });
@@ -25,6 +25,14 @@
25
25
  * The apply-job guard (#4624) starts each wave job as on GitHub, with the
26
26
  * forge set to Forgejo: it checks the ref and, for a `self-hosted` label,
27
27
  * the runner, and no forge environment, since Forgejo has none.
28
+ *
29
+ * Like GitHub's, the workflow carries no concurrency group (ruling for
30
+ * ci-products 2026-10-28, "Ledger lock"; Forgejo 16.0.5 has no job-level
31
+ * concurrency either). Two pushes run their waves side by side: a stock
32
+ * Pulumi stack or a Terraform root waits for its row on chant's ledger,
33
+ * oldest commit first, up to the job's `timeout-minutes`, and a plunge stack
34
+ * on the resource grain leases its resource rows and never waits on another
35
+ * stack.
28
36
  */
29
37
 
30
38
  import { buildGithubOpWavesDoc } from "@intentius/chant-lexicon-github/components/generate-op-waves-pipeline";
@@ -22,6 +22,13 @@ describe("the Forgejo workflow with ci.locks: plan", () => {
22
22
  expect(doc.jobs.unlock!.steps.some((s) => s.run === 'chant unlock --pr "$PR_NUMBER"')).toBe(true);
23
23
  });
24
24
 
25
+ test("with plywood's words the lines run through its bin (plywood#22)", () => {
26
+ const words = { product: "plywood", bin: "npx --no-install plywood" };
27
+ const own = parseYAML(generateForgejoPipeline(ESTATE, { env: "prod", prLoop: { locks: "plan", words } }).yaml) as Doc;
28
+ expect(own.jobs.lock!.steps.some((s) => s.run?.startsWith("npx --no-install plywood lock --from-report ") && s.run.endsWith("--forge forgejo"))).toBe(true);
29
+ expect(own.jobs.unlock!.steps.some((s) => s.run === 'npx --no-install plywood unlock --pr "$PR_NUMBER"')).toBe(true);
30
+ });
31
+
25
32
  test("without ci.locks neither job is written", () => {
26
33
  const plain = parseYAML(generateForgejoPipeline(ESTATE, { env: "prod", prLoop: {} }).yaml) as Doc;
27
34
  expect(Object.keys(plain.jobs)).not.toContain("lock");