@intentius/chant-lexicon-gitlab 0.56.0 → 0.58.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.
@@ -3,10 +3,12 @@
3
3
  *
4
4
  * The Op counterpart to `./generate-pipeline.ts` (#563): that module
5
5
  * synthesizes a deploy-time component graph as one `.gitlab-ci.yml`; this one
6
- * synthesizes a cron-triggered job per stateless Op — the CI-native
7
- * alternative to a Temporal `TemporalSchedule` for downstream projects that
8
- * don't run Temporal (`WorkflowAuditOp`/`PipelineAuditOp`/`ReconcileOp` all
9
- * accept an optional `schedule` precisely for this).
6
+ * synthesizes a cron-triggered job per stateless Op. An Op's cadence is an
7
+ * `OpSchedule` on the Op itself (`packages/core/src/op/types.ts`),
8
+ * runtime-neutral data each reader interprets; this module is the reader that
9
+ * turns it into a GitLab pipeline schedule (`WorkflowAuditOp`/
10
+ * `PipelineAuditOp`/`ReconcileOp` all accept an optional `schedule` precisely
11
+ * for this).
10
12
  *
11
13
  * Unlike GitHub Actions' per-workflow `on.schedule`, GitLab has no in-file
12
14
  * cron at all — a schedule is a project-level object (Settings → CI/CD →
@@ -1 +1 @@
1
- {"version":3,"file":"generate-op-pipeline.d.ts","sourceRoot":"","sources":["../../src/components/generate-op-pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,KAAK,EACV,wBAAwB,IAAI,uBAAuB,EAGnD,gBAAgB,IAAI,sBAAsB,EAC1C,eAAe,EAChB,MAAM,0BAA0B,CAAC;AAElC,YAAY,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,CAAC;AAmBhE;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,eAAe,EAAE,EACtB,OAAO,GAAE,uBAA4B,GACpC,sBAAsB,CA6CxB"}
1
+ {"version":3,"file":"generate-op-pipeline.d.ts","sourceRoot":"","sources":["../../src/components/generate-op-pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAIH,OAAO,KAAK,EACV,wBAAwB,IAAI,uBAAuB,EAGnD,gBAAgB,IAAI,sBAAsB,EAC1C,eAAe,EAChB,MAAM,0BAA0B,CAAC;AAElC,YAAY,EAAE,uBAAuB,EAAE,sBAAsB,EAAE,CAAC;AAmBhE;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,eAAe,EAAE,EACtB,OAAO,GAAE,uBAA4B,GACpC,sBAAsB,CAoDxB"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGhD,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAQxC,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAG/C,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAG7D,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AAIjC,cAAc,mBAAmB,CAAC;AAGlC,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACnI,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAGtI,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACrF,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpF,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,cAAc,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAGzH,OAAO,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGhD,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAOxC,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAG/C,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAG7D,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AAIjC,cAAc,mBAAmB,CAAC;AAGlC,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACnI,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAGtI,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACrF,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpF,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,cAAc,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAGzH,OAAO,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC"}
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "algorithm": "sha256",
3
3
  "artifacts": {
4
- "manifest.json": "2d555a71e6c5f87541933dc5961f4d8ee115b98a3113d48c7368362e217c7e44",
4
+ "manifest.json": "35158c32b55ed8f86ec453b7575d06fd8005641a5edb2ad972f0f4cf06fccd7e",
5
5
  "meta.json": "931fc3246a55645b1493080bbeb160e5d205e42349e8bdca96ca243adb5f0da3",
6
6
  "types/index.d.ts": "5cd2e99f135a929b72bdd822d00d780d39b1cd407ba0cfb3d511c7ac9d667b58",
7
7
  "rules/artifact-no-expiry.ts": "3f3cabf9792cbf8207e53a25f506715466b19ec25e9c3b4d0d77fed6b2eb4542",
@@ -55,5 +55,5 @@
55
55
  "skills/chant-gitlab-migrate.md": "4853d04980560b379e5b0f7267dcb0a1e5d5879cb9e9931681ce76b2a5fe69d8",
56
56
  "skills/chant-gitlab-patterns.md": "6d9a44e9e8de4c3820be9d65381b0d2ede4cb3626aaaf0011e21838a9fbf556e"
57
57
  },
58
- "composite": "23a82eb88eb182226439ef2d6a90df9a6e2fa6552f1788eff10ae340482de92f"
58
+ "composite": "59706e7a6edf95b2ecec5fe2220d0899b0282322ef921583a940a03fb623e7c0"
59
59
  }
@@ -1 +1 @@
1
- {"version":3,"file":"audit-catalog.d.ts","sourceRoot":"","sources":["../../src/lint/audit-catalog.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAA0E,KAAK,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAEvI,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CA6CvD,CAAC"}
1
+ {"version":3,"file":"audit-catalog.d.ts","sourceRoot":"","sources":["../../src/lint/audit-catalog.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAA0E,KAAK,QAAQ,EAAgB,MAAM,gCAAgC,CAAC;AAGrJ,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CA6CvD,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Prior art for these audit rules: the open-source tools whose checks cover the
3
+ * same condition, credited per rule. See packages/core/src/audit/prior-art.ts for
4
+ * the registry, the relation vocabulary, and why this is credit rather than
5
+ * authority. Kept by hand; the prior-art sweep (scripts/prior-art-sweep.ts) reports
6
+ * when a credited tool's index no longer lists a rule cited here.
7
+ */
8
+ import type { Lineage } from "@intentius/chant/audit/catalog";
9
+ export declare const gitlabAuditLineage: Record<string, Lineage[]>;
10
+ //# sourceMappingURL=audit-lineage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-lineage.d.ts","sourceRoot":"","sources":["../../src/lint/audit-lineage.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAC;AAE9D,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CA+DxD,CAAC"}
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gitlab",
3
- "version": "0.56.0",
3
+ "version": "0.58.0",
4
4
  "chantVersion": ">=0.1.0",
5
5
  "namespace": "GitLab",
6
6
  "intrinsics": [
@@ -9,7 +9,7 @@ export interface GitlabPipelineArgs {
9
9
  /**
10
10
  * Trigger a GitLab CI pipeline and wait for it to complete successfully.
11
11
  * Requires `glab` CLI authenticated in the environment.
12
- * Uses longInfra profile — 20m timeout, heartbeat every poll.
12
+ * Uses the longInfra profile: 20m timeout, three attempts backing off from 30s.
13
13
  */
14
14
  export declare function gitlabPipeline(args: GitlabPipelineArgs, signal?: AbortSignal): Promise<void>;
15
15
  //# sourceMappingURL=gitlab.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"gitlab.d.ts","sourceRoot":"","sources":["../../../src/op/activities/gitlab.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,kBAAkB;IACjC,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,kBAAkB,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAsClG"}
1
+ {"version":3,"file":"gitlab.d.ts","sourceRoot":"","sources":["../../../src/op/activities/gitlab.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,kBAAkB;IACjC,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,kBAAkB,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAqClG"}
@@ -1,10 +1,11 @@
1
1
  /**
2
2
  * gitlab Op activities — resolved by the core activity registry when a project's
3
3
  * `chant.config.ts` lists the `gitlab` lexicon. `gitlabPipeline` triggers a
4
- * pipeline over the GitLab CLI with heartbeat/retry semantics; relocated from the
5
- * temporal lexicon (#809) so gitlab's imperative activity lives with its product.
6
- * The `gitlabPipeline` step builder stays in core, re-exported from the temporal
7
- * Op-authoring barrel like the other core builders.
4
+ * pipeline over the GitLab CLI and polls it to completion under the step's
5
+ * profile; relocated from the hosting lexicon (#809) so gitlab's imperative
6
+ * activity lives with its product. The `gitlabPipeline` step builder stays in
7
+ * core and reaches authors through `@intentius/chant/op` like the other core
8
+ * builders.
8
9
  */
9
10
  export { gitlabPipeline } from "./gitlab.js";
10
11
  export type { GitlabPipelineArgs } from "./gitlab.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/op/activities/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC1C,YAAY,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/op/activities/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC1C,YAAY,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC"}
@@ -7,12 +7,11 @@
7
7
  * `./activities/gitlab.ts`. `opts`'s type below IS `GitlabPipelineArgs`
8
8
  * itself (via `Omit`/`WithStepRefs`) — never a hand-restated mirror.
9
9
  *
10
- * `core`'s own `gitlabPipeline` (in `@intentius/chant/op`, re-exported from
11
- * `@intentius/chant-lexicon-temporal`) is UNCHANGED and produces a
12
- * byte-identical `ActivityStep` for the same inputs — purely additive, and
13
- * deliberately not swapped into the temporal barrel (see
10
+ * `core`'s own `gitlabPipeline` (in `@intentius/chant/op`) is UNCHANGED and
11
+ * produces a byte-identical `ActivityStep` for the same inputs — purely
12
+ * additive, and deliberately not swapped into core's barrel (see
14
13
  * `lexicons/k8s/src/op/builders.ts`'s module doc for why: that would make
15
- * temporal depend on this package at runtime). An author who wants the typed
14
+ * core depend on this package at runtime). An author who wants the typed
16
15
  * surface imports it from here — `@intentius/chant-lexicon-gitlab`.
17
16
  */
18
17
  import { type ActivityStep, type NamedActivityStep, type WithStepRefs } from "@intentius/chant/op";
@@ -1 +1 @@
1
- {"version":3,"file":"builders.d.ts","sourceRoot":"","sources":["../../src/op/builders.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,YAAY,EAClB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAE9D;;;;GAIG;AACH,eAAO,MAAM,cAAc,GACzB,MAAM,MAAM,EACZ,OAAO,YAAY,CAAC,IAAI,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAAC,GAAG;IAAE,OAAO,CAAC,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,KACzG,iBAGF,CAAC"}
1
+ {"version":3,"file":"builders.d.ts","sourceRoot":"","sources":["../../src/op/builders.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,YAAY,EAClB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAE9D;;;;GAIG;AACH,eAAO,MAAM,cAAc,GACzB,MAAM,MAAM,EACZ,OAAO,YAAY,CAAC,IAAI,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAAC,GAAG;IAAE,OAAO,CAAC,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,KACzG,iBAGF,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intentius/chant-lexicon-gitlab",
3
- "version": "0.56.0",
3
+ "version": "0.58.0",
4
4
  "description": "GitLab CI lexicon for chant — declarative IaC in TypeScript",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://intentius.io/chant",
@@ -67,8 +67,8 @@
67
67
  "typescript": "^5.9.3"
68
68
  },
69
69
  "peerDependencies": {
70
- "@intentius/chant": "^0.56.0",
71
- "@intentius/chant-lexicon-github": "^0.56.0",
70
+ "@intentius/chant": "^0.58.0",
71
+ "@intentius/chant-lexicon-github": "^0.58.0",
72
72
  "typescript": "^5.9.3"
73
73
  },
74
74
  "peerDependenciesMeta": {
@@ -70,6 +70,18 @@ describe("generateGitlabOpPipeline: one file, one job per scheduled Op", () => {
70
70
  });
71
71
  });
72
72
 
73
+ describe("generateGitlabOpPipeline: no pull_request/push event model (#2084)", () => {
74
+ test("a pull_request trigger throws a clear error instead of silently ignoring it", () => {
75
+ const specs: ScheduledOpSpec[] = [{ name: "tf-plan", trigger: { kind: "pull_request" } }];
76
+ expect(() => generateGitlabOpPipeline(specs)).toThrow(/pull_request.*GitLab has no pull_request\/push event model/s);
77
+ });
78
+
79
+ test("a push trigger throws a clear error instead of silently ignoring it", () => {
80
+ const specs: ScheduledOpSpec[] = [{ name: "tf-apply", trigger: { kind: "push" } }];
81
+ expect(() => generateGitlabOpPipeline(specs)).toThrow(/push.*GitLab has no pull_request\/push event model/s);
82
+ });
83
+ });
84
+
73
85
  describe("generateGitlabOpPipeline: a cross-cutting change is one generator edit, not per-job", () => {
74
86
  test("runCommand/beforeScript/extraScript apply uniformly across every job", () => {
75
87
  const specs: ScheduledOpSpec[] = [
@@ -77,7 +89,7 @@ describe("generateGitlabOpPipeline: a cross-cutting change is one generator edit
77
89
  { name: "prod-reconcile", schedule: "0 * * * *" },
78
90
  ];
79
91
  const result = generateGitlabOpPipeline(specs, {
80
- runCommand: ["chant", "run", "{name}", "--temporal"],
92
+ runCommand: ["chant", "run", "{name}", "--json"],
81
93
  beforeScript: ["npm ci"],
82
94
  extraScript: ["echo done"],
83
95
  });
@@ -87,7 +99,7 @@ describe("generateGitlabOpPipeline: a cross-cutting change is one generator edit
87
99
  const job = parsed[spec.name] as Record<string, unknown>;
88
100
  const script = job.script as string[];
89
101
  expect(script[0]).toBe("npm ci");
90
- expect(script[1]).toContain("--temporal");
102
+ expect(script[1]).toContain("--json");
91
103
  expect(script[2]).toBe("echo done");
92
104
  }
93
105
  });
@@ -3,10 +3,12 @@
3
3
  *
4
4
  * The Op counterpart to `./generate-pipeline.ts` (#563): that module
5
5
  * synthesizes a deploy-time component graph as one `.gitlab-ci.yml`; this one
6
- * synthesizes a cron-triggered job per stateless Op — the CI-native
7
- * alternative to a Temporal `TemporalSchedule` for downstream projects that
8
- * don't run Temporal (`WorkflowAuditOp`/`PipelineAuditOp`/`ReconcileOp` all
9
- * accept an optional `schedule` precisely for this).
6
+ * synthesizes a cron-triggered job per stateless Op. An Op's cadence is an
7
+ * `OpSchedule` on the Op itself (`packages/core/src/op/types.ts`),
8
+ * runtime-neutral data each reader interprets; this module is the reader that
9
+ * turns it into a GitLab pipeline schedule (`WorkflowAuditOp`/
10
+ * `PipelineAuditOp`/`ReconcileOp` all accept an optional `schedule` precisely
11
+ * for this).
10
12
  *
11
13
  * Unlike GitHub Actions' per-workflow `on.schedule`, GitLab has no in-file
12
14
  * cron at all — a schedule is a project-level object (Settings → CI/CD →
@@ -27,6 +29,7 @@
27
29
  */
28
30
 
29
31
  import { emitYAML } from "@intentius/chant/yaml";
32
+ import { resolveOpTrigger } from "@intentius/chant/lexicon";
30
33
  import type {
31
34
  ComponentPipelineOptions as GenerateGitlabOpOptions,
32
35
  OpFindingMode,
@@ -49,9 +52,9 @@ const STAGE = "scheduled-ops";
49
52
  const SELECTOR_VAR = "CHANT_SCHEDULED_OP";
50
53
 
51
54
  /** One setup line per Op in the generated file's header comment. */
52
- function setupLine(spec: ScheduledOpSpec, jobName: string, mode: OpFindingMode): string {
55
+ function setupLine(spec: ScheduledOpSpec, cron: string, jobName: string, mode: OpFindingMode): string {
53
56
  const tokenNote = mode === "report" ? "" : " — needs a GITLAB_TOKEN CI/CD variable (masked, scope: api)";
54
- return `# ${jobName}: cron "${spec.schedule}", ${SELECTOR_VAR}="${spec.name}", finding-mode ${mode}${tokenNote}`;
57
+ return `# ${jobName}: cron "${cron}", ${SELECTOR_VAR}="${spec.name}", finding-mode ${mode}${tokenNote}`;
55
58
  }
56
59
 
57
60
  /**
@@ -83,9 +86,16 @@ export function generateGitlabOpPipeline(
83
86
 
84
87
  for (const spec of ops) {
85
88
  const findingMode = spec.findingMode ?? "report";
89
+ const trigger = resolveOpTrigger(spec);
90
+ if (trigger.kind !== "cron") {
91
+ throw new Error(
92
+ `Scheduled Op "${spec.name}" has a "${trigger.kind}" trigger, but GitLab has no pull_request/push event model ` +
93
+ `(#2084) — only a project-level Pipeline Schedule (cron). Give it a cron trigger, or generate it for github/forgejo instead.`,
94
+ );
95
+ }
86
96
  const jobName = toJobName(spec.name);
87
- jobs.push({ jobName, op: spec.name, schedule: spec.schedule, findingMode });
88
- headerLines.push(setupLine(spec, jobName, findingMode));
97
+ jobs.push({ jobName, op: spec.name, trigger, findingMode });
98
+ headerLines.push(setupLine(spec, trigger.schedule, jobName, findingMode));
89
99
 
90
100
  const runParts = runCommand.map((part) => part.replace("{name}", spec.name));
91
101
  const script = [...beforeScript, runParts.join(" "), ...extraScript];
@@ -186,7 +186,7 @@ describe("generateGitlabPipeline: a cross-cutting change is one generator edit,
186
186
  test("changing the trigger command (runCommand) updates every job's script uniformly", () => {
187
187
  const components = pilotComponents();
188
188
  const result = generateGitlabPipeline(components, {
189
- runCommand: ["chant", "run", "--components", "{name}", "--env", "staging", "--temporal"],
189
+ runCommand: ["chant", "run", "--components", "{name}", "--env", "staging", "--verbose"],
190
190
  });
191
191
  const parsed = parseYAML(result.yaml);
192
192
 
@@ -194,7 +194,7 @@ describe("generateGitlabPipeline: a cross-cutting change is one generator edit,
194
194
  const script = (parsed[job.jobName] as Record<string, unknown>).script as string[];
195
195
  // The runCommand prefix reflects in every job; output-threading flags
196
196
  // (--seed-outputs/--dump-outputs) may be appended per the dependency graph.
197
- expect(script[0].startsWith(`chant run --components ${job.component} --env staging --temporal`)).toBe(true);
197
+ expect(script[0].startsWith(`chant run --components ${job.component} --env staging --verbose`)).toBe(true);
198
198
  }
199
199
  });
200
200
 
package/src/index.ts CHANGED
@@ -7,9 +7,8 @@ export { gitlabPlugin } from "./plugin";
7
7
  // Typed Op step-builder wrapper (chant #1288 Stage 2) — gitlabPipeline with
8
8
  // authoring-time types derived from this lexicon's own GitlabPipelineArgs
9
9
  // (see lexicons/k8s/src/op/builders.ts's module doc for why this lives here
10
- // rather than in core or the temporal barrel). Opt-in:
11
- // `@intentius/chant-lexicon-temporal`'s same-named export is core's original
12
- // untyped builder, unchanged, for cloud-agnostic authoring.
10
+ // rather than in core). Opt-in: `@intentius/chant/op`'s same-named export is
11
+ // core's original untyped builder, unchanged, for cloud-agnostic authoring.
13
12
  export { gitlabPipeline } from "./op/builders";
14
13
 
15
14
  // Intrinsics
@@ -2,7 +2,8 @@
2
2
  * The gitlab lexicon's chant audit catalog — metadata for its post-synth rules
3
3
  * (WGL GitLab CI rules). Contributed via gitlabPlugin.auditCatalog() (#687).
4
4
  */
5
- import { auditRule, GH_INJECTION, GH_OIDC, GH_PWN, GH_SECRETS, SCORECARD_PINNED, type RuleMeta } from "@intentius/chant/audit/catalog";
5
+ import { auditRule, GH_INJECTION, GH_OIDC, GH_PWN, GH_SECRETS, SCORECARD_PINNED, type RuleMeta, applyLineage } from "@intentius/chant/audit/catalog";
6
+ import { gitlabAuditLineage } from "./audit-lineage";
6
7
 
7
8
  export const gitlabAuditCatalog: Record<string, RuleMeta> = {
8
9
  WGL010: auditRule("WGL010", "merge-worthy", "guidance", "Job references an undefined stage", "Add the stage to `stages:` or fix the job's `stage:`.", { category: "correctness" }),
@@ -50,3 +51,6 @@ export const gitlabAuditCatalog: Record<string, RuleMeta> = {
50
51
  WGL049: auditRule("WGL049", "report-only", "guidance", "Dependency install without a cache", "Add a `cache:` covering the dependency directory.", { category: "efficiency" }),
51
52
  WGL050: auditRule("WGL050", "report-only", "guidance", "Merge-request job missing interruptible", "Add `interruptible: true` so a superseded pipeline can be cancelled.", { category: "efficiency" }),
52
53
  };
54
+
55
+ // Prior art credits live beside the rules in ./audit-lineage.ts (see core audit/prior-art.ts).
56
+ applyLineage(gitlabAuditCatalog, gitlabAuditLineage);
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Prior art for these audit rules: the open-source tools whose checks cover the
3
+ * same condition, credited per rule. See packages/core/src/audit/prior-art.ts for
4
+ * the registry, the relation vocabulary, and why this is credit rather than
5
+ * authority. Kept by hand; the prior-art sweep (scripts/prior-art-sweep.ts) reports
6
+ * when a credited tool's index no longer lists a rule cited here.
7
+ */
8
+ import type { Lineage } from "@intentius/chant/audit/catalog";
9
+
10
+ export const gitlabAuditLineage: Record<string, Lineage[]> = {
11
+ WGL010: [
12
+ { tool: "gitlab-docs", rule: "stage: supported values are the default stages or stages listed in `stages`", url: "https://docs.gitlab.com/ci/yaml/#stage", relation: "equivalent" },
13
+ ],
14
+ WGL012: [
15
+ { tool: "gitlab-docs", rule: "Deprecated keywords (only/except, globally-defined image/services/cache/before_script/after_script)", url: "https://docs.gitlab.com/ci/yaml/deprecated_keywords/#only--except", relation: "equivalent" },
16
+ ],
17
+ WGL013: [
18
+ { tool: "gitlab-docs", rule: "Error: 'job' does not exist in the pipeline (needs)", url: "https://docs.gitlab.com/ci/yaml/needs/#error-job-does-not-exist-in-the-pipeline", relation: "equivalent" },
19
+ ],
20
+ WGL014: [
21
+ { tool: "gitlab-docs", rule: "extends: supported values are the name(s) of another job in the pipeline", url: "https://docs.gitlab.com/ci/yaml/#extends", relation: "equivalent" },
22
+ ],
23
+ WGL016: [
24
+ { tool: "gitlab-docs", rule: "CI/CD variable security (secrets belong in masked/protected variables, not in .gitlab-ci.yml)", url: "https://docs.gitlab.com/ci/variables/#cicd-variable-security", relation: "overlaps" },
25
+ ],
26
+ WGL023: [
27
+ { tool: "gitlab-docs", rule: "Pipeline warning: Job may allow multiple pipelines to run for a single action (final `when` rule without conditions)", url: "https://docs.gitlab.com/ci/debugging/#job-may-allow-multiple-pipelines-to-run-for-a-single-action-warning", relation: "overlaps" },
28
+ ],
29
+ WGL024: [
30
+ { tool: "gitlab-docs", rule: "allow_failure default: true for manual jobs, false for rules:when: manual", url: "https://docs.gitlab.com/ci/yaml/#allow_failure", relation: "overlaps" },
31
+ ],
32
+ WGL025: [
33
+ { tool: "gitlab-docs", rule: "cache:key: all jobs with `cache` but no `cache:key` share the `default` cache", url: "https://docs.gitlab.com/ci/yaml/#cachekey", relation: "overlaps" },
34
+ ],
35
+ WGL026: [
36
+ { tool: "gitlab-docs", rule: "Docker-in-Docker with TLS enabled (recommended); DOCKER_TLS_CERTDIR", url: "https://docs.gitlab.com/ci/docker/docker_in_docker/#docker-in-docker-with-tls-enabled-in-the-docker-executor-recommended", relation: "overlaps" },
37
+ ],
38
+ WGL029: [
39
+ { tool: "gitlab-docs", rule: "include:project ref guidance: use a specific SHA hash, protected branch/tag rules", url: "https://docs.gitlab.com/ci/yaml/#includeproject", relation: "overlaps" },
40
+ { tool: "gitlab-docs", rule: "CI/CD component security best practices: use pinned versions (commit SHA preferred), avoid `latest`", url: "https://docs.gitlab.com/ci/components/#for-component-users", relation: "overlaps" },
41
+ ],
42
+ WGL030: [
43
+ { tool: "gitlab-docs", rule: "include:remote: treat as a third-party dependency; verify integrity with include:integrity", url: "https://docs.gitlab.com/ci/yaml/#includeremote", relation: "overlaps" },
44
+ ],
45
+ WGL031: [
46
+ { tool: "gitlab-docs", rule: "Use checksum to keep your image secure (image@sha256:digest)", url: "https://docs.gitlab.com/ci/docker/using_docker_images/#use-checksum-to-keep-your-image-secure", relation: "overlaps" },
47
+ ],
48
+ WGL033: [
49
+ { tool: "gitlab-docs", rule: "id_tokens: the required `aud` sub-keyword configures the aud claim", url: "https://docs.gitlab.com/ci/yaml/#id_tokens", relation: "overlaps" },
50
+ ],
51
+ WGL035: [
52
+ { tool: "poutine", rule: "injection", url: "https://boostsecurityio.github.io/poutine/rules/injection/", relation: "overlaps" },
53
+ ],
54
+ WGL038: [
55
+ { tool: "gitlab-docs", rule: "Protect a CI/CD variable (available only to protected branches/tags)", url: "https://docs.gitlab.com/ci/variables/#protect-a-cicd-variable", relation: "overlaps" },
56
+ { tool: "gitlab-docs", rule: "Merge request pipelines from forked projects can steal secrets in the parent project", url: "https://docs.gitlab.com/ci/pipelines/merge_request_pipelines/#use-with-forked-projects", relation: "overlaps" },
57
+ ],
58
+ WGL039: [
59
+ { tool: "gitlab-docs", rule: "CI/CD variable security: accidental-leak-job example (echo of $PASSWORD); mask sensitive variables", url: "https://docs.gitlab.com/ci/variables/#mask-a-cicd-variable", relation: "overlaps" },
60
+ ],
61
+ WGL044: [
62
+ { tool: "gitlab-docs", rule: "artifacts:public (default true: downloadable by anonymous users in public pipelines)", url: "https://docs.gitlab.com/ci/yaml/#artifactspublic", relation: "overlaps" },
63
+ ],
64
+ WGL046: [
65
+ { tool: "gitlab-docs", rule: "Cache key names: protected and non-protected branches do not share the cache by default", url: "https://docs.gitlab.com/ci/caching/#cache-key-names", relation: "overlaps" },
66
+ ],
67
+ WGL047: [
68
+ { tool: "poutine", rule: "unverified_script_exec", url: "https://boostsecurityio.github.io/poutine/rules/unverified_script_exec/", relation: "equivalent" },
69
+ ],
70
+ WGL048: [
71
+ { tool: "gitlab-docs", rule: "Use pipeline names (workflow:name)", url: "https://docs.gitlab.com/ci/debugging/#use-pipeline-names", relation: "overlaps" },
72
+ ],
73
+ };
@@ -1,6 +1,6 @@
1
1
  import { exec } from "node:child_process";
2
2
  import { promisify } from "node:util";
3
- import { safeHeartbeat, sleep } from "@intentius/chant/op";
3
+ import { sleep } from "@intentius/chant/op";
4
4
 
5
5
  const execAsync = promisify(exec);
6
6
 
@@ -16,7 +16,7 @@ export interface GitlabPipelineArgs {
16
16
  /**
17
17
  * Trigger a GitLab CI pipeline and wait for it to complete successfully.
18
18
  * Requires `glab` CLI authenticated in the environment.
19
- * Uses longInfra profile — 20m timeout, heartbeat every poll.
19
+ * Uses the longInfra profile: 20m timeout, three attempts backing off from 30s.
20
20
  */
21
21
  export async function gitlabPipeline(args: GitlabPipelineArgs, signal?: AbortSignal): Promise<void> {
22
22
  const ref = args.ref ?? "HEAD";
@@ -34,7 +34,6 @@ export async function gitlabPipeline(args: GitlabPipelineArgs, signal?: AbortSig
34
34
  while (true) {
35
35
  if (signal?.aborted) throw new Error("gitlabPipeline aborted");
36
36
  attempt++;
37
- safeHeartbeat({ step: "gitlabPipeline", project: args.name, attempt });
38
37
 
39
38
  const { stdout } = await execAsync(
40
39
  `glab ci status --project ${args.name} --format json`,
@@ -1,10 +1,11 @@
1
1
  /**
2
2
  * gitlab Op activities — resolved by the core activity registry when a project's
3
3
  * `chant.config.ts` lists the `gitlab` lexicon. `gitlabPipeline` triggers a
4
- * pipeline over the GitLab CLI with heartbeat/retry semantics; relocated from the
5
- * temporal lexicon (#809) so gitlab's imperative activity lives with its product.
6
- * The `gitlabPipeline` step builder stays in core, re-exported from the temporal
7
- * Op-authoring barrel like the other core builders.
4
+ * pipeline over the GitLab CLI and polls it to completion under the step's
5
+ * profile; relocated from the hosting lexicon (#809) so gitlab's imperative
6
+ * activity lives with its product. The `gitlabPipeline` step builder stays in
7
+ * core and reaches authors through `@intentius/chant/op` like the other core
8
+ * builders.
8
9
  */
9
10
  export { gitlabPipeline } from "./gitlab";
10
11
  export type { GitlabPipelineArgs } from "./gitlab";
@@ -7,12 +7,11 @@
7
7
  * `./activities/gitlab.ts`. `opts`'s type below IS `GitlabPipelineArgs`
8
8
  * itself (via `Omit`/`WithStepRefs`) — never a hand-restated mirror.
9
9
  *
10
- * `core`'s own `gitlabPipeline` (in `@intentius/chant/op`, re-exported from
11
- * `@intentius/chant-lexicon-temporal`) is UNCHANGED and produces a
12
- * byte-identical `ActivityStep` for the same inputs — purely additive, and
13
- * deliberately not swapped into the temporal barrel (see
10
+ * `core`'s own `gitlabPipeline` (in `@intentius/chant/op`) is UNCHANGED and
11
+ * produces a byte-identical `ActivityStep` for the same inputs — purely
12
+ * additive, and deliberately not swapped into core's barrel (see
14
13
  * `lexicons/k8s/src/op/builders.ts`'s module doc for why: that would make
15
- * temporal depend on this package at runtime). An author who wants the typed
14
+ * core depend on this package at runtime). An author who wants the typed
16
15
  * surface imports it from here — `@intentius/chant-lexicon-gitlab`.
17
16
  */
18
17