@htekdev/actions-debugger 1.0.7 → 1.0.9
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/errors/caching-artifacts/upload-artifact-v4-same-name-409-conflict.yml +145 -0
- package/errors/concurrency-timing/concurrency-group-name-collision.yml +165 -0
- package/errors/known-unsolved/upload-artifact-v4-ghes-not-supported.yml +120 -0
- package/errors/runner-environment/docker-29-compose-v2-40-breaking.yml +144 -0
- package/errors/runner-environment/node-20-toolcache-removal.yml +134 -0
- package/errors/runner-environment/ubuntu-arm64-docker-not-preinstalled.yml +137 -0
- package/errors/runner-environment/windows-2019-runner-retirement.yml +100 -0
- package/errors/silent-failures/upload-artifact-v4-hidden-files-excluded.yml +121 -0
- package/errors/yaml-syntax/vars-context-rejected-composite-actions.yml +127 -0
- package/package.json +1 -1
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
id: caching-artifacts-012
|
|
2
|
+
title: "upload-artifact v4 Rejects Duplicate Artifact Names from Multiple Jobs (409 Conflict)"
|
|
3
|
+
category: caching-artifacts
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- upload-artifact
|
|
7
|
+
- artifact-v4
|
|
8
|
+
- matrix
|
|
9
|
+
- parallel-jobs
|
|
10
|
+
- 409
|
|
11
|
+
- immutability
|
|
12
|
+
patterns:
|
|
13
|
+
- regex: "Failed to CreateArtifact.*409.*Conflict.*artifact.*already exists"
|
|
14
|
+
flags: "i"
|
|
15
|
+
- regex: "artifact.*already exists.*workflow run|duplicate.*artifact.*name"
|
|
16
|
+
flags: "i"
|
|
17
|
+
- regex: "Received non-retryable error.*409.*Conflict"
|
|
18
|
+
flags: "i"
|
|
19
|
+
error_messages:
|
|
20
|
+
- "Failed to CreateArtifact: Received non-retryable error: Failed request: (409) Conflict: an artifact with this name already exists on the workflow run"
|
|
21
|
+
- "Error: ENOENT: no such file or directory — artifact upload failed with conflict"
|
|
22
|
+
- "Upload failed: 409 Conflict — Artifact 'build-output' already exists"
|
|
23
|
+
root_cause: |
|
|
24
|
+
**actions/upload-artifact v4** (backed by the v2 `@actions/artifact` client) makes
|
|
25
|
+
artifacts **immutable and job-scoped by default**. Once an artifact name is uploaded
|
|
26
|
+
by any job in a workflow run, that name is locked — a second job attempting to upload
|
|
27
|
+
an artifact with the same name will receive a `409 Conflict` error from the Artifact
|
|
28
|
+
API and the upload fails.
|
|
29
|
+
|
|
30
|
+
This is a **breaking behavior change from v3**, which allowed multiple jobs to
|
|
31
|
+
append to the same artifact name. v4 deliberately prevents this to ensure artifact
|
|
32
|
+
content integrity and predictable downloads.
|
|
33
|
+
|
|
34
|
+
**Common scenarios that trigger this:**
|
|
35
|
+
|
|
36
|
+
1. **Matrix jobs** — all matrix jobs use the same artifact name (e.g., `build-output`)
|
|
37
|
+
and upload in parallel; only the first to complete succeeds.
|
|
38
|
+
|
|
39
|
+
2. **Retry logic** — a job is retried (manually or via `retry-on-failure`) and the
|
|
40
|
+
original run already uploaded the artifact under the same name.
|
|
41
|
+
|
|
42
|
+
3. **Split test/build jobs** — multiple parallel jobs each generate and upload an
|
|
43
|
+
artifact with a shared generic name (e.g., `test-results`).
|
|
44
|
+
|
|
45
|
+
4. **Copy-pasted workflows** — two separate jobs have identical `upload-artifact`
|
|
46
|
+
steps with the same name.
|
|
47
|
+
|
|
48
|
+
The artifact immutability change was introduced to enable the new artifact download
|
|
49
|
+
model where artifacts are uniquely addressable and not corrupted by multiple writers.
|
|
50
|
+
fix: |
|
|
51
|
+
**Use unique artifact names per job.** The standard pattern is to embed job/matrix
|
|
52
|
+
context in the artifact name so each upload is distinct.
|
|
53
|
+
|
|
54
|
+
For matrix jobs, include the matrix value in the name. For parallel jobs, include
|
|
55
|
+
the job name. The v4 `download-artifact` action supports wildcard patterns, so all
|
|
56
|
+
job-scoped artifacts can be downloaded together in a merge step.
|
|
57
|
+
fix_code:
|
|
58
|
+
- language: yaml
|
|
59
|
+
label: "Matrix jobs — include matrix value in artifact name"
|
|
60
|
+
code: |
|
|
61
|
+
jobs:
|
|
62
|
+
build:
|
|
63
|
+
strategy:
|
|
64
|
+
matrix:
|
|
65
|
+
os: [ubuntu-latest, windows-latest, macos-latest]
|
|
66
|
+
runs-on: ${{ matrix.os }}
|
|
67
|
+
steps:
|
|
68
|
+
- uses: actions/checkout@v4
|
|
69
|
+
|
|
70
|
+
- name: Build
|
|
71
|
+
run: make build
|
|
72
|
+
|
|
73
|
+
# ❌ Causes 409: all matrix jobs use same name
|
|
74
|
+
# - uses: actions/upload-artifact@v4
|
|
75
|
+
# with:
|
|
76
|
+
# name: build-output
|
|
77
|
+
# path: dist/
|
|
78
|
+
|
|
79
|
+
# ✅ Unique name per matrix dimension
|
|
80
|
+
- uses: actions/upload-artifact@v4
|
|
81
|
+
with:
|
|
82
|
+
name: build-output-${{ matrix.os }}
|
|
83
|
+
path: dist/
|
|
84
|
+
|
|
85
|
+
package:
|
|
86
|
+
needs: build
|
|
87
|
+
runs-on: ubuntu-latest
|
|
88
|
+
steps:
|
|
89
|
+
# ✅ Download all matrix artifacts with wildcard
|
|
90
|
+
- uses: actions/download-artifact@v4
|
|
91
|
+
with:
|
|
92
|
+
pattern: build-output-*
|
|
93
|
+
merge-multiple: true
|
|
94
|
+
path: dist/
|
|
95
|
+
- language: yaml
|
|
96
|
+
label: "Parallel jobs — unique names with merge step"
|
|
97
|
+
code: |
|
|
98
|
+
jobs:
|
|
99
|
+
test-unit:
|
|
100
|
+
runs-on: ubuntu-latest
|
|
101
|
+
steps:
|
|
102
|
+
- uses: actions/checkout@v4
|
|
103
|
+
- run: npm test -- --reporter=junit --output-file=test-results.xml
|
|
104
|
+
- uses: actions/upload-artifact@v4
|
|
105
|
+
with:
|
|
106
|
+
name: test-results-unit # unique name
|
|
107
|
+
path: test-results.xml
|
|
108
|
+
|
|
109
|
+
test-integration:
|
|
110
|
+
runs-on: ubuntu-latest
|
|
111
|
+
steps:
|
|
112
|
+
- uses: actions/checkout@v4
|
|
113
|
+
- run: npm run test:integration -- --output-file=test-results.xml
|
|
114
|
+
- uses: actions/upload-artifact@v4
|
|
115
|
+
with:
|
|
116
|
+
name: test-results-integration # unique name
|
|
117
|
+
path: test-results.xml
|
|
118
|
+
|
|
119
|
+
report:
|
|
120
|
+
needs: [test-unit, test-integration]
|
|
121
|
+
runs-on: ubuntu-latest
|
|
122
|
+
steps:
|
|
123
|
+
- uses: actions/download-artifact@v4
|
|
124
|
+
with:
|
|
125
|
+
pattern: test-results-*
|
|
126
|
+
merge-multiple: true
|
|
127
|
+
path: all-results/
|
|
128
|
+
prevention:
|
|
129
|
+
- "Always include a unique identifier in artifact names when multiple jobs upload
|
|
130
|
+
artifacts — use `${{ matrix.* }}`, `${{ github.job }}`, or a descriptive suffix."
|
|
131
|
+
- "Treat artifact names like immutable keys: once uploaded in a run, they cannot be
|
|
132
|
+
overwritten; design names accordingly."
|
|
133
|
+
- "Use `download-artifact@v4` with `pattern:` and `merge-multiple: true` to collect
|
|
134
|
+
artifacts from multiple jobs into a single directory in a downstream job."
|
|
135
|
+
- "If your workflow retries jobs automatically, include the attempt number
|
|
136
|
+
(`${{ github.run_attempt }}`) in the artifact name to avoid conflicts on retry."
|
|
137
|
+
docs:
|
|
138
|
+
- url: "https://github.com/actions/upload-artifact/issues/478"
|
|
139
|
+
label: "actions/upload-artifact#478 — 409 Conflict: artifact with this name already exists"
|
|
140
|
+
- url: "https://github.com/actions/upload-artifact/blob/main/RELEASES.md"
|
|
141
|
+
label: "upload-artifact v4 release notes — immutability change"
|
|
142
|
+
- url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/storing-and-sharing-data-from-a-workflow"
|
|
143
|
+
label: "GitHub Docs: Storing and sharing data from a workflow"
|
|
144
|
+
- url: "https://github.com/actions/download-artifact?tab=readme-ov-file#download-multiple-artifacts"
|
|
145
|
+
label: "download-artifact: Downloading multiple artifacts with patterns"
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
id: concurrency-timing-009
|
|
2
|
+
title: "Concurrency Group Name Collision Cancels Unrelated Workflows"
|
|
3
|
+
category: concurrency-timing
|
|
4
|
+
severity: silent-failure
|
|
5
|
+
tags:
|
|
6
|
+
- concurrency
|
|
7
|
+
- concurrency-group
|
|
8
|
+
- cancel-in-progress
|
|
9
|
+
- workflow-cancellation
|
|
10
|
+
- naming
|
|
11
|
+
- cross-workflow
|
|
12
|
+
patterns:
|
|
13
|
+
- regex: "concurrency.*group.*cancelled|run.*cancelled.*concurrency"
|
|
14
|
+
flags: "i"
|
|
15
|
+
- regex: "previous run.*same concurrency group.*cancelled"
|
|
16
|
+
flags: "i"
|
|
17
|
+
- regex: "workflow run.*cancelled.*due to.*concurrency"
|
|
18
|
+
flags: "i"
|
|
19
|
+
error_messages:
|
|
20
|
+
- "This workflow run was cancelled because a more recent run with the same concurrency group is in progress."
|
|
21
|
+
- "Workflow cancelled: superseded by a newer run in the same concurrency group."
|
|
22
|
+
- "Run #XXXX was cancelled because run #YYYY (same concurrency group 'deploy') is queued."
|
|
23
|
+
root_cause: |
|
|
24
|
+
GitHub Actions concurrency groups operate **across all workflows** that share the
|
|
25
|
+
same group name string in the same repository. If two different workflows (or two
|
|
26
|
+
jobs in different workflows) declare the same `concurrency.group` name, they compete
|
|
27
|
+
for the same queue — leading to unintended cancellations between completely unrelated
|
|
28
|
+
workflows.
|
|
29
|
+
|
|
30
|
+
**Example of the collision pattern:**
|
|
31
|
+
```yaml
|
|
32
|
+
# workflow-a.yml — CI pipeline
|
|
33
|
+
concurrency:
|
|
34
|
+
group: deploy
|
|
35
|
+
cancel-in-progress: true
|
|
36
|
+
|
|
37
|
+
# workflow-b.yml — Release pipeline (independent)
|
|
38
|
+
concurrency:
|
|
39
|
+
group: deploy # ← same name! collides with workflow-a
|
|
40
|
+
cancel-in-progress: true
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
In this example, triggering `workflow-b` cancels any in-progress run of `workflow-a`
|
|
44
|
+
and vice versa, even though they are completely independent processes.
|
|
45
|
+
|
|
46
|
+
**Common sources of collisions:**
|
|
47
|
+
- Copy-pasting a workflow file and forgetting to rename the concurrency group
|
|
48
|
+
- Using generic names like `deploy`, `build`, `ci`, `test`
|
|
49
|
+
- Multiple reusable workflows called from different callers with the same
|
|
50
|
+
`concurrency.group` in the caller
|
|
51
|
+
- Organization-wide template workflows with hardcoded group names
|
|
52
|
+
|
|
53
|
+
**Why this is a silent failure:** The cancellation log message appears in the
|
|
54
|
+
cancelled workflow run, but developers may not notice or may attribute the cancellation
|
|
55
|
+
to an unrelated cause. The triggering workflow (the one that caused the cancellation)
|
|
56
|
+
shows no indication it cancelled another workflow.
|
|
57
|
+
|
|
58
|
+
**Note:** Starting May 2026, GitHub Actions added support for **larger concurrency
|
|
59
|
+
queues** (`queue: max` option), allowing more pending runs instead of cancelling them.
|
|
60
|
+
This reduces pain but does not eliminate collisions caused by shared group names.
|
|
61
|
+
fix: |
|
|
62
|
+
Make concurrency group names unique and descriptive by including the workflow name,
|
|
63
|
+
branch/ref, and optionally the event type. Never use generic single-word names
|
|
64
|
+
like `deploy`, `ci`, or `build` as the sole concurrency group name.
|
|
65
|
+
|
|
66
|
+
A safe pattern is: `${{ github.workflow }}-${{ github.ref }}`
|
|
67
|
+
This scopes the group to the specific workflow and branch combination, preventing
|
|
68
|
+
cross-workflow and cross-branch collisions.
|
|
69
|
+
fix_code:
|
|
70
|
+
- language: yaml
|
|
71
|
+
label: "Use workflow + ref in concurrency group name"
|
|
72
|
+
code: |
|
|
73
|
+
# ✅ Safe pattern: workflow name + branch prevents cross-workflow collisions
|
|
74
|
+
name: Deploy Production
|
|
75
|
+
|
|
76
|
+
on:
|
|
77
|
+
push:
|
|
78
|
+
branches: [main]
|
|
79
|
+
|
|
80
|
+
concurrency:
|
|
81
|
+
# Unique per workflow + branch combination
|
|
82
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
83
|
+
cancel-in-progress: true
|
|
84
|
+
|
|
85
|
+
jobs:
|
|
86
|
+
deploy:
|
|
87
|
+
runs-on: ubuntu-latest
|
|
88
|
+
steps:
|
|
89
|
+
- uses: actions/checkout@v4
|
|
90
|
+
- run: ./deploy.sh
|
|
91
|
+
- language: yaml
|
|
92
|
+
label: "Per-PR concurrency — cancel superseded PR runs only"
|
|
93
|
+
code: |
|
|
94
|
+
# ✅ Scope to PR number — only cancels stale runs of the same PR
|
|
95
|
+
name: CI
|
|
96
|
+
|
|
97
|
+
on:
|
|
98
|
+
pull_request:
|
|
99
|
+
|
|
100
|
+
concurrency:
|
|
101
|
+
group: ${{ github.workflow }}-pr-${{ github.event.pull_request.number }}
|
|
102
|
+
cancel-in-progress: true
|
|
103
|
+
|
|
104
|
+
jobs:
|
|
105
|
+
test:
|
|
106
|
+
runs-on: ubuntu-latest
|
|
107
|
+
steps:
|
|
108
|
+
- uses: actions/checkout@v4
|
|
109
|
+
- run: npm test
|
|
110
|
+
- language: yaml
|
|
111
|
+
label: "Job-level concurrency — scope to specific job, not whole workflow"
|
|
112
|
+
code: |
|
|
113
|
+
name: CI + Deploy
|
|
114
|
+
|
|
115
|
+
on:
|
|
116
|
+
push:
|
|
117
|
+
branches: [main]
|
|
118
|
+
|
|
119
|
+
jobs:
|
|
120
|
+
test:
|
|
121
|
+
runs-on: ubuntu-latest
|
|
122
|
+
# No concurrency on test job — let tests always run
|
|
123
|
+
steps:
|
|
124
|
+
- uses: actions/checkout@v4
|
|
125
|
+
- run: npm test
|
|
126
|
+
|
|
127
|
+
deploy:
|
|
128
|
+
needs: test
|
|
129
|
+
runs-on: ubuntu-latest
|
|
130
|
+
# Concurrency only on deploy, scoped to this specific workflow + job
|
|
131
|
+
concurrency:
|
|
132
|
+
group: ${{ github.workflow }}-deploy-${{ github.ref }}
|
|
133
|
+
cancel-in-progress: false # queue deploys, don't cancel them
|
|
134
|
+
steps:
|
|
135
|
+
- uses: actions/checkout@v4
|
|
136
|
+
- run: ./deploy.sh
|
|
137
|
+
- language: yaml
|
|
138
|
+
label: "Larger queue option (May 2026+) — allow pending runs instead of cancelling"
|
|
139
|
+
code: |
|
|
140
|
+
# ✅ Use larger queues to queue runs instead of cancelling
|
|
141
|
+
# Requires GitHub Actions concurrency queue support (May 2026+)
|
|
142
|
+
concurrency:
|
|
143
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
144
|
+
cancel-in-progress: false # do not cancel; queue instead
|
|
145
|
+
# queue: max # allow maximum pending runs (if supported)
|
|
146
|
+
prevention:
|
|
147
|
+
- "Always include `${{ github.workflow }}` in the concurrency group name to prevent
|
|
148
|
+
cross-workflow collisions — bare names like `deploy` or `build` are collision-prone."
|
|
149
|
+
- "Include the ref (`${{ github.ref }}`) in group names so parallel PRs/branches
|
|
150
|
+
don't cancel each other's runs."
|
|
151
|
+
- "Audit all workflow files for concurrency group names when onboarding new workflows
|
|
152
|
+
into a repository — duplicates cause mysterious cancellations that are hard to trace."
|
|
153
|
+
- "Use job-level concurrency (not workflow-level) when only certain jobs (e.g., deploy)
|
|
154
|
+
need serialization — keep CI/test jobs unrestricted."
|
|
155
|
+
- "Document the concurrency group naming convention in your repository's CONTRIBUTING
|
|
156
|
+
or workflow guidelines so future contributors follow the same pattern."
|
|
157
|
+
docs:
|
|
158
|
+
- url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/control-the-concurrency-of-workflows-and-jobs"
|
|
159
|
+
label: "GitHub Docs: Control the concurrency of workflows and jobs"
|
|
160
|
+
- url: "https://github.blog/changelog/2026-05-07-github-actions-concurrency-groups-now-allow-larger-queues"
|
|
161
|
+
label: "GitHub Changelog: Concurrency groups now allow larger queues (May 2026)"
|
|
162
|
+
- url: "https://oneuptime.com/blog/post/2026-01-25-github-actions-concurrency-control/view"
|
|
163
|
+
label: "GitHub Actions Concurrency Control — best practices blog post"
|
|
164
|
+
- url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/control-the-concurrency-of-workflows-and-jobs#example-using-concurrency-to-cancel-any-in-progress-job-or-run"
|
|
165
|
+
label: "GitHub Docs: Concurrency examples — cancel in-progress"
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
id: known-unsolved-010
|
|
2
|
+
title: "upload-artifact v4 and download-artifact v4 Not Supported on GitHub Enterprise Server"
|
|
3
|
+
category: known-unsolved
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- upload-artifact
|
|
7
|
+
- download-artifact
|
|
8
|
+
- artifact-v4
|
|
9
|
+
- ghes
|
|
10
|
+
- github-enterprise-server
|
|
11
|
+
- compatibility
|
|
12
|
+
- enterprise
|
|
13
|
+
patterns:
|
|
14
|
+
- regex: "@actions/artifact v2\\.0\\.0.*not.*supported.*GHES|upload-artifact@v4.*not.*supported.*GHES"
|
|
15
|
+
flags: "i"
|
|
16
|
+
- regex: "download-artifact@v4.*not currently supported on GHES"
|
|
17
|
+
flags: "i"
|
|
18
|
+
- regex: "requires.*newer.*version.*GHES|GHES.*does not support.*artifact.*v[234]"
|
|
19
|
+
flags: "i"
|
|
20
|
+
error_messages:
|
|
21
|
+
- "Error: @actions/artifact v2.0.0+, upload-artifact@v4+ and download-artifact@v4+ are not currently supported on GHES"
|
|
22
|
+
- "Error: upload-artifact@v4 is not supported on your current GHES version. Use v3 instead."
|
|
23
|
+
- "Failed to create artifact: The artifact service is not available on this instance"
|
|
24
|
+
root_cause: |
|
|
25
|
+
**actions/upload-artifact v4** and **actions/download-artifact v4** depend on a
|
|
26
|
+
new Artifact API (`@actions/artifact` v2+) that uses the Blob service and updated
|
|
27
|
+
artifact storage endpoints introduced in GitHub.com in late 2023. This API is
|
|
28
|
+
**not available on GitHub Enterprise Server (GHES)** instances running versions
|
|
29
|
+
prior to the minimum supported release for the new artifact service.
|
|
30
|
+
|
|
31
|
+
As of mid-2026, artifact v4 support on GHES has a version gate. GHES instances
|
|
32
|
+
that have not been upgraded to the minimum supported version will fail immediately
|
|
33
|
+
when any workflow step uses `upload-artifact@v4` or `download-artifact@v4`, with
|
|
34
|
+
a clear error message indicating the feature is unsupported.
|
|
35
|
+
|
|
36
|
+
**Key facts:**
|
|
37
|
+
- `upload-artifact@v3` and `download-artifact@v3` continue to work on all GHES versions
|
|
38
|
+
- There is no workaround that makes v4 work on unsupported GHES versions
|
|
39
|
+
- Self-hosted runners connected to GHES are subject to the same restriction as
|
|
40
|
+
GitHub-hosted runners on that instance
|
|
41
|
+
- The error is immediate (not a race condition or transient issue) — the artifact
|
|
42
|
+
service API rejects the request at connection time
|
|
43
|
+
|
|
44
|
+
**Impact:** Teams that copy workflows from GitHub.com repositories or follow
|
|
45
|
+
documentation written for GitHub.com find their enterprise CI broken after upgrading
|
|
46
|
+
actions to v4. The fix is to pin back to v3 on GHES or upgrade the GHES instance.
|
|
47
|
+
fix: |
|
|
48
|
+
**Option 1 (recommended for most teams):** Pin `upload-artifact` and
|
|
49
|
+
`download-artifact` to `@v3` on your GHES-connected workflows until your GHES
|
|
50
|
+
instance is upgraded to a version that supports the new artifact service.
|
|
51
|
+
|
|
52
|
+
**Option 2:** Upgrade your GHES instance to the minimum version that supports
|
|
53
|
+
artifact v4. Consult the GHES release notes to find the minimum supported version.
|
|
54
|
+
|
|
55
|
+
**Option 3:** Use conditional version selection based on the `github.server_url`
|
|
56
|
+
context to use v4 on GitHub.com and v3 on GHES.
|
|
57
|
+
fix_code:
|
|
58
|
+
- language: yaml
|
|
59
|
+
label: "Pin to v3 on GHES instances"
|
|
60
|
+
code: |
|
|
61
|
+
jobs:
|
|
62
|
+
build:
|
|
63
|
+
runs-on: self-hosted
|
|
64
|
+
steps:
|
|
65
|
+
- uses: actions/checkout@v4
|
|
66
|
+
|
|
67
|
+
- name: Build
|
|
68
|
+
run: make build
|
|
69
|
+
|
|
70
|
+
# ✅ Use v3 on GHES until your instance supports v4
|
|
71
|
+
- uses: actions/upload-artifact@v3
|
|
72
|
+
with:
|
|
73
|
+
name: build-output
|
|
74
|
+
path: dist/
|
|
75
|
+
retention-days: 7
|
|
76
|
+
|
|
77
|
+
deploy:
|
|
78
|
+
needs: build
|
|
79
|
+
runs-on: self-hosted
|
|
80
|
+
steps:
|
|
81
|
+
# ✅ Match the upload version for download
|
|
82
|
+
- uses: actions/download-artifact@v3
|
|
83
|
+
with:
|
|
84
|
+
name: build-output
|
|
85
|
+
path: dist/
|
|
86
|
+
- language: yaml
|
|
87
|
+
label: "Conditional version — v4 on GitHub.com, v3 on GHES"
|
|
88
|
+
code: |
|
|
89
|
+
jobs:
|
|
90
|
+
build:
|
|
91
|
+
runs-on: ${{ github.server_url == 'https://github.com' && 'ubuntu-latest' || 'self-hosted' }}
|
|
92
|
+
steps:
|
|
93
|
+
- uses: actions/checkout@v4
|
|
94
|
+
|
|
95
|
+
- name: Build
|
|
96
|
+
run: make build
|
|
97
|
+
|
|
98
|
+
# GitHub.com: use v4; GHES: use v3
|
|
99
|
+
- uses: ${{ github.server_url == 'https://github.com' && 'actions/upload-artifact@v4' || 'actions/upload-artifact@v3' }}
|
|
100
|
+
with:
|
|
101
|
+
name: build-output
|
|
102
|
+
path: dist/
|
|
103
|
+
prevention:
|
|
104
|
+
- "Before upgrading to upload-artifact@v4 in a repository, verify whether the
|
|
105
|
+
repository is hosted on GitHub.com or a GHES instance."
|
|
106
|
+
- "For multi-environment repositories (same workflow runs on both GitHub.com and GHES),
|
|
107
|
+
use conditional `uses:` expressions or maintain separate workflow files per environment."
|
|
108
|
+
- "Monitor GHES release notes for artifact v4 support announcements before upgrading
|
|
109
|
+
enterprise workflows."
|
|
110
|
+
- "Pin action versions explicitly in GHES-hosted workflows — avoid floating `@latest`
|
|
111
|
+
tags that may resolve to v4 on GHES before the instance supports it."
|
|
112
|
+
docs:
|
|
113
|
+
- url: "https://stackoverflow.com/questions/79267706/error-actions-artifact-v2-0-0-upload-artifactv4-and-download-artifactv4"
|
|
114
|
+
label: "Stack Overflow: upload-artifact@v4 and download-artifact@v4 not supported on GHES"
|
|
115
|
+
- url: "https://github.com/actions/upload-artifact/blob/main/RELEASES.md"
|
|
116
|
+
label: "upload-artifact v4 release notes — GHES compatibility notes"
|
|
117
|
+
- url: "https://docs.github.com/en/enterprise-server@latest/admin/release-notes"
|
|
118
|
+
label: "GitHub Enterprise Server release notes"
|
|
119
|
+
- url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/storing-and-sharing-data-from-a-workflow"
|
|
120
|
+
label: "GitHub Docs: Storing and sharing data from a workflow"
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
id: runner-environment-031
|
|
2
|
+
title: "Docker 29.1 + Compose 2.40.3 Runner Update Breaks Compose Commands"
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- docker
|
|
7
|
+
- docker-compose
|
|
8
|
+
- docker-29
|
|
9
|
+
- compose-v2
|
|
10
|
+
- ubuntu
|
|
11
|
+
- windows
|
|
12
|
+
- runner-image-update
|
|
13
|
+
patterns:
|
|
14
|
+
- regex: "docker compose.*unknown flag|unknown flag.*docker compose"
|
|
15
|
+
flags: "i"
|
|
16
|
+
- regex: "docker-compose.*command not found|docker-compose.*deprecated"
|
|
17
|
+
flags: "i"
|
|
18
|
+
- regex: "compose.*unknown command|error.*compose.*not a docker command"
|
|
19
|
+
flags: "i"
|
|
20
|
+
- regex: "docker compose.*plugin.*not found|failed to get plugins"
|
|
21
|
+
flags: "i"
|
|
22
|
+
error_messages:
|
|
23
|
+
- "docker-compose: command not found"
|
|
24
|
+
- "unknown flag: --compatibility"
|
|
25
|
+
- "unknown shorthand flag: 'f' in -f"
|
|
26
|
+
- "Error response from daemon: client version 1.24 is too old. Minimum supported API version is 1.25"
|
|
27
|
+
- "'docker compose' requires at least 1 argument"
|
|
28
|
+
root_cause: |
|
|
29
|
+
On **February 9, 2026**, GitHub pushed an update to Ubuntu and Windows runner images
|
|
30
|
+
that bumped Docker Server and Client from 28.x to **29.1.*** and Docker Compose from
|
|
31
|
+
2.x to **2.40.3** (announced in actions/runner-images#13474).
|
|
32
|
+
|
|
33
|
+
For Ubuntu 24.04, the update was **rolled back** on February 20, 2026 due to multiple
|
|
34
|
+
reported issues (#13682, #13691, #13684) and is being re-evaluated (tracked in
|
|
35
|
+
#14105). The Windows runner update proceeded.
|
|
36
|
+
|
|
37
|
+
**Breaking changes in Docker Compose 2.40.x and Docker 29.x:**
|
|
38
|
+
|
|
39
|
+
1. **`docker-compose` v1 binary removed** — Many older workflows use the hyphenated
|
|
40
|
+
`docker-compose` command (Compose v1). As of Docker Compose v2, only the plugin
|
|
41
|
+
form `docker compose` (no hyphen) is installed. Workflows with
|
|
42
|
+
`run: docker-compose up -d` fail with `command not found`.
|
|
43
|
+
|
|
44
|
+
2. **`--compatibility` flag removed** — The `docker compose --compatibility` flag
|
|
45
|
+
(for mapping v2 configs to v2-compatible behavior) was removed in 2.40.x.
|
|
46
|
+
Workflows that use `docker compose --compatibility up` fail.
|
|
47
|
+
|
|
48
|
+
3. **API version minimums** — Docker 29 raises the minimum supported Docker daemon
|
|
49
|
+
API version, breaking some older base images in service containers that use the
|
|
50
|
+
Docker socket with old clients.
|
|
51
|
+
|
|
52
|
+
4. **`COMPOSE_DOCKER_CLI_BUILD` env var deprecated** — Setting
|
|
53
|
+
`COMPOSE_DOCKER_CLI_BUILD=1` no longer has any effect; BuildKit is always used.
|
|
54
|
+
|
|
55
|
+
5. **Docker 29.5 `CLONE_NEWTIME` private time namespaces** — Docker 29.5 (released
|
|
56
|
+
May 2026) enables private time namespaces by default on kernels ≥ 5.6, which
|
|
57
|
+
breaks Docker-socket-passthrough patterns used in Cloud Native Buildpacks (CNB)
|
|
58
|
+
lifecycle builds. Buildpack builds via `pack build` or Spring Boot's built-in
|
|
59
|
+
Buildpacks fail silently or with lifecycle container errors.
|
|
60
|
+
fix: |
|
|
61
|
+
**For `docker-compose` → `docker compose` migration:**
|
|
62
|
+
Replace all `docker-compose` (hyphenated) invocations with `docker compose` (space).
|
|
63
|
+
This is the most common fix.
|
|
64
|
+
|
|
65
|
+
**For `--compatibility` flag removal:**
|
|
66
|
+
Remove the `--compatibility` flag. Docker Compose v2 handles modern compose file
|
|
67
|
+
formats natively without this flag.
|
|
68
|
+
|
|
69
|
+
**For CNB/Buildpack Docker socket passthrough (Docker 29.5+):**
|
|
70
|
+
Mount the Docker socket without private time namespaces by using
|
|
71
|
+
`--security-opt=no-new-privileges:false` or by setting
|
|
72
|
+
`DOCKER_HOST` to use a sidecar daemon.
|
|
73
|
+
|
|
74
|
+
**For pinning Docker version on self-hosted runners:**
|
|
75
|
+
Pin to Docker 28.x until your Compose files and build pipelines are validated against
|
|
76
|
+
29.x.
|
|
77
|
+
fix_code:
|
|
78
|
+
- language: yaml
|
|
79
|
+
label: "Replace docker-compose (v1) with docker compose (v2 plugin)"
|
|
80
|
+
code: |
|
|
81
|
+
jobs:
|
|
82
|
+
deploy:
|
|
83
|
+
runs-on: ubuntu-latest
|
|
84
|
+
steps:
|
|
85
|
+
- uses: actions/checkout@v4
|
|
86
|
+
|
|
87
|
+
# ❌ Old (docker-compose v1 — removed)
|
|
88
|
+
# - run: docker-compose up -d
|
|
89
|
+
# - run: docker-compose --compatibility up -d
|
|
90
|
+
|
|
91
|
+
# ✅ New (docker compose v2 plugin)
|
|
92
|
+
- name: Start services
|
|
93
|
+
run: docker compose up -d
|
|
94
|
+
|
|
95
|
+
- name: Run tests
|
|
96
|
+
run: docker compose exec app npm test
|
|
97
|
+
|
|
98
|
+
- name: Tear down
|
|
99
|
+
run: docker compose down
|
|
100
|
+
- language: yaml
|
|
101
|
+
label: "Verify Docker and Compose versions in workflow"
|
|
102
|
+
code: |
|
|
103
|
+
jobs:
|
|
104
|
+
debug:
|
|
105
|
+
runs-on: ubuntu-latest
|
|
106
|
+
steps:
|
|
107
|
+
- name: Check Docker version
|
|
108
|
+
run: |
|
|
109
|
+
docker version
|
|
110
|
+
docker compose version
|
|
111
|
+
# If docker-compose (v1) is needed, install it explicitly:
|
|
112
|
+
# pip install docker-compose
|
|
113
|
+
- language: yaml
|
|
114
|
+
label: "Pin Docker version for self-hosted runners sensitive to 29.x changes"
|
|
115
|
+
code: |
|
|
116
|
+
jobs:
|
|
117
|
+
build:
|
|
118
|
+
runs-on: self-hosted
|
|
119
|
+
steps:
|
|
120
|
+
- name: Pin Docker to 28.x (if 29.x breaks your workflow)
|
|
121
|
+
run: |
|
|
122
|
+
sudo apt-get remove -y docker-ce docker-ce-cli
|
|
123
|
+
sudo apt-get install -y docker-ce=5:28.0.4-1~ubuntu.24.04~noble \
|
|
124
|
+
docker-ce-cli=5:28.0.4-1~ubuntu.24.04~noble
|
|
125
|
+
prevention:
|
|
126
|
+
- "Migrate from `docker-compose` (v1) to `docker compose` (v2 plugin) immediately —
|
|
127
|
+
v1 is no longer maintained and is removed in Docker 29.x images."
|
|
128
|
+
- "Remove `--compatibility` flags from all Compose invocations; the flag was
|
|
129
|
+
deprecated and is removed in Compose 2.40.x."
|
|
130
|
+
- "Subscribe to `actions/runner-images` announcements to get advance notice of
|
|
131
|
+
Docker version bumps before they land on hosted runners."
|
|
132
|
+
- "Pin Docker Compose file format version at `version: '3.8'` or later; v2 Compose
|
|
133
|
+
files have better compatibility with modern Compose plugin versions."
|
|
134
|
+
- "Test workflows in a local Docker 29.x environment before relying on them in CI
|
|
135
|
+
to catch API and behavioral differences early."
|
|
136
|
+
docs:
|
|
137
|
+
- url: "https://github.com/actions/runner-images/issues/13474"
|
|
138
|
+
label: "Announcement: Docker 29.1 + Compose 2.40.3 update (runner-images#13474)"
|
|
139
|
+
- url: "https://github.com/actions/runner-images/issues/14105"
|
|
140
|
+
label: "Tracking: Ubuntu Docker v29 rollback and re-attempt (runner-images#14105)"
|
|
141
|
+
- url: "https://docs.docker.com/compose/releases/migrate/"
|
|
142
|
+
label: "Docker Docs: Migrate from Compose v1 to v2"
|
|
143
|
+
- url: "https://docs.docker.com/engine/release-notes/29.1/"
|
|
144
|
+
label: "Docker Engine 29.1 release notes"
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
id: runner-environment-029
|
|
2
|
+
title: "Node.js 20 Removed from Runner Image Toolcache — Scripts Break Without setup-node"
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- node
|
|
7
|
+
- nodejs
|
|
8
|
+
- toolcache
|
|
9
|
+
- node20
|
|
10
|
+
- node22
|
|
11
|
+
- setup-node
|
|
12
|
+
- eol
|
|
13
|
+
patterns:
|
|
14
|
+
- regex: "node.*not found|node: command not found"
|
|
15
|
+
flags: "i"
|
|
16
|
+
- regex: "node.*version.*20.*not.*available|node 20.*removed"
|
|
17
|
+
flags: "i"
|
|
18
|
+
- regex: "required node.*20|node@20.*not installed"
|
|
19
|
+
flags: "i"
|
|
20
|
+
- regex: "engines.*node.*20.*not satisfied"
|
|
21
|
+
flags: "i"
|
|
22
|
+
error_messages:
|
|
23
|
+
- "node: command not found"
|
|
24
|
+
- "The tool 'node' for version spec '20' was not found locally."
|
|
25
|
+
- "Couldn't resolve the package 'node' to a version matching '20'"
|
|
26
|
+
- "error engines: The engine \"node\" is incompatible with this module."
|
|
27
|
+
root_cause: |
|
|
28
|
+
Node.js 20 reached **end-of-life on April 30, 2026**. Starting with runner image
|
|
29
|
+
releases on **May 18, 2026** (commit 249562679f on actions/runner-images), Node.js 20
|
|
30
|
+
was removed from the pre-installed toolcache on all runner images (Ubuntu, macOS,
|
|
31
|
+
Windows).
|
|
32
|
+
|
|
33
|
+
**What changed:**
|
|
34
|
+
- The default system `node` binary on all runner images changed from Node.js **20**
|
|
35
|
+
to Node.js **22** (Maintenance LTS).
|
|
36
|
+
- `node 20` is no longer available in the toolcache — `actions/setup-node` will
|
|
37
|
+
download it from the internet if explicitly requested, or fail if the network is
|
|
38
|
+
not available (self-hosted runners with restricted network access).
|
|
39
|
+
- Workflows that use `node` without `actions/setup-node` now get Node 22 by default.
|
|
40
|
+
|
|
41
|
+
**Three distinct breakage patterns:**
|
|
42
|
+
|
|
43
|
+
1. **Shell scripts calling `node script.js`** — these now run under Node 22, which
|
|
44
|
+
may break code that relied on Node 20 behavior (e.g., `fetch` API differences,
|
|
45
|
+
removed experimental APIs, `--openssl-legacy-provider` not available by default).
|
|
46
|
+
|
|
47
|
+
2. **`actions/setup-node` without version** — previously defaulted to node-version-
|
|
48
|
+
file lookup or the installed 20.x; now defaults to the latest LTS (22.x). Any
|
|
49
|
+
`package.json` `engines` field restricting to `>=20 <21` still works, but strict
|
|
50
|
+
`20.x` pins will now cause download overhead or failure.
|
|
51
|
+
|
|
52
|
+
3. **Self-hosted runners with restricted internet access** — if a workflow requests
|
|
53
|
+
`node-version: '20'` via `actions/setup-node` and the runner has no internet
|
|
54
|
+
access to download from nodejs.org, the setup step fails because 20 is no longer
|
|
55
|
+
in the local toolcache.
|
|
56
|
+
|
|
57
|
+
Note: This is distinct from the **action runtime migration** (Node 20 → Node 24 for
|
|
58
|
+
running JavaScript actions themselves, announced separately). This entry covers the
|
|
59
|
+
*pre-installed Node.js available to shell scripts*.
|
|
60
|
+
fix: |
|
|
61
|
+
Update workflows to use Node.js 22 (current Maintenance LTS) or pin an explicit LTS
|
|
62
|
+
version via `actions/setup-node`.
|
|
63
|
+
|
|
64
|
+
**Option 1 — Explicit version pin (recommended for reproducibility):**
|
|
65
|
+
Add `actions/setup-node` with an explicit `node-version` or `node-version-file`.
|
|
66
|
+
|
|
67
|
+
**Option 2 — Use `.nvmrc` or `.node-version` file:**
|
|
68
|
+
Create a version file in the repo root and use `node-version-file` input.
|
|
69
|
+
|
|
70
|
+
**Option 3 — Accept Node 22:**
|
|
71
|
+
Test your application on Node 22 and update `package.json` `engines` accordingly.
|
|
72
|
+
|
|
73
|
+
**For self-hosted runners with no internet:**
|
|
74
|
+
Pre-install Node.js 22 in the runner's local toolcache directory and point
|
|
75
|
+
`AGENT_TOOLSDIRECTORY` to it.
|
|
76
|
+
fix_code:
|
|
77
|
+
- language: yaml
|
|
78
|
+
label: "Pin explicit Node.js version via actions/setup-node"
|
|
79
|
+
code: |
|
|
80
|
+
jobs:
|
|
81
|
+
build:
|
|
82
|
+
runs-on: ubuntu-latest
|
|
83
|
+
steps:
|
|
84
|
+
- uses: actions/checkout@v4
|
|
85
|
+
- uses: actions/setup-node@v4
|
|
86
|
+
with:
|
|
87
|
+
node-version: '22' # or '20' to keep on 20 (downloaded from web)
|
|
88
|
+
cache: 'npm'
|
|
89
|
+
- run: npm ci
|
|
90
|
+
- run: npm test
|
|
91
|
+
- language: yaml
|
|
92
|
+
label: "Use .nvmrc to declare Node version in the repo"
|
|
93
|
+
code: |
|
|
94
|
+
# .nvmrc (in repo root)
|
|
95
|
+
# 22
|
|
96
|
+
|
|
97
|
+
# workflow step
|
|
98
|
+
- uses: actions/setup-node@v4
|
|
99
|
+
with:
|
|
100
|
+
node-version-file: '.nvmrc'
|
|
101
|
+
cache: 'npm'
|
|
102
|
+
- language: yaml
|
|
103
|
+
label: "Matrix build to verify compatibility across Node versions"
|
|
104
|
+
code: |
|
|
105
|
+
jobs:
|
|
106
|
+
test:
|
|
107
|
+
strategy:
|
|
108
|
+
matrix:
|
|
109
|
+
node-version: ['20', '22', '24']
|
|
110
|
+
runs-on: ubuntu-latest
|
|
111
|
+
steps:
|
|
112
|
+
- uses: actions/checkout@v4
|
|
113
|
+
- uses: actions/setup-node@v4
|
|
114
|
+
with:
|
|
115
|
+
node-version: ${{ matrix.node-version }}
|
|
116
|
+
- run: npm ci && npm test
|
|
117
|
+
prevention:
|
|
118
|
+
- "Always use `actions/setup-node` with an explicit `node-version` or
|
|
119
|
+
`node-version-file` — never rely on the runner's pre-installed Node.js version."
|
|
120
|
+
- "Add a `.nvmrc` or `.node-version` file to your repository to pin Node.js version
|
|
121
|
+
for local dev, CI, and Vercel/Netlify deployments simultaneously."
|
|
122
|
+
- "Watch for Node.js EOL dates at https://github.com/nodejs/release#readme — plan
|
|
123
|
+
upgrades before the runner image drops the EOL version."
|
|
124
|
+
- "For self-hosted runners, maintain a local toolcache refresh process whenever a
|
|
125
|
+
new Node.js LTS is released or an old one reaches EOL."
|
|
126
|
+
docs:
|
|
127
|
+
- url: "https://github.com/actions/runner-images/issues/14029"
|
|
128
|
+
label: "Announcement: Node.js 20 removal from runner images (runner-images#14029)"
|
|
129
|
+
- url: "https://github.com/nodejs/release#readme"
|
|
130
|
+
label: "Node.js Release Schedule — EOL dates"
|
|
131
|
+
- url: "https://github.com/actions/setup-node"
|
|
132
|
+
label: "actions/setup-node — official action documentation"
|
|
133
|
+
- url: "https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/customizing-github-hosted-runners"
|
|
134
|
+
label: "GitHub Docs: Customizing GitHub-hosted runners"
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
id: runner-environment-030
|
|
2
|
+
title: "Ubuntu ARM64 Runner Missing Docker — docker: command not found on arm64"
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- arm64
|
|
7
|
+
- aarch64
|
|
8
|
+
- docker
|
|
9
|
+
- ubuntu
|
|
10
|
+
- partner-runner
|
|
11
|
+
- docker-buildx
|
|
12
|
+
- setup-buildx-action
|
|
13
|
+
patterns:
|
|
14
|
+
- regex: "docker.*command not found|docker.*not found.*arm64"
|
|
15
|
+
flags: "i"
|
|
16
|
+
- regex: "docker/setup-buildx-action.*error|setup-buildx.*arm64.*fail"
|
|
17
|
+
flags: "i"
|
|
18
|
+
- regex: "Cannot connect to the Docker daemon|Is the docker daemon running"
|
|
19
|
+
flags: "i"
|
|
20
|
+
- regex: "Error: Unable to locate executable file: docker"
|
|
21
|
+
flags: "i"
|
|
22
|
+
error_messages:
|
|
23
|
+
- "docker: command not found"
|
|
24
|
+
- "Error: Unable to locate executable file: docker"
|
|
25
|
+
- "Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?"
|
|
26
|
+
- "exec: \"docker\": executable file not found in $PATH"
|
|
27
|
+
root_cause: |
|
|
28
|
+
GitHub-hosted **Ubuntu 24.04 ARM64** runner images (available via labels such as
|
|
29
|
+
`ubuntu-24.04-arm64`, `ubuntu-arm`, or partner runner images for ARM64) do **not**
|
|
30
|
+
have Docker pre-installed on `PATH`, despite the partner image README listing Docker
|
|
31
|
+
client and server versions.
|
|
32
|
+
|
|
33
|
+
This is a **documentation mismatch** affecting ARM64 runner users (actions/runner-
|
|
34
|
+
images#14051, created March 2026, still open as of May 2026):
|
|
35
|
+
- The `partner-runner-images` README lists Docker Client 28.0.4 and Docker Server
|
|
36
|
+
28.0.4 as installed software.
|
|
37
|
+
- In practice, `docker` is **not present on `PATH`** in these runners.
|
|
38
|
+
- The runner is identified as `Source: Partner` and `Base Image for Ubuntu Server
|
|
39
|
+
24.04`.
|
|
40
|
+
|
|
41
|
+
**Affected workflows:**
|
|
42
|
+
- Any step using `docker build`, `docker run`, `docker pull`, or `docker push`
|
|
43
|
+
directly in a `run:` block.
|
|
44
|
+
- `docker/setup-buildx-action@v3` fails because it cannot find the Docker CLI.
|
|
45
|
+
- Container-based jobs that use the host Docker socket.
|
|
46
|
+
- Multi-platform builds that need BuildKit on ARM64.
|
|
47
|
+
|
|
48
|
+
**x86-64 runners are not affected.** This is specific to ARM64 GitHub-hosted
|
|
49
|
+
runners using the partner image.
|
|
50
|
+
|
|
51
|
+
This is distinct from the `docker-buildx-not-setup.yml` entry (which covers x64
|
|
52
|
+
runners where Docker BuildKit is present but `buildx` is not configured).
|
|
53
|
+
fix: |
|
|
54
|
+
Install Docker explicitly at the start of ARM64 workflow jobs, or use a Docker
|
|
55
|
+
action that handles installation automatically.
|
|
56
|
+
|
|
57
|
+
**Option 1 — Install Docker via the official convenience script (fastest):**
|
|
58
|
+
Run the Docker install script at the start of the job. This adds ~60 seconds to
|
|
59
|
+
job start time but ensures Docker is available.
|
|
60
|
+
|
|
61
|
+
**Option 2 — Use `docker/setup-buildx-action@v3` after Docker install:**
|
|
62
|
+
After installing Docker, `setup-buildx-action` can then install BuildKit buildx.
|
|
63
|
+
|
|
64
|
+
**Option 3 — Use a Docker-pre-installed large runner:**
|
|
65
|
+
If budget allows, use GitHub's x86-64 larger runners which have Docker pre-installed,
|
|
66
|
+
or a self-hosted ARM64 runner with Docker pre-configured.
|
|
67
|
+
|
|
68
|
+
**Option 4 — Use `runs-on: ubuntu-latest` (x86-64) instead of ARM64:**
|
|
69
|
+
If ARM64 is not strictly required, run on x86-64 which has Docker pre-installed.
|
|
70
|
+
fix_code:
|
|
71
|
+
- language: yaml
|
|
72
|
+
label: "Install Docker on ARM64 runner before using it"
|
|
73
|
+
code: |
|
|
74
|
+
jobs:
|
|
75
|
+
build:
|
|
76
|
+
runs-on: ubuntu-24.04-arm64
|
|
77
|
+
steps:
|
|
78
|
+
- uses: actions/checkout@v4
|
|
79
|
+
|
|
80
|
+
- name: Install Docker
|
|
81
|
+
run: |
|
|
82
|
+
curl -fsSL https://get.docker.com -o get-docker.sh
|
|
83
|
+
sudo sh get-docker.sh
|
|
84
|
+
sudo usermod -aG docker $USER
|
|
85
|
+
sudo systemctl start docker
|
|
86
|
+
docker --version
|
|
87
|
+
|
|
88
|
+
- name: Set up Docker Buildx
|
|
89
|
+
uses: docker/setup-buildx-action@v3
|
|
90
|
+
|
|
91
|
+
- name: Build image
|
|
92
|
+
run: docker build -t myapp:latest .
|
|
93
|
+
- language: yaml
|
|
94
|
+
label: "Cross-platform build with explicit ARM64 Docker install"
|
|
95
|
+
code: |
|
|
96
|
+
jobs:
|
|
97
|
+
build:
|
|
98
|
+
strategy:
|
|
99
|
+
matrix:
|
|
100
|
+
include:
|
|
101
|
+
- runner: ubuntu-latest
|
|
102
|
+
platform: linux/amd64
|
|
103
|
+
- runner: ubuntu-24.04-arm64
|
|
104
|
+
platform: linux/arm64
|
|
105
|
+
install_docker: true
|
|
106
|
+
runs-on: ${{ matrix.runner }}
|
|
107
|
+
steps:
|
|
108
|
+
- uses: actions/checkout@v4
|
|
109
|
+
|
|
110
|
+
- name: Install Docker (ARM64 only)
|
|
111
|
+
if: matrix.install_docker == true
|
|
112
|
+
run: |
|
|
113
|
+
curl -fsSL https://get.docker.com | sudo sh
|
|
114
|
+
sudo usermod -aG docker $USER
|
|
115
|
+
sudo systemctl enable --now docker
|
|
116
|
+
|
|
117
|
+
- name: Build for ${{ matrix.platform }}
|
|
118
|
+
run: docker build --platform ${{ matrix.platform }} -t myapp .
|
|
119
|
+
prevention:
|
|
120
|
+
- "Before adding `runs-on: ubuntu-24.04-arm64` to a workflow that uses Docker,
|
|
121
|
+
verify Docker availability by running `docker --version` in a test job."
|
|
122
|
+
- "Check the current partner runner image README at
|
|
123
|
+
https://github.com/actions/partner-runner-images before relying on pre-installed
|
|
124
|
+
tooling on non-standard runner images."
|
|
125
|
+
- "Consider using self-hosted ARM64 runners with Docker pre-configured for
|
|
126
|
+
production workloads that depend on Docker on ARM64."
|
|
127
|
+
- "Track the open issue (actions/runner-images#14051) for when GitHub adds Docker
|
|
128
|
+
to ARM64 partner images natively."
|
|
129
|
+
docs:
|
|
130
|
+
- url: "https://github.com/actions/runner-images/issues/14051"
|
|
131
|
+
label: "Issue: Ubuntu 24.04 ARM64 missing Docker (runner-images#14051)"
|
|
132
|
+
- url: "https://github.com/actions/partner-runner-images"
|
|
133
|
+
label: "actions/partner-runner-images — partner runner image definitions"
|
|
134
|
+
- url: "https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#standard-github-hosted-runners-for-public-repositories"
|
|
135
|
+
label: "GitHub Docs: GitHub-hosted runner specifications"
|
|
136
|
+
- url: "https://docs.docker.com/engine/install/ubuntu/"
|
|
137
|
+
label: "Docker Docs: Install Docker Engine on Ubuntu"
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
id: runner-environment-028
|
|
2
|
+
title: "windows-2019 Runner Retired — Jobs Fail with No Runner Found"
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- windows
|
|
7
|
+
- windows-2019
|
|
8
|
+
- runner-retirement
|
|
9
|
+
- deprecation
|
|
10
|
+
- runs-on
|
|
11
|
+
- migration
|
|
12
|
+
patterns:
|
|
13
|
+
- regex: "No runner matching the requested labels.*windows-2019"
|
|
14
|
+
flags: "i"
|
|
15
|
+
- regex: "Could not find any runner matching.*windows-2019"
|
|
16
|
+
flags: "i"
|
|
17
|
+
- regex: "windows-2019.*is no longer supported"
|
|
18
|
+
flags: "i"
|
|
19
|
+
- regex: "windows-2019.*deprecated.*unsupported"
|
|
20
|
+
flags: "i"
|
|
21
|
+
error_messages:
|
|
22
|
+
- "No runner matching the requested labels was found: windows-2019"
|
|
23
|
+
- "Could not find any runner matching the requested labels: [windows-2019]"
|
|
24
|
+
- "This request was automatically failed because 'windows-2019' is no longer available."
|
|
25
|
+
root_cause: |
|
|
26
|
+
GitHub retired the `windows-2019` runner image on **June 30, 2025** following the
|
|
27
|
+
GitHub Actions N-1 OS support policy (only the latest two major versions of each OS
|
|
28
|
+
are hosted).
|
|
29
|
+
|
|
30
|
+
**Timeline:**
|
|
31
|
+
- **2025-04-15**: Deprecation announcement (actions/runner-images#12045)
|
|
32
|
+
- **2025-06-01**: Deprecation begins — longer queue times during peak hours
|
|
33
|
+
- **Between June 1–30**: GitHub temporarily fails jobs using `windows-2019` to raise
|
|
34
|
+
awareness in advance of the hard removal
|
|
35
|
+
- **2025-06-30**: `windows-2019` fully unsupported — all jobs using this label fail
|
|
36
|
+
|
|
37
|
+
Workflows that explicitly specify `runs-on: windows-2019` (or any combination like
|
|
38
|
+
`[self-hosted, windows-2019]` on non-self-hosted runners) will fail immediately after
|
|
39
|
+
the retirement date. Workflows that used `windows-latest` were not affected since
|
|
40
|
+
`windows-latest` already pointed to `windows-2022`.
|
|
41
|
+
|
|
42
|
+
The replacement is `windows-2022` (already the current `windows-latest` at time of
|
|
43
|
+
retirement) or `windows-2025` (Windows Server 2025 image).
|
|
44
|
+
fix: |
|
|
45
|
+
Update all `runs-on` references from `windows-2019` to `windows-2022` or
|
|
46
|
+
`windows-2025` (or use `windows-latest`).
|
|
47
|
+
|
|
48
|
+
**Migration path:**
|
|
49
|
+
- `windows-2019` → `windows-2022` (minimal change, widely compatible)
|
|
50
|
+
- `windows-2019` → `windows-2025` (latest; check for VS 2026 path changes if using
|
|
51
|
+
hardcoded MSVC paths)
|
|
52
|
+
- `windows-2019` → `windows-latest` (tracks latest, reduces future manual migrations)
|
|
53
|
+
|
|
54
|
+
**Before migrating**, verify that your workflow does not depend on Windows Server 2019
|
|
55
|
+
-specific behavior such as:
|
|
56
|
+
- VS 2019 toolchain at `C:\Program Files (x86)\Microsoft Visual Studio\2019\`
|
|
57
|
+
- Older .NET Framework SDK versions not present on 2022 or 2025 images
|
|
58
|
+
- Windows Server 2019-specific APIs or registry keys
|
|
59
|
+
fix_code:
|
|
60
|
+
- language: yaml
|
|
61
|
+
label: "Replace windows-2019 with windows-2022"
|
|
62
|
+
code: |
|
|
63
|
+
jobs:
|
|
64
|
+
build:
|
|
65
|
+
# Before: runs-on: windows-2019
|
|
66
|
+
runs-on: windows-2022
|
|
67
|
+
steps:
|
|
68
|
+
- uses: actions/checkout@v4
|
|
69
|
+
- name: Build
|
|
70
|
+
run: msbuild MyApp.sln /p:Configuration=Release
|
|
71
|
+
- language: yaml
|
|
72
|
+
label: "Use windows-latest to avoid future manual migrations"
|
|
73
|
+
code: |
|
|
74
|
+
jobs:
|
|
75
|
+
build:
|
|
76
|
+
# windows-latest currently points to windows-2025 (as of June 2026)
|
|
77
|
+
runs-on: windows-latest
|
|
78
|
+
steps:
|
|
79
|
+
- uses: actions/checkout@v4
|
|
80
|
+
- language: bash
|
|
81
|
+
label: "Audit all workflows for windows-2019 references"
|
|
82
|
+
code: |
|
|
83
|
+
# Find all workflow files using windows-2019
|
|
84
|
+
grep -r "windows-2019" .github/workflows/
|
|
85
|
+
prevention:
|
|
86
|
+
- "Use `windows-latest` instead of pinned OS versions unless you have a specific
|
|
87
|
+
reason to pin. This avoids retirement failures entirely."
|
|
88
|
+
- "Subscribe to the `actions/runner-images` repository announcements to receive
|
|
89
|
+
deprecation notices before they become hard failures."
|
|
90
|
+
- "When you must pin an OS version, add a calendar reminder or Renovate/Dependabot
|
|
91
|
+
rule to review the pin when the N-1 policy applies."
|
|
92
|
+
- "Run a periodic repository search for retired runner labels:
|
|
93
|
+
`grep -r 'windows-2019\\|ubuntu-20.04\\|macos-12' .github/workflows/`"
|
|
94
|
+
docs:
|
|
95
|
+
- url: "https://github.com/actions/runner-images/issues/12045"
|
|
96
|
+
label: "Announcement: Windows 2019 deprecation and retirement (runner-images#12045)"
|
|
97
|
+
- url: "https://github.blog/changelog/2025-04-15-upcoming-breaking-changes-and-releases-for-github-actions/"
|
|
98
|
+
label: "GitHub Changelog: Windows Server 2019 is closing down"
|
|
99
|
+
- url: "https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources"
|
|
100
|
+
label: "GitHub Docs: Supported GitHub-hosted runners"
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
id: silent-failures-012
|
|
2
|
+
title: "upload-artifact v4.4.0 Silently Excludes Hidden Files and Directories"
|
|
3
|
+
category: silent-failures
|
|
4
|
+
severity: silent-failure
|
|
5
|
+
tags:
|
|
6
|
+
- upload-artifact
|
|
7
|
+
- artifact-v4
|
|
8
|
+
- hidden-files
|
|
9
|
+
- dotfiles
|
|
10
|
+
- path-patterns
|
|
11
|
+
- silent
|
|
12
|
+
patterns:
|
|
13
|
+
- regex: "upload.*artifact.*no files.*found|artifact.*upload.*0.*bytes"
|
|
14
|
+
flags: "i"
|
|
15
|
+
- regex: "Artifact.*successfully uploaded.*0 files|uploaded 0 item"
|
|
16
|
+
flags: "i"
|
|
17
|
+
- regex: "include-hidden-files"
|
|
18
|
+
flags: "i"
|
|
19
|
+
error_messages:
|
|
20
|
+
- "Warning: No files were found with the provided path: .env.dist"
|
|
21
|
+
- "Artifact upload: 0 items, 0 bytes"
|
|
22
|
+
- "With the provided path, there will be 0 files uploaded"
|
|
23
|
+
- "Uploaded artifact 'dotfiles' (0 bytes)"
|
|
24
|
+
root_cause: |
|
|
25
|
+
Starting with **actions/upload-artifact v4.4.0** (released February 2026), the action
|
|
26
|
+
excludes files and directories whose names begin with `.` (dot/hidden files) **by
|
|
27
|
+
default**. This is a **silent behavior change** — the upload action still reports
|
|
28
|
+
"success" but skips all dotfiles, resulting in an artifact that is missing expected
|
|
29
|
+
content without any error or warning in most cases.
|
|
30
|
+
|
|
31
|
+
**Files and directories affected:**
|
|
32
|
+
- `.env`, `.env.dist`, `.env.example`, `.env.test`
|
|
33
|
+
- `.gitignore`, `.gitattributes`, `.eslintrc`, `.prettierrc`
|
|
34
|
+
- `.docker/`, `.github/`, `.cache/`, `.npm/`
|
|
35
|
+
- Any file or directory with a name starting with `.`
|
|
36
|
+
|
|
37
|
+
**Why this is a silent failure:** The action reports "Artifact uploaded successfully"
|
|
38
|
+
even when all matched files happen to be hidden files and thus are excluded. In cases
|
|
39
|
+
where the path glob matches only hidden files, the artifact is created with 0 bytes
|
|
40
|
+
and no error is thrown. Downstream jobs that download and use the artifact will
|
|
41
|
+
receive an empty directory or encounter missing file errors, far from the upload step.
|
|
42
|
+
|
|
43
|
+
**Historical context:** This change was introduced for security consistency —
|
|
44
|
+
dotfiles often contain secrets (`.env`), credentials, or sensitive configuration that
|
|
45
|
+
developers might accidentally expose through artifacts. The default exclusion prevents
|
|
46
|
+
accidental secret leakage via artifacts.
|
|
47
|
+
fix: |
|
|
48
|
+
Set `include-hidden-files: true` on the `upload-artifact` step to restore the
|
|
49
|
+
previous behavior and include dotfiles in the artifact.
|
|
50
|
+
|
|
51
|
+
**Security note:** Before enabling `include-hidden-files: true`, review whether
|
|
52
|
+
the files being uploaded contain secrets. Consider using GitHub secrets or environment
|
|
53
|
+
variables for sensitive values rather than uploading `.env` files as artifacts.
|
|
54
|
+
|
|
55
|
+
Alternatively, rename configuration files to not start with `.` if they don't
|
|
56
|
+
contain sensitive values (e.g., `env.example` instead of `.env.example`).
|
|
57
|
+
fix_code:
|
|
58
|
+
- language: yaml
|
|
59
|
+
label: "Enable hidden file inclusion with include-hidden-files"
|
|
60
|
+
code: |
|
|
61
|
+
jobs:
|
|
62
|
+
build:
|
|
63
|
+
runs-on: ubuntu-latest
|
|
64
|
+
steps:
|
|
65
|
+
- uses: actions/checkout@v4
|
|
66
|
+
|
|
67
|
+
- name: Build
|
|
68
|
+
run: make build
|
|
69
|
+
|
|
70
|
+
# ❌ v4.4.0+: .env.dist, .config/, etc. are silently excluded
|
|
71
|
+
# - uses: actions/upload-artifact@v4
|
|
72
|
+
# with:
|
|
73
|
+
# name: build-output
|
|
74
|
+
# path: dist/
|
|
75
|
+
|
|
76
|
+
# ✅ Explicitly include hidden files when needed
|
|
77
|
+
- uses: actions/upload-artifact@v4
|
|
78
|
+
with:
|
|
79
|
+
name: build-output
|
|
80
|
+
path: dist/
|
|
81
|
+
include-hidden-files: true # restores pre-v4.4.0 behavior
|
|
82
|
+
- language: yaml
|
|
83
|
+
label: "Targeted upload — avoid hidden files where possible"
|
|
84
|
+
code: |
|
|
85
|
+
jobs:
|
|
86
|
+
build:
|
|
87
|
+
runs-on: ubuntu-latest
|
|
88
|
+
steps:
|
|
89
|
+
- uses: actions/checkout@v4
|
|
90
|
+
|
|
91
|
+
- name: Build
|
|
92
|
+
run: make build
|
|
93
|
+
|
|
94
|
+
# ✅ Better: upload specific file types, not entire directories
|
|
95
|
+
# This avoids accidentally including or excluding hidden files
|
|
96
|
+
- uses: actions/upload-artifact@v4
|
|
97
|
+
with:
|
|
98
|
+
name: build-artifacts
|
|
99
|
+
path: |
|
|
100
|
+
dist/**/*.js
|
|
101
|
+
dist/**/*.css
|
|
102
|
+
dist/**/*.html
|
|
103
|
+
env.example # renamed from .env.example to avoid hiding
|
|
104
|
+
prevention:
|
|
105
|
+
- "Audit workflows that upload artifacts containing dotfiles (`.env.*`, `.config`,
|
|
106
|
+
`.cache/`) — add `include-hidden-files: true` explicitly if those files are needed."
|
|
107
|
+
- "Check artifact sizes after upgrading to v4.4.0+: a 0-byte or unexpectedly small
|
|
108
|
+
artifact often indicates hidden files were silently excluded."
|
|
109
|
+
- "For environment template files that should be shared as artifacts, rename them
|
|
110
|
+
to not start with `.` (e.g., `env.template` instead of `.env.template`)."
|
|
111
|
+
- "Never upload actual `.env` files with real secrets as artifacts — use GitHub
|
|
112
|
+
secrets or OIDC-based secret retrieval instead."
|
|
113
|
+
docs:
|
|
114
|
+
- url: "https://stackoverflow.com/questions/78941839/github-actions-upload-artifactv4-4-0-path-patterns-not-working-after-upgrade"
|
|
115
|
+
label: "Stack Overflow: upload-artifact v4.4.0 path patterns not working (hidden files)"
|
|
116
|
+
- url: "https://github.blog/changelog/2026-02-26-github-actions-now-supports-uploading-and-downloading-non-zipped-artifacts"
|
|
117
|
+
label: "GitHub Changelog: artifact upload/download improvements (Feb 2026)"
|
|
118
|
+
- url: "https://github.com/actions/upload-artifact/blob/main/RELEASES.md"
|
|
119
|
+
label: "upload-artifact v4 release notes"
|
|
120
|
+
- url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/storing-and-sharing-data-from-a-workflow"
|
|
121
|
+
label: "GitHub Docs: Storing and sharing data from a workflow"
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
id: yaml-syntax-016
|
|
2
|
+
title: "vars Context Rejected Inside Composite Action Expressions"
|
|
3
|
+
category: yaml-syntax
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- composite-actions
|
|
7
|
+
- vars-context
|
|
8
|
+
- expression
|
|
9
|
+
- runner-validation
|
|
10
|
+
- organization-variables
|
|
11
|
+
- repository-variables
|
|
12
|
+
patterns:
|
|
13
|
+
- regex: "Unrecognized named-value.*'?vars'?"
|
|
14
|
+
flags: "i"
|
|
15
|
+
- regex: "Unexpected value.*vars\\.\\w+"
|
|
16
|
+
flags: "i"
|
|
17
|
+
- regex: "inputs\\.\\w+.*\\|\\|.*vars\\.\\w+.*not.*recognized"
|
|
18
|
+
flags: "i"
|
|
19
|
+
error_messages:
|
|
20
|
+
- "Unrecognized named-value: 'vars'. Located at position X within expression: inputs.region || vars.AWS_REGION || 'us-east-1'"
|
|
21
|
+
- "Error: Unrecognized named-value: 'vars'"
|
|
22
|
+
- "Invalid workflow file: .github/actions/my-action/action.yml (Line N, Col M): Unrecognized named-value: 'vars'"
|
|
23
|
+
root_cause: |
|
|
24
|
+
The `vars` context (organization/repository/environment variables) is **not available
|
|
25
|
+
inside composite action definitions** (`action.yml`). Runner validation enforces
|
|
26
|
+
context availability rules per the element type, and composite actions are not
|
|
27
|
+
permitted to reference `vars.*` in their step expressions.
|
|
28
|
+
|
|
29
|
+
This was not always enforced — older runner versions allowed some cross-context
|
|
30
|
+
references in composite actions, but a runner validation tightening (tracked in
|
|
31
|
+
actions/runner#4311) made this a hard error. Workflows that worked before started
|
|
32
|
+
failing after runner updates were rolled out to GitHub-hosted and self-hosted runners.
|
|
33
|
+
|
|
34
|
+
**Why the restriction exists:** Composite actions are designed to be reusable across
|
|
35
|
+
repositories and organizations. The `vars` context is scoped to the calling repository
|
|
36
|
+
or organization — a composite action cannot safely resolve `vars.*` at definition time
|
|
37
|
+
because it would create an implicit dependency on the caller's variable set without
|
|
38
|
+
explicit declaration as an `input`.
|
|
39
|
+
|
|
40
|
+
**Affected expression positions:**
|
|
41
|
+
- `with:` value fields in composite action steps
|
|
42
|
+
- `run:` shell commands using `${{ vars.* }}` syntax
|
|
43
|
+
- `if:` conditions on composite action steps
|
|
44
|
+
- Default values for composite action inputs that fall back to `vars.*`
|
|
45
|
+
fix: |
|
|
46
|
+
Remove `vars.*` references from composite action definitions. Instead, require
|
|
47
|
+
callers to pass variables explicitly as action `inputs`, and reference those inputs
|
|
48
|
+
inside the composite action.
|
|
49
|
+
|
|
50
|
+
**Pattern:**
|
|
51
|
+
1. Add an explicit `input` to the composite action for any value currently read from
|
|
52
|
+
`vars.*`
|
|
53
|
+
2. Give it a meaningful name and a default value (empty string or a sensible default)
|
|
54
|
+
3. In the calling workflow, pass the variable value as `with: my-input: ${{ vars.MY_VAR }}`
|
|
55
|
+
4. Inside the composite action, replace `${{ vars.MY_VAR }}` with `${{ inputs.my-input }}`
|
|
56
|
+
fix_code:
|
|
57
|
+
- language: yaml
|
|
58
|
+
label: "action.yml — Replace vars.* with an explicit input"
|
|
59
|
+
code: |
|
|
60
|
+
# ❌ BROKEN: vars context not available in composite actions
|
|
61
|
+
# action.yml
|
|
62
|
+
inputs:
|
|
63
|
+
region:
|
|
64
|
+
description: "AWS region"
|
|
65
|
+
required: false
|
|
66
|
+
default: "" # cannot use: ${{ vars.AWS_REGION }}
|
|
67
|
+
|
|
68
|
+
runs:
|
|
69
|
+
using: composite
|
|
70
|
+
steps:
|
|
71
|
+
- name: Deploy
|
|
72
|
+
shell: bash
|
|
73
|
+
run: |
|
|
74
|
+
# ❌ This will fail:
|
|
75
|
+
# REGION="${{ inputs.region || vars.AWS_REGION || 'us-east-1' }}"
|
|
76
|
+
|
|
77
|
+
# ✅ Use only inputs:
|
|
78
|
+
REGION="${{ inputs.region || 'us-east-1' }}"
|
|
79
|
+
echo "Deploying to $REGION"
|
|
80
|
+
- language: yaml
|
|
81
|
+
label: "caller workflow — Pass vars.* as an explicit input"
|
|
82
|
+
code: |
|
|
83
|
+
# ✅ Calling workflow passes vars.* to the composite action explicitly
|
|
84
|
+
jobs:
|
|
85
|
+
deploy:
|
|
86
|
+
runs-on: ubuntu-latest
|
|
87
|
+
steps:
|
|
88
|
+
- uses: ./.github/actions/deploy
|
|
89
|
+
with:
|
|
90
|
+
region: ${{ vars.AWS_REGION }} # resolved in caller, not inside composite
|
|
91
|
+
- language: yaml
|
|
92
|
+
label: "action.yml — Full corrected composite action"
|
|
93
|
+
code: |
|
|
94
|
+
# ✅ CORRECT: composite action with explicit input, no vars.* reference
|
|
95
|
+
name: Deploy to AWS
|
|
96
|
+
description: Deploy application to AWS
|
|
97
|
+
|
|
98
|
+
inputs:
|
|
99
|
+
region:
|
|
100
|
+
description: "AWS region (pass vars.AWS_REGION from caller)"
|
|
101
|
+
required: false
|
|
102
|
+
default: "us-east-1"
|
|
103
|
+
|
|
104
|
+
runs:
|
|
105
|
+
using: composite
|
|
106
|
+
steps:
|
|
107
|
+
- name: Deploy
|
|
108
|
+
shell: bash
|
|
109
|
+
run: echo "Deploying to ${{ inputs.region }}"
|
|
110
|
+
prevention:
|
|
111
|
+
- "Never reference `vars.*`, `secrets.*`, or `env.*` directly inside composite action
|
|
112
|
+
step expressions — these contexts are not available at composite action evaluation time."
|
|
113
|
+
- "Treat composite actions like reusable library functions: all runtime values must
|
|
114
|
+
come in through declared `inputs`."
|
|
115
|
+
- "In the calling workflow, resolve `vars.*` or `secrets.*` at the `with:` level and
|
|
116
|
+
pass resulting values as string inputs."
|
|
117
|
+
- "Run `act` locally or validate with `actionlint` to catch context availability
|
|
118
|
+
errors before pushing to GitHub."
|
|
119
|
+
docs:
|
|
120
|
+
- url: "https://github.com/actions/runner/issues/4311"
|
|
121
|
+
label: "actions/runner#4311 — vars context rejected in composite actions"
|
|
122
|
+
- url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/accessing-contextual-information-about-workflow-runs#context-availability"
|
|
123
|
+
label: "GitHub Docs: Context availability by element type"
|
|
124
|
+
- url: "https://docs.github.com/en/actions/sharing-automations/creating-actions/creating-a-composite-action"
|
|
125
|
+
label: "GitHub Docs: Creating a composite action"
|
|
126
|
+
- url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/variables#using-the-vars-context-to-access-configuration-variable-values"
|
|
127
|
+
label: "GitHub Docs: Using the vars context"
|
package/package.json
CHANGED