@htekdev/actions-debugger 1.0.36 → 1.0.38
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/runner-environment/macos-latest-macos-15-xcode16-sdk-mismatch.yml +84 -0
- package/errors/runner-environment/multi-platform-docker-build-missing-qemu.yml +84 -0
- package/errors/runner-environment/node16-actions-runtime-deprecated-disabled.yml +87 -0
- package/errors/runner-environment/ubuntu-latest-ubuntu-24-python2-package-removal.yml +75 -0
- package/errors/silent-failures/fork-pr-secrets-empty-string-steps-silently-skipped.yml +97 -0
- package/errors/silent-failures/github-sha-pr-merge-commit-status-invisible.yml +95 -0
- package/errors/triggers/pull-request-labeled-type-not-default.yml +98 -0
- package/errors/yaml-syntax/cache-v3-save-always-unexpected-input.yml +85 -0
- package/package.json +1 -1
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
id: runner-environment-095
|
|
2
|
+
title: macos-latest Points to macOS 15 — Xcode 16 Default Breaks Hardcoded SDK References
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- macos-latest
|
|
7
|
+
- macos-15
|
|
8
|
+
- xcode-16
|
|
9
|
+
- runner-migration
|
|
10
|
+
- apple-silicon
|
|
11
|
+
patterns:
|
|
12
|
+
- regex: 'SDK ''macosx14\.\d+'' cannot be located'
|
|
13
|
+
flags: i
|
|
14
|
+
- regex: 'SDKROOT.*macosx14'
|
|
15
|
+
flags: i
|
|
16
|
+
- regex: 'built for macOS 14.*linking for macOS 15'
|
|
17
|
+
flags: i
|
|
18
|
+
- regex: 'xcodebuild: error:.*SDK ''macosx14'
|
|
19
|
+
flags: i
|
|
20
|
+
error_messages:
|
|
21
|
+
- "error: SDK 'macosx14.5' cannot be located"
|
|
22
|
+
- "xcodebuild: error: The requested SDK 'macosx14.5' cannot be found."
|
|
23
|
+
- "ld: warning: ignoring file ...: built for macOS 14, but linking for macOS 15"
|
|
24
|
+
root_cause: |
|
|
25
|
+
GitHub updated macos-latest to point to macOS 15 (Sequoia) on Apple Silicon
|
|
26
|
+
(M1) runners in January 2025 (GitHub Changelog 2025-01-16). The macOS 15 runner
|
|
27
|
+
image ships with Xcode 16 as the default toolchain.
|
|
28
|
+
|
|
29
|
+
Workflows and Xcode project files that hardcode `SDKROOT=macosx14.5` or
|
|
30
|
+
`MACOSX_DEPLOYMENT_TARGET=14` fail because the macOS 14 SDK is not bundled
|
|
31
|
+
with Xcode 16 by default. Common failure modes:
|
|
32
|
+
|
|
33
|
+
- Hardcoded SDK version strings in .xcconfig files
|
|
34
|
+
- Xcode project targets specifying a minimum macOS deployment target of 14.x
|
|
35
|
+
that resolve against the now-absent SDK
|
|
36
|
+
- Homebrew formulae and pre-installed tool versions changed on macOS 15,
|
|
37
|
+
breaking workflows that assumed specific tool paths or versions
|
|
38
|
+
- The pre-installed Ruby version changed, breaking Fastlane and CocoaPods
|
|
39
|
+
workflows that did not pin a Ruby version
|
|
40
|
+
fix: |
|
|
41
|
+
Option 1: Pin the runner to `macos-14` explicitly to continue using Xcode 15
|
|
42
|
+
and the macOS 14 SDK until you are ready to migrate.
|
|
43
|
+
|
|
44
|
+
Option 2: Use the `maxim-lobanov/setup-xcode` action to pin a specific Xcode
|
|
45
|
+
version on macos-latest, keeping the runner current while controlling toolchain.
|
|
46
|
+
|
|
47
|
+
Option 3: Update Xcode project settings to remove hardcoded SDK version strings.
|
|
48
|
+
Use `$(SDKROOT)` relative targets and set `MACOSX_DEPLOYMENT_TARGET` to a value
|
|
49
|
+
supported by Xcode 16.
|
|
50
|
+
|
|
51
|
+
For Ruby-dependent workflows (Fastlane, CocoaPods), use `ruby/setup-ruby` with
|
|
52
|
+
an explicit version rather than relying on the system Ruby.
|
|
53
|
+
fix_code:
|
|
54
|
+
- language: yaml
|
|
55
|
+
label: Pin explicit macOS version to avoid macos-latest drift
|
|
56
|
+
code: |
|
|
57
|
+
jobs:
|
|
58
|
+
build:
|
|
59
|
+
runs-on: macos-14 # explicit; Xcode 15 + macOS 14 SDK
|
|
60
|
+
|
|
61
|
+
- language: yaml
|
|
62
|
+
label: Pin Xcode version on macos-latest
|
|
63
|
+
code: |
|
|
64
|
+
- uses: maxim-lobanov/setup-xcode@v1
|
|
65
|
+
with:
|
|
66
|
+
xcode-version: '15.4'
|
|
67
|
+
|
|
68
|
+
- language: yaml
|
|
69
|
+
label: Use ruby/setup-ruby for Fastlane and CocoaPods workflows
|
|
70
|
+
code: |
|
|
71
|
+
- uses: ruby/setup-ruby@v1
|
|
72
|
+
with:
|
|
73
|
+
ruby-version: '3.3'
|
|
74
|
+
bundler-cache: true
|
|
75
|
+
prevention:
|
|
76
|
+
- "Pin explicit runner OS versions (macos-14, macos-15) instead of macos-latest for stable CI builds"
|
|
77
|
+
- "Never hardcode SDK version strings (macosx14.x) in Xcode project .xcconfig files — use $(SDKROOT)"
|
|
78
|
+
- "Use ruby/setup-ruby, actions/setup-python, and similar version-pinning actions for all language runtimes"
|
|
79
|
+
- "Subscribe to GitHub Changelog and runner-images repository releases for macOS image update notices"
|
|
80
|
+
docs:
|
|
81
|
+
- url: https://github.blog/changelog/2025-01-16-github-actions-macos-15-is-now-the-latest-macos-runner-image/
|
|
82
|
+
label: "GitHub Changelog: macOS 15 becomes macos-latest (Jan 2025)"
|
|
83
|
+
- url: https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners
|
|
84
|
+
label: "GitHub-hosted runner images documentation"
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
id: runner-environment-092
|
|
2
|
+
title: "Multi-platform Docker Build Fails — Missing QEMU Setup for Cross-Architecture"
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- docker
|
|
7
|
+
- multi-platform
|
|
8
|
+
- qemu
|
|
9
|
+
- buildx
|
|
10
|
+
- arm64
|
|
11
|
+
- cross-arch
|
|
12
|
+
patterns:
|
|
13
|
+
- regex: 'failed to solve: no match for platform in manifest'
|
|
14
|
+
flags: "i"
|
|
15
|
+
- regex: 'no match for platform in manifest: linux/(arm64|arm/v[67]|riscv64|ppc64le|s390x)'
|
|
16
|
+
flags: "i"
|
|
17
|
+
- regex: 'exec format error'
|
|
18
|
+
flags: "i"
|
|
19
|
+
error_messages:
|
|
20
|
+
- "ERROR: failed to solve: no match for platform in manifest: linux/arm64"
|
|
21
|
+
- "failed to solve: no match for platform in manifest: linux/arm64"
|
|
22
|
+
- "exec format error"
|
|
23
|
+
- "cannot execute binary file: Exec format error"
|
|
24
|
+
root_cause: |
|
|
25
|
+
GitHub-hosted runners (ubuntu-*, macos-*, windows-*) are single-architecture machines.
|
|
26
|
+
When docker/build-push-action is configured with platforms: linux/amd64,linux/arm64 (or
|
|
27
|
+
any other non-native architecture), Docker BuildKit needs QEMU user-mode emulation to
|
|
28
|
+
execute non-native binaries during the build. Without docker/setup-qemu-action registered
|
|
29
|
+
first, BuildKit cannot emulate the target architecture and immediately fails with "no match
|
|
30
|
+
for platform in manifest" or exec format errors when a RUN instruction in the Dockerfile
|
|
31
|
+
executes a binary compiled for the wrong architecture.
|
|
32
|
+
|
|
33
|
+
This is a common mistake when adding multi-arch support to an existing single-arch workflow.
|
|
34
|
+
The amd64 platform succeeds while arm64 fails, producing confusing partial-success output.
|
|
35
|
+
Self-hosted ARM64 runners (e.g. macos-14/15, ubuntu ARM) can build their native arch without
|
|
36
|
+
QEMU but still need it for other non-native targets.
|
|
37
|
+
fix: |
|
|
38
|
+
Add docker/setup-qemu-action before docker/setup-buildx-action in your workflow steps.
|
|
39
|
+
QEMU must be installed before buildx initializes so BuildKit discovers the emulators at
|
|
40
|
+
setup time. Order matters — QEMU before buildx, buildx before build-push-action.
|
|
41
|
+
fix_code:
|
|
42
|
+
- language: yaml
|
|
43
|
+
label: "WRONG — buildx without QEMU (arm64 fails)"
|
|
44
|
+
code: |
|
|
45
|
+
- name: Set up Docker Buildx
|
|
46
|
+
uses: docker/setup-buildx-action@v3
|
|
47
|
+
|
|
48
|
+
- name: Build and push
|
|
49
|
+
uses: docker/build-push-action@v6
|
|
50
|
+
with:
|
|
51
|
+
platforms: linux/amd64,linux/arm64 # arm64 fails without QEMU
|
|
52
|
+
push: true
|
|
53
|
+
tags: myimage:latest
|
|
54
|
+
- language: yaml
|
|
55
|
+
label: "RIGHT — QEMU registered before buildx"
|
|
56
|
+
code: |
|
|
57
|
+
- name: Set up QEMU
|
|
58
|
+
uses: docker/setup-qemu-action@v3
|
|
59
|
+
|
|
60
|
+
- name: Set up Docker Buildx
|
|
61
|
+
uses: docker/setup-buildx-action@v3
|
|
62
|
+
|
|
63
|
+
- name: Build and push
|
|
64
|
+
uses: docker/build-push-action@v6
|
|
65
|
+
with:
|
|
66
|
+
platforms: linux/amd64,linux/arm64
|
|
67
|
+
push: true
|
|
68
|
+
tags: myimage:latest
|
|
69
|
+
cache-from: type=gha
|
|
70
|
+
cache-to: type=gha,mode=max
|
|
71
|
+
prevention:
|
|
72
|
+
- "Always add docker/setup-qemu-action before docker/setup-buildx-action when targeting non-native platforms."
|
|
73
|
+
- "Verify QEMU platform list covers your targets: linux/arm64, linux/arm/v7, linux/arm/v6, linux/riscv64, linux/ppc64le, linux/s390x."
|
|
74
|
+
- "Use a platform matrix to build and test each architecture independently for faster CI feedback loops."
|
|
75
|
+
- "Check runner architecture with 'uname -m' in a run step when debugging platform mismatches."
|
|
76
|
+
docs:
|
|
77
|
+
- url: "https://github.com/docker/setup-qemu-action"
|
|
78
|
+
label: "docker/setup-qemu-action — GitHub Action"
|
|
79
|
+
- url: "https://docs.docker.com/build/building/multi-platform/"
|
|
80
|
+
label: "Docker — Multi-platform builds"
|
|
81
|
+
- url: "https://github.com/docker/build-push-action/blob/master/docs/advanced/multi-platform.md"
|
|
82
|
+
label: "docker/build-push-action — Multi-platform builds guide"
|
|
83
|
+
- url: "https://stackoverflow.com/questions/69984898/github-action-multi-arch-docker-build-failed-to-solve-no-match-for-platform-in"
|
|
84
|
+
label: "Stack Overflow — Multi-arch Docker build: no match for platform in manifest (400+ votes)"
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
id: runner-environment-094
|
|
2
|
+
title: Node.js 16 Actions Runtime Deprecated and Disabled — Actions Using node16 Fail
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- node16
|
|
7
|
+
- node20
|
|
8
|
+
- action-runtime
|
|
9
|
+
- deprecation
|
|
10
|
+
- runs-using
|
|
11
|
+
patterns:
|
|
12
|
+
- regex: 'Node\.js 16 actions are deprecated'
|
|
13
|
+
flags: i
|
|
14
|
+
- regex: 'Please update the following actions to use Node\.js 20'
|
|
15
|
+
flags: i
|
|
16
|
+
- regex: 'uses a deprecated version of `actions/node`'
|
|
17
|
+
flags: i
|
|
18
|
+
error_messages:
|
|
19
|
+
- "Node.js 16 actions are deprecated. Please update the following actions to use Node.js 20: actions/checkout@v3"
|
|
20
|
+
- "Warning: Node.js 16 is End-of-Life. Upgrade to Node.js 20 or later."
|
|
21
|
+
- "Error: This request has been automatically failed because it uses a deprecated version of `actions/node`"
|
|
22
|
+
root_cause: |
|
|
23
|
+
Node.js 16 reached end-of-life on September 11, 2023. GitHub announced on
|
|
24
|
+
September 22, 2023 (GitHub Changelog) that it would deprecate the Node.js 16
|
|
25
|
+
runtime for GitHub Actions, with a hard enforcement cutoff on September 22, 2024.
|
|
26
|
+
|
|
27
|
+
Actions authored with `runs.using: node16` in their action.yml emit deprecation
|
|
28
|
+
warnings from late 2023 onward. From September 2024, these actions produce hard
|
|
29
|
+
errors and may not execute. Third-party actions pinned to older major versions
|
|
30
|
+
that internally use node16 are affected, including actions/checkout@v3,
|
|
31
|
+
actions/setup-node@v3, actions/cache@v3, and many community actions. Composite
|
|
32
|
+
actions that transitively call a node16-based action also fail.
|
|
33
|
+
fix: |
|
|
34
|
+
Update all action references in your workflows to major versions that use the
|
|
35
|
+
node20 (or node22) runtime. Common upgrades needed:
|
|
36
|
+
- actions/checkout@v3 → @v4
|
|
37
|
+
- actions/setup-node@v3 → @v4
|
|
38
|
+
- actions/cache@v3 → @v4
|
|
39
|
+
- actions/upload-artifact@v3 → @v4
|
|
40
|
+
- actions/download-artifact@v3 → @v4
|
|
41
|
+
|
|
42
|
+
For custom actions you own, update `runs.using` in action.yml from
|
|
43
|
+
`node16` to `node20`.
|
|
44
|
+
|
|
45
|
+
Use Dependabot or Renovate with the `github-actions` package ecosystem to
|
|
46
|
+
keep action versions current automatically.
|
|
47
|
+
fix_code:
|
|
48
|
+
- language: yaml
|
|
49
|
+
label: Update official actions from node16 to node20-based versions
|
|
50
|
+
code: |
|
|
51
|
+
- uses: actions/checkout@v4 # was @v3 (node16)
|
|
52
|
+
- uses: actions/setup-node@v4 # was @v3 (node16)
|
|
53
|
+
with:
|
|
54
|
+
node-version: '20'
|
|
55
|
+
- uses: actions/cache@v4 # was @v3 (node16)
|
|
56
|
+
with:
|
|
57
|
+
path: ~/.npm
|
|
58
|
+
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
|
|
59
|
+
|
|
60
|
+
- language: yaml
|
|
61
|
+
label: Update custom action.yml to node20 runtime
|
|
62
|
+
code: |
|
|
63
|
+
# In your action's action.yml
|
|
64
|
+
runs:
|
|
65
|
+
using: node20
|
|
66
|
+
main: dist/index.js
|
|
67
|
+
|
|
68
|
+
- language: yaml
|
|
69
|
+
label: Enable Dependabot for github-actions ecosystem
|
|
70
|
+
code: |
|
|
71
|
+
# .github/dependabot.yml
|
|
72
|
+
version: 2
|
|
73
|
+
updates:
|
|
74
|
+
- package-ecosystem: github-actions
|
|
75
|
+
directory: /
|
|
76
|
+
schedule:
|
|
77
|
+
interval: weekly
|
|
78
|
+
prevention:
|
|
79
|
+
- "Enable Dependabot for the github-actions package ecosystem to receive automatic PRs for action version updates"
|
|
80
|
+
- "Audit all action.yml files in custom actions for runs.using: node16 before the hard cutoff"
|
|
81
|
+
- "Watch the actions/* repositories on GitHub for major version releases that upgrade the runtime"
|
|
82
|
+
- "Prefer Dependabot or Renovate over manually pinned major versions to stay ahead of deprecations"
|
|
83
|
+
docs:
|
|
84
|
+
- url: https://github.blog/changelog/2023-09-22-github-actions-transitioning-from-node-16-to-node-20/
|
|
85
|
+
label: "GitHub Changelog: Transitioning from Node.js 16 to Node.js 20 (Sep 2023)"
|
|
86
|
+
- url: https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions#runs-for-javascript-actions
|
|
87
|
+
label: "Actions metadata syntax: runs.using"
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
id: runner-environment-093
|
|
2
|
+
title: ubuntu-latest Now Points to Ubuntu 24.04 — Python 2 and Legacy Packages Removed
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- ubuntu-latest
|
|
7
|
+
- ubuntu-24-04
|
|
8
|
+
- python2
|
|
9
|
+
- apt-get
|
|
10
|
+
- runner-migration
|
|
11
|
+
patterns:
|
|
12
|
+
- regex: 'E: Package ''python'' has no installation candidate'
|
|
13
|
+
flags: i
|
|
14
|
+
- regex: 'python: command not found'
|
|
15
|
+
flags: i
|
|
16
|
+
- regex: 'Unable to locate package python2'
|
|
17
|
+
flags: i
|
|
18
|
+
- regex: 'E: Package ''libssl1\.1'' has no installation candidate'
|
|
19
|
+
flags: i
|
|
20
|
+
error_messages:
|
|
21
|
+
- "E: Package 'python' has no installation candidate"
|
|
22
|
+
- "python: command not found"
|
|
23
|
+
- "Unable to locate package python2"
|
|
24
|
+
- "E: Package 'libssl1.1' has no installation candidate"
|
|
25
|
+
root_cause: |
|
|
26
|
+
GitHub changed ubuntu-latest to point to Ubuntu 24.04 on November 7, 2024
|
|
27
|
+
(announced via GitHub Changelog on September 25, 2024). Ubuntu 24.04 (Noble
|
|
28
|
+
Numbat) removes several packages that were present on Ubuntu 20.04 and 22.04:
|
|
29
|
+
|
|
30
|
+
- The `python` package (Python 2.7) is entirely absent; only `python3` is available
|
|
31
|
+
- `python2` and `python-is-python2` are not installable via apt
|
|
32
|
+
- `libssl1.1` (OpenSSL 1.1.x) is removed; only OpenSSL 3.x ships with 24.04
|
|
33
|
+
- Various other legacy apt packages dropped in the 24.04 LTS release
|
|
34
|
+
|
|
35
|
+
Workflows that ran `sudo apt-get install python`, invoked `python script.py`
|
|
36
|
+
(instead of `python3`), or installed packages transitively depending on
|
|
37
|
+
libssl1.1 started failing immediately after the image switch.
|
|
38
|
+
fix: |
|
|
39
|
+
Option 1: Replace all `python` calls with `python3` and use `actions/setup-python`
|
|
40
|
+
to install a specific Python 3 version rather than relying on the system default.
|
|
41
|
+
|
|
42
|
+
Option 2: Pin the runner to `ubuntu-22.04` explicitly if Python 2 is genuinely
|
|
43
|
+
required or if you need time to migrate. Note that ubuntu-22.04 will eventually
|
|
44
|
+
be retired from the GitHub-hosted runner fleet.
|
|
45
|
+
|
|
46
|
+
Audit all `apt-get install` steps for packages removed in Ubuntu 24.04, including
|
|
47
|
+
libssl1.1, python2, python-is-python2, libffi7, and others listed in the Ubuntu
|
|
48
|
+
24.04 release notes.
|
|
49
|
+
fix_code:
|
|
50
|
+
- language: yaml
|
|
51
|
+
label: Use actions/setup-python and replace python with python3
|
|
52
|
+
code: |
|
|
53
|
+
- uses: actions/setup-python@v5
|
|
54
|
+
with:
|
|
55
|
+
python-version: '3.12'
|
|
56
|
+
|
|
57
|
+
- name: Run script
|
|
58
|
+
run: python3 script.py
|
|
59
|
+
|
|
60
|
+
- language: yaml
|
|
61
|
+
label: Pin explicit runner version to avoid ubuntu-latest drift
|
|
62
|
+
code: |
|
|
63
|
+
jobs:
|
|
64
|
+
build:
|
|
65
|
+
runs-on: ubuntu-22.04 # explicit version; do not rely on ubuntu-latest
|
|
66
|
+
prevention:
|
|
67
|
+
- "Pin explicit runner versions (ubuntu-22.04, ubuntu-24.04) instead of ubuntu-latest to prevent surprise image changes"
|
|
68
|
+
- "Use actions/setup-python for all Python installs rather than apt-get"
|
|
69
|
+
- "Replace python with python3 in all shell commands and scripts"
|
|
70
|
+
- "Subscribe to GitHub Changelog for runner image update announcements before they take effect"
|
|
71
|
+
docs:
|
|
72
|
+
- url: https://github.blog/changelog/2024-09-25-actions-new-images-and-ubuntu-latest-changes/
|
|
73
|
+
label: "GitHub Changelog: ubuntu-latest points to Ubuntu 24.04 (Sep 2024)"
|
|
74
|
+
- url: https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners
|
|
75
|
+
label: "GitHub-hosted runner images documentation"
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
id: silent-failures-042
|
|
2
|
+
title: Fork pull_request Secrets Are Empty Strings — Secret-Gated Steps Silently Skip
|
|
3
|
+
category: silent-failures
|
|
4
|
+
severity: silent-failure
|
|
5
|
+
tags:
|
|
6
|
+
- fork
|
|
7
|
+
- pull-request
|
|
8
|
+
- secrets
|
|
9
|
+
- empty-string
|
|
10
|
+
- conditional-step
|
|
11
|
+
patterns:
|
|
12
|
+
- regex: 'secrets\.[A-Z_]+ != ''''.*if.*condition'
|
|
13
|
+
flags: i
|
|
14
|
+
- regex: 'npm ERR! code E401'
|
|
15
|
+
flags: ''
|
|
16
|
+
- regex: 'Error: HttpError: Resource not accessible by integration'
|
|
17
|
+
flags: i
|
|
18
|
+
error_messages:
|
|
19
|
+
- "npm ERR! code E401"
|
|
20
|
+
- "Error: HttpError: Resource not accessible by integration"
|
|
21
|
+
- "(No log output — the step shows 'skipped' status when secrets.MY_TOKEN != '' evaluates false on fork PRs)"
|
|
22
|
+
root_cause: |
|
|
23
|
+
When a pull_request event is triggered from a fork, GitHub Actions intentionally
|
|
24
|
+
provides empty strings ("") for all secrets in the `secrets` context — not null,
|
|
25
|
+
but empty string. This is a security measure to prevent secret exfiltration from
|
|
26
|
+
untrusted fork code running in the base repository's context.
|
|
27
|
+
|
|
28
|
+
The silent-failure pattern occurs when a workflow guards a step with a secrets
|
|
29
|
+
check:
|
|
30
|
+
|
|
31
|
+
- if: ${{ secrets.NPM_TOKEN != '' }}
|
|
32
|
+
run: npm publish
|
|
33
|
+
|
|
34
|
+
On fork PRs, `secrets.NPM_TOKEN` is `""`, so the condition evaluates to `false`
|
|
35
|
+
and the step is silently skipped with no error, no warning, and no indication
|
|
36
|
+
in normal logs. Developers expecting either a published artifact or a clear
|
|
37
|
+
failure instead see a green workflow with a quietly skipped deploy step.
|
|
38
|
+
|
|
39
|
+
A related failure mode: when the empty secret IS used directly (without a guard),
|
|
40
|
+
the downstream tool emits a generic auth error (E401, 403) that gives no indication
|
|
41
|
+
the root cause is an empty secret from a fork trigger.
|
|
42
|
+
fix: |
|
|
43
|
+
Separate concerns: run untrusted fork code in a `pull_request` workflow (no
|
|
44
|
+
secrets needed), then gate secret-requiring operations on a `workflow_run`
|
|
45
|
+
workflow that triggers after the pull_request workflow completes. The
|
|
46
|
+
workflow_run event runs in the base branch context and has full access to
|
|
47
|
+
repository secrets.
|
|
48
|
+
|
|
49
|
+
If you must use secrets in a `pull_request` workflow (e.g., to post PR comments
|
|
50
|
+
via GITHUB_TOKEN), rely on the automatically-provided GITHUB_TOKEN with
|
|
51
|
+
appropriate `permissions:` — do not depend on user-defined secrets in
|
|
52
|
+
pull_request context from forks.
|
|
53
|
+
|
|
54
|
+
Avoid the `if: ${{ secrets.MY_SECRET != '' }}` guard pattern entirely;
|
|
55
|
+
document the fork limitation explicitly in the workflow file instead.
|
|
56
|
+
fix_code:
|
|
57
|
+
- language: yaml
|
|
58
|
+
label: "Split pattern: pull_request for tests (no secrets), workflow_run for deploys"
|
|
59
|
+
code: |
|
|
60
|
+
# pr-tests.yml — runs untrusted fork code, no secrets needed
|
|
61
|
+
on: pull_request
|
|
62
|
+
jobs:
|
|
63
|
+
test:
|
|
64
|
+
runs-on: ubuntu-latest
|
|
65
|
+
steps:
|
|
66
|
+
- uses: actions/checkout@v4
|
|
67
|
+
- run: npm ci && npm test
|
|
68
|
+
|
|
69
|
+
- language: yaml
|
|
70
|
+
label: workflow_run continuation with secrets (runs in base branch context)
|
|
71
|
+
code: |
|
|
72
|
+
# pr-deploy.yml — triggers after pr-tests completes; has full secret access
|
|
73
|
+
on:
|
|
74
|
+
workflow_run:
|
|
75
|
+
workflows: [PR Tests]
|
|
76
|
+
types: [completed]
|
|
77
|
+
jobs:
|
|
78
|
+
publish:
|
|
79
|
+
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
|
80
|
+
runs-on: ubuntu-latest
|
|
81
|
+
steps:
|
|
82
|
+
- uses: actions/checkout@v4
|
|
83
|
+
- run: npm publish
|
|
84
|
+
env:
|
|
85
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
86
|
+
prevention:
|
|
87
|
+
- "Never write if: ${{ secrets.MY_SECRET != '' }} as a fork guard — this silently evaluates false on all fork PRs"
|
|
88
|
+
- "Use the pull_request + workflow_run split pattern for any workflow needing both fork code and repository secrets"
|
|
89
|
+
- "Add a comment in your workflow file explaining that secret-gated steps intentionally skip on fork PRs"
|
|
90
|
+
- "Use GITHUB_TOKEN with explicit permissions: blocks for operations that only require base repository access"
|
|
91
|
+
docs:
|
|
92
|
+
- url: https://docs.github.com/en/actions/security-for-github-actions/security-guides/security-hardening-for-github-actions#using-secrets
|
|
93
|
+
label: "GitHub Docs: Security hardening for GitHub Actions — using secrets"
|
|
94
|
+
- url: https://securitylab.github.com/resources/github-actions-preventing-pwn-requests/
|
|
95
|
+
label: "GitHub Security Lab: Preventing pwn requests (pull_request_target risks)"
|
|
96
|
+
- url: https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#workflow_run
|
|
97
|
+
label: "GitHub Docs: workflow_run event"
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
id: silent-failures-041
|
|
2
|
+
title: "`github.sha` Is the Merge Commit on Pull Request Events — Commit Status Invisible"
|
|
3
|
+
category: silent-failures
|
|
4
|
+
severity: silent-failure
|
|
5
|
+
tags:
|
|
6
|
+
- github.sha
|
|
7
|
+
- pull_request
|
|
8
|
+
- commit-status
|
|
9
|
+
- merge-commit
|
|
10
|
+
- sha
|
|
11
|
+
- statuses
|
|
12
|
+
patterns:
|
|
13
|
+
- regex: 'github\.sha'
|
|
14
|
+
flags: "i"
|
|
15
|
+
- regex: 'pull_request\.head\.sha'
|
|
16
|
+
flags: "i"
|
|
17
|
+
error_messages:
|
|
18
|
+
- "No error — commit status silently attached to ephemeral merge commit not visible in PR timeline"
|
|
19
|
+
- "No pending/passing status appears on the PR despite successful workflow run"
|
|
20
|
+
root_cause: |
|
|
21
|
+
On pull_request and pull_request_target events, github.sha is set to the SHA of a temporary
|
|
22
|
+
merge commit GitHub creates to test mergeability (refs/pull/<n>/merge), NOT the actual head
|
|
23
|
+
commit of the feature branch (refs/pull/<n>/head). This merge commit is ephemeral and is
|
|
24
|
+
never directly visible in the PR timeline or commit history.
|
|
25
|
+
|
|
26
|
+
Developers who pass github.sha to the GitHub Commit Status API (POST
|
|
27
|
+
/repos/{owner}/{repo}/statuses/{sha}), build provenance attestation tools, cosign, or other
|
|
28
|
+
tooling expecting the PR head commit get a silent mismatch: the API call succeeds with HTTP
|
|
29
|
+
201, the status is written, but it targets a commit no reviewer can see. The PR status checks
|
|
30
|
+
panel remains empty or stale, required checks are never satisfied, and the PR cannot be merged
|
|
31
|
+
even though the workflow ran successfully.
|
|
32
|
+
|
|
33
|
+
This is distinct from the checkout/ref problem where the wrong code is built — here the build
|
|
34
|
+
is correct but status reporting is silently targeting the wrong commit.
|
|
35
|
+
fix: |
|
|
36
|
+
Use github.event.pull_request.head.sha instead of github.sha when targeting the PR head
|
|
37
|
+
commit for status APIs or attestation. For non-PR events (push, workflow_dispatch,
|
|
38
|
+
schedule), github.sha is correct. Use a combined expression for reusable workflows that
|
|
39
|
+
run on both event types.
|
|
40
|
+
fix_code:
|
|
41
|
+
- language: yaml
|
|
42
|
+
label: "WRONG — status set on merge commit (never shows on PR)"
|
|
43
|
+
code: |
|
|
44
|
+
- name: Set commit status
|
|
45
|
+
uses: actions/github-script@v7
|
|
46
|
+
with:
|
|
47
|
+
script: |
|
|
48
|
+
await github.rest.repos.createCommitStatus({
|
|
49
|
+
owner: context.repo.owner,
|
|
50
|
+
repo: context.repo.repo,
|
|
51
|
+
sha: context.sha, // merge commit SHA on pull_request events
|
|
52
|
+
state: 'success',
|
|
53
|
+
context: 'my-check',
|
|
54
|
+
});
|
|
55
|
+
- language: yaml
|
|
56
|
+
label: "RIGHT — use PR head SHA for pull_request events"
|
|
57
|
+
code: |
|
|
58
|
+
- name: Set commit status
|
|
59
|
+
uses: actions/github-script@v7
|
|
60
|
+
with:
|
|
61
|
+
script: |
|
|
62
|
+
const sha = context.eventName === 'pull_request'
|
|
63
|
+
? context.payload.pull_request.head.sha // actual PR head commit
|
|
64
|
+
: context.sha;
|
|
65
|
+
await github.rest.repos.createCommitStatus({
|
|
66
|
+
owner: context.repo.owner,
|
|
67
|
+
repo: context.repo.repo,
|
|
68
|
+
sha,
|
|
69
|
+
state: 'success',
|
|
70
|
+
context: 'my-check',
|
|
71
|
+
});
|
|
72
|
+
- language: yaml
|
|
73
|
+
label: "RIGHT — pass head SHA via env for run steps"
|
|
74
|
+
code: |
|
|
75
|
+
- name: Attest or sign artifact
|
|
76
|
+
env:
|
|
77
|
+
COMMIT_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
|
|
78
|
+
run: |
|
|
79
|
+
cosign sign-blob --bundle bundle.json artifact.tar.gz
|
|
80
|
+
# $COMMIT_SHA is the visible PR head SHA on pull_request events,
|
|
81
|
+
# falls back to github.sha for push/schedule/workflow_dispatch
|
|
82
|
+
prevention:
|
|
83
|
+
- "Never use github.sha directly for Commit Status API calls in pull_request workflows — always use github.event.pull_request.head.sha."
|
|
84
|
+
- "For workflows triggered by both push and pull_request, use the safe fallback expression: ${{ github.event.pull_request.head.sha || github.sha }}."
|
|
85
|
+
- "After adding required status checks, verify they actually appear in the PR timeline — a missing check often means the wrong SHA is being targeted."
|
|
86
|
+
- "Run 'echo ${{ github.sha }} ${{ github.event.pull_request.head.sha }}' in a debug step to confirm the SHAs differ on a PR event."
|
|
87
|
+
docs:
|
|
88
|
+
- url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/accessing-contextual-information-about-workflow-runs#github-context"
|
|
89
|
+
label: "GitHub context — github.sha documentation"
|
|
90
|
+
- url: "https://docs.github.com/en/rest/commits/statuses"
|
|
91
|
+
label: "GitHub REST API — Commit statuses"
|
|
92
|
+
- url: "https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#pull_request"
|
|
93
|
+
label: "Events that trigger workflows — pull_request event and merge commit"
|
|
94
|
+
- url: "https://stackoverflow.com/questions/71264370/why-is-github-sha-not-pointing-to-the-pr-head-commit-on-pull-request-events"
|
|
95
|
+
label: "Stack Overflow — Why is github.sha not the PR head commit on pull_request events?"
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
id: triggers-030
|
|
2
|
+
title: "`pull_request` Default Activity Types Exclude `labeled` and `unlabeled` — Label-Gated Workflows Never Fire"
|
|
3
|
+
category: triggers
|
|
4
|
+
severity: silent-failure
|
|
5
|
+
tags:
|
|
6
|
+
- pull_request
|
|
7
|
+
- labeled
|
|
8
|
+
- unlabeled
|
|
9
|
+
- activity-types
|
|
10
|
+
- types
|
|
11
|
+
- label-gate
|
|
12
|
+
patterns:
|
|
13
|
+
- regex: 'on:\s*\n\s*pull_request:\s*\n(?!\s*types:)'
|
|
14
|
+
flags: "im"
|
|
15
|
+
- regex: 'types:\s*\[?\s*labeled'
|
|
16
|
+
flags: "i"
|
|
17
|
+
error_messages:
|
|
18
|
+
- "No error — workflow simply never runs when a label is added to or removed from a PR"
|
|
19
|
+
root_cause: |
|
|
20
|
+
The pull_request event triggers on three activity types by default: opened, synchronize,
|
|
21
|
+
and reopened. The labeled and unlabeled activity types — which fire when a label is added
|
|
22
|
+
or removed from a pull request — are NOT in the default set. Any workflow that relies on
|
|
23
|
+
label additions to trigger CI (deploy-preview gates, security scan exclusions, manual
|
|
24
|
+
override flags, environment promotion labels) will silently never run.
|
|
25
|
+
|
|
26
|
+
This affects common workflows such as:
|
|
27
|
+
- "preview" label triggers a staging deployment
|
|
28
|
+
- "approved-for-staging" label kicks off an integration test suite
|
|
29
|
+
- "skip-e2e" label skips expensive test steps
|
|
30
|
+
- "force-rebuild" label retriggers a build without a new commit
|
|
31
|
+
|
|
32
|
+
Because there is no workflow run at all (no skipped run, no failed run, no log entry),
|
|
33
|
+
the failure is completely invisible. Developers typically spend significant time debugging
|
|
34
|
+
the conditional logic inside the workflow before discovering the trigger itself never fired.
|
|
35
|
+
The workflow only runs if the PR is also opened, synchronized, or reopened coincidentally
|
|
36
|
+
with the label operation.
|
|
37
|
+
fix: |
|
|
38
|
+
Explicitly declare all required activity types in the pull_request trigger using the
|
|
39
|
+
types: key. Include labeled (and unlabeled if removals also matter) alongside the
|
|
40
|
+
standard types if the workflow should run for both code changes and label changes.
|
|
41
|
+
fix_code:
|
|
42
|
+
- language: yaml
|
|
43
|
+
label: "WRONG — pull_request without types never fires on label add"
|
|
44
|
+
code: |
|
|
45
|
+
on:
|
|
46
|
+
pull_request: # defaults: opened, synchronize, reopened only
|
|
47
|
+
branches: [main]
|
|
48
|
+
|
|
49
|
+
jobs:
|
|
50
|
+
preview:
|
|
51
|
+
if: contains(github.event.pull_request.labels.*.name, 'preview')
|
|
52
|
+
runs-on: ubuntu-latest
|
|
53
|
+
steps:
|
|
54
|
+
- run: echo "Deploying preview..." # never reached from label addition
|
|
55
|
+
- language: yaml
|
|
56
|
+
label: "RIGHT — explicitly include labeled in types"
|
|
57
|
+
code: |
|
|
58
|
+
on:
|
|
59
|
+
pull_request:
|
|
60
|
+
branches: [main]
|
|
61
|
+
types:
|
|
62
|
+
- opened
|
|
63
|
+
- synchronize
|
|
64
|
+
- reopened
|
|
65
|
+
- labeled # fires when a label is added
|
|
66
|
+
- unlabeled # fires when a label is removed
|
|
67
|
+
|
|
68
|
+
jobs:
|
|
69
|
+
preview:
|
|
70
|
+
if: contains(github.event.pull_request.labels.*.name, 'preview')
|
|
71
|
+
runs-on: ubuntu-latest
|
|
72
|
+
steps:
|
|
73
|
+
- run: echo "Deploying preview..."
|
|
74
|
+
- language: yaml
|
|
75
|
+
label: "RIGHT — label-only workflow (fires only on label events)"
|
|
76
|
+
code: |
|
|
77
|
+
on:
|
|
78
|
+
pull_request:
|
|
79
|
+
types: [labeled, unlabeled]
|
|
80
|
+
|
|
81
|
+
jobs:
|
|
82
|
+
handle-label:
|
|
83
|
+
if: github.event.label.name == 'deploy-preview'
|
|
84
|
+
runs-on: ubuntu-latest
|
|
85
|
+
steps:
|
|
86
|
+
- run: echo "Label '${{ github.event.label.name }}' added/removed"
|
|
87
|
+
prevention:
|
|
88
|
+
- "Always explicitly declare types: when workflow logic depends on specific PR activity — labels, reviews, drafts, assignments, or milestones."
|
|
89
|
+
- "The default pull_request types are ONLY opened, synchronize, and reopened — all other activity types must be opt-in."
|
|
90
|
+
- "Test label-triggered workflows by adding the label manually after the workflow file is merged to the default branch."
|
|
91
|
+
- "Use github.event.action in run steps to distinguish between labeled and unlabeled events when both types are declared."
|
|
92
|
+
docs:
|
|
93
|
+
- url: "https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#pull_request"
|
|
94
|
+
label: "Events that trigger workflows — pull_request activity types"
|
|
95
|
+
- url: "https://docs.github.com/en/webhooks/webhook-events-and-payloads#pull_request"
|
|
96
|
+
label: "Webhook events — pull_request payload (full activity type list)"
|
|
97
|
+
- url: "https://stackoverflow.com/questions/63699767/github-actions-on-pull-request-labeled-trigger-not-working"
|
|
98
|
+
label: "Stack Overflow — GitHub Actions on: pull_request labeled trigger not working"
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
id: yaml-syntax-033
|
|
2
|
+
title: "`save-always` Input Does Not Exist in `actions/cache` v3 — Unexpected Input Error"
|
|
3
|
+
category: yaml-syntax
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- actions/cache
|
|
7
|
+
- save-always
|
|
8
|
+
- v3
|
|
9
|
+
- v4
|
|
10
|
+
- unexpected-input
|
|
11
|
+
- version-mismatch
|
|
12
|
+
patterns:
|
|
13
|
+
- regex: "Unexpected input\\(s\\) 'save-always'"
|
|
14
|
+
flags: "i"
|
|
15
|
+
- regex: "Unexpected input.*save-always.*valid inputs are"
|
|
16
|
+
flags: "i"
|
|
17
|
+
error_messages:
|
|
18
|
+
- "Unexpected input(s) 'save-always', valid inputs are ['path', 'key', 'restore-keys', 'upload-chunk-size', 'enableCrossOsArchive', 'fail-on-cache-miss', 'lookup-only']"
|
|
19
|
+
- "Warning: Unexpected input(s) 'save-always'"
|
|
20
|
+
root_cause: |
|
|
21
|
+
The save-always input was introduced in actions/cache v4.0.0 to allow the internal
|
|
22
|
+
post-step cache save to run even when the job fails or is cancelled, bypassing the
|
|
23
|
+
hardcoded post-if: success() guard present in v3. In v3, saving on failure required
|
|
24
|
+
explicitly splitting the monolithic cache step into separate actions/cache/restore and
|
|
25
|
+
actions/cache/save steps with if: always().
|
|
26
|
+
|
|
27
|
+
Developers who copy examples from v4 documentation or Stack Overflow answers written
|
|
28
|
+
after December 2023 and apply them to a workflow still pinned to actions/cache@v3
|
|
29
|
+
receive an "Unexpected input(s) 'save-always'" warning or error. In v3 the input is
|
|
30
|
+
silently ignored in some versions and causes a non-zero exit in others. Either way,
|
|
31
|
+
the intent (save cache on failure) is never fulfilled.
|
|
32
|
+
fix: |
|
|
33
|
+
Upgrade to actions/cache@v4 (or v4+) to use save-always: true directly. If upgrading
|
|
34
|
+
is not possible, replace the single cache step with explicit restore + save steps and
|
|
35
|
+
guard the save step with if: always().
|
|
36
|
+
fix_code:
|
|
37
|
+
- language: yaml
|
|
38
|
+
label: "WRONG — save-always on cache@v3 (input does not exist)"
|
|
39
|
+
code: |
|
|
40
|
+
- uses: actions/cache@v3
|
|
41
|
+
with:
|
|
42
|
+
path: ~/.npm
|
|
43
|
+
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
|
|
44
|
+
save-always: true # does not exist in v3 — unexpected input error
|
|
45
|
+
- language: yaml
|
|
46
|
+
label: "RIGHT — upgrade to cache@v4 to use save-always"
|
|
47
|
+
code: |
|
|
48
|
+
- uses: actions/cache@v4
|
|
49
|
+
with:
|
|
50
|
+
path: ~/.npm
|
|
51
|
+
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
|
|
52
|
+
save-always: true # introduced in v4.0.0
|
|
53
|
+
- language: yaml
|
|
54
|
+
label: "RIGHT — v3 workaround with explicit restore and save steps"
|
|
55
|
+
code: |
|
|
56
|
+
- name: Restore cache
|
|
57
|
+
id: cache-restore
|
|
58
|
+
uses: actions/cache/restore@v3
|
|
59
|
+
with:
|
|
60
|
+
path: ~/.npm
|
|
61
|
+
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
|
|
62
|
+
|
|
63
|
+
- name: Install dependencies
|
|
64
|
+
run: npm ci
|
|
65
|
+
|
|
66
|
+
- name: Save cache
|
|
67
|
+
if: always()
|
|
68
|
+
uses: actions/cache/save@v3
|
|
69
|
+
with:
|
|
70
|
+
path: ~/.npm
|
|
71
|
+
key: ${{ steps.cache-restore.outputs.cache-primary-key }}
|
|
72
|
+
prevention:
|
|
73
|
+
- "Pin all new workflows to actions/cache@v4 — v3 is missing save-always, restore-first-match-in-branch, and other v4 inputs."
|
|
74
|
+
- "When copying cache examples from documentation, check the version badge — inputs differ significantly between v3 and v4."
|
|
75
|
+
- "Enable Dependabot or Renovate for action version updates to avoid accumulating version-mismatch debt."
|
|
76
|
+
- "If still on v3, use the split restore/save pattern with if: always() for any workflow that must cache on failure."
|
|
77
|
+
docs:
|
|
78
|
+
- url: "https://github.com/actions/cache/releases/tag/v4.0.0"
|
|
79
|
+
label: "actions/cache v4.0.0 release notes — save-always introduced"
|
|
80
|
+
- url: "https://github.com/actions/cache/blob/main/tips-and-workarounds.md#saving-cache-even-if-the-build-fails"
|
|
81
|
+
label: "actions/cache — Saving cache even if the build fails"
|
|
82
|
+
- url: "https://github.com/actions/cache/blob/main/save/README.md"
|
|
83
|
+
label: "actions/cache/save — Explicit save action"
|
|
84
|
+
- url: "https://stackoverflow.com/questions/60491837/saving-cache-on-job-failure-in-github-actions"
|
|
85
|
+
label: "Stack Overflow — Saving cache on job failure in GitHub Actions (200+ votes)"
|
package/package.json
CHANGED