@intentius/chant-lexicon-gitlab 0.0.8 → 0.0.10
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/integrity.json +10 -6
- package/dist/manifest.json +1 -1
- package/dist/meta.json +186 -8
- package/dist/rules/wgl012.ts +86 -0
- package/dist/rules/wgl013.ts +62 -0
- package/dist/rules/wgl014.ts +51 -0
- package/dist/rules/wgl015.ts +85 -0
- package/dist/rules/yaml-helpers.ts +65 -3
- package/dist/skills/chant-gitlab.md +467 -24
- package/dist/types/index.d.ts +55 -16
- package/package.json +2 -2
- package/src/codegen/__snapshots__/snapshot.test.ts.snap +58 -0
- package/src/codegen/docs.ts +32 -9
- package/src/codegen/generate-lexicon.ts +6 -1
- package/src/codegen/generate.ts +45 -50
- package/src/codegen/naming.ts +3 -0
- package/src/codegen/parse.test.ts +154 -4
- package/src/codegen/parse.ts +161 -49
- package/src/codegen/snapshot.test.ts +7 -5
- package/src/composites/composites.test.ts +452 -0
- package/src/composites/docker-build.ts +81 -0
- package/src/composites/index.ts +8 -0
- package/src/composites/node-pipeline.ts +104 -0
- package/src/composites/python-pipeline.ts +75 -0
- package/src/composites/review-app.ts +63 -0
- package/src/generated/index.d.ts +55 -16
- package/src/generated/index.ts +3 -0
- package/src/generated/lexicon-gitlab.json +186 -8
- package/src/import/generator.ts +3 -2
- package/src/index.ts +4 -0
- package/src/lint/post-synth/wgl012.test.ts +131 -0
- package/src/lint/post-synth/wgl012.ts +86 -0
- package/src/lint/post-synth/wgl013.test.ts +164 -0
- package/src/lint/post-synth/wgl013.ts +62 -0
- package/src/lint/post-synth/wgl014.test.ts +97 -0
- package/src/lint/post-synth/wgl014.ts +51 -0
- package/src/lint/post-synth/wgl015.test.ts +139 -0
- package/src/lint/post-synth/wgl015.ts +85 -0
- package/src/lint/post-synth/yaml-helpers.ts +65 -3
- package/src/plugin.test.ts +39 -13
- package/src/plugin.ts +636 -40
- package/src/serializer.test.ts +140 -0
- package/src/serializer.ts +63 -5
- package/src/validate.ts +1 -0
- package/src/variables.ts +4 -0
|
@@ -4,56 +4,499 @@ description: Build, validate, and deploy GitLab CI pipelines from a chant projec
|
|
|
4
4
|
user-invocable: true
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
#
|
|
7
|
+
# GitLab CI/CD Operational Playbook
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
## How chant and GitLab CI relate
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
chant is a **synthesis-only** tool — it compiles TypeScript source files into `.gitlab-ci.yml` (YAML). chant does NOT call GitLab APIs. Your job as an agent is to bridge the two:
|
|
12
|
+
|
|
13
|
+
- Use **chant** for: build, lint, diff (local YAML comparison)
|
|
14
|
+
- Use **git + GitLab API** for: push, merge requests, pipeline monitoring, job logs, rollback, and all deployment operations
|
|
15
|
+
|
|
16
|
+
The source of truth for pipeline configuration is the TypeScript in `src/`. The generated `.gitlab-ci.yml` is an intermediate artifact — never edit it by hand.
|
|
17
|
+
|
|
18
|
+
## Scaffolding a new project
|
|
19
|
+
|
|
20
|
+
### Initialize with a template
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
chant init --lexicon gitlab # default: config.ts + pipeline.ts
|
|
24
|
+
chant init --lexicon gitlab --template node-pipeline # NodePipeline composite
|
|
25
|
+
chant init --lexicon gitlab --template python-pipeline # PythonPipeline composite
|
|
26
|
+
chant init --lexicon gitlab --template docker-build # DockerBuild composite
|
|
27
|
+
chant init --lexicon gitlab --template review-app # ReviewApp composite
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
This creates `src/` with chant pipeline definitions. It does NOT create application files — you bring your own app code.
|
|
31
|
+
|
|
32
|
+
### Available templates
|
|
33
|
+
|
|
34
|
+
| Template | What it generates | Best for |
|
|
35
|
+
|----------|-------------------|----------|
|
|
36
|
+
| *(default)* | `config.ts` + `pipeline.ts` with build/test jobs | Custom pipelines from scratch |
|
|
37
|
+
| `node-pipeline` | `NodePipeline` composite with npm install/build/test | Node.js apps |
|
|
38
|
+
| `python-pipeline` | `PythonPipeline` composite with venv/pytest | Python apps |
|
|
39
|
+
| `docker-build` | `DockerBuild` composite + test job | Containerized apps |
|
|
40
|
+
| `review-app` | `ReviewApp` composite + test job | Apps needing per-MR environments |
|
|
41
|
+
|
|
42
|
+
## Deploying to GitLab
|
|
43
|
+
|
|
44
|
+
### What goes in the GitLab repo
|
|
45
|
+
|
|
46
|
+
The GitLab repo needs TWO things:
|
|
47
|
+
1. **`.gitlab-ci.yml`** — generated by `chant build`
|
|
48
|
+
2. **Your application files** — whatever the pipeline scripts reference
|
|
49
|
+
|
|
50
|
+
chant only generates the YAML. Application files (`package.json`, `Dockerfile`, `requirements.txt`, source code, tests) are your responsibility.
|
|
51
|
+
|
|
52
|
+
### Typical project structure in the GitLab repo
|
|
53
|
+
|
|
54
|
+
**Node.js project:**
|
|
55
|
+
```
|
|
56
|
+
.gitlab-ci.yml # generated by chant
|
|
57
|
+
package.json # your app's package.json with build/test scripts
|
|
58
|
+
index.js # your app code
|
|
59
|
+
test.js # your tests
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Python project:**
|
|
63
|
+
```
|
|
64
|
+
.gitlab-ci.yml
|
|
65
|
+
requirements.txt # must include pytest, pytest-cov if using PythonPipeline defaults
|
|
66
|
+
app.py
|
|
67
|
+
test_app.py
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**Docker project:**
|
|
71
|
+
```
|
|
72
|
+
.gitlab-ci.yml
|
|
73
|
+
Dockerfile
|
|
74
|
+
src/ # your app source
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Important: npm ci vs npm install
|
|
78
|
+
|
|
79
|
+
The `NodePipeline` composite defaults to `npm ci`, which requires a `package-lock.json` in the repo. If your repo does not have a lockfile, override with:
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
NodePipeline({
|
|
83
|
+
installCommand: "npm install", // use instead of npm ci
|
|
84
|
+
...
|
|
85
|
+
})
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Or generate a lockfile: `npm install && git add package-lock.json`.
|
|
89
|
+
|
|
90
|
+
### Step-by-step: push to GitLab
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
# 1. Build the YAML from chant source
|
|
94
|
+
chant build src/ --output .gitlab-ci.yml
|
|
95
|
+
|
|
96
|
+
# 2. Initialize git (if needed) and commit everything
|
|
97
|
+
git init -b main
|
|
98
|
+
git add .gitlab-ci.yml package.json index.js test.js # add your app files
|
|
99
|
+
git commit -m "Initial pipeline"
|
|
100
|
+
|
|
101
|
+
# 3. Push to GitLab
|
|
102
|
+
git remote add origin git@gitlab.com:YOUR_GROUP/YOUR_PROJECT.git
|
|
103
|
+
git push -u origin main
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
The pipeline triggers automatically on push. Do NOT commit the chant `src/` directory, `node_modules/`, or `.chant/` to the GitLab repo — those are local development files.
|
|
107
|
+
|
|
108
|
+
## Build and validate
|
|
109
|
+
|
|
110
|
+
### Build the pipeline
|
|
12
111
|
|
|
13
112
|
```bash
|
|
14
113
|
chant build src/ --output .gitlab-ci.yml
|
|
15
114
|
```
|
|
16
115
|
|
|
17
|
-
|
|
116
|
+
Options:
|
|
117
|
+
- `--format yaml` — emit YAML (default for GitLab)
|
|
118
|
+
- `--watch` — rebuild on source changes
|
|
119
|
+
- `--output <path>` — write to a specific file
|
|
120
|
+
|
|
121
|
+
### Lint the source
|
|
18
122
|
|
|
19
123
|
```bash
|
|
20
124
|
chant lint src/
|
|
21
125
|
```
|
|
22
126
|
|
|
23
|
-
|
|
127
|
+
Options:
|
|
128
|
+
- `--fix` — auto-fix violations where possible
|
|
129
|
+
- `--format sarif` — SARIF output for CI integration
|
|
130
|
+
- `--watch` — re-lint on changes
|
|
131
|
+
|
|
132
|
+
### Validate with GitLab CI Lint API
|
|
133
|
+
|
|
24
134
|
```bash
|
|
25
135
|
curl --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
26
|
-
"
|
|
27
|
-
|
|
136
|
+
--header "Content-Type: application/json" \
|
|
137
|
+
"https://gitlab.com/api/v4/projects/$PROJECT_ID/ci/lint" \
|
|
138
|
+
--data-binary @- <<EOF
|
|
139
|
+
{"content": $(cat .gitlab-ci.yml | jq -Rs .)}
|
|
140
|
+
EOF
|
|
28
141
|
```
|
|
29
142
|
|
|
30
|
-
|
|
143
|
+
Add `"dry_run": true, "include_merged_yaml": true` for full expansion with includes resolved.
|
|
144
|
+
|
|
145
|
+
### What each step catches
|
|
146
|
+
|
|
147
|
+
| Step | Catches | When to run |
|
|
148
|
+
|------|---------|-------------|
|
|
149
|
+
| `chant lint` | Deprecated only/except (WGL001), missing script (WGL002), missing stage (WGL003), artifacts without expiry (WGL004) | Every edit |
|
|
150
|
+
| `chant build` | Post-synth checks: undefined stages (WGL010), unreachable jobs (WGL011), deprecated properties (WGL012), invalid needs targets (WGL013), invalid extends targets (WGL014), circular needs chains (WGL015) | Before push |
|
|
151
|
+
| CI Lint API | GitLab-specific validation: include resolution, variable expansion, YAML schema errors | Before merge to default branch |
|
|
152
|
+
|
|
153
|
+
Always run all three before deploying. Lint catches things the API cannot (and vice versa).
|
|
31
154
|
|
|
32
|
-
|
|
155
|
+
## Diffing and change preview
|
|
156
|
+
|
|
157
|
+
### Local diff
|
|
158
|
+
|
|
159
|
+
Compare generated `.gitlab-ci.yml` against the version on the remote branch:
|
|
33
160
|
|
|
34
161
|
```bash
|
|
162
|
+
# Build the proposed config
|
|
35
163
|
chant build src/ --output .gitlab-ci.yml
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
git
|
|
164
|
+
|
|
165
|
+
# Diff against the remote version
|
|
166
|
+
git diff origin/main -- .gitlab-ci.yml
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### MR pipeline preview
|
|
170
|
+
|
|
171
|
+
Push to a branch and open a merge request — GitLab shows the pipeline that would run without executing it. This is the safest way to preview pipeline changes for production.
|
|
172
|
+
|
|
173
|
+
### CI Lint API with dry run
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
curl --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
177
|
+
--header "Content-Type: application/json" \
|
|
178
|
+
"https://gitlab.com/api/v4/projects/$PROJECT_ID/ci/lint" \
|
|
179
|
+
--data-binary @- <<EOF
|
|
180
|
+
{"content": $(cat .gitlab-ci.yml | jq -Rs .), "dry_run": true, "include_merged_yaml": true}
|
|
181
|
+
EOF
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
This resolves all `include:` directives and expands the full pipeline — useful for catching issues with cross-file references.
|
|
185
|
+
|
|
186
|
+
### Safe preview checklist
|
|
187
|
+
|
|
188
|
+
Before merging pipeline changes, verify:
|
|
189
|
+
1. All jobs have valid `stage:` values and stages are defined
|
|
190
|
+
2. `needs:` references point to existing job names
|
|
191
|
+
3. `rules:` conditions match the intended branches/events
|
|
192
|
+
4. Environment names and `on_stop` references are correct
|
|
193
|
+
5. Docker images are accessible from your runners
|
|
194
|
+
6. Secrets/variables referenced in scripts exist in project settings
|
|
195
|
+
|
|
196
|
+
## Deploying pipeline changes
|
|
197
|
+
|
|
198
|
+
### Safe path (production pipelines)
|
|
199
|
+
|
|
200
|
+
1. Build: `chant build src/ --output .gitlab-ci.yml`
|
|
201
|
+
2. Lint: `chant lint src/`
|
|
202
|
+
3. Validate: CI Lint API (see above)
|
|
203
|
+
4. Push to feature branch: `git push -u origin feature/pipeline-update`
|
|
204
|
+
5. Open MR — review pipeline diff in the MR widget
|
|
205
|
+
6. Merge — pipeline runs on the default branch
|
|
206
|
+
|
|
207
|
+
### Fast path (dev/iteration)
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
chant build src/ --output .gitlab-ci.yml
|
|
211
|
+
git add .gitlab-ci.yml && git commit -m "Update pipeline" && git push
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Which path to use
|
|
215
|
+
|
|
216
|
+
| Scenario | Path |
|
|
217
|
+
|----------|------|
|
|
218
|
+
| Production pipeline with deploy jobs | Safe path (MR review) |
|
|
219
|
+
| Pipeline with environment/secrets changes | Safe path (MR review) |
|
|
220
|
+
| Dev/test pipeline iteration | Fast path (direct push) |
|
|
221
|
+
| CI/CD with approval gates or protected environments | Safe path + protected branch |
|
|
222
|
+
|
|
223
|
+
## Environment lifecycle
|
|
224
|
+
|
|
225
|
+
Environments are created by jobs with an `environment:` keyword. They track deployments and enable rollback.
|
|
226
|
+
|
|
227
|
+
### Review apps pattern
|
|
228
|
+
|
|
229
|
+
Deploy on MR, auto-stop when MR is merged or closed:
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
new Job({
|
|
233
|
+
stage: "deploy",
|
|
234
|
+
environment: new Environment({
|
|
235
|
+
name: "review/$CI_COMMIT_REF_SLUG",
|
|
236
|
+
url: "https://$CI_COMMIT_REF_SLUG.example.com",
|
|
237
|
+
onStop: "stop_review",
|
|
238
|
+
autoStopIn: "1 week",
|
|
239
|
+
}),
|
|
240
|
+
script: ["./deploy-review.sh"],
|
|
241
|
+
rules: [{ if: "$CI_MERGE_REQUEST_IID" }],
|
|
242
|
+
});
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Environment promotion
|
|
246
|
+
|
|
247
|
+
Deploy through environments in order: dev → staging → production. Use `rules:` and `when: manual` to gate promotions.
|
|
248
|
+
|
|
249
|
+
### Rollback to a previous deployment
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
# List deployments for an environment
|
|
253
|
+
curl --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
254
|
+
"https://gitlab.com/api/v4/projects/$PROJECT_ID/environments/$ENV_ID/deployments?order_by=created_at&sort=desc&per_page=5"
|
|
255
|
+
|
|
256
|
+
# Re-deploy a previous deployment's commit
|
|
257
|
+
curl --request POST --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
258
|
+
"https://gitlab.com/api/v4/projects/$PROJECT_ID/deployments" \
|
|
259
|
+
--data "environment=production&sha=$PREVIOUS_SHA&ref=main&tag=false&status=created"
|
|
39
260
|
```
|
|
40
261
|
|
|
41
|
-
|
|
262
|
+
Alternatively, revert the MR that introduced the change and let the pipeline re-run.
|
|
42
263
|
|
|
43
|
-
|
|
44
|
-
- API: `curl --header "PRIVATE-TOKEN: $GITLAB_TOKEN" "https://gitlab.com/api/v4/projects/$PROJECT_ID/pipelines?per_page=5"`
|
|
264
|
+
## Pipeline and job states
|
|
45
265
|
|
|
46
|
-
|
|
266
|
+
### Pipeline states
|
|
47
267
|
|
|
48
|
-
|
|
49
|
-
|
|
268
|
+
| State | Meaning | Action |
|
|
269
|
+
|-------|---------|--------|
|
|
270
|
+
| `created` | Pipeline created, not yet started | Wait |
|
|
271
|
+
| `waiting_for_resource` | Waiting for runner | Check runner availability |
|
|
272
|
+
| `preparing` | Job is being prepared | Wait |
|
|
273
|
+
| `pending` | Waiting for runner to pick up | Check runner tags/availability |
|
|
274
|
+
| `running` | Pipeline is executing | Monitor |
|
|
275
|
+
| `success` | All jobs passed | None — healthy |
|
|
276
|
+
| `failed` | One or more jobs failed | Check failed job logs |
|
|
277
|
+
| `canceled` | Pipeline was canceled | Re-run if needed |
|
|
278
|
+
| `skipped` | Pipeline was skipped by rules | Check rules configuration |
|
|
279
|
+
| `manual` | Pipeline waiting for manual action | Trigger manual job or cancel |
|
|
280
|
+
| `scheduled` | Waiting for scheduled time | Wait |
|
|
50
281
|
|
|
51
|
-
|
|
282
|
+
### Job states
|
|
52
283
|
|
|
53
|
-
|
|
284
|
+
| State | Meaning | Action |
|
|
285
|
+
|-------|---------|--------|
|
|
286
|
+
| `created` | Job created | Wait |
|
|
287
|
+
| `pending` | Waiting for runner | Check runner tags |
|
|
288
|
+
| `running` | Job executing | Monitor logs |
|
|
289
|
+
| `success` | Job passed | None |
|
|
290
|
+
| `failed` | Job failed | Read trace log |
|
|
291
|
+
| `canceled` | Job canceled | Re-run if needed |
|
|
292
|
+
| `skipped` | Job skipped by rules/needs | Check rules |
|
|
293
|
+
| `manual` | Waiting for manual trigger | Play or skip |
|
|
294
|
+
| `allowed_failure` | Failed but allowed | Review — may indicate flaky test |
|
|
54
295
|
|
|
55
|
-
##
|
|
296
|
+
## Monitoring pipelines
|
|
297
|
+
|
|
298
|
+
### Check pipeline status
|
|
299
|
+
|
|
300
|
+
```bash
|
|
301
|
+
curl --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
302
|
+
"https://gitlab.com/api/v4/projects/$PROJECT_ID/pipelines/$PIPELINE_ID"
|
|
303
|
+
```
|
|
56
304
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
305
|
+
### List recent pipelines for a branch
|
|
306
|
+
|
|
307
|
+
```bash
|
|
308
|
+
curl --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
309
|
+
"https://gitlab.com/api/v4/projects/$PROJECT_ID/pipelines?ref=main&per_page=5"
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### Get jobs in a pipeline
|
|
313
|
+
|
|
314
|
+
```bash
|
|
315
|
+
curl --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
316
|
+
"https://gitlab.com/api/v4/projects/$PROJECT_ID/pipelines/$PIPELINE_ID/jobs"
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
### Stream job logs
|
|
320
|
+
|
|
321
|
+
```bash
|
|
322
|
+
curl --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
323
|
+
"https://gitlab.com/api/v4/projects/$PROJECT_ID/jobs/$JOB_ID/trace"
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
### Download job artifacts
|
|
327
|
+
|
|
328
|
+
```bash
|
|
329
|
+
curl --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
330
|
+
--output artifacts.zip \
|
|
331
|
+
"https://gitlab.com/api/v4/projects/$PROJECT_ID/jobs/$JOB_ID/artifacts"
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
## Merge request pipeline workflow
|
|
335
|
+
|
|
336
|
+
### How MR pipelines differ
|
|
337
|
+
|
|
338
|
+
MR pipelines run in a merge request context with `CI_MERGE_REQUEST_IID` available. Branch pipelines run on push with `CI_COMMIT_BRANCH`. A job cannot have both — use `rules:` to target one or the other.
|
|
339
|
+
|
|
340
|
+
### Common rules patterns
|
|
341
|
+
|
|
342
|
+
```yaml
|
|
343
|
+
# Run only on MR pipelines
|
|
344
|
+
rules:
|
|
345
|
+
- if: $CI_MERGE_REQUEST_IID
|
|
346
|
+
|
|
347
|
+
# Run only on the default branch
|
|
348
|
+
rules:
|
|
349
|
+
- if: $CI_COMMIT_BRANCH == "main"
|
|
350
|
+
|
|
351
|
+
# Run on MRs and the default branch (but not both at once)
|
|
352
|
+
rules:
|
|
353
|
+
- if: $CI_MERGE_REQUEST_IID
|
|
354
|
+
- if: $CI_COMMIT_BRANCH == "main"
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### Merged results pipelines
|
|
358
|
+
|
|
359
|
+
Enable in project settings → CI/CD → General pipelines → "Merged results pipelines". These test the result of merging your branch into the target — catching integration issues before merge.
|
|
360
|
+
|
|
361
|
+
### Merge trains
|
|
362
|
+
|
|
363
|
+
Merge trains queue MRs and test each one merged on top of the previous. Enable in project settings → Merge requests → "Merge trains". Requires merged results pipelines.
|
|
364
|
+
|
|
365
|
+
## Troubleshooting decision tree
|
|
366
|
+
|
|
367
|
+
### Step 1: Check pipeline status
|
|
368
|
+
|
|
369
|
+
```bash
|
|
370
|
+
curl --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
371
|
+
"https://gitlab.com/api/v4/projects/$PROJECT_ID/pipelines/$PIPELINE_ID" | jq '.status'
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
### Step 2: Branch on status
|
|
375
|
+
|
|
376
|
+
- **`running` / `pending` / `created`** → Wait. Do not take action while the pipeline is in progress.
|
|
377
|
+
- **`failed`** → Read the failed job logs (Step 3).
|
|
378
|
+
- **`success`** → Pipeline is healthy. If behavior is wrong, check job scripts and configuration.
|
|
379
|
+
- **`canceled`** → Re-run if needed: `curl --request POST ... /pipelines/$PIPELINE_ID/retry`
|
|
380
|
+
- **`skipped`** → All jobs were filtered out by `rules:`. Check rule conditions.
|
|
381
|
+
|
|
382
|
+
### Step 3: Read failed job logs
|
|
383
|
+
|
|
384
|
+
```bash
|
|
385
|
+
# Get failed jobs
|
|
386
|
+
curl --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
387
|
+
"https://gitlab.com/api/v4/projects/$PROJECT_ID/pipelines/$PIPELINE_ID/jobs?scope=failed" | jq '.[].id'
|
|
388
|
+
|
|
389
|
+
# Read the trace for a failed job
|
|
390
|
+
curl --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
391
|
+
"https://gitlab.com/api/v4/projects/$PROJECT_ID/jobs/$JOB_ID/trace"
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
### Step 4: Diagnose by error pattern
|
|
395
|
+
|
|
396
|
+
| Error pattern | Likely cause | Fix |
|
|
397
|
+
|---------------|-------------|-----|
|
|
398
|
+
| "no matching runner" | No runner with matching tags | Check runner tags, register a runner |
|
|
399
|
+
| "image pull failed" | Docker image not found or auth failed | Check image name, registry credentials |
|
|
400
|
+
| "script exit code 1" | Script command failed | Read job log for the failing command |
|
|
401
|
+
| "artifact upload failed" | Artifact path doesn't exist or too large | Check `artifacts.paths`, size limits |
|
|
402
|
+
| "cache not found" | Cache key mismatch or first run | Expected on first run; check `cache.key` |
|
|
403
|
+
| "yaml invalid" | Syntax error in generated YAML | Run `chant lint src/` and CI Lint API |
|
|
404
|
+
| "pipeline filtered out" | All jobs filtered by rules | Check `rules:` conditions |
|
|
405
|
+
| "job timed out" | Job exceeded timeout | Increase `timeout:` or optimize job |
|
|
406
|
+
| "stuck or pending" | No available runner | Check runner status, tags, executor capacity |
|
|
407
|
+
| "environment does not exist" | `on_stop` references non-existent job | Check `on_stop` job name matches expanded name |
|
|
408
|
+
| "needs job not found" | `needs:` references non-existent job | Check job names, stage ordering |
|
|
409
|
+
|
|
410
|
+
## Variable management
|
|
411
|
+
|
|
412
|
+
### Variable types and precedence
|
|
413
|
+
|
|
414
|
+
Variables are resolved in this order (highest priority first):
|
|
415
|
+
1. Job-level `variables:`
|
|
416
|
+
2. Project CI/CD variables (Settings → CI/CD → Variables)
|
|
417
|
+
3. Group CI/CD variables
|
|
418
|
+
4. Instance CI/CD variables
|
|
419
|
+
|
|
420
|
+
### Protected and masked variables
|
|
421
|
+
|
|
422
|
+
- **Protected**: only available in pipelines on protected branches/tags
|
|
423
|
+
- **Masked**: hidden in job logs (value must meet masking requirements)
|
|
424
|
+
|
|
425
|
+
### Managing variables via API
|
|
426
|
+
|
|
427
|
+
```bash
|
|
428
|
+
# List project variables
|
|
429
|
+
curl --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
430
|
+
"https://gitlab.com/api/v4/projects/$PROJECT_ID/variables"
|
|
431
|
+
|
|
432
|
+
# Create a variable
|
|
433
|
+
curl --request POST --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
434
|
+
"https://gitlab.com/api/v4/projects/$PROJECT_ID/variables" \
|
|
435
|
+
--form "key=DEPLOY_TOKEN" --form "value=secret" --form "masked=true" --form "protected=true"
|
|
436
|
+
|
|
437
|
+
# Update a variable
|
|
438
|
+
curl --request PUT --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
439
|
+
"https://gitlab.com/api/v4/projects/$PROJECT_ID/variables/DEPLOY_TOKEN" \
|
|
440
|
+
--form "value=new-secret"
|
|
441
|
+
|
|
442
|
+
# Delete a variable
|
|
443
|
+
curl --request DELETE --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
444
|
+
"https://gitlab.com/api/v4/projects/$PROJECT_ID/variables/DEPLOY_TOKEN"
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
## Quick reference
|
|
448
|
+
|
|
449
|
+
### Pipeline info commands
|
|
450
|
+
|
|
451
|
+
```bash
|
|
452
|
+
# List recent pipelines
|
|
453
|
+
curl --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
454
|
+
"https://gitlab.com/api/v4/projects/$PROJECT_ID/pipelines?per_page=5"
|
|
455
|
+
|
|
456
|
+
# Get pipeline status
|
|
457
|
+
curl --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
458
|
+
"https://gitlab.com/api/v4/projects/$PROJECT_ID/pipelines/$PIPELINE_ID"
|
|
459
|
+
|
|
460
|
+
# Get jobs in a pipeline
|
|
461
|
+
curl --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
462
|
+
"https://gitlab.com/api/v4/projects/$PROJECT_ID/pipelines/$PIPELINE_ID/jobs"
|
|
463
|
+
|
|
464
|
+
# Read job log
|
|
465
|
+
curl --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
466
|
+
"https://gitlab.com/api/v4/projects/$PROJECT_ID/jobs/$JOB_ID/trace"
|
|
467
|
+
|
|
468
|
+
# Retry a failed pipeline
|
|
469
|
+
curl --request POST --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
470
|
+
"https://gitlab.com/api/v4/projects/$PROJECT_ID/pipelines/$PIPELINE_ID/retry"
|
|
471
|
+
|
|
472
|
+
# Cancel a running pipeline
|
|
473
|
+
curl --request POST --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
474
|
+
"https://gitlab.com/api/v4/projects/$PROJECT_ID/pipelines/$PIPELINE_ID/cancel"
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
### Full build-to-deploy pipeline
|
|
478
|
+
|
|
479
|
+
```bash
|
|
480
|
+
# 1. Lint
|
|
481
|
+
chant lint src/
|
|
482
|
+
|
|
483
|
+
# 2. Build
|
|
484
|
+
chant build src/ --output .gitlab-ci.yml
|
|
485
|
+
|
|
486
|
+
# 3. Validate via API
|
|
487
|
+
curl --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
|
|
488
|
+
--header "Content-Type: application/json" \
|
|
489
|
+
"https://gitlab.com/api/v4/projects/$PROJECT_ID/ci/lint" \
|
|
490
|
+
--data-binary @- <<EOF
|
|
491
|
+
{"content": $(cat .gitlab-ci.yml | jq -Rs .)}
|
|
492
|
+
EOF
|
|
493
|
+
|
|
494
|
+
# 4. Push to feature branch
|
|
495
|
+
git checkout -b feature/pipeline-update
|
|
496
|
+
git add .gitlab-ci.yml
|
|
497
|
+
git commit -m "Update pipeline"
|
|
498
|
+
git push -u origin feature/pipeline-update
|
|
499
|
+
|
|
500
|
+
# 5. Open MR, review pipeline diff, merge
|
|
501
|
+
# Pipeline runs automatically on the default branch after merge
|
|
502
|
+
```
|
package/dist/types/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
export declare class AllowFailure {
|
|
6
6
|
constructor(props: {
|
|
7
|
-
exit_codes: number;
|
|
7
|
+
exit_codes: number | number[];
|
|
8
8
|
});
|
|
9
9
|
}
|
|
10
10
|
|
|
@@ -48,7 +48,7 @@ export declare class Default {
|
|
|
48
48
|
before_script?: string | string[];
|
|
49
49
|
cache?: Cache | Cache[];
|
|
50
50
|
hooks?: Record<string, unknown>;
|
|
51
|
-
id_tokens?: Record<string,
|
|
51
|
+
id_tokens?: Record<string, { aud: string | string[] }>;
|
|
52
52
|
identity?: "google_cloud";
|
|
53
53
|
image?: Image;
|
|
54
54
|
interruptible?: boolean;
|
|
@@ -85,19 +85,34 @@ export declare class Image {
|
|
|
85
85
|
docker?: Record<string, unknown>;
|
|
86
86
|
/** Command or script that should be executed as the container's entrypoint. It will be translated to Docker's --entrypoint option while creating the container. The syntax is similar to Dockerfile's ENTRYPOINT directive, where each shell token is a separate string in the array. */
|
|
87
87
|
entrypoint?: any[];
|
|
88
|
-
pull_policy?: "always" | "never" | "if-not-present" | "always" | "never" | "if-not-present"[];
|
|
88
|
+
pull_policy?: "always" | "never" | "if-not-present" | ("always" | "never" | "if-not-present")[];
|
|
89
89
|
});
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
export declare class Include {
|
|
93
93
|
constructor(props: {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
94
|
+
/** Local path to component directory or full path to external component directory. */
|
|
95
|
+
component?: string;
|
|
96
|
+
file?: string | string[];
|
|
97
97
|
inputs?: Record<string, unknown>;
|
|
98
|
+
/** Relative path from local repository root (`/`) to the `yaml`/`yml` file template. The file must be on the same branch, and does not work across git submodules. */
|
|
99
|
+
local?: string;
|
|
100
|
+
/** Path to the project, e.g. `group/project`, or `group/sub-group/project` [Learn more](https://docs.gitlab.com/ee/ci/yaml/index.html#includefile). */
|
|
101
|
+
project?: string;
|
|
98
102
|
/** Branch/Tag/Commit-hash for the target project. */
|
|
99
103
|
ref?: string;
|
|
104
|
+
/** URL to a `yaml`/`yml` template file using HTTP/HTTPS. */
|
|
105
|
+
remote?: string;
|
|
100
106
|
rules?: any[];
|
|
107
|
+
/** Use a `.gitlab-ci.yml` template as a base, e.g. `Nodejs.gitlab-ci.yml`. */
|
|
108
|
+
template?: string;
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export declare class Inherit {
|
|
113
|
+
constructor(props: {
|
|
114
|
+
default?: boolean | ("after_script" | "artifacts" | "before_script" | "cache" | "image" | "interruptible" | "retry" | "services" | "tags" | "timeout")[];
|
|
115
|
+
variables?: boolean | string[];
|
|
101
116
|
});
|
|
102
117
|
}
|
|
103
118
|
|
|
@@ -113,20 +128,20 @@ export declare class Job {
|
|
|
113
128
|
/** Specify a list of job names from earlier stages from which artifacts should be loaded. By default, all previous artifacts are passed. Use an empty array to skip downloading artifacts. */
|
|
114
129
|
dependencies?: string[];
|
|
115
130
|
/** Used to associate environment metadata with a deploy. Environment can have a name and URL attached to it, and will be displayed under /environments under the project. */
|
|
116
|
-
environment?:
|
|
131
|
+
environment?: Environment | string;
|
|
117
132
|
/** Job will run *except* for when these filtering options match. */
|
|
118
133
|
except?: any;
|
|
119
134
|
/** The name of one or more jobs to inherit configuration from. */
|
|
120
135
|
extends?: string | string[];
|
|
121
136
|
hooks?: Record<string, unknown>;
|
|
122
|
-
id_tokens?: Record<string,
|
|
137
|
+
id_tokens?: Record<string, { aud: string | string[] }>;
|
|
123
138
|
identity?: "google_cloud";
|
|
124
139
|
image?: Image;
|
|
125
|
-
inherit?:
|
|
140
|
+
inherit?: Inherit;
|
|
126
141
|
interruptible?: boolean;
|
|
127
142
|
manual_confirmation?: string;
|
|
128
143
|
/** The list of jobs in previous stages whose sole completion is needed to start the current job. */
|
|
129
|
-
needs?:
|
|
144
|
+
needs?: Need[];
|
|
130
145
|
/** Job will run *only* when these filtering options match. */
|
|
131
146
|
only?: any;
|
|
132
147
|
pages?: Record<string, any> | boolean;
|
|
@@ -134,7 +149,7 @@ export declare class Job {
|
|
|
134
149
|
/** A path to a directory that contains the files to be published with Pages */
|
|
135
150
|
publish?: string;
|
|
136
151
|
/** Indicates that the job creates a Release. */
|
|
137
|
-
release?:
|
|
152
|
+
release?: Release;
|
|
138
153
|
/** Limit job concurrency. Can be used to ensure that the Runner will not run certain jobs simultaneously. */
|
|
139
154
|
resource_group?: string;
|
|
140
155
|
retry?: Retry | number;
|
|
@@ -148,12 +163,24 @@ export declare class Job {
|
|
|
148
163
|
start_in?: string;
|
|
149
164
|
tags?: any[];
|
|
150
165
|
timeout?: string;
|
|
151
|
-
trigger?:
|
|
166
|
+
trigger?: Trigger | string;
|
|
152
167
|
variables?: Record<string, unknown>;
|
|
153
168
|
when?: "on_success" | "on_failure" | "always" | "never" | "manual" | "delayed";
|
|
154
169
|
});
|
|
155
170
|
}
|
|
156
171
|
|
|
172
|
+
export declare class Need {
|
|
173
|
+
constructor(props: {
|
|
174
|
+
job: string;
|
|
175
|
+
artifacts?: boolean;
|
|
176
|
+
optional?: boolean;
|
|
177
|
+
parallel?: any;
|
|
178
|
+
pipeline?: string;
|
|
179
|
+
project?: string;
|
|
180
|
+
ref?: string;
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
157
184
|
export declare class Parallel {
|
|
158
185
|
constructor(props: {
|
|
159
186
|
/** Defines different variables for jobs that are running in parallel. */
|
|
@@ -211,19 +238,20 @@ export declare class Service {
|
|
|
211
238
|
command?: string[];
|
|
212
239
|
docker?: Record<string, unknown>;
|
|
213
240
|
entrypoint?: string[];
|
|
214
|
-
pull_policy?: "always" | "never" | "if-not-present" | "always" | "never" | "if-not-present"[];
|
|
241
|
+
pull_policy?: "always" | "never" | "if-not-present" | ("always" | "never" | "if-not-present")[];
|
|
215
242
|
variables?: Record<string, unknown>;
|
|
216
243
|
});
|
|
217
244
|
}
|
|
218
245
|
|
|
219
246
|
export declare class Trigger {
|
|
220
247
|
constructor(props: {
|
|
221
|
-
/** Path to the project, e.g. `group/project`, or `group/sub-group/project`. */
|
|
222
|
-
project: string;
|
|
223
248
|
/** The branch name that a downstream pipeline will use */
|
|
224
249
|
branch?: string;
|
|
225
250
|
/** Specify what to forward to the downstream pipeline. */
|
|
226
251
|
forward?: Record<string, unknown>;
|
|
252
|
+
include?: string | Record<string, any>[];
|
|
253
|
+
/** Path to the project, e.g. `group/project`, or `group/sub-group/project`. */
|
|
254
|
+
project?: string;
|
|
227
255
|
/** You can mirror the pipeline status from the triggered pipeline to the source bridge job by using strategy: depend */
|
|
228
256
|
strategy?: "depend";
|
|
229
257
|
});
|
|
@@ -233,7 +261,18 @@ export declare class Workflow {
|
|
|
233
261
|
constructor(props: {
|
|
234
262
|
auto_cancel?: AutoCancel;
|
|
235
263
|
name?: string;
|
|
236
|
-
rules?:
|
|
264
|
+
rules?: WorkflowRule[];
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export declare class WorkflowRule {
|
|
269
|
+
constructor(props: {
|
|
270
|
+
auto_cancel?: AutoCancel;
|
|
271
|
+
changes?: any;
|
|
272
|
+
exists?: any;
|
|
273
|
+
if?: string;
|
|
274
|
+
variables?: Record<string, unknown>;
|
|
275
|
+
when?: "always" | "never";
|
|
237
276
|
});
|
|
238
277
|
}
|
|
239
278
|
|