-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgitlab_ci.yaml
More file actions
425 lines (420 loc) · 17.8 KB
/
Copy pathgitlab_ci.yaml
File metadata and controls
425 lines (420 loc) · 17.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
- id: gitlab_ci.stuck_no_runners
technology: gitlab_ci
title: "Job stuck: no runners with matching tags"
summary: >-
A pipeline job stays pending because no active runner is online whose tags
match the job's tags (or the job has tags but only untagged runners exist).
applies_to: [log, command_output, error_string, yaml]
match:
any_of:
- "This job is stuck because"
- "no (active )?runners online"
- "no runners that match all of the job's tags"
- "stuck.*no.*runner"
weight: 0.82
root_causes:
- title: "No runner has the required tags"
description: >-
The job specifies tags that no online runner carries, so nothing can pick it
up.
confidence: 0.6
category: configuration
- title: "Runner offline or paused"
description: >-
The matching runner exists but is offline (lost contact) or paused in the
project/instance settings.
confidence: 0.5
category: availability
- title: "Tagged job but only untagged runners"
description: >-
Runners are not set to 'run untagged jobs', and the job's tags do not match,
leaving it unpicked.
confidence: 0.4
category: configuration
diagnostic_commands:
- command: "gitlab-runner list"
explanation: "Lists registered runners and their configured tags on the host."
expected_output: "Registered runners with their executor and tags."
platform: "gitlab-runner host"
- command: "gitlab-runner verify"
explanation: "Checks whether the registered runners are still valid/online with GitLab."
expected_output: "Each runner verified as still registered (or removed)."
platform: "gitlab-runner host"
- command: "cat /etc/gitlab-runner/config.toml"
explanation: "Shows runner tags, limits, and run_untagged settings."
expected_output: "[[runners]] entries with tags and run_untagged values."
platform: "gitlab-runner host"
suggested_fixes:
- title: "Align job tags with an online runner"
description: >-
Set the job's tags to match an available runner, or register/tag a runner for
the required label.
snippet: |
build:
tags: [docker, linux] # must match a runner's tags
script: [make build]
- title: "Allow untagged jobs where appropriate"
description: >-
Enable 'run untagged jobs' on the runner for jobs that legitimately have no
tags.
references:
- title: "GitLab CI job stuck with no runners"
url: "https://devopsaitoolkit.com/blog/gitlab-ci-job-stuck-no-runners"
source: "devopsaitoolkit"
- title: "GitLab Runner tags"
url: "https://docs.gitlab.com/ci/runners/configure_runners/#use-tags-to-control-which-jobs-a-runner-can-run"
source: "official"
best_practices:
- "Standardize a small, documented set of runner tags."
- "Monitor runner online status and alert when key runners drop."
prevention:
- "Validate that every job's tags map to at least one active runner."
tags: [runners, tags, pending]
- id: gitlab_ci.job_exit_code_1
technology: gitlab_ci
title: "Job failed: exit code 1"
summary: >-
A job's script step returned a non-zero exit code, so GitLab marks the job
failed. The real cause is in the failing command's own output above.
applies_to: [log, command_output, error_string]
match:
any_of:
- "ERROR: Job failed: exit code 1"
- "ERROR: Job failed: exit status 1"
- "Job failed: exit code \\d+"
weight: 0.7
root_causes:
- title: "A script command genuinely failed"
description: >-
A build/test/lint command returned non-zero (the actual error is printed just
above this line).
confidence: 0.6
category: application
- title: "Missing dependency or tool in the image"
description: >-
The job image lacks a required binary/package, so the command exits with an
error.
confidence: 0.45
category: configuration
- title: "Missing variable, secret, or file"
description: >-
A required CI/CD variable or input file is absent, so the script aborts.
confidence: 0.4
category: configuration
- title: "Environment differs from local"
description: >-
Different OS, tool versions, or working directory in the runner cause a command
that passes locally to fail in CI.
confidence: 0.35
category: environment
diagnostic_commands:
- command: "cat .gitlab-ci.yml"
explanation: "Shows the job's script so you can identify which step exited non-zero."
expected_output: "The script lines for the failing job."
- command: "docker run --rm -it <job-image> sh -c 'which <tool>'"
explanation: "Reproduces the runner environment to confirm a tool/dependency is present."
expected_output: "The tool path, or empty if it is missing from the image."
platform: "docker executor"
suggested_fixes:
- title: "Fix the failing command shown above"
description: >-
Read the lines immediately before the exit-code line, fix that command, and
reproduce locally with the same image.
- title: "Add the missing dependency or variable"
description: >-
Install the required tool in the job image or define the missing CI/CD
variable, then re-run.
snippet: |
test:
image: python:3.12
before_script: [pip install -r requirements-dev.txt]
script: [pytest -q]
references:
- title: "Debugging GitLab CI exit code 1"
url: "https://devopsaitoolkit.com/blog/gitlab-ci-job-failed-exit-code-1"
source: "devopsaitoolkit"
- title: "GitLab CI debugging"
url: "https://docs.gitlab.com/ci/debugging/"
source: "official"
best_practices:
- "Pin job images to specific versions for reproducibility."
- "Surface the failing command's full output (avoid swallowing errors)."
prevention:
- "Run the same commands in a pre-commit/local container before pushing."
tags: [scripts, failure, exit-code]
- id: gitlab_ci.invalid_config_yaml
technology: gitlab_ci
title: "Invalid CI configuration (YAML / lint error)"
summary: >-
GitLab refuses to create the pipeline because .gitlab-ci.yml is syntactically
invalid YAML or violates the CI schema.
applies_to: [yaml, log, command_output, error_string]
match:
any_of:
- "Invalid CI config"
- "jobs config should contain"
- "yaml invalid"
- "did not find expected key"
- "mapping values are not allowed"
weight: 0.82
root_causes:
- title: "YAML syntax error"
description: >-
Bad indentation, a tab character, an unquoted colon, or a missing key breaks
YAML parsing.
confidence: 0.6
category: configuration
- title: "Schema violation"
description: >-
A key is misspelled, a job lacks a script, or a stage/keyword is used
incorrectly per the CI schema.
confidence: 0.5
category: configuration
- title: "Broken include/template"
description: >-
An included or extended template is missing, unreachable, or itself invalid,
invalidating the whole config.
confidence: 0.4
category: configuration
diagnostic_commands:
- command: "cat .gitlab-ci.yml"
explanation: "Inspects the raw file to locate the indentation/syntax problem."
expected_output: "The CI config; look at the line the error references."
- command: "python -c 'import sys,yaml; yaml.safe_load(open(\".gitlab-ci.yml\"))'"
explanation: "Validates pure YAML syntax locally before pushing."
expected_output: "No output on success, or a YAML error with line/column."
platform: "any host with python+pyyaml"
suggested_fixes:
- title: "Fix the YAML at the reported line"
description: >-
Correct indentation/quoting (use spaces, never tabs) and re-validate with the
pipeline editor's lint.
snippet: |
build:
stage: build
script:
- make build
- title: "Validate includes/templates"
description: >-
Ensure every include path exists and resolves, then re-lint the merged config.
references:
- title: "Fixing invalid GitLab CI YAML"
url: "https://devopsaitoolkit.com/blog/gitlab-ci-invalid-config-yaml"
source: "devopsaitoolkit"
- title: "GitLab CI/CD YAML syntax reference"
url: "https://docs.gitlab.com/ci/yaml/"
source: "official"
best_practices:
- "Use the pipeline editor / CI lint before merging config changes."
- "Use spaces for indentation; configure your editor to reject tabs."
prevention:
- "Lint .gitlab-ci.yml in a pre-commit hook or merge-request check."
tags: [yaml, config, lint]
- id: gitlab_ci.prepare_environment_failed
technology: gitlab_ci
title: "Prepare environment: exit status 1"
summary: >-
The job failed before the script ran, during the runner's prepare phase —
usually a shell-profile error, container/image problem, or executor setup
failure.
applies_to: [log, command_output, error_string]
match:
any_of:
- "Preparing environment"
- "prepare environment: exit status 1"
- "Failed to prepare environment"
weight: 0.8
root_causes:
- title: "Error in shell profile (.bashrc/.bash_logout)"
description: >-
On shell executors, a command in the user's profile returns non-zero during
prepare, failing the whole job.
confidence: 0.55
category: configuration
- title: "Image cannot be pulled or started"
description: >-
For docker executors, the job image fails to pull or start, so the environment
cannot be prepared.
confidence: 0.5
category: configuration
- title: "Executor/runner host issue"
description: >-
Disk full, permissions, or a broken executor (docker/k8s) prevents the runner
from setting up the build.
confidence: 0.4
category: environment
diagnostic_commands:
- command: "cat /etc/gitlab-runner/config.toml"
explanation: "Shows the executor type and image so you know which prepare path runs."
expected_output: "The [[runners]] executor and default image settings."
platform: "gitlab-runner host"
- command: "journalctl -u gitlab-runner --no-pager -n 100"
explanation: "Surfaces the runner's own logs around the prepare failure."
expected_output: "The prepare-phase error (profile, image pull, or executor)."
platform: "linux with systemd"
- command: "df -h"
explanation: "Checks for a full disk on the runner host that breaks prepare."
expected_output: "Use% well below 100% on the runner's build path."
platform: "linux"
suggested_fixes:
- title: "Fix the shell profile or use a clean executor"
description: >-
Remove the failing command from the runner user's profile, or switch the job to
a docker/k8s executor with a known-good image.
- title: "Ensure the job image is pullable"
description: >-
Verify the image reference and registry credentials so the docker executor can
start it.
snippet: |
default:
image: registry.example.com/ci/base:1.0
references:
- title: "GitLab CI prepare environment exit status 1"
url: "https://devopsaitoolkit.com/blog/gitlab-ci-prepare-environment-exit-status-1"
source: "devopsaitoolkit"
- title: "GitLab Runner shell executor"
url: "https://docs.gitlab.com/runner/executors/shell/"
source: "official"
best_practices:
- "Prefer container executors over shell for clean, reproducible prepare."
- "Keep the runner user's shell profile minimal and side-effect-free."
prevention:
- "Monitor runner host disk and image registry reachability."
tags: [runner, prepare, executor]
- id: gitlab_ci.registry_401_unauthorized
technology: gitlab_ci
title: "401 Unauthorized pulling/pushing to registry"
summary: >-
A job cannot authenticate to a container registry (HTTP 401), so the image
pull or push is denied — usually a missing/expired credential or insufficient
token scope.
applies_to: [log, command_output, error_string]
match:
any_of:
- "401 Unauthorized"
- "unauthorized: HTTP Basic: Access denied"
- "denied: access forbidden"
- "unauthorized: authentication required"
weight: 0.82
root_causes:
- title: "Not logged in to the registry"
description: >-
The job never authenticated (no docker login / DOCKER_AUTH_CONFIG) before
pulling or pushing.
confidence: 0.55
category: authentication
- title: "Expired or wrong credentials"
description: >-
The token, deploy token, or password is expired, revoked, or scoped to a
different project.
confidence: 0.5
category: authentication
- title: "Insufficient token scope"
description: >-
CI_JOB_TOKEN or a PAT lacks read_registry/write_registry scope for the target
project.
confidence: 0.4
category: authorization
diagnostic_commands:
- command: "cat $HOME/.docker/config.json"
explanation: "Shows which registries the job is authenticated to in this environment."
expected_output: "An auths entry for the target registry, or none."
platform: "docker executor"
- command: "env | grep -E 'CI_REGISTRY|DOCKER_AUTH_CONFIG'"
explanation: "Confirms the registry variables/credentials are present in the job."
expected_output: "CI_REGISTRY and a credential variable populated."
suggested_fixes:
- title: "Authenticate to the GitLab registry in the job"
description: >-
Log in with the predefined CI registry variables before pull/push.
snippet: |
before_script:
- echo "$CI_REGISTRY_PASSWORD" | docker login -u "$CI_REGISTRY_USER" --password-stdin "$CI_REGISTRY"
- title: "Grant the token the right registry scope"
description: >-
Use a deploy token or job token with read_registry/write_registry for the
target project.
references:
- title: "GitLab CI registry 401 unauthorized"
url: "https://devopsaitoolkit.com/blog/gitlab-ci-registry-401-unauthorized"
source: "devopsaitoolkit"
- title: "Authenticate to the GitLab container registry"
url: "https://docs.gitlab.com/user/packages/container_registry/authenticate_with_container_registry/"
source: "official"
warnings:
- message: "Never echo registry passwords into logs; use --password-stdin and masked variables."
severity: high
best_practices:
- "Use CI_REGISTRY_USER/PASSWORD predefined variables for the built-in registry."
- "Mask and protect all registry credential variables."
prevention:
- "Rotate deploy tokens before expiry and verify scopes in CI."
tags: [registry, auth, login]
- id: gitlab_ci.could_not_read_username
technology: gitlab_ci
title: "Could not read Username (CI_JOB_TOKEN clone)"
summary: >-
A git operation in CI fails with 'could not read Username' because it tried to
clone/fetch over HTTPS without credentials — typically a submodule or
dependency on another repo not authorized via CI_JOB_TOKEN.
applies_to: [log, command_output, error_string]
match:
any_of:
- "could not read Username for"
- "fatal: could not read Username"
- "terminal prompts disabled"
- "Authentication failed for .*\\.git"
weight: 0.82
root_causes:
- title: "Cross-repo access not allowed for CI_JOB_TOKEN"
description: >-
The job token tries to clone another project (submodule or package) that does
not allow this project in its job-token allowlist.
confidence: 0.55
category: authorization
- title: "HTTPS URL without embedded credentials"
description: >-
A submodule or dependency uses a plain https:// git URL, so git prompts for a
username that CI cannot provide.
confidence: 0.5
category: configuration
- title: "Token expired or insufficient scope"
description: >-
A custom token used instead of CI_JOB_TOKEN is expired or lacks read_repository
scope.
confidence: 0.4
category: authentication
diagnostic_commands:
- command: "cat .gitmodules"
explanation: "Shows submodule URLs to spot plain HTTPS references that need credentials."
expected_output: "Submodule entries; look for https:// URLs without tokens."
- command: "git config --get-regexp 'url\\..*\\.insteadof'"
explanation: "Reveals any URL-rewrite rules that inject CI credentials."
expected_output: "An insteadOf rewrite for the registry/git host, or none."
suggested_fixes:
- title: "Rewrite git URLs to use CI_JOB_TOKEN"
description: >-
Configure git to clone via the job token so no username prompt is needed.
snippet: |
before_script:
- git config --global url."https://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_HOST}/".insteadOf "https://${CI_SERVER_HOST}/"
- title: "Allow this project in the target's job-token allowlist"
description: >-
In the depended-on project's CI/CD settings, add this project to the
CI_JOB_TOKEN allowlist so cross-repo clones are authorized.
references:
- title: "GitLab CI could not read Username (CI_JOB_TOKEN)"
url: "https://devopsaitoolkit.com/blog/gitlab-ci-could-not-read-username"
source: "devopsaitoolkit"
- title: "GitLab CI/CD job token"
url: "https://docs.gitlab.com/ci/jobs/ci_job_token/"
source: "official"
warnings:
- message: "Do not hardcode personal access tokens in .gitmodules or CI files; use CI_JOB_TOKEN URL rewriting."
severity: high
best_practices:
- "Use CI_JOB_TOKEN URL rewriting for internal submodule/dependency clones."
- "Maintain explicit job-token allowlists between dependent projects."
prevention:
- "Audit submodule URLs to ensure none require interactive credentials."
tags: [git, job-token, submodules]