@intentius/chant-lexicon-gitlab 0.44.14 → 0.45.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/codegen/docs.d.ts.map +1 -1
- package/dist/integrity.json +2 -2
- package/dist/manifest.json +1 -1
- package/package.json +3 -3
- package/src/codegen/docs.ts +3 -836
- package/src/serializer.test.ts +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docs.d.ts","sourceRoot":"","sources":["../../src/codegen/docs.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAiFH;;GAEG;AACH,wBAAsB,YAAY,CAAC,IAAI,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"docs.d.ts","sourceRoot":"","sources":["../../src/codegen/docs.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAiFH;;GAEG;AACH,wBAAsB,YAAY,CAAC,IAAI,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsC9E"}
|
package/dist/integrity.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"algorithm": "sha256",
|
|
3
3
|
"artifacts": {
|
|
4
|
-
"manifest.json": "
|
|
4
|
+
"manifest.json": "a27b63fa5201adcb799321a8f86557e232c4cb5871ad0d9a257cd50adebf58c3",
|
|
5
5
|
"meta.json": "931fc3246a55645b1493080bbeb160e5d205e42349e8bdca96ca243adb5f0da3",
|
|
6
6
|
"types/index.d.ts": "5cd2e99f135a929b72bdd822d00d780d39b1cd407ba0cfb3d511c7ac9d667b58",
|
|
7
7
|
"rules/artifact-no-expiry.ts": "3f3cabf9792cbf8207e53a25f506715466b19ec25e9c3b4d0d77fed6b2eb4542",
|
|
@@ -52,5 +52,5 @@
|
|
|
52
52
|
"skills/chant-gitlab-migrate.md": "4853d04980560b379e5b0f7267dcb0a1e5d5879cb9e9931681ce76b2a5fe69d8",
|
|
53
53
|
"skills/chant-gitlab-patterns.md": "6d9a44e9e8de4c3820be9d65381b0d2ede4cb3626aaaf0011e21838a9fbf556e"
|
|
54
54
|
},
|
|
55
|
-
"composite": "
|
|
55
|
+
"composite": "9c55ab2b05186a57c1311aa9b43816c21dcb5a9e58d131cfd7f8de9b00e02ca7"
|
|
56
56
|
}
|
package/dist/manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intentius/chant-lexicon-gitlab",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.45.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.
|
|
71
|
-
"@intentius/chant-lexicon-github": "^0.
|
|
70
|
+
"@intentius/chant": "^0.45.0",
|
|
71
|
+
"@intentius/chant-lexicon-github": "^0.45.0",
|
|
72
72
|
"typescript": "^5.9.3"
|
|
73
73
|
},
|
|
74
74
|
"peerDependenciesMeta": {
|
package/src/codegen/docs.ts
CHANGED
|
@@ -103,849 +103,16 @@ export async function generateDocs(opts?: { verbose?: boolean }): Promise<void>
|
|
|
103
103
|
// `intrinsics()` registration (docsPipeline's generateIntrinsics, same
|
|
104
104
|
// mechanism azure/helm already use), so its "Folds?" column can never
|
|
105
105
|
// drift from the registration the way #1062's foldability matrix
|
|
106
|
-
// depends on. The hand-written `reference()` usage guide
|
|
107
|
-
// separate "intrinsics-guide" page
|
|
108
|
-
// longer sharing a slug with generated data.
|
|
106
|
+
// depends on. The hand-written `reference()` usage guide lives in a
|
|
107
|
+
// separate "intrinsics-guide" page under docs/pages/ — content unchanged,
|
|
108
|
+
// just no longer sharing a slug with generated data.
|
|
109
109
|
examplesDir: join(pkgDir, "examples"),
|
|
110
|
-
extraPages: [
|
|
111
|
-
{
|
|
112
|
-
slug: "pipeline-concepts",
|
|
113
|
-
title: "Pipeline Concepts",
|
|
114
|
-
description: "Jobs, stages, artifacts, caching, images, rules, environments, and triggers in the GitLab CI/CD lexicon",
|
|
115
|
-
content: `import Diagram from '../../components/Diagram.astro';
|
|
116
|
-
|
|
117
|
-
Every exported \`Job\` declaration becomes a job entry in the generated \`.gitlab-ci.yml\`. The serializer handles the translation automatically:
|
|
118
|
-
|
|
119
|
-
<Diagram name="pipeline-hierarchy" alt="GitLab Pipeline with stages (build, test, deploy) each containing jobs, with stage dependencies flowing left to right" caption="GitLab CI pipeline hierarchy" />
|
|
120
|
-
|
|
121
|
-
- Property names use spec-native snake_case (\`expire_in\`, \`allow_failure\`)
|
|
122
|
-
- Converts export names to kebab-case job keys (\`buildApp\` → \`build-app\`)
|
|
123
|
-
- Collects stages from all jobs into a \`stages:\` list
|
|
124
|
-
- Collapses single-property objects (\`new Image({ name: "node:20" })\` → \`image: node:20\`)
|
|
125
|
-
|
|
126
|
-
{{file:docs-snippets/src/job-basic.ts}}
|
|
127
|
-
|
|
128
|
-
Produces this YAML:
|
|
129
|
-
|
|
130
|
-
\`\`\`yaml
|
|
131
|
-
stages:
|
|
132
|
-
- build
|
|
133
|
-
|
|
134
|
-
build-app:
|
|
135
|
-
stage: build
|
|
136
|
-
image: node:20
|
|
137
|
-
script:
|
|
138
|
-
- npm ci
|
|
139
|
-
- npm run build
|
|
140
|
-
\`\`\`
|
|
141
|
-
|
|
142
|
-
## Resource types
|
|
143
|
-
|
|
144
|
-
The lexicon provides 3 resource types and 16 property types:
|
|
145
|
-
|
|
146
|
-
### Resources
|
|
147
|
-
|
|
148
|
-
| Type | Description |
|
|
149
|
-
|------|-------------|
|
|
150
|
-
| \`Job\` | A CI/CD job — the fundamental unit of a pipeline |
|
|
151
|
-
| \`Workflow\` | Top-level \`workflow:\` configuration (pipeline-level rules, name, auto_cancel) |
|
|
152
|
-
| \`Default\` | Top-level \`default:\` block (shared defaults inherited by all jobs) |
|
|
153
|
-
|
|
154
|
-
### Property types
|
|
155
|
-
|
|
156
|
-
| Type | Used in | Description |
|
|
157
|
-
|------|---------|-------------|
|
|
158
|
-
| \`Image\` | Job, Default | Docker image for the job runner |
|
|
159
|
-
| \`Cache\` | Job, Default | Files cached between pipeline runs |
|
|
160
|
-
| \`Artifacts\` | Job | Files passed between stages or stored after completion |
|
|
161
|
-
| \`Rule\` | Job, Workflow | Conditional execution rules (\`rules:\` entries) |
|
|
162
|
-
| \`Environment\` | Job | Deployment target environment |
|
|
163
|
-
| \`Trigger\` | Job | Downstream pipeline trigger |
|
|
164
|
-
| \`Include\` | Workflow | External YAML file inclusion |
|
|
165
|
-
| \`AllowFailure\` | Job | Failure tolerance configuration |
|
|
166
|
-
| \`Retry\` | Job | Automatic retry on failure |
|
|
167
|
-
| \`Parallel\` | Job | Job parallelization (matrix builds) |
|
|
168
|
-
| \`Release\` | Job | GitLab Release creation |
|
|
169
|
-
| \`AutoCancel\` | Workflow | Pipeline auto-cancellation settings |
|
|
170
|
-
| \`Need\` | Job | Job dependency for DAG-mode execution |
|
|
171
|
-
| \`Inherit\` | Job | Controls which global defaults a job inherits |
|
|
172
|
-
| \`Service\` | Job, Default | Sidecar service container (e.g. Docker-in-Docker, databases) |
|
|
173
|
-
| \`WorkflowRule\` | Workflow | Conditional rules for pipeline-level execution |
|
|
174
|
-
|
|
175
|
-
## Shared config
|
|
176
|
-
|
|
177
|
-
Extract reusable objects into a shared config file and import them across your pipeline files:
|
|
178
|
-
|
|
179
|
-
{{file:docs-snippets/src/pipeline-shared-config.ts}}
|
|
180
|
-
|
|
181
|
-
## Jobs
|
|
182
|
-
|
|
183
|
-
A \`Job\` is the fundamental unit. Every exported \`Job\` becomes a job entry in the YAML:
|
|
184
|
-
|
|
185
|
-
{{file:docs-snippets/src/job-test.ts}}
|
|
186
|
-
|
|
187
|
-
Key properties:
|
|
188
|
-
- \`script\` — **required** (or \`trigger\`/\`run\`). Array of shell commands to execute.
|
|
189
|
-
- \`stage\` — which pipeline stage this job belongs to. Defaults to \`test\` if omitted.
|
|
190
|
-
- \`image\` — Docker image. Use \`new Image({ name: "..." })\` or pass a string to the YAML.
|
|
191
|
-
- \`needs\` — job dependencies for DAG-mode execution (run before stage ordering).
|
|
192
|
-
|
|
193
|
-
## Stages
|
|
194
|
-
|
|
195
|
-
Stages define the execution order of a pipeline. The serializer automatically collects unique stage values from all jobs:
|
|
196
|
-
|
|
197
|
-
{{file:docs-snippets/src/stages.ts}}
|
|
198
|
-
|
|
199
|
-
Produces:
|
|
200
|
-
|
|
201
|
-
\`\`\`yaml
|
|
202
|
-
stages:
|
|
203
|
-
- test
|
|
204
|
-
- build
|
|
205
|
-
- deploy
|
|
206
|
-
\`\`\`
|
|
207
|
-
|
|
208
|
-
Jobs in the same stage run in parallel. Stages run sequentially in declaration order.
|
|
209
|
-
|
|
210
|
-
## Artifacts and caching
|
|
211
|
-
|
|
212
|
-
**Artifacts** are files produced by a job and passed to later stages or stored for download. **Caches** persist files between pipeline runs to speed up builds. Both are shown in the shared config:
|
|
213
|
-
|
|
214
|
-
{{file:docs-snippets/src/config.ts:4-22}}
|
|
215
|
-
|
|
216
|
-
The key difference: artifacts are for passing files between **stages in the same pipeline**; caches are for speeding up **repeated pipeline runs**.
|
|
217
|
-
|
|
218
|
-
## Conditional execution with rules
|
|
219
|
-
|
|
220
|
-
\`Rule\` objects control when a job runs. They map to \`rules:\` entries in the YAML:
|
|
221
|
-
|
|
222
|
-
{{file:docs-snippets/src/rules-conditions.ts}}
|
|
223
|
-
|
|
224
|
-
Produces:
|
|
225
|
-
|
|
226
|
-
\`\`\`yaml
|
|
227
|
-
deploy:
|
|
228
|
-
stage: deploy
|
|
229
|
-
script:
|
|
230
|
-
- npm run deploy
|
|
231
|
-
rules:
|
|
232
|
-
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
|
233
|
-
when: manual
|
|
234
|
-
\`\`\`
|
|
235
|
-
|
|
236
|
-
The \`if\` property maps directly to \`if:\` in the YAML. Use the \`CI\` pseudo-parameter object for type-safe variable references.
|
|
237
|
-
|
|
238
|
-
## Environments
|
|
239
|
-
|
|
240
|
-
\`Environment\` defines a deployment target:
|
|
241
|
-
|
|
242
|
-
{{file:docs-snippets/src/environment.ts}}
|
|
243
|
-
|
|
244
|
-
GitLab tracks deployments to environments and provides rollback capabilities in the UI.
|
|
245
|
-
|
|
246
|
-
## Images and services
|
|
247
|
-
|
|
248
|
-
\`Image\` specifies the Docker image for a job:
|
|
249
|
-
|
|
250
|
-
{{file:docs-snippets/src/images.ts}}
|
|
251
|
-
|
|
252
|
-
## Workflow
|
|
253
|
-
|
|
254
|
-
\`Workflow\` controls pipeline-level settings — when pipelines run, auto-cancellation, and global includes:
|
|
255
|
-
|
|
256
|
-
{{file:docs-snippets/src/workflow.ts}}
|
|
257
|
-
|
|
258
|
-
## Default
|
|
259
|
-
|
|
260
|
-
\`Default\` sets shared configuration inherited by all jobs:
|
|
261
|
-
|
|
262
|
-
{{file:docs-snippets/src/defaults.ts}}
|
|
263
|
-
|
|
264
|
-
Jobs can override any default property individually.
|
|
265
|
-
|
|
266
|
-
## Triggers
|
|
267
|
-
|
|
268
|
-
\`Trigger\` creates downstream pipeline jobs:
|
|
269
|
-
|
|
270
|
-
{{file:docs-snippets/src/trigger.ts}}`,
|
|
271
|
-
},
|
|
272
|
-
{
|
|
273
|
-
slug: "variables",
|
|
274
|
-
title: "Predefined Variables",
|
|
275
|
-
description: "GitLab CI/CD predefined variable references",
|
|
276
|
-
content: `The \`CI\` object provides type-safe access to GitLab CI/CD predefined variables. These map to \`$CI_*\` environment variables at runtime.
|
|
277
|
-
|
|
278
|
-
{{file:docs-snippets/src/variables-usage.ts}}
|
|
279
|
-
|
|
280
|
-
## Variable reference
|
|
281
|
-
|
|
282
|
-
| Property | Variable | Description |
|
|
283
|
-
|----------|----------|-------------|
|
|
284
|
-
| \`CI.CommitBranch\` | \`$CI_COMMIT_BRANCH\` | Current branch name (not set for tag pipelines) |
|
|
285
|
-
| \`CI.CommitRef\` | \`$CI_COMMIT_REF_NAME\` | Branch or tag name |
|
|
286
|
-
| \`CI.CommitSha\` | \`$CI_COMMIT_SHA\` | Full commit SHA |
|
|
287
|
-
| \`CI.CommitTag\` | \`$CI_COMMIT_TAG\` | Tag name (only set for tag pipelines) |
|
|
288
|
-
| \`CI.DefaultBranch\` | \`$CI_DEFAULT_BRANCH\` | Default branch (usually \`main\`) |
|
|
289
|
-
| \`CI.Environment\` | \`$CI_ENVIRONMENT_NAME\` | Environment name (set during deploy jobs) |
|
|
290
|
-
| \`CI.JobId\` | \`$CI_JOB_ID\` | Unique job ID |
|
|
291
|
-
| \`CI.JobName\` | \`$CI_JOB_NAME\` | Job name |
|
|
292
|
-
| \`CI.JobStage\` | \`$CI_JOB_STAGE\` | Job stage name |
|
|
293
|
-
| \`CI.MergeRequestIid\` | \`$CI_MERGE_REQUEST_IID\` | MR internal ID (merge request pipelines only) |
|
|
294
|
-
| \`CI.PipelineId\` | \`$CI_PIPELINE_ID\` | Unique pipeline ID |
|
|
295
|
-
| \`CI.PipelineSource\` | \`$CI_PIPELINE_SOURCE\` | How the pipeline was triggered (\`push\`, \`merge_request_event\`, \`schedule\`, etc.) |
|
|
296
|
-
| \`CI.ProjectDir\` | \`$CI_PROJECT_DIR\` | Full path of the repository clone |
|
|
297
|
-
| \`CI.ProjectId\` | \`$CI_PROJECT_ID\` | Unique project ID |
|
|
298
|
-
| \`CI.ProjectName\` | \`$CI_PROJECT_NAME\` | Project name (URL-safe) |
|
|
299
|
-
| \`CI.ProjectPath\` | \`$CI_PROJECT_PATH\` | Project namespace with project name |
|
|
300
|
-
| \`CI.Registry\` | \`$CI_REGISTRY\` | Container registry URL |
|
|
301
|
-
| \`CI.RegistryImage\` | \`$CI_REGISTRY_IMAGE\` | Registry image path for the project |
|
|
302
|
-
|
|
303
|
-
## Common patterns
|
|
304
|
-
|
|
305
|
-
{{file:docs-snippets/src/variables-patterns.ts}}
|
|
306
|
-
`,
|
|
307
|
-
},
|
|
308
|
-
{
|
|
309
|
-
slug: "intrinsics-guide",
|
|
310
|
-
title: "Intrinsics Guide",
|
|
311
|
-
description: "Worked examples for the GitLab reference() intrinsic and its chant syntax",
|
|
312
|
-
content: `See [Intrinsic Functions](../intrinsics/) for the generated reference table (name, description, output key, whether it's a tagged template, whether folding can reduce it). This page is the worked-example companion.
|
|
313
|
-
|
|
314
|
-
The GitLab lexicon provides one intrinsic function: \`reference()\`, which maps to GitLab's \`!reference\` YAML tag.
|
|
315
|
-
|
|
316
|
-
\`reference()\` is a plain function call, not a TypeScript tagged template — like any function call used as a value, it's outside the subset [folding](/chant/concepts/typescript-as-data/#folded-vs-run) can reduce. A file that calls \`reference()\` anywhere in a resource's properties falls back to the normal run path.
|
|
317
|
-
|
|
318
|
-
## \`reference()\` — reuse job properties
|
|
319
|
-
|
|
320
|
-
The \`reference()\` intrinsic lets you reuse properties from other jobs or hidden keys. It produces the \`!reference\` YAML tag:
|
|
321
|
-
|
|
322
|
-
{{file:docs-snippets/src/reference-basic.ts}}
|
|
323
|
-
|
|
324
|
-
Serializes to:
|
|
325
|
-
|
|
326
|
-
\`\`\`yaml
|
|
327
|
-
deploy:
|
|
328
|
-
script: !reference [.setup, script]
|
|
329
|
-
\`\`\`
|
|
330
|
-
|
|
331
|
-
### Syntax
|
|
332
|
-
|
|
333
|
-
\`\`\`typescript
|
|
334
|
-
reference(jobName: string, property: string): ReferenceTag
|
|
335
|
-
\`\`\`
|
|
336
|
-
|
|
337
|
-
- \`jobName\` — the job or hidden key to reference (e.g. \`".setup"\`, \`"build"\`)
|
|
338
|
-
- \`property\` — the property to extract (e.g. \`"script"\`, \`"before_script"\`, \`"rules"\`)
|
|
339
|
-
|
|
340
|
-
### Use cases
|
|
341
|
-
|
|
342
|
-
{{file:docs-snippets/src/reference-shared.ts}}
|
|
343
|
-
|
|
344
|
-
Produces:
|
|
345
|
-
|
|
346
|
-
\`\`\`yaml
|
|
347
|
-
test:
|
|
348
|
-
stage: test
|
|
349
|
-
before_script: !reference [.node-setup, before_script]
|
|
350
|
-
script:
|
|
351
|
-
- npm test
|
|
352
|
-
|
|
353
|
-
lint:
|
|
354
|
-
stage: test
|
|
355
|
-
before_script: !reference [.node-setup, before_script]
|
|
356
|
-
script:
|
|
357
|
-
- npm run lint
|
|
358
|
-
\`\`\`
|
|
359
|
-
|
|
360
|
-
### When to use \`reference()\` vs direct imports
|
|
361
|
-
|
|
362
|
-
{{file:docs-snippets/src/reference-vs-import.ts}}
|
|
363
|
-
`,
|
|
364
|
-
},
|
|
365
|
-
{
|
|
366
|
-
slug: "lint-rules",
|
|
367
|
-
title: "Lint Rules",
|
|
368
|
-
description: "Built-in lint rules and post-synth checks for GitLab CI/CD",
|
|
369
|
-
content: `The GitLab lexicon ships lint rules that run during \`chant lint\` and post-synth checks that validate the serialized YAML after \`chant build\`.
|
|
370
|
-
|
|
371
|
-
## Lint rules
|
|
372
|
-
|
|
373
|
-
Lint rules analyze your TypeScript source code before build.
|
|
374
|
-
|
|
375
|
-
### WGL001 — Deprecated only/except
|
|
376
|
-
|
|
377
|
-
**Severity:** warning | **Category:** style
|
|
378
|
-
|
|
379
|
-
Flags usage of \`only:\` and \`except:\` keywords, which are deprecated in favor of \`rules:\`. The \`rules:\` syntax is more flexible and is the recommended approach.
|
|
380
|
-
|
|
381
|
-
{{file:docs-snippets/src/lint-wgl001.ts}}
|
|
382
|
-
|
|
383
|
-
### WGL002 — Missing script
|
|
384
|
-
|
|
385
|
-
**Severity:** error | **Category:** correctness
|
|
386
|
-
|
|
387
|
-
A GitLab CI job must have \`script\`, \`trigger\`, or \`run\` defined. Jobs without any of these will fail pipeline validation.
|
|
388
|
-
|
|
389
|
-
{{file:docs-snippets/src/lint-wgl002.ts}}
|
|
390
|
-
|
|
391
|
-
### WGL003 — Missing stage
|
|
392
|
-
|
|
393
|
-
**Severity:** info | **Category:** style
|
|
394
|
-
|
|
395
|
-
Jobs should declare a \`stage\` property. Without it, the job defaults to the \`test\` stage, which may not be the intended behavior.
|
|
396
|
-
|
|
397
|
-
{{file:docs-snippets/src/lint-wgl003.ts}}
|
|
398
|
-
|
|
399
|
-
### WGL004 — Artifacts without expiry
|
|
400
|
-
|
|
401
|
-
**Severity:** warning | **Category:** performance
|
|
402
|
-
|
|
403
|
-
Flags \`Artifacts\` without \`expireIn\`. Artifacts without expiry are kept indefinitely, consuming storage. Always set an expiration.
|
|
404
|
-
|
|
405
|
-
{{file:docs-snippets/src/lint-wgl004.ts}}
|
|
406
|
-
|
|
407
|
-
## Post-synth checks
|
|
408
|
-
|
|
409
|
-
Post-synth checks run against the serialized YAML after build. They catch issues only visible in the final output.
|
|
410
|
-
|
|
411
|
-
### WGL010 — Undefined stage
|
|
412
|
-
|
|
413
|
-
**Severity:** error
|
|
414
|
-
|
|
415
|
-
Flags jobs that reference a stage not present in the collected stages list. This causes a pipeline validation error in GitLab.
|
|
416
|
-
|
|
417
|
-
### WGL011 — Unreachable job
|
|
418
|
-
|
|
419
|
-
**Severity:** warning
|
|
420
|
-
|
|
421
|
-
Flags jobs where all \`rules:\` entries have \`when: "never"\`, making the job unreachable. This usually indicates a configuration error.
|
|
422
|
-
|
|
423
|
-
{{file:docs-snippets/src/lint-wgl011.ts}}
|
|
424
|
-
|
|
425
|
-
### WGL012 — Deprecated property usage
|
|
426
|
-
|
|
427
|
-
**Severity:** warning
|
|
428
|
-
|
|
429
|
-
Flags properties marked as deprecated in the GitLab CI schema. Deprecation signals are mined from property descriptions (keywords like "deprecated", "legacy", "no longer available"). Using deprecated properties may cause unexpected behavior in future GitLab versions.
|
|
430
|
-
|
|
431
|
-
### WGL013 — Invalid \`needs:\` target
|
|
432
|
-
|
|
433
|
-
**Severity:** error
|
|
434
|
-
|
|
435
|
-
Flags jobs whose \`needs:\` entries reference a job not defined in the pipeline, or reference themselves. Both cause GitLab pipeline validation failures. When \`include:\` is present, the check is skipped since needed jobs may come from included files.
|
|
436
|
-
|
|
437
|
-
### WGL014 — Invalid \`extends:\` target
|
|
438
|
-
|
|
439
|
-
**Severity:** error
|
|
440
|
-
|
|
441
|
-
Flags jobs whose \`extends:\` references a template or hidden job not defined in the pipeline. GitLab rejects pipelines with unresolved extends references. When \`include:\` is present, the check is skipped since templates may come from included files.
|
|
442
|
-
|
|
443
|
-
### WGL015 — Circular \`needs:\` chain
|
|
444
|
-
|
|
445
|
-
**Severity:** error
|
|
446
|
-
|
|
447
|
-
Detects cycles in the \`needs:\` dependency graph. If job A needs B and B needs A (directly or transitively), GitLab rejects the pipeline. Reports the full cycle chain in the diagnostic message.
|
|
448
|
-
|
|
449
|
-
### WGL016 — Secret in a variables block
|
|
450
|
-
|
|
451
|
-
**Severity:** error
|
|
452
|
-
|
|
453
|
-
Detects hardcoded passwords, tokens, or keys in a \`variables:\` block. Move them to CI/CD masked variables instead of committing them to the pipeline. The precursor to the WGL038–040 secret-scoping checks.
|
|
454
|
-
|
|
455
|
-
### WGL017 — Insecure registry
|
|
456
|
-
|
|
457
|
-
**Severity:** warning
|
|
458
|
-
|
|
459
|
-
Flags Docker push/pull to a non-HTTPS registry in a job script. HTTP gives the registry traffic no transport integrity.
|
|
460
|
-
|
|
461
|
-
### WGL018 — Missing timeout
|
|
462
|
-
|
|
463
|
-
**Severity:** warning
|
|
464
|
-
|
|
465
|
-
Flags jobs without an explicit \`timeout:\`. The instance default (often 1 hour) is too long for most jobs and lets a hung job hold a runner.
|
|
466
|
-
|
|
467
|
-
### WGL019 — Missing retry on deploy jobs
|
|
468
|
-
|
|
469
|
-
**Severity:** info
|
|
470
|
-
|
|
471
|
-
Deploy-stage jobs benefit from a \`retry:\` strategy to ride out transient infrastructure failures. Informational, not required.
|
|
472
|
-
|
|
473
|
-
### WGL020 — Duplicate job names
|
|
474
|
-
|
|
475
|
-
**Severity:** error
|
|
476
|
-
|
|
477
|
-
Detects multiple jobs that resolve to the same kebab-case key in the serialized YAML. GitLab silently merges duplicate keys, so one job's config quietly overwrites the other.
|
|
478
|
-
|
|
479
|
-
### WGL021 — Unused variables
|
|
480
|
-
|
|
481
|
-
**Severity:** warning
|
|
482
|
-
|
|
483
|
-
Flags global \`variables:\` not referenced by any job script — usually stale configuration adding noise.
|
|
484
|
-
|
|
485
|
-
### WGL022 — Missing artifacts expiry
|
|
486
|
-
|
|
487
|
-
**Severity:** warning
|
|
488
|
-
|
|
489
|
-
Flags \`artifacts:\` without \`expire_in:\`. Depending on instance config the default is "never expire," which bloats storage.
|
|
490
|
-
|
|
491
|
-
### WGL023 — Overly broad rules
|
|
492
|
-
|
|
493
|
-
**Severity:** info
|
|
494
|
-
|
|
495
|
-
Flags a job whose only rule is \`when: always\` with no conditions (\`if:\`, \`changes:\`, …). That disables all pipeline filtering for the job, which is usually unintended.
|
|
496
|
-
|
|
497
|
-
### WGL024 — Manual without allow_failure
|
|
498
|
-
|
|
499
|
-
**Severity:** warning
|
|
500
|
-
|
|
501
|
-
Flags \`when: manual\` jobs that don't set \`allow_failure: true\`. Without it the manual job blocks the pipeline from progressing past its stage until someone triggers it.
|
|
502
|
-
|
|
503
|
-
### WGL025 — Missing cache key
|
|
504
|
-
|
|
505
|
-
**Severity:** warning
|
|
506
|
-
|
|
507
|
-
Flags \`cache:\` without a \`key:\`. GitLab falls back to the \`default\` key, causing cache collisions between unrelated jobs on the same runner.
|
|
508
|
-
|
|
509
|
-
### WGL026 — Privileged services without TLS
|
|
510
|
-
|
|
511
|
-
**Severity:** warning
|
|
512
|
-
|
|
513
|
-
Flags Docker-in-Docker (DinD) services that don't set \`DOCKER_TLS_CERTDIR\`, leaving the Docker daemon on an unencrypted socket. Extended by WGL036 for the merge-request-reachable case.
|
|
514
|
-
|
|
515
|
-
### WGL027 — Empty script
|
|
516
|
-
|
|
517
|
-
**Severity:** error
|
|
518
|
-
|
|
519
|
-
Detects jobs with \`script: []\` or only empty strings. GitLab rejects empty scripts at pipeline validation time.
|
|
520
|
-
|
|
521
|
-
### WGL028 — Redundant needs
|
|
522
|
-
|
|
523
|
-
**Severity:** info
|
|
524
|
-
|
|
525
|
-
Detects \`needs:\` entries already implied by stage ordering. Not incorrect, but redundant needs add noise and make the pipeline harder to maintain.
|
|
526
|
-
|
|
527
|
-
## Supply-chain security pass (WGL029–048)
|
|
528
|
-
|
|
529
|
-
WGL029 onward are a CI/CD supply-chain security pass, the GitLab counterpart to the github lexicon's GHA029–058: pin & vet includes/components/images, scope \`CI_JOB_TOKEN\` and OIDC, guard trust boundaries against untrusted CI input, mask/protect/scope secrets, reject unsound \`rules:\` expressions, and keep artifacts/caches honest. They run statically on the emitted \`.gitlab-ci.yml\`.
|
|
530
|
-
|
|
531
|
-
The checks that need a *moving external truth* — whether a pinned component/include ref still resolves, whether an upstream was archived or moved, whether a new advisory covers a component in use — live in the operational layer instead. Schedule the [\`PipelineAuditOp\`](/chant/guide/ops/#audit-supply-chain-drift) (temporal lexicon) for that live half; it reads the emitted \`include:\` / \`component:\` / \`image:\` references and reports drift via \`report | issue | merge-request\`.
|
|
532
|
-
|
|
533
|
-
### WGL029 — Unpinned include:project / component
|
|
534
|
-
|
|
535
|
-
**Severity:** warning
|
|
536
|
-
|
|
537
|
-
Flags an \`include:project\` or CI/CD \`component:\` resolved by a moving ref — a branch, a missing \`ref:\` (defaults to the default branch), or a floating component version — instead of a pinned tag or commit SHA.
|
|
538
|
-
|
|
539
|
-
### WGL030 — Mutable or insecure include:remote
|
|
540
|
-
|
|
541
|
-
**Severity:** error (HTTP) / warning (HTTPS)
|
|
542
|
-
|
|
543
|
-
Flags \`include:remote\` URLs fetched over HTTP (no transport integrity) or over HTTPS but inherently mutable. Prefer a pinned \`include:project\` or component. Generalizes WGL017 to includes.
|
|
544
|
-
|
|
545
|
-
### WGL031 — Container image without a digest
|
|
546
|
-
|
|
547
|
-
**Severity:** warning
|
|
548
|
-
|
|
549
|
-
Flags \`image:\` and \`services:\` references not pinned to an immutable \`@sha256:\` digest. Variable-based references (e.g. \`$CI_REGISTRY_IMAGE:tag\`) are skipped.
|
|
550
|
-
|
|
551
|
-
### WGL032 — Look-alike include/component source
|
|
552
|
-
|
|
553
|
-
**Severity:** warning
|
|
554
|
-
|
|
555
|
-
Flags an \`include:project\` / \`component:\` source that is a near-miss (edit distance 1–2) of a well-known GitLab CI source but not an exact match — a likely typo or impersonation. Backed by a vendored reference list.
|
|
556
|
-
|
|
557
|
-
### WGL033 — OIDC id_token without a scoped audience
|
|
558
|
-
|
|
559
|
-
**Severity:** warning
|
|
560
|
-
|
|
561
|
-
Flags an \`id_tokens:\` declaration with no \`aud:\` or a wildcard audience. The audience binds the minted OIDC token to a relying party; without it a leaked token is accepted anywhere.
|
|
562
|
-
|
|
563
|
-
### WGL034 — OIDC id_token mintable from a merge-request pipeline
|
|
564
|
-
|
|
565
|
-
**Severity:** warning
|
|
566
|
-
|
|
567
|
-
Flags a job that declares \`id_tokens:\` and is reachable from merge-request pipelines, which outside contributors can trigger. Restrict OIDC jobs to protected refs or require approval.
|
|
568
|
-
|
|
569
|
-
> The project-level \`CI_JOB_TOKEN\` allowlist and a variable's protected status are project settings, not emitted pipeline YAML, so they are out of scope for these post-synth checks (see issue #298's caveat).
|
|
570
|
-
|
|
571
|
-
### WGL035 — Untrusted CI variable in a script
|
|
572
|
-
|
|
573
|
-
**Severity:** warning
|
|
574
|
-
|
|
575
|
-
Flags an attacker-controllable predefined variable (branch/tag name, commit or MR title/description, author) referenced in a \`script:\` command, where a crafted value can inject shell commands. Quote it and avoid using it in sensitive commands.
|
|
576
|
-
|
|
577
|
-
### WGL036 — Privileged DinD reachable from merge requests
|
|
578
|
-
|
|
579
|
-
**Severity:** warning
|
|
580
|
-
|
|
581
|
-
Flags a Docker-in-Docker (privileged) job reachable from merge-request pipelines, which outside contributors can trigger. Restrict privileged services to protected refs. Complements WGL026.
|
|
582
|
-
|
|
583
|
-
### WGL037 — Regex gate on an untrusted ref
|
|
584
|
-
|
|
585
|
-
**Severity:** warning
|
|
586
|
-
|
|
587
|
-
Flags a \`rules:if\` that gates on a regex match (\`=~\`) over an attacker-controllable ref variable — a crafted branch/tag name can satisfy the pattern. Match the full ref with \`==\` or gate on a protected condition.
|
|
588
|
-
|
|
589
|
-
### WGL038 — Secret reachable from a merge-request pipeline
|
|
590
|
-
|
|
591
|
-
**Severity:** warning
|
|
592
|
-
|
|
593
|
-
Flags a user-defined secret-like variable read by a job reachable from merge-request pipelines, which can run untrusted code. Gate the job to protected refs or mark the variable protected. (Built-in \`CI_*\` variables are excluded.)
|
|
594
|
-
|
|
595
|
-
### WGL039 — Secret echoed to job logs
|
|
596
|
-
|
|
597
|
-
**Severity:** warning
|
|
598
|
-
|
|
599
|
-
Flags a \`script:\` command that prints a secret-like variable (\`echo\`/\`printf\`/\`cat\`). Logs are broadly readable and masking can be defeated by transforms.
|
|
600
|
-
|
|
601
|
-
### WGL040 — Hardcoded registry credential
|
|
602
|
-
|
|
603
|
-
**Severity:** error
|
|
604
|
-
|
|
605
|
-
Flags a \`docker login\` (or compatible) passing a literal password via \`-p\`/\`--password\` instead of a variable or \`--password-stdin\`. Extends WGL016 to scripts.
|
|
606
|
-
|
|
607
|
-
> Variable *masking* and *protected* status are GitLab project/CI-settings, not emitted YAML — WGL016 already nudges toward masked variables; this group covers the exposure paths visible in the pipeline.
|
|
608
|
-
|
|
609
|
-
### WGL041 — Unsound rules:if condition
|
|
610
|
-
|
|
611
|
-
**Severity:** warning
|
|
612
|
-
|
|
613
|
-
Flags a tautological \`rules:if\` where both sides of \`==\`/\`!=\` are identical, so the condition is always true or always false. Generalizes WGL011 to conditions presented as gates.
|
|
614
|
-
|
|
615
|
-
### WGL042 — Unreachable rules after an unconditional match
|
|
616
|
-
|
|
617
|
-
**Severity:** warning
|
|
618
|
-
|
|
619
|
-
Flags rules listed after an unconditional rule (no \`if:\`, not \`when: never\`). GitLab takes the first matching rule, so a catch-all makes everything after it dead. Put specific rules first.
|
|
620
|
-
|
|
621
|
-
### WGL043 — Match-anything regex gate
|
|
622
|
-
|
|
623
|
-
**Severity:** warning
|
|
624
|
-
|
|
625
|
-
Flags a \`rules:if\` whose \`=~\` regex matches every value (empty, dot-star, anchored dot-star) — a filter that admits everything. Tighten the pattern or remove the gate.
|
|
626
|
-
|
|
627
|
-
> The auto-fix acceptance item is N/A at the post-synth layer (PostSynthDiagnostic has no fix channel); it belongs to the declarative source-lint rules.
|
|
628
|
-
|
|
629
|
-
### WGL044 — Public artifacts
|
|
630
|
-
|
|
631
|
-
**Severity:** warning
|
|
632
|
-
|
|
633
|
-
Flags \`artifacts:public: true\`, which makes build output downloadable by anyone. Keep artifacts private unless they are meant to be world-readable.
|
|
634
|
-
|
|
635
|
-
### WGL045 — Credential-bearing artifact path
|
|
636
|
-
|
|
637
|
-
**Severity:** error
|
|
638
|
-
|
|
639
|
-
Flags an \`artifacts:paths:\` entry that looks like a credential or sensitive file (\`.env\`, \`*.pem\`, \`id_rsa\`, \`*.key\`, \`.npmrc\`, \`.netrc\`, \`credentials\`). Artifacts flow downstream and are downloadable — exclude the file.
|
|
640
|
-
|
|
641
|
-
### WGL046 — Cache poisoning from a merge-request pipeline
|
|
642
|
-
|
|
643
|
-
**Severity:** warning
|
|
644
|
-
|
|
645
|
-
Flags a job that writes a cache (push policy) and is reachable from merge-request pipelines. An MR can poison the cache for a later protected run that restores the same key. Restrict cache writes to protected refs or scope the key.
|
|
646
|
-
|
|
647
|
-
> Artifact / \`dependencies:\` flow across a *protected* boundary depends on a ref's protected status, a project setting not present in emitted YAML — out of scope here.
|
|
648
|
-
|
|
649
|
-
### WGL047 — Software fetched and piped to a shell
|
|
650
|
-
|
|
651
|
-
**Severity:** warning
|
|
652
|
-
|
|
653
|
-
Flags a \`script:\` command that pipes a network download straight into a shell (\`curl ... | bash\`). The fetched code is unpinned and unverified — download to a file, verify a checksum/signature, then run it.
|
|
654
|
-
|
|
655
|
-
### WGL048 — Pipeline without a name
|
|
656
|
-
|
|
657
|
-
**Severity:** info
|
|
658
|
-
|
|
659
|
-
Flags a pipeline that defines a \`workflow:\` block but no \`workflow:name\`. A pipeline name aids identification in the GitLab UI and audit output.
|
|
660
|
-
|
|
661
|
-
> Two #304 items stay out of scope: a broad privileged-service / DinD check (already covered by WGL026 for DinD-TLS and WGL036 for MR-reachable DinD; a runner's privileged isolation is not in emitted YAML) and an optional include/component allowlist policy (configuration, overlapping WGL032's vendored source list).
|
|
662
|
-
|
|
663
|
-
## Running lint
|
|
664
|
-
|
|
665
|
-
\`\`\`bash
|
|
666
|
-
# Lint your chant project
|
|
667
|
-
chant lint
|
|
668
|
-
|
|
669
|
-
# Lint with auto-fix where supported
|
|
670
|
-
chant lint --fix
|
|
671
|
-
\`\`\`
|
|
672
|
-
|
|
673
|
-
To suppress a rule on a specific line:
|
|
674
|
-
|
|
675
|
-
\`\`\`typescript
|
|
676
|
-
// chant-disable-next-line WGL001
|
|
677
|
-
export const deploy = new Job({ only: ["main"], script: ["deploy"] });
|
|
678
|
-
\`\`\`
|
|
679
|
-
|
|
680
|
-
To suppress globally in \`chant.config.ts\`:
|
|
681
|
-
|
|
682
|
-
\`\`\`typescript
|
|
683
|
-
export default {
|
|
684
|
-
lint: {
|
|
685
|
-
rules: {
|
|
686
|
-
WGL003: "off",
|
|
687
|
-
},
|
|
688
|
-
},
|
|
689
|
-
};
|
|
690
|
-
\`\`\`
|
|
691
|
-
`,
|
|
692
|
-
},
|
|
693
|
-
{
|
|
694
|
-
slug: "examples",
|
|
695
|
-
title: "Examples",
|
|
696
|
-
description: "Walkthrough of GitLab CI/CD examples — pipelines, composites, and cross-lexicon patterns",
|
|
697
|
-
content: `Runnable examples live in the lexicon's \`examples/\` directory. Clone the repo and try them:
|
|
698
|
-
|
|
699
|
-
\`\`\`bash
|
|
700
|
-
cd examples/getting-started
|
|
701
|
-
npm install
|
|
702
|
-
chant build # produces .gitlab-ci.yml
|
|
703
|
-
chant lint # runs lint rules
|
|
704
|
-
npx vitest run # run the tests
|
|
705
|
-
\`\`\`
|
|
706
|
-
|
|
707
|
-
## Getting Started
|
|
708
|
-
|
|
709
|
-
\`examples/getting-started/\` — a 2-stage Node.js pipeline with build and test jobs.
|
|
710
|
-
|
|
711
|
-
\`\`\`
|
|
712
|
-
src/
|
|
713
|
-
├── config.ts # Shared config: image, cache
|
|
714
|
-
└── pipeline.ts # Job definitions: build, test
|
|
715
|
-
\`\`\`
|
|
716
|
-
|
|
717
|
-
### Shared configuration
|
|
718
|
-
|
|
719
|
-
\`config.ts\` extracts reusable objects — image and cache — so jobs stay concise:
|
|
720
|
-
|
|
721
|
-
{{file:getting-started/src/config.ts}}
|
|
722
|
-
|
|
723
|
-
### Pipeline jobs
|
|
724
|
-
|
|
725
|
-
\`pipeline.ts\` defines two jobs that import shared config:
|
|
726
|
-
|
|
727
|
-
{{file:getting-started/src/pipeline.ts}}
|
|
728
|
-
|
|
729
|
-
### Generated output
|
|
730
|
-
|
|
731
|
-
\`chant build\` produces this \`.gitlab-ci.yml\`:
|
|
732
|
-
|
|
733
|
-
\`\`\`yaml
|
|
734
|
-
stages:
|
|
735
|
-
- build
|
|
736
|
-
- test
|
|
737
|
-
|
|
738
|
-
build:
|
|
739
|
-
stage: build
|
|
740
|
-
image:
|
|
741
|
-
name: node:20-alpine
|
|
742
|
-
cache:
|
|
743
|
-
key: '$CI_COMMIT_REF_SLUG'
|
|
744
|
-
paths:
|
|
745
|
-
- node_modules/
|
|
746
|
-
policy: pull-push
|
|
747
|
-
script:
|
|
748
|
-
- npm install
|
|
749
|
-
- npm run build
|
|
750
|
-
|
|
751
|
-
test:
|
|
752
|
-
stage: test
|
|
753
|
-
image:
|
|
754
|
-
name: node:20-alpine
|
|
755
|
-
cache:
|
|
756
|
-
key: '$CI_COMMIT_REF_SLUG'
|
|
757
|
-
paths:
|
|
758
|
-
- node_modules/
|
|
759
|
-
policy: pull-push
|
|
760
|
-
script:
|
|
761
|
-
- npm install
|
|
762
|
-
- npm test
|
|
763
|
-
artifacts:
|
|
764
|
-
reports:
|
|
765
|
-
junit: coverage/junit.xml
|
|
766
|
-
paths:
|
|
767
|
-
- coverage/
|
|
768
|
-
expire_in: '1 week'
|
|
769
|
-
\`\`\`
|
|
770
|
-
|
|
771
|
-
**Patterns demonstrated:**
|
|
772
|
-
|
|
773
|
-
1. **Shared config** — reusable image and cache extracted into \`config.ts\`
|
|
774
|
-
2. **JUnit reports** — test artifacts include JUnit XML for GitLab MR display
|
|
775
|
-
3. **Stage ordering** — stages collected automatically from job declarations
|
|
776
|
-
|
|
777
|
-
## Docker Build
|
|
778
|
-
|
|
779
|
-
\`examples/docker-build/\` — builds and pushes a Docker image using the \`DockerBuild\` composite.
|
|
780
|
-
|
|
781
|
-
{{file:docker-build/src/pipeline.ts}}
|
|
782
|
-
|
|
783
|
-
The \`DockerBuild\` composite expands to a job with Docker-in-Docker service, registry login, build, and push steps.
|
|
784
|
-
|
|
785
|
-
## Node Pipeline
|
|
786
|
-
|
|
787
|
-
\`examples/node-pipeline/\` — a full Node.js CI pipeline using the \`NodePipeline\` composite.
|
|
788
|
-
|
|
789
|
-
{{file:node-pipeline/src/pipeline.ts}}
|
|
790
|
-
|
|
791
|
-
## Python Pipeline
|
|
792
|
-
|
|
793
|
-
\`examples/python-pipeline/\` — a Python CI pipeline using the \`PythonPipeline\` composite.
|
|
794
|
-
|
|
795
|
-
{{file:python-pipeline/src/pipeline.ts}}
|
|
796
|
-
|
|
797
|
-
## Review App
|
|
798
|
-
|
|
799
|
-
\`examples/review-app/\` — deploys a review environment per merge request using the \`ReviewApp\` composite.
|
|
800
|
-
|
|
801
|
-
{{file:review-app/src/pipeline.ts}}
|
|
802
|
-
|
|
803
|
-
## Merge-request plan widget
|
|
804
|
-
|
|
805
|
-
The \`MrPlanReport\` composite turns \`chant lifecycle plan\` into the GitLab merge-request plan widget — the "N to add, M to change, K to delete" summary GitLab renders from an \`artifacts:reports:terraform\` artifact:
|
|
806
|
-
|
|
807
|
-
\`\`\`typescript
|
|
808
|
-
import { MrPlanReport } from "@intentius/chant-lexicon-gitlab";
|
|
809
|
-
|
|
810
|
-
export const plan = MrPlanReport({
|
|
811
|
-
environment: "prod",
|
|
812
|
-
// credential setup — the plan queries the live system to classify drift
|
|
813
|
-
before: ["aws sts get-caller-identity"],
|
|
814
|
-
});
|
|
815
|
-
\`\`\`
|
|
816
|
-
|
|
817
|
-
The job runs \`chant lifecycle plan prod --report gitlab-mr\`, writes the count JSON to \`tfplan.json\`, and declares it as \`artifacts:reports:terraform\`. On the merge request, GitLab shows the plan summary inline.
|
|
818
|
-
|
|
819
|
-
Caveats worth knowing:
|
|
820
|
-
|
|
821
|
-
- The widget label always reads **"Terraform"** — that is GitLab's fixed string for this report type, not a claim chant makes.
|
|
822
|
-
- It is **counts only** (create/update/delete). \`adopt\` and \`noop\` are excluded, since the widget has no column for live-but-undeclared or no-change. There is no per-resource breakdown — run \`chant lifecycle plan\` in the job log for that.
|
|
823
|
-
- It is a **GitLab-only** surface. The same plan JSON is portable, but the widget is GitLab's.
|
|
824
|
-
- The plan reads the live system, so the job needs cloud credentials — wire them via \`before\` or CI variables.
|
|
825
|
-
|
|
826
|
-
## AWS ALB Deployment
|
|
827
|
-
|
|
828
|
-
A cross-lexicon example showing how to deploy AWS CloudFormation stacks from GitLab CI. Three separate pipelines mirror the separate-project AWS ALB pattern:
|
|
829
|
-
|
|
830
|
-
### Infra pipeline
|
|
831
|
-
|
|
832
|
-
Deploys the shared ALB stack (VPC, ALB, ECS cluster, ECR repos):
|
|
833
|
-
|
|
834
|
-
\`\`\`typescript
|
|
835
|
-
import { Job, Image, Rule } from "@intentius/chant-lexicon-gitlab";
|
|
836
|
-
|
|
837
|
-
const awsImage = new Image({ name: "amazon/aws-cli:latest" });
|
|
838
|
-
|
|
839
|
-
export const deployInfra = new Job({
|
|
840
|
-
stage: "deploy",
|
|
841
|
-
image: awsImage,
|
|
842
|
-
script: [
|
|
843
|
-
"aws cloudformation deploy --template-file templates/template.json --stack-name shared-alb --capabilities CAPABILITY_IAM --no-fail-on-empty-changeset",
|
|
844
|
-
],
|
|
845
|
-
rules: [
|
|
846
|
-
new Rule({ if: "$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH" }),
|
|
847
|
-
],
|
|
848
|
-
});
|
|
849
|
-
\`\`\`
|
|
850
|
-
|
|
851
|
-
### Service pipeline (API)
|
|
852
|
-
|
|
853
|
-
Builds a Docker image, pushes to ECR, and deploys the API service stack with cross-stack parameter passing. The full source lives in the cross-lexicon example \`examples/gitlab-aws-alb-api/\`:
|
|
854
|
-
|
|
855
|
-
{{file:../../../examples/gitlab-aws-alb-api/src/pipeline.ts}}
|
|
856
|
-
|
|
857
|
-
**Key patterns:**
|
|
858
|
-
|
|
859
|
-
1. **ECR login** — uses \`aws ecr get-login-password\` instead of GitLab registry credentials
|
|
860
|
-
2. **Cross-stack parameter passing** — \`describe-stacks\` fetches outputs from the infra stack, \`jq\` maps them to \`--parameter-overrides\`
|
|
861
|
-
3. **Job naming** — \`buildImage\` serializes to \`build-image\` in YAML; \`Need\` references must use kebab-case
|
|
862
|
-
4. **Docker-in-Docker** — \`docker:27-cli\` image with \`docker:27-dind\` service for container builds
|
|
863
|
-
|
|
864
|
-
The full examples live in \`examples/gitlab-aws-alb-infra/\`, \`examples/gitlab-aws-alb-api/\`, and \`examples/gitlab-aws-alb-ui/\`.
|
|
865
|
-
`,
|
|
866
|
-
},
|
|
867
|
-
{
|
|
868
|
-
slug: "skills",
|
|
869
|
-
title: "AI Skills",
|
|
870
|
-
description: "AI agent skills bundled with the GitLab CI/CD lexicon",
|
|
871
|
-
content: `The GitLab lexicon ships an AI skill called **chant-gitlab** that teaches AI coding agents (like Claude Code) how to build, validate, and deploy GitLab CI pipelines from a chant project.
|
|
872
|
-
|
|
873
|
-
## What are skills?
|
|
874
|
-
|
|
875
|
-
Skills are structured markdown documents bundled with a lexicon. When an AI agent works in a chant project, it discovers and loads relevant skills automatically — giving it operational knowledge about the deployment workflow without requiring the user to explain each step.
|
|
876
|
-
|
|
877
|
-
## Installation
|
|
878
|
-
|
|
879
|
-
When you scaffold a new project with \`chant init --lexicon gitlab\`, the skill is installed to \`skills/chant-gitlab/SKILL.md\` for automatic discovery by Claude Code.
|
|
880
|
-
|
|
881
|
-
For existing projects, create the file manually:
|
|
882
|
-
|
|
883
|
-
\`\`\`
|
|
884
|
-
.claude/
|
|
885
|
-
skills/
|
|
886
|
-
chant-gitlab/
|
|
887
|
-
SKILL.md # skill content (see below)
|
|
888
|
-
\`\`\`
|
|
889
|
-
|
|
890
|
-
## Skill: chant-gitlab
|
|
891
|
-
|
|
892
|
-
The \`chant-gitlab\` skill covers the full deployment lifecycle:
|
|
893
|
-
|
|
894
|
-
- **Build** — \`chant build src/ --output .gitlab-ci.yml\`
|
|
895
|
-
- **Validate** — \`chant lint src/\` + GitLab CI Lint API
|
|
896
|
-
- **Deploy** — commit and push the generated YAML
|
|
897
|
-
- **Status** — GitLab UI or pipelines API
|
|
898
|
-
- **Retry** — retry failed jobs via UI or API
|
|
899
|
-
- **Cancel** — cancel running pipelines via API
|
|
900
|
-
- **Troubleshooting** — job logs, lint rule codes (WGL001–WGL004), post-synth checks (WGL010–WGL048)
|
|
901
|
-
|
|
902
|
-
The skill is invocable as a slash command: \`/chant-gitlab\`
|
|
903
|
-
|
|
904
|
-
## Skill: chant-gitlab-migrate
|
|
905
|
-
|
|
906
|
-
Operational glue for translating GitHub Actions workflows to GitLab CI/CD. The skill detects the user's intent (paste a \`.github/workflows/*.yml\`, ask about migrating, etc.), invokes \`chant migrate\`, surfaces the report, and suggests GitLab-native upgrade moments like \`--use-composites\`.
|
|
907
|
-
|
|
908
|
-
See [Migration](../migration) for the full CLI surface, supported translations, and limitations.
|
|
909
|
-
|
|
910
|
-
## MCP integration
|
|
911
|
-
|
|
912
|
-
The lexicon also provides MCP (Model Context Protocol) tools and resources that AI agents can use programmatically:
|
|
913
|
-
|
|
914
|
-
| MCP tool | Description |
|
|
915
|
-
|----------|-------------|
|
|
916
|
-
| \`build\` | Build the chant project |
|
|
917
|
-
| \`lint\` | Run lint rules |
|
|
918
|
-
| \`explain\` | Summarize project resources |
|
|
919
|
-
| \`scaffold\` | Generate starter files |
|
|
920
|
-
| \`search\` | Search available resource types |
|
|
921
|
-
| \`gitlab:diff\` | Compare current build output against previous |
|
|
922
|
-
| \`gitlab:migrate\` | Translate a GitHub Actions workflow into GitLab CI/CD (see [Migration](../migration)) |
|
|
923
|
-
| \`gitlab:checks\` | Build and return the pipeline's security/correctness findings (the WGL checks) |
|
|
924
|
-
| \`gitlab:pipeline\` | Build and return the pipeline's stages and jobs (name, stage, run order), as written |
|
|
925
|
-
| \`gitlab:references\` | Build and list what the pipeline pulls in (includes, components, images) and whether each is pinned |
|
|
926
|
-
| \`gitlab:affected\` | Given a job, list the jobs that would re-run because they depend on it |
|
|
927
|
-
| \`gitlab:pipeline-yaml\` | Build and return the generated \`.gitlab-ci.yml\` |
|
|
928
|
-
| \`gitlab:source\` | Given a job, where it came from in the TypeScript — the declaring file and the composite that expanded it, if any (entity-level, not a YAML-line source map) |
|
|
929
|
-
| \`gitlab:owns\` | Given a job, whether it is declared (owned) by chant in this project. Pipeline jobs are not taggable cloud resources, so ownership here means "declared here" — live ownership markers apply to cloud lexicons |
|
|
930
|
-
| \`gitlab:compare\` | Given a GitHub Actions workflow file, migrate it to GitLab CI and report which security properties survive (translated/approximated/needs-review/lost) — the migration safety view |
|
|
931
|
-
|
|
932
|
-
The \`gitlab:checks\` / \`gitlab:pipeline\` / \`gitlab:references\` / \`gitlab:affected\` / \`gitlab:pipeline-yaml\` / \`gitlab:source\` / \`gitlab:owns\` / \`gitlab:compare\` tools are **read-only**: they build (or migrate) from source and never touch the live GitLab instance. They give an agent a *before-it-runs* view of the pipeline — what it does, what it pulls in, whether it is safe, where it came from, and what survives a migration — to complement the *after-it-ran* view it gets from the instance.
|
|
933
|
-
|
|
934
|
-
> **Why no \`github:compare\`?** The GitHub → GitLab migration lives in the GitLab lexicon (the GitHub lexicon does not depend on GitLab). A \`github:compare\` would invert that dependency, so the migration safety view is exposed once, here, as \`gitlab:compare\`.
|
|
935
|
-
|
|
936
|
-
| MCP resource | Description |
|
|
937
|
-
|--------------|-------------|
|
|
938
|
-
| \`resource-catalog\` | JSON list of all supported GitLab CI entity types |
|
|
939
|
-
| \`examples/basic-pipeline\` | Example pipeline with build, test, and deploy jobs |`,
|
|
940
|
-
},
|
|
941
|
-
],
|
|
942
110
|
extraSections: [
|
|
943
111
|
{
|
|
944
112
|
title: "Migrating from GitHub Actions",
|
|
945
113
|
content: `\`chant migrate\` translates GitHub Actions workflows into GitLab CI/CD pipelines or typed chant source. See [Migration](./migration) for the full CLI surface, supported translations, and limitations.`,
|
|
946
114
|
},
|
|
947
115
|
],
|
|
948
|
-
sidebarExtra: [{ label: "Migration", slug: "migration" }],
|
|
949
116
|
basePath: "/chant/lexicons/gitlab/",
|
|
950
117
|
};
|
|
951
118
|
|
package/src/serializer.test.ts
CHANGED
|
@@ -107,7 +107,7 @@ describe("gitlabSerializer.serialize", () => {
|
|
|
107
107
|
entities.set("jobA", new MockJob({ stage: "build", script: ["build1"] }));
|
|
108
108
|
entities.set("jobB", new MockJob({ stage: "build", script: ["build2"] }));
|
|
109
109
|
|
|
110
|
-
const output = gitlabSerializer.serialize(entities);
|
|
110
|
+
const output = gitlabSerializer.serialize(entities) as string;
|
|
111
111
|
// "build" should appear only once in the stages list
|
|
112
112
|
const stagesSection = output.split("\n\n")[0]; // stages is the first section
|
|
113
113
|
const stagesMatch = stagesSection.match(/- build/g);
|