@intentius/chant-lexicon-github 0.53.0 → 0.54.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.
@@ -54,9 +54,24 @@ export type { GeneratedJob, GenerateGithubOptions, GenerateGithubResult };
54
54
  * apply its dialect transform + emit, rather than re-deriving the graph.
55
55
  */
56
56
  export interface GithubPipelineDoc {
57
+ /**
58
+ * The workflow's `name:` — `chant-components-<env>` (#2046), so two
59
+ * pipelines generated for two environments are tellable apart in the
60
+ * committed file, the Actions UI, and the API without lexing a job's
61
+ * `run:` line.
62
+ */
63
+ name: string;
64
+ /** The environment the pipeline deploys — `options.env` with the default applied (#2046). */
65
+ environment: string;
57
66
  /** The `on:` trigger mapping (a bare `workflow_dispatch`). */
58
67
  on: Record<string, unknown>;
59
- /** The `env:` mapping, when `options.variables` is set. */
68
+ /**
69
+ * The `env:` mapping: the caller's `variables`, plus `CHANT_ENV` naming the
70
+ * deployed environment (#2046) — the machine-readable identity on the
71
+ * document itself. `CHANT_ENV` always reflects the environment baked into
72
+ * the run lines, so a caller-supplied variable of the same name cannot make
73
+ * the document lie about what its jobs deploy.
74
+ */
60
75
  env?: Record<string, unknown>;
61
76
  /** The `jobs:` mapping — one entry per component. */
62
77
  jobsDoc: Record<string, unknown>;
@@ -1 +1 @@
1
- {"version":3,"file":"generate-pipeline.d.ts","sourceRoot":"","sources":["../../src/components/generate-pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAGH,OAAO,EAAyB,KAAK,eAAe,EAAE,MAAM,oCAAoC,CAAC;AACjG,OAAO,KAAK,EACV,oBAAoB,IAAI,YAAY,EACpC,wBAAwB,IAAI,qBAAqB,EACjD,uBAAuB,IAAI,oBAAoB,EAChD,MAAM,0BAA0B,CAAC;AAElC,YAAY,EAAE,YAAY,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,CAAC;AAE1E;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IAChC,8DAA8D;IAC9D,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5B,2DAA2D;IAC3D,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,qDAAqD;IACrD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,uEAAuE;IACvE,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,0DAA0D;IAC1D,IAAI,EAAE,YAAY,EAAE,CAAC;CACtB;AAmBD;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,eAAe,EAAE,EAC7B,OAAO,GAAE,qBAA0B,GAClC,iBAAiB,CAwFnB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,iBAAiB,GAAG,MAAM,CAQ/D;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,eAAe,EAAE,EAC7B,OAAO,GAAE,qBAA0B,GAClC,oBAAoB,CAGtB"}
1
+ {"version":3,"file":"generate-pipeline.d.ts","sourceRoot":"","sources":["../../src/components/generate-pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAGH,OAAO,EAAyB,KAAK,eAAe,EAAE,MAAM,oCAAoC,CAAC;AACjG,OAAO,KAAK,EACV,oBAAoB,IAAI,YAAY,EACpC,wBAAwB,IAAI,qBAAqB,EACjD,uBAAuB,IAAI,oBAAoB,EAChD,MAAM,0BAA0B,CAAC;AAElC,YAAY,EAAE,YAAY,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,CAAC;AAE1E;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;;OAKG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,6FAA6F;IAC7F,WAAW,EAAE,MAAM,CAAC;IACpB,8DAA8D;IAC9D,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5B;;;;;;OAMG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,qDAAqD;IACrD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,uEAAuE;IACvE,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,0DAA0D;IAC1D,IAAI,EAAE,YAAY,EAAE,CAAC;CACtB;AAmBD;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,eAAe,EAAE,EAC7B,OAAO,GAAE,qBAA0B,GAClC,iBAAiB,CA0FnB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,iBAAiB,GAAG,MAAM,CAS/D;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,UAAU,EAAE,eAAe,EAAE,EAC7B,OAAO,GAAE,qBAA0B,GAClC,oBAAoB,CAGtB"}
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "algorithm": "sha256",
3
3
  "artifacts": {
4
- "manifest.json": "1b94e4c8ea61d27b1e99e6e80aa3e9392cbfa6a255f213e9c4c78dabd9e221de",
4
+ "manifest.json": "8376a4151966d96884b6d16ad83e6727cf0a5daa33a1d83dc7cd799ca7d6585d",
5
5
  "meta.json": "dc3977afc2b6ddc4904de906d1b1e448b786b2aced9d82f8eade2ff915203344",
6
- "types/index.d.ts": "1bd44e392981b8b0c01e4db9ca3a7ddb53782276d6210639f478af47241374a1",
6
+ "types/index.d.ts": "f207946d7ab52f712d0c09995366440a6bba8b39358057b0da38ff9c0acca429",
7
7
  "rules/deprecated-action-version.ts": "d41e6e532ab7f623af1bee4ac5279fcb2baada7defa1c5d022a5bc71983e8797",
8
8
  "rules/detect-secrets.ts": "5829832eb7b43993424971041ed386b196850183bffd34bddd6439f99061e4ae",
9
9
  "rules/extract-inline-structs.ts": "8f8147c200de8ffd0620dfdcca2e2cea76a520303ce431479ebecad6aa26aab5",
@@ -77,5 +77,5 @@
77
77
  "skills/chant-github-patterns.md": "bb3abef289a8fdfcf07d6bb2d7289dcb2f38bc0cb0321ea320b78b45a6f548c0",
78
78
  "skills/chant-github-security.md": "aab111cb0871cad30281ce48d7da23663689619351029219e2be019a1a61e394"
79
79
  },
80
- "composite": "03817a7e6869e374379753d1ffa793d31be96c9a4d0ad775ccdee5fdd7388f49"
80
+ "composite": "6608b4fcff3858c45f340b5bb75d09242b60ff117cb48a50a47af98d08b201b0"
81
81
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "github",
3
- "version": "0.53.0",
3
+ "version": "0.54.0",
4
4
  "chantVersion": ">=0.1.0",
5
5
  "namespace": "GitHub",
6
6
  "intrinsics": [
@@ -12,7 +12,7 @@ resource_type: GitHub::Actions::ReusableWorkflowCallJob
12
12
 
13
13
  - `uses` (`string`, required): The location and version of a reusable workflow file to run as a job, of the form './{path/to}/{localfile}.yml' or '{owner}/{repo}/{path}/{filename}@{ref}'. {ref} can be a SHA, a release tag, or a branch name. Using the commit SHA is the safest for stability and security.
14
14
  - `concurrency` (`string | Record<string, any>`, optional): Concurrency ensures that only a single job or workflow using the same concurrency group will run at a time. A concurrency group can be any string or expression. The expression can use any context except for the secrets context. You can also specify concurrency at the workflow level. When a concurrent job or workflow is queued, if another job or workflow using the same concurrency group in the repository is in progress, the queued job or workflow will be pending. By default any previously pending job or workflow in the concurrency group will be canceled; this behavior can be changed with `queue`. To also cancel any currently running job or workflow in the same concurrency group, specify cancel-in-progress: true.
15
- - `if` (`boolean`, optional): You can use the if conditional to prevent a job from running unless a condition is met. You can use any supported context and expression to create a conditional. Expressions in an if conditional do not require the ${{ }} syntax. For more information, see https://help.github.com/en/articles/contexts-and-expression-syntax-for-github-actions.
15
+ - `if` (`boolean | number | string`, optional): You can use the if conditional to prevent a job from running unless a condition is met. You can use any supported context and expression to create a conditional. Expressions in an if conditional do not require the ${{ }} syntax. For more information, see https://help.github.com/en/articles/contexts-and-expression-syntax-for-github-actions.
16
16
  - `name` (`string`, optional): The name of the job displayed on GitHub.
17
17
  - `needs` (`any`, optional)
18
18
  - `permissions` (`any`, optional)
@@ -163,7 +163,7 @@ When a concurrent job or workflow is queued, if another job or workflow using th
163
163
  concurrency?: string | Record<string, any>;
164
164
  /** You can use the if conditional to prevent a job from running unless a condition is met. You can use any supported context and expression to create a conditional.
165
165
  Expressions in an if conditional do not require the ${{ }} syntax. For more information, see https://help.github.com/en/articles/contexts-and-expression-syntax-for-github-actions. */
166
- if?: boolean;
166
+ if?: boolean | number | string;
167
167
  /** The name of the job displayed on GitHub. */
168
168
  name?: string;
169
169
  needs?: any;
@@ -227,9 +227,9 @@ export declare class Strategy {
227
227
  constructor(props: {
228
228
  matrix: Record<string, unknown>;
229
229
  /** When set to true, GitHub cancels all in-progress jobs if any matrix job fails. Default: true */
230
- "fail-fast"?: boolean;
230
+ "fail-fast"?: boolean | string;
231
231
  /** The maximum number of jobs that can run simultaneously when using a matrix job strategy. By default, GitHub will maximize the number of jobs run in parallel depending on the available runners on GitHub-hosted virtual machines. */
232
- "max-parallel"?: number;
232
+ "max-parallel"?: number | string;
233
233
  });
234
234
  }
235
235
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intentius/chant-lexicon-github",
3
- "version": "0.53.0",
3
+ "version": "0.54.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.53.0",
64
+ "@intentius/chant": "^0.54.0",
65
65
  "typescript": "^5.9.3"
66
66
  }
67
67
  }
@@ -249,18 +249,36 @@ describe("generateGithubPipeline: a cross-cutting change is one generator edit,
249
249
  });
250
250
 
251
251
  describe("generateGithubPipeline: options", () => {
252
- test("emits a top-level env: block when variables are provided", () => {
252
+ test("merges caller variables into the env: block alongside CHANT_ENV", () => {
253
253
  const result = generateGithubPipeline(pilotComponents(), {
254
- variables: { CHANT_ENV: "staging" },
254
+ env: "staging",
255
+ variables: { AWS_REGION: "eu-west-1" },
255
256
  });
256
257
  const parsed = parseYAML(result.yaml);
257
- expect(parsed.env).toEqual({ CHANT_ENV: "staging" });
258
+ expect(parsed.env).toEqual({ AWS_REGION: "eu-west-1", CHANT_ENV: "staging" });
258
259
  });
259
260
 
260
- test("omits the env: block when no variables are provided", () => {
261
- const result = generateGithubPipeline(pilotComponents());
262
- const parsed = parseYAML(result.yaml);
263
- expect(parsed.env).toBeUndefined();
261
+ test("the document carries its environment identity: name + CHANT_ENV (#2046)", () => {
262
+ const staging = generateGithubPipeline(pilotComponents(), { env: "staging" });
263
+ const prod = generateGithubPipeline(pilotComponents());
264
+
265
+ // Two environments' workflows are tellable apart without lexing a run: line.
266
+ expect(parseYAML(staging.yaml).name).toBe("chant-components-staging");
267
+ expect(parseYAML(prod.yaml).name).toBe("chant-components-production");
268
+ expect(parseYAML(staging.yaml).env).toEqual({ CHANT_ENV: "staging" });
269
+ expect(parseYAML(prod.yaml).env).toEqual({ CHANT_ENV: "production" });
270
+
271
+ // And the machine-readable result names it too.
272
+ expect(staging.env).toBe("staging");
273
+ expect(prod.env).toBe("production");
274
+ });
275
+
276
+ test("CHANT_ENV always reflects the environment baked into the run lines — a caller variable cannot override it", () => {
277
+ const result = generateGithubPipeline(pilotComponents(), {
278
+ env: "staging",
279
+ variables: { CHANT_ENV: "prod" },
280
+ });
281
+ expect((parseYAML(result.yaml).env as Record<string, unknown>).CHANT_ENV).toBe("staging");
264
282
  });
265
283
 
266
284
  test("uses a custom container image for every job when provided", () => {
@@ -62,9 +62,24 @@ export type { GeneratedJob, GenerateGithubOptions, GenerateGithubResult };
62
62
  * apply its dialect transform + emit, rather than re-deriving the graph.
63
63
  */
64
64
  export interface GithubPipelineDoc {
65
+ /**
66
+ * The workflow's `name:` — `chant-components-<env>` (#2046), so two
67
+ * pipelines generated for two environments are tellable apart in the
68
+ * committed file, the Actions UI, and the API without lexing a job's
69
+ * `run:` line.
70
+ */
71
+ name: string;
72
+ /** The environment the pipeline deploys — `options.env` with the default applied (#2046). */
73
+ environment: string;
65
74
  /** The `on:` trigger mapping (a bare `workflow_dispatch`). */
66
75
  on: Record<string, unknown>;
67
- /** The `env:` mapping, when `options.variables` is set. */
76
+ /**
77
+ * The `env:` mapping: the caller's `variables`, plus `CHANT_ENV` naming the
78
+ * deployed environment (#2046) — the machine-readable identity on the
79
+ * document itself. `CHANT_ENV` always reflects the environment baked into
80
+ * the run lines, so a caller-supplied variable of the same name cannot make
81
+ * the document lie about what its jobs deploy.
82
+ */
68
83
  env?: Record<string, unknown>;
69
84
  /** The `jobs:` mapping — one entry per component. */
70
85
  jobsDoc: Record<string, unknown>;
@@ -185,8 +200,10 @@ export function buildGithubPipelineDoc(
185
200
  });
186
201
 
187
202
  return {
203
+ name: `chant-components-${env}`,
204
+ environment: env,
188
205
  on: { workflow_dispatch: {} },
189
- ...(options.variables && Object.keys(options.variables).length > 0 ? { env: options.variables } : {}),
206
+ env: { ...options.variables, CHANT_ENV: env },
190
207
  jobsDoc,
191
208
  stages,
192
209
  jobs,
@@ -199,6 +216,7 @@ export function buildGithubPipelineDoc(
199
216
  */
200
217
  export function emitPipelineYAML(doc: GithubPipelineDoc): string {
201
218
  const sections: string[] = [];
219
+ sections.push("name: " + emitYAML(doc.name, 0));
202
220
  sections.push("on:" + emitYAML(doc.on, 1));
203
221
  if (doc.env && Object.keys(doc.env).length > 0) {
204
222
  sections.push("env:" + emitYAML(doc.env, 1));
@@ -218,5 +236,5 @@ export function generateGithubPipeline(
218
236
  options: GenerateGithubOptions = {},
219
237
  ): GenerateGithubResult {
220
238
  const doc = buildGithubPipelineDoc(components, options);
221
- return { yaml: emitPipelineYAML(doc), stages: doc.stages, jobs: doc.jobs };
239
+ return { yaml: emitPipelineYAML(doc), stages: doc.stages, jobs: doc.jobs, env: doc.environment };
222
240
  }
@@ -163,7 +163,7 @@ When a concurrent job or workflow is queued, if another job or workflow using th
163
163
  concurrency?: string | Record<string, any>;
164
164
  /** You can use the if conditional to prevent a job from running unless a condition is met. You can use any supported context and expression to create a conditional.
165
165
  Expressions in an if conditional do not require the ${{ }} syntax. For more information, see https://help.github.com/en/articles/contexts-and-expression-syntax-for-github-actions. */
166
- if?: boolean;
166
+ if?: boolean | number | string;
167
167
  /** The name of the job displayed on GitHub. */
168
168
  name?: string;
169
169
  needs?: any;
@@ -227,9 +227,9 @@ export declare class Strategy {
227
227
  constructor(props: {
228
228
  matrix: Record<string, unknown>;
229
229
  /** When set to true, GitHub cancels all in-progress jobs if any matrix job fails. Default: true */
230
- "fail-fast"?: boolean;
230
+ "fail-fast"?: boolean | string;
231
231
  /** The maximum number of jobs that can run simultaneously when using a matrix job strategy. By default, GitHub will maximize the number of jobs run in parallel depending on the available runners on GitHub-hosted virtual machines. */
232
- "max-parallel"?: number;
232
+ "max-parallel"?: number | string;
233
233
  });
234
234
  }
235
235