@htekdev/actions-debugger 1.0.67 → 1.0.69
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/artifact-retention-days-silently-capped-org-maximum.yml +69 -0
- package/errors/concurrency-timing/cancel-in-progress-deployment-environment-review-loop.yml +76 -0
- package/errors/concurrency-timing/concurrency-group-missing-ref-cross-branch-cancellation.yml +62 -0
- package/errors/known-unsolved/composite-action-no-pre-post-lifecycle-hooks.yml +94 -0
- package/errors/runner-environment/docker-build-push-provenance-default-manifest-index.yml +81 -0
- package/errors/runner-environment/setup-node-yarn-packagemanager-corepack-conflict.yml +71 -0
- package/errors/triggers/schedule-workflow-disabled-on-fork.yml +69 -0
- package/errors/yaml-syntax/run-block-scalar-folded-gt-collapses-newlines.yml +76 -0
- package/package.json +1 -1
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
id: caching-artifacts-043
|
|
2
|
+
title: "upload-artifact retention-days silently capped at organization maximum — artifact expires earlier than configured"
|
|
3
|
+
category: caching-artifacts
|
|
4
|
+
severity: silent-failure
|
|
5
|
+
tags:
|
|
6
|
+
- upload-artifact
|
|
7
|
+
- retention-days
|
|
8
|
+
- artifacts
|
|
9
|
+
- organization-policy
|
|
10
|
+
- expiry
|
|
11
|
+
patterns:
|
|
12
|
+
- regex: 'Artifact will be retained for \d+ days'
|
|
13
|
+
flags: "i"
|
|
14
|
+
error_messages:
|
|
15
|
+
- "Artifact will be retained for"
|
|
16
|
+
root_cause: |
|
|
17
|
+
When actions/upload-artifact is configured with a retention-days value that exceeds the
|
|
18
|
+
organization's or repository's maximum artifact retention setting, GitHub silently caps
|
|
19
|
+
the retention period to the configured maximum without emitting any error or warning.
|
|
20
|
+
The upload step completes successfully, the workflow shows green, and the artifact is
|
|
21
|
+
created — but it expires sooner than the workflow author intended.
|
|
22
|
+
|
|
23
|
+
This is particularly dangerous for:
|
|
24
|
+
- Compliance workflows that retain build artifacts for audits
|
|
25
|
+
- Release workflows where binaries must survive for customer download periods
|
|
26
|
+
- Security scanning workflows that need artifacts for post-incident review
|
|
27
|
+
|
|
28
|
+
The only way to discover the cap is to inspect the artifact's expiration date in the
|
|
29
|
+
repository's Actions UI after upload, or query the REST API. Developers who set
|
|
30
|
+
retention-days: 365 expecting one-year retention will find artifacts disappearing after
|
|
31
|
+
90 days (the default org maximum) with no log evidence of the cap.
|
|
32
|
+
fix: |
|
|
33
|
+
Check your organization's artifact retention maximum under Organization Settings → Actions
|
|
34
|
+
→ General → Artifact and log retention, and ensure retention-days in upload-artifact is
|
|
35
|
+
set to a value at or below this limit. If you need retention beyond the org maximum
|
|
36
|
+
(e.g., for compliance), use GitHub Releases for tagged builds, or an external artifact
|
|
37
|
+
store (S3, Azure Blob, GCS). You can also query the artifact API to assert the actual
|
|
38
|
+
expiry date and fail the workflow if it doesn't match expectations.
|
|
39
|
+
fix_code:
|
|
40
|
+
- language: yaml
|
|
41
|
+
label: "Cap retention-days to org maximum and use GitHub Releases for long-term storage"
|
|
42
|
+
code: |
|
|
43
|
+
- name: Upload build artifact
|
|
44
|
+
uses: actions/upload-artifact@v4
|
|
45
|
+
with:
|
|
46
|
+
name: build-output-${{ github.sha }}
|
|
47
|
+
path: dist/
|
|
48
|
+
# Must be <= your org's maximum retention setting
|
|
49
|
+
# Check: Org Settings → Actions → General → Artifact and log retention
|
|
50
|
+
retention-days: 30
|
|
51
|
+
|
|
52
|
+
# For artifacts requiring retention beyond the org maximum (e.g., release binaries),
|
|
53
|
+
# attach them to a GitHub Release instead:
|
|
54
|
+
- name: Create GitHub Release with artifact
|
|
55
|
+
uses: softprops/action-gh-release@v2
|
|
56
|
+
if: startsWith(github.ref, 'refs/tags/')
|
|
57
|
+
with:
|
|
58
|
+
files: dist/**
|
|
59
|
+
# Release assets are NOT subject to the artifact retention policy
|
|
60
|
+
prevention:
|
|
61
|
+
- "Check your organization's artifact retention maximum before setting retention-days in upload-artifact"
|
|
62
|
+
- "For artifacts requiring long-term storage, use GitHub Releases or an external object store (S3, GCS, Azure Blob)"
|
|
63
|
+
- "Add a workflow step that queries the artifact expiry via the REST API and fails if it doesn't match the intended retention"
|
|
64
|
+
- "Document the org retention limit in a comment next to retention-days to alert future editors"
|
|
65
|
+
docs:
|
|
66
|
+
- url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/storing-workflow-data-as-artifacts"
|
|
67
|
+
label: "Storing workflow data as artifacts — GitHub Docs"
|
|
68
|
+
- url: "https://docs.github.com/en/organizations/managing-organization-settings/configuring-the-retention-period-for-github-actions-artifacts-and-logs-in-your-organization"
|
|
69
|
+
label: "Configuring artifact retention period for your organization — GitHub Docs"
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
id: concurrency-timing-036
|
|
2
|
+
title: "cancel-in-progress: true cancels pending deployment environment reviews — deployment never completes"
|
|
3
|
+
category: concurrency-timing
|
|
4
|
+
severity: silent-failure
|
|
5
|
+
tags:
|
|
6
|
+
- concurrency
|
|
7
|
+
- deployment
|
|
8
|
+
- environment
|
|
9
|
+
- cancel-in-progress
|
|
10
|
+
- required-reviewers
|
|
11
|
+
patterns:
|
|
12
|
+
- regex: 'waiting for a required environment'
|
|
13
|
+
flags: "i"
|
|
14
|
+
- regex: 'Deployment to .+ was cancelled'
|
|
15
|
+
flags: "i"
|
|
16
|
+
error_messages:
|
|
17
|
+
- "This workflow run is waiting for a required environment"
|
|
18
|
+
- "Deployment to production was cancelled"
|
|
19
|
+
root_cause: |
|
|
20
|
+
When a deployment job targets an environment with required reviewers (protection rules)
|
|
21
|
+
and cancel-in-progress: true is set on the concurrency group, every new push cancels the
|
|
22
|
+
pending workflow run — including the one awaiting reviewer approval. The reviewer is
|
|
23
|
+
notified, starts the review process, but before they approve a new commit arrives and
|
|
24
|
+
cancels the run. The cycle repeats indefinitely: deployments queue, reviewers are
|
|
25
|
+
interrupted, and nothing ever reaches production. No diagnostic error is surfaced; the
|
|
26
|
+
workflow simply shows "Cancelled" with no indication that a required-reviewer gate was
|
|
27
|
+
involved.
|
|
28
|
+
fix: |
|
|
29
|
+
Remove cancel-in-progress: true from the concurrency group used by the deployment job.
|
|
30
|
+
Use cancel-in-progress: false (the default) so pending approval runs survive new commits.
|
|
31
|
+
To still get fast feedback on CI, split the workflow into two separate files: a fast CI
|
|
32
|
+
workflow with cancel-in-progress: true, and a deployment workflow (triggered on CI success)
|
|
33
|
+
with cancel-in-progress: false so approval gates are preserved.
|
|
34
|
+
fix_code:
|
|
35
|
+
- language: yaml
|
|
36
|
+
label: "Split CI and deploy workflows with separate concurrency policies"
|
|
37
|
+
code: |
|
|
38
|
+
# .github/workflows/ci.yml — cancel old CI runs freely
|
|
39
|
+
on: [push, pull_request]
|
|
40
|
+
concurrency:
|
|
41
|
+
group: ci-${{ github.ref }}
|
|
42
|
+
cancel-in-progress: true
|
|
43
|
+
jobs:
|
|
44
|
+
test:
|
|
45
|
+
runs-on: ubuntu-latest
|
|
46
|
+
steps:
|
|
47
|
+
- uses: actions/checkout@v4
|
|
48
|
+
- run: npm test
|
|
49
|
+
|
|
50
|
+
# .github/workflows/deploy.yml — preserve pending deployment approvals
|
|
51
|
+
on:
|
|
52
|
+
workflow_run:
|
|
53
|
+
workflows: [CI]
|
|
54
|
+
types: [completed]
|
|
55
|
+
branches: [main]
|
|
56
|
+
concurrency:
|
|
57
|
+
group: deploy-${{ github.ref }}
|
|
58
|
+
cancel-in-progress: false # preserves pending required-reviewer approval
|
|
59
|
+
jobs:
|
|
60
|
+
deploy:
|
|
61
|
+
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
|
62
|
+
environment: production # has required reviewers
|
|
63
|
+
runs-on: ubuntu-latest
|
|
64
|
+
steps:
|
|
65
|
+
- uses: actions/checkout@v4
|
|
66
|
+
- run: echo "Deploying..."
|
|
67
|
+
prevention:
|
|
68
|
+
- "Never combine cancel-in-progress: true with deployment jobs that have required-reviewer environment protection rules"
|
|
69
|
+
- "Use separate workflow files for CI and deployment to apply different concurrency policies"
|
|
70
|
+
- "Set cancel-in-progress: false (or omit it) on any concurrency group that wraps a deployment environment job"
|
|
71
|
+
- "Test the deployment approval flow explicitly after adding or changing concurrency settings"
|
|
72
|
+
docs:
|
|
73
|
+
- url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/using-concurrency"
|
|
74
|
+
label: "Using concurrency — GitHub Docs"
|
|
75
|
+
- url: "https://docs.github.com/en/actions/managing-workflow-runs-and-deployments/managing-deployments/reviewing-deployments"
|
|
76
|
+
label: "Reviewing deployments — GitHub Docs"
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
id: concurrency-timing-037
|
|
2
|
+
title: "Concurrency group key missing github.ref accidentally cancels runs on other branches"
|
|
3
|
+
category: concurrency-timing
|
|
4
|
+
severity: silent-failure
|
|
5
|
+
tags:
|
|
6
|
+
- concurrency
|
|
7
|
+
- cancel-in-progress
|
|
8
|
+
- github-ref
|
|
9
|
+
- branches
|
|
10
|
+
- cross-branch
|
|
11
|
+
patterns:
|
|
12
|
+
- regex: 'cancelled because a more recent run with the same concurrency'
|
|
13
|
+
flags: "i"
|
|
14
|
+
- regex: 'This run was cancelled'
|
|
15
|
+
flags: "i"
|
|
16
|
+
error_messages:
|
|
17
|
+
- "This run was cancelled because a more recent run with the same concurrency key is in progress"
|
|
18
|
+
root_cause: |
|
|
19
|
+
When the concurrency group key is set to a static string or uses only github.workflow
|
|
20
|
+
without including github.ref, all branches share the same concurrency slot. A push to
|
|
21
|
+
any feature branch will cancel an in-progress run on main — or vice versa. With
|
|
22
|
+
cancel-in-progress: true, a developer's feature branch push can silently abort a
|
|
23
|
+
production branch deployment or a release CI run. The cancellation message ("This run
|
|
24
|
+
was cancelled because a more recent run with the same concurrency key is in progress")
|
|
25
|
+
gives no indication that the runs are on completely different branches. This is among the
|
|
26
|
+
most common misconfiguration in copy-pasted concurrency examples that omit github.ref.
|
|
27
|
+
fix: |
|
|
28
|
+
Always include github.ref (or github.head_ref for pull_request events) in the concurrency
|
|
29
|
+
group key so each branch maintains its own independent concurrency slot. For pull requests,
|
|
30
|
+
use github.event.pull_request.number to prevent conflicts between simultaneously open PRs
|
|
31
|
+
targeting the same branch. For scheduled or manual workflows where github.ref is always
|
|
32
|
+
the same, use github.run_id to allow parallel runs.
|
|
33
|
+
fix_code:
|
|
34
|
+
- language: yaml
|
|
35
|
+
label: "Include github.ref in the concurrency key to isolate each branch"
|
|
36
|
+
code: |
|
|
37
|
+
# WRONG — all branches share one concurrency slot, pushes to any branch
|
|
38
|
+
# cancel runs on all other branches
|
|
39
|
+
# concurrency:
|
|
40
|
+
# group: ${{ github.workflow }}
|
|
41
|
+
# cancel-in-progress: true
|
|
42
|
+
|
|
43
|
+
# CORRECT — each branch has its own independent concurrency slot
|
|
44
|
+
concurrency:
|
|
45
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
46
|
+
cancel-in-progress: true
|
|
47
|
+
|
|
48
|
+
# For pull_request events, scope to the PR number for extra precision
|
|
49
|
+
# (prevents PR-A and PR-B from cancelling each other when both target main)
|
|
50
|
+
concurrency:
|
|
51
|
+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
|
52
|
+
cancel-in-progress: true
|
|
53
|
+
prevention:
|
|
54
|
+
- "Always include github.ref or github.head_ref in the concurrency group key"
|
|
55
|
+
- "For pull_request workflows, use github.event.pull_request.number || github.ref to scope to individual PRs"
|
|
56
|
+
- "Audit all workflow concurrency keys whenever enabling cancel-in-progress: true"
|
|
57
|
+
- "Use a unique prefix per workflow type (ci-, deploy-, lint-) to prevent cross-workflow collisions even when github.ref is included"
|
|
58
|
+
docs:
|
|
59
|
+
- url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/using-concurrency"
|
|
60
|
+
label: "Using concurrency — GitHub Docs"
|
|
61
|
+
- url: "https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#concurrency"
|
|
62
|
+
label: "Concurrency syntax — GitHub Docs"
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
id: known-unsolved-043
|
|
2
|
+
title: 'Composite actions do not support pre: and post: lifecycle hooks — no guaranteed setup or cleanup code'
|
|
3
|
+
category: known-unsolved
|
|
4
|
+
severity: limitation
|
|
5
|
+
tags:
|
|
6
|
+
- composite-action
|
|
7
|
+
- pre-step
|
|
8
|
+
- post-step
|
|
9
|
+
- cleanup
|
|
10
|
+
- lifecycle
|
|
11
|
+
patterns:
|
|
12
|
+
- regex: 'Unexpected value ''pre'''
|
|
13
|
+
flags: 'i'
|
|
14
|
+
- regex: 'Unexpected value ''post'''
|
|
15
|
+
flags: 'i'
|
|
16
|
+
error_messages:
|
|
17
|
+
- "Unexpected value 'pre'"
|
|
18
|
+
- "Unexpected value 'post'"
|
|
19
|
+
- 'pre: and post: are only supported in JavaScript and Docker container actions'
|
|
20
|
+
root_cause: |
|
|
21
|
+
GitHub Actions supports pre: and post: lifecycle hooks in JavaScript actions (using: node20/node24)
|
|
22
|
+
and Docker container actions (using: docker). These hooks run before and after the main action
|
|
23
|
+
step respectively, and the post: hook runs even when the workflow is cancelled or fails —
|
|
24
|
+
making them ideal for guaranteed resource cleanup.
|
|
25
|
+
|
|
26
|
+
Composite actions (using: composite) do NOT support pre: or post: hooks. Attempting to add
|
|
27
|
+
pre: or post: to an action.yml with using: composite causes a validation error. This means
|
|
28
|
+
shell-based or Python-based composite actions cannot register guaranteed cleanup code that
|
|
29
|
+
runs after the job, regardless of success, failure, or cancellation.
|
|
30
|
+
|
|
31
|
+
Common affected patterns:
|
|
32
|
+
- Database seeding in setup steps that must be torn down in post:
|
|
33
|
+
- Port forwarding or tunnel setup that must be closed after the job
|
|
34
|
+
- Temporary credential setup that must be revoked after the workflow
|
|
35
|
+
- Cloud resource creation that must be deleted to avoid cost leaks
|
|
36
|
+
fix: |
|
|
37
|
+
There is no direct fix — this is a known GitHub Actions platform limitation. Common workarounds:
|
|
38
|
+
|
|
39
|
+
Option A: Add explicit cleanup steps in calling workflows using if: always().
|
|
40
|
+
Option B: Wrap the composite logic in a thin JavaScript action that shells out to scripts,
|
|
41
|
+
enabling pre:/post: hook support.
|
|
42
|
+
Option C: Use a separate cleanup job with needs: [main-job] and if: always() for teardown.
|
|
43
|
+
Note: Option C adds latency and does not run on runner process kill.
|
|
44
|
+
fix_code:
|
|
45
|
+
- language: yaml
|
|
46
|
+
label: 'Workaround: use if: always() cleanup step in the calling workflow'
|
|
47
|
+
code: |
|
|
48
|
+
jobs:
|
|
49
|
+
build:
|
|
50
|
+
runs-on: ubuntu-latest
|
|
51
|
+
steps:
|
|
52
|
+
- name: Setup composite action
|
|
53
|
+
uses: ./.github/actions/my-composite-action
|
|
54
|
+
|
|
55
|
+
- name: Run build
|
|
56
|
+
run: make build
|
|
57
|
+
|
|
58
|
+
# Cleanup runs even if previous steps fail or are cancelled
|
|
59
|
+
- name: Cleanup resources
|
|
60
|
+
if: always()
|
|
61
|
+
run: |
|
|
62
|
+
echo "Cleaning up resources created by composite action..."
|
|
63
|
+
# teardown commands here
|
|
64
|
+
|
|
65
|
+
- language: yaml
|
|
66
|
+
label: 'Workaround: separate cleanup job guaranteed to run after main job'
|
|
67
|
+
code: |
|
|
68
|
+
jobs:
|
|
69
|
+
build:
|
|
70
|
+
runs-on: ubuntu-latest
|
|
71
|
+
steps:
|
|
72
|
+
- uses: ./.github/actions/my-composite-action
|
|
73
|
+
- run: make build
|
|
74
|
+
|
|
75
|
+
cleanup:
|
|
76
|
+
runs-on: ubuntu-latest
|
|
77
|
+
needs: [build]
|
|
78
|
+
# Runs even when the build job fails or is cancelled
|
|
79
|
+
if: always()
|
|
80
|
+
steps:
|
|
81
|
+
- name: Teardown
|
|
82
|
+
run: |
|
|
83
|
+
echo "Running post-job cleanup..."
|
|
84
|
+
prevention:
|
|
85
|
+
- "Design composite actions to be stateless and idempotent when possible — avoid side effects that require guaranteed cleanup"
|
|
86
|
+
- "Document in the composite action README that callers must add if: always() cleanup steps"
|
|
87
|
+
- "For actions that require guaranteed pre:/post: lifecycle hooks, consider wrapping in a JavaScript action"
|
|
88
|
+
docs:
|
|
89
|
+
- url: 'https://github.com/actions/runner/issues/1478'
|
|
90
|
+
label: 'actions/runner#1478 — Support pre and post steps in Composite Actions (393 reactions)'
|
|
91
|
+
- url: 'https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions#runs-for-composite-actions'
|
|
92
|
+
label: 'Metadata syntax for composite actions — GitHub Docs'
|
|
93
|
+
- url: 'https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions#runspre'
|
|
94
|
+
label: 'pre: lifecycle hook — JavaScript and Docker actions only'
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
id: runner-environment-130
|
|
2
|
+
title: 'docker/build-push-action default provenance: true pushes OCI image index for single-platform builds — breaks registries that do not support image indexes'
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: silent-failure
|
|
5
|
+
tags:
|
|
6
|
+
- docker
|
|
7
|
+
- build-push-action
|
|
8
|
+
- provenance
|
|
9
|
+
- oci
|
|
10
|
+
- manifest-index
|
|
11
|
+
patterns:
|
|
12
|
+
- regex: 'manifest unknown'
|
|
13
|
+
flags: 'i'
|
|
14
|
+
- regex: 'unexpected status: \d{3}'
|
|
15
|
+
flags: 'i'
|
|
16
|
+
error_messages:
|
|
17
|
+
- 'manifest unknown'
|
|
18
|
+
- 'unexpected status: 400'
|
|
19
|
+
- 'unexpected status: 403'
|
|
20
|
+
root_cause: |
|
|
21
|
+
Starting with docker/build-push-action v4, the provenance input defaults to mode=min,
|
|
22
|
+
which attaches an SLSA provenance attestation to every pushed image. This causes the action
|
|
23
|
+
to push an OCI image index (manifest list) to the registry instead of a plain image manifest,
|
|
24
|
+
even for single-platform builds.
|
|
25
|
+
|
|
26
|
+
Registries and tools that do not support OCI image indexes may return "manifest unknown"
|
|
27
|
+
errors, return 400/403 HTTP responses, or silently resolve to an unexpected image variant.
|
|
28
|
+
Some container registries (such as older versions of GCR) display the provenance attestation
|
|
29
|
+
as a separate image entry with a creation timestamp of 0 epoch (Unix epoch), causing
|
|
30
|
+
confusion in image management dashboards.
|
|
31
|
+
|
|
32
|
+
The behavior is silent in successful-looking cases: the push completes without error, but
|
|
33
|
+
downstream 'docker pull' or 'FROM image:tag' in a Dockerfile may resolve the image index
|
|
34
|
+
instead of a plain image manifest, causing unexpected platform or size differences.
|
|
35
|
+
fix: |
|
|
36
|
+
Set provenance: false in docker/build-push-action to restore plain image manifest behavior
|
|
37
|
+
for single-platform builds. If SLSA provenance is required, use actions/attest-build-provenance
|
|
38
|
+
as a separate step after the push.
|
|
39
|
+
fix_code:
|
|
40
|
+
- language: yaml
|
|
41
|
+
label: 'Disable provenance to push plain image manifest for single-platform builds'
|
|
42
|
+
code: |
|
|
43
|
+
- name: Build and push
|
|
44
|
+
uses: docker/build-push-action@v6
|
|
45
|
+
with:
|
|
46
|
+
context: .
|
|
47
|
+
push: true
|
|
48
|
+
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
|
|
49
|
+
# Disable default provenance attestation to push a plain image manifest.
|
|
50
|
+
# Required for registries that do not support OCI image indexes.
|
|
51
|
+
provenance: false
|
|
52
|
+
|
|
53
|
+
- language: yaml
|
|
54
|
+
label: 'Add SLSA provenance separately using actions/attest-build-provenance'
|
|
55
|
+
code: |
|
|
56
|
+
- name: Build and push
|
|
57
|
+
id: push
|
|
58
|
+
uses: docker/build-push-action@v6
|
|
59
|
+
with:
|
|
60
|
+
context: .
|
|
61
|
+
push: true
|
|
62
|
+
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
|
|
63
|
+
provenance: false
|
|
64
|
+
|
|
65
|
+
- name: Attest build provenance
|
|
66
|
+
uses: actions/attest-build-provenance@v2
|
|
67
|
+
with:
|
|
68
|
+
subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
|
69
|
+
subject-digest: ${{ steps.push.outputs.digest }}
|
|
70
|
+
push-to-registry: true
|
|
71
|
+
prevention:
|
|
72
|
+
- "Set 'provenance: false' in docker/build-push-action unless your target registry explicitly supports OCI image indexes"
|
|
73
|
+
- "Test image pulling from the registry after pushing to confirm the correct manifest type was stored"
|
|
74
|
+
- "Use 'docker manifest inspect' to verify the pushed image is a plain manifest and not a manifest index when provenance is enabled"
|
|
75
|
+
docs:
|
|
76
|
+
- url: 'https://github.com/docker/build-push-action/issues/755'
|
|
77
|
+
label: 'docker/build-push-action#755 — Action started to push manifest indexes instead of images for a single platform'
|
|
78
|
+
- url: 'https://docs.docker.com/build/ci/github-actions/attestations/'
|
|
79
|
+
label: 'Docker build attestations with GitHub Actions'
|
|
80
|
+
- url: 'https://docs.docker.com/reference/cli/docker/buildx/build/#provenance'
|
|
81
|
+
label: 'docker buildx build --provenance flag documentation'
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
id: runner-environment-129
|
|
2
|
+
title: 'setup-node cache: yarn fails when packageManager specifies Yarn 4 in package.json — Corepack version mismatch'
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- setup-node
|
|
7
|
+
- yarn
|
|
8
|
+
- corepack
|
|
9
|
+
- packageManager
|
|
10
|
+
- package-json
|
|
11
|
+
patterns:
|
|
12
|
+
- regex: 'Presence of the "packageManager" field indicates that the project is meant to be used with Corepack'
|
|
13
|
+
flags: 'i'
|
|
14
|
+
- regex: 'the current global version of Yarn is \d+\.\d+'
|
|
15
|
+
flags: 'i'
|
|
16
|
+
error_messages:
|
|
17
|
+
- 'This project''s package.json defines "packageManager": "yarn@4.x.x". However the current global version of Yarn is 1.22.22.'
|
|
18
|
+
- 'Presence of the "packageManager" field indicates that the project is meant to be used with Corepack'
|
|
19
|
+
root_cause: |
|
|
20
|
+
When package.json contains a "packageManager" field specifying Yarn 4 (e.g., "yarn@4.1.1"),
|
|
21
|
+
Yarn's integrity check detects the field and requires the project to be managed via Corepack.
|
|
22
|
+
The system Yarn installed on GitHub-hosted runners is Yarn Classic (1.x), which responds to
|
|
23
|
+
the "packageManager" constraint by throwing an error if Corepack is not enabled.
|
|
24
|
+
|
|
25
|
+
When actions/setup-node is configured with cache: 'yarn', it detects the "packageManager"
|
|
26
|
+
field, attempts to use the specified Yarn version via Corepack, but Corepack is not enabled
|
|
27
|
+
by default on GitHub-hosted runners. The resulting error prevents setup-node from completing
|
|
28
|
+
and fails the job before any build steps run.
|
|
29
|
+
|
|
30
|
+
This affects workflows being upgraded from Yarn Classic to Yarn 4 (Berry) via the
|
|
31
|
+
"packageManager" field in package.json, or projects that adopted the "packageManager"
|
|
32
|
+
field for strict version pinning.
|
|
33
|
+
fix: |
|
|
34
|
+
Enable Corepack before running setup-node. Two options depending on your setup-node version:
|
|
35
|
+
|
|
36
|
+
Option A: Add a 'corepack enable' run step before setup-node (works with all versions).
|
|
37
|
+
Option B: Use 'enable-node-corepack: true' input (requires setup-node v4.2+).
|
|
38
|
+
Option C: Remove 'packageManager' from package.json and manage Yarn version via .yarnrc.yml only.
|
|
39
|
+
fix_code:
|
|
40
|
+
- language: yaml
|
|
41
|
+
label: 'Enable Corepack before setup-node (Yarn 4 / Berry projects)'
|
|
42
|
+
code: |
|
|
43
|
+
- name: Enable Corepack
|
|
44
|
+
run: corepack enable
|
|
45
|
+
|
|
46
|
+
- name: Set up Node.js with Yarn cache
|
|
47
|
+
uses: actions/setup-node@v4
|
|
48
|
+
with:
|
|
49
|
+
node-version: '20'
|
|
50
|
+
cache: 'yarn'
|
|
51
|
+
|
|
52
|
+
- language: yaml
|
|
53
|
+
label: 'Alternative: enable-node-corepack input (setup-node v4.2+)'
|
|
54
|
+
code: |
|
|
55
|
+
- name: Set up Node.js
|
|
56
|
+
uses: actions/setup-node@v4
|
|
57
|
+
with:
|
|
58
|
+
node-version: '20'
|
|
59
|
+
cache: 'yarn'
|
|
60
|
+
enable-node-corepack: true
|
|
61
|
+
prevention:
|
|
62
|
+
- "Always run 'corepack enable' before setup-node when package.json has a 'packageManager' field specifying Yarn 4+"
|
|
63
|
+
- "Verify Corepack is enabled before relying on setup-node's yarn cache integration in Yarn Berry projects"
|
|
64
|
+
- "Pin the Yarn version in .yarnrc.yml in addition to the packageManager field to ensure consistent resolution"
|
|
65
|
+
docs:
|
|
66
|
+
- url: 'https://github.com/actions/setup-node/issues/1027'
|
|
67
|
+
label: 'actions/setup-node#1027 — If cache: yarn is specified, this action fails (38 reactions)'
|
|
68
|
+
- url: 'https://github.com/actions/setup-node/blob/main/docs/advanced-usage.md#corepack'
|
|
69
|
+
label: 'setup-node advanced usage — Corepack support'
|
|
70
|
+
- url: 'https://yarnpkg.com/getting-started/install'
|
|
71
|
+
label: 'Yarn Berry — Installation via Corepack'
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
id: triggers-048
|
|
2
|
+
title: 'Scheduled workflows silently disabled on forked repositories — on.schedule never fires until manually re-enabled in Settings'
|
|
3
|
+
category: triggers
|
|
4
|
+
severity: silent-failure
|
|
5
|
+
tags:
|
|
6
|
+
- schedule
|
|
7
|
+
- fork
|
|
8
|
+
- workflow-disabled
|
|
9
|
+
- cron
|
|
10
|
+
- repository-settings
|
|
11
|
+
patterns:
|
|
12
|
+
- regex: 'Scheduled workflows are disabled for this repository'
|
|
13
|
+
flags: 'i'
|
|
14
|
+
- regex: 'This workflow is disabled'
|
|
15
|
+
flags: 'i'
|
|
16
|
+
error_messages:
|
|
17
|
+
- 'Scheduled workflows are disabled for this repository'
|
|
18
|
+
- 'This workflow is disabled'
|
|
19
|
+
root_cause: |
|
|
20
|
+
When a repository containing scheduled workflows is forked, GitHub automatically disables
|
|
21
|
+
all workflow triggers in the fork. This prevents scheduled CI runs from unexpectedly
|
|
22
|
+
consuming GitHub Actions minutes from the fork owner's account and avoids unintended
|
|
23
|
+
side effects from cloned automation.
|
|
24
|
+
|
|
25
|
+
Scheduled workflows (on.schedule:) stop firing entirely on the fork, even if the workflow
|
|
26
|
+
YAML is correct and the branch is up to date. The workflow appears in the Actions tab and
|
|
27
|
+
can be triggered manually via workflow_dispatch, but on.schedule: events are suppressed.
|
|
28
|
+
|
|
29
|
+
This commonly affects:
|
|
30
|
+
- Contributors forking repos to test or contribute scheduled jobs (e.g., nightly builds,
|
|
31
|
+
dependency updates, scheduled reports)
|
|
32
|
+
- Organizations using forks as part of their branching or release strategy and expecting
|
|
33
|
+
scheduled maintenance tasks to continue
|
|
34
|
+
- CI setups where scheduled smoke tests or integration tests are part of the fork workflow
|
|
35
|
+
|
|
36
|
+
The only indicator is the workflow showing as "disabled" in the Actions tab or in the
|
|
37
|
+
workflow run history, which is easy to miss.
|
|
38
|
+
fix: |
|
|
39
|
+
Navigate to the fork repository and enable workflows manually:
|
|
40
|
+
Settings (fork repo) -> Actions -> General -> Allow all actions and reusable workflows.
|
|
41
|
+
Then enable the specific workflow in the Actions tab by clicking "Enable workflow".
|
|
42
|
+
There is no workflow-level or API-level way to force-enable schedules on a fork automatically.
|
|
43
|
+
fix_code:
|
|
44
|
+
- language: yaml
|
|
45
|
+
label: 'Add workflow_dispatch fallback so contributors can trigger manually on forks'
|
|
46
|
+
code: |
|
|
47
|
+
on:
|
|
48
|
+
# Note: scheduled runs are DISABLED on forked repositories by default.
|
|
49
|
+
# Contributors must enable workflows in Settings -> Actions -> General.
|
|
50
|
+
schedule:
|
|
51
|
+
- cron: '0 2 * * *'
|
|
52
|
+
|
|
53
|
+
# Add workflow_dispatch as a fallback for manual triggering on forks
|
|
54
|
+
workflow_dispatch:
|
|
55
|
+
inputs:
|
|
56
|
+
reason:
|
|
57
|
+
description: 'Reason for manual run (required when testing on a fork)'
|
|
58
|
+
required: false
|
|
59
|
+
default: 'manual trigger'
|
|
60
|
+
|
|
61
|
+
prevention:
|
|
62
|
+
- "Document in CONTRIBUTING.md that scheduled workflows must be manually enabled on forks via Settings -> Actions -> General"
|
|
63
|
+
- "Add workflow_dispatch to all scheduled workflows so contributors can manually trigger them on forks during development"
|
|
64
|
+
- "Use repository_dispatch or workflow_run from the upstream repo to trigger downstream automation instead of relying on fork schedules"
|
|
65
|
+
docs:
|
|
66
|
+
- url: 'https://docs.github.com/en/actions/managing-workflow-runs-and-deployments/managing-workflow-runs/disabling-and-enabling-a-workflow'
|
|
67
|
+
label: 'Disabling and enabling a workflow — GitHub Docs'
|
|
68
|
+
- url: 'https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#schedule'
|
|
69
|
+
label: 'schedule event — GitHub Docs'
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
id: yaml-syntax-044
|
|
2
|
+
title: "run: > (folded block scalar) collapses newlines to spaces — multi-line shell scripts break silently"
|
|
3
|
+
category: yaml-syntax
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- yaml
|
|
7
|
+
- run
|
|
8
|
+
- block-scalar
|
|
9
|
+
- multiline
|
|
10
|
+
- shell
|
|
11
|
+
- folded
|
|
12
|
+
patterns:
|
|
13
|
+
- regex: 'syntax error near unexpected token'
|
|
14
|
+
flags: "i"
|
|
15
|
+
- regex: 'command not found'
|
|
16
|
+
flags: "i"
|
|
17
|
+
- regex: 'unexpected EOF while looking for matching'
|
|
18
|
+
flags: "i"
|
|
19
|
+
error_messages:
|
|
20
|
+
- "syntax error near unexpected token"
|
|
21
|
+
- "command not found"
|
|
22
|
+
- "unexpected EOF while looking for matching `\"'"
|
|
23
|
+
root_cause: |
|
|
24
|
+
YAML has two block scalar indicators: | (literal) preserves newlines exactly, while >
|
|
25
|
+
(folded) collapses newlines between non-empty lines into a single space. When a GitHub
|
|
26
|
+
Actions run: block uses > instead of |, every line break in the shell script becomes a
|
|
27
|
+
space. Multi-line scripts are silently concatenated into a single command that the shell
|
|
28
|
+
cannot parse, producing confusing errors like "syntax error near unexpected token" or
|
|
29
|
+
"command not found" pointing to the wrong line.
|
|
30
|
+
|
|
31
|
+
This is especially common when:
|
|
32
|
+
- Developers copy YAML examples from documentation that use > for prose (not scripts)
|
|
33
|
+
- IDEs or formatters suggest > to reduce visual indentation
|
|
34
|
+
- Developers confuse > (folded) and | (literal) because both produce multi-line blocks
|
|
35
|
+
|
|
36
|
+
Example: a three-line script becomes one run-together line:
|
|
37
|
+
# With run: > becomes: echo "start" VAR=hello echo "$VAR"
|
|
38
|
+
# With run: | becomes: echo "start" \n VAR=hello \n echo "$VAR" (correct)
|
|
39
|
+
fix: |
|
|
40
|
+
Always use | (pipe / literal block scalar) for run: steps that contain shell scripts.
|
|
41
|
+
The | indicator preserves newlines exactly as written. The > indicator should only be
|
|
42
|
+
used for prose strings (e.g., long error messages or descriptions) where newline
|
|
43
|
+
collapsing is intentional.
|
|
44
|
+
fix_code:
|
|
45
|
+
- language: yaml
|
|
46
|
+
label: "Use | (literal) not > (folded) for run: shell scripts"
|
|
47
|
+
code: |
|
|
48
|
+
jobs:
|
|
49
|
+
build:
|
|
50
|
+
runs-on: ubuntu-latest
|
|
51
|
+
steps:
|
|
52
|
+
# WRONG — > folds newlines into spaces, script becomes one broken command
|
|
53
|
+
# - name: Build
|
|
54
|
+
# run: >
|
|
55
|
+
# echo "Starting build"
|
|
56
|
+
# npm install
|
|
57
|
+
# npm run build
|
|
58
|
+
|
|
59
|
+
# CORRECT — | preserves newlines, each command runs on its own line
|
|
60
|
+
- name: Build
|
|
61
|
+
run: |
|
|
62
|
+
echo "Starting build"
|
|
63
|
+
npm install
|
|
64
|
+
npm run build
|
|
65
|
+
prevention:
|
|
66
|
+
- "Always use | (literal block scalar) for run: blocks containing shell scripts"
|
|
67
|
+
- "Reserve > (folded block scalar) for non-executable prose strings only"
|
|
68
|
+
- "Enable a YAML linter (e.g., actionlint, yamllint) in pre-commit hooks to catch > in run: blocks"
|
|
69
|
+
- "When in doubt: | keeps lines as lines; > joins lines with spaces"
|
|
70
|
+
docs:
|
|
71
|
+
- url: "https://yaml.org/spec/1.2.2/#chapter-8-block-style-productions"
|
|
72
|
+
label: "YAML block scalar styles — YAML spec"
|
|
73
|
+
- url: "https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun"
|
|
74
|
+
label: "jobs.<id>.steps[*].run — GitHub Docs"
|
|
75
|
+
- url: "https://rhysd.github.io/actionlint/"
|
|
76
|
+
label: "actionlint — static checker for GitHub Actions workflow files"
|
package/package.json
CHANGED