@htekdev/actions-debugger 1.0.87 → 1.0.89

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.
@@ -0,0 +1,94 @@
1
+ id: known-unsolved-051
2
+ title: 'No workflow-level `timeout-minutes` — only job-level and step-level timeouts; runaway workflows consume runner hours with no global cap'
3
+ category: known-unsolved
4
+ severity: limitation
5
+ tags:
6
+ - timeout
7
+ - workflow-level
8
+ - runner-hours
9
+ - billing
10
+ - limitation
11
+ - runaway-workflow
12
+ patterns:
13
+ - regex: 'timeout.minutes'
14
+ flags: 'i'
15
+ - regex: 'workflow.*timed? ?out|timed? ?out.*workflow'
16
+ flags: 'i'
17
+ error_messages:
18
+ - "No workflow-level timeout — only job-level timeout-minutes is supported"
19
+ - "Unexpected key 'timeout-minutes' at workflow level — property is only valid on jobs"
20
+ root_cause: |
21
+ GitHub Actions supports `timeout-minutes:` only at the JOB level and STEP level.
22
+ There is no `timeout-minutes:` field at the workflow level (the level containing
23
+ `on:`, `env:`, and `jobs:`). If placed at the workflow level, actionlint reports
24
+ "unexpected key 'timeout-minutes'" and the key is silently ignored at runtime
25
+ with no effect on execution.
26
+
27
+ The default job timeout is 360 minutes (6 hours). A workflow with multiple jobs,
28
+ each using the default timeout, can run for many times 360 minutes total. There is
29
+ no built-in way to enforce a global "if this entire workflow hasn't finished in X
30
+ hours, cancel everything."
31
+
32
+ Common scenarios where this causes unexpected runner hour consumption:
33
+ - A self-hosted runner goes offline mid-job; the job hangs until its per-job timeout
34
+ - A workflow waiting on a deployment environment review that is never approved
35
+ - A matrix job with a misconfigured container that hangs on startup
36
+ - A network call in a step that never times out (no step-level timeout set)
37
+
38
+ This is a long-requested GitHub Actions feature with hundreds of community upvotes.
39
+ fix: |
40
+ Workarounds (no official workflow-level timeout exists):
41
+
42
+ 1. SET CONSERVATIVE JOB TIMEOUTS: Add explicit `timeout-minutes:` to every job
43
+ with a value appropriate for that job's actual expected runtime plus a buffer.
44
+ Do not rely on the 360-minute default.
45
+
46
+ 2. SET STEP-LEVEL TIMEOUTS: Add `timeout-minutes:` to individual steps that perform
47
+ network calls, long-running builds, or any operation that can hang.
48
+
49
+ 3. WATCHDOG WORKFLOW: A separate workflow triggered by `workflow_run` can monitor
50
+ in-progress runs and cancel them via the API if they exceed a threshold duration.
51
+
52
+ 4. ENVIRONMENT REVIEW EXPIRY: For deployment workflows stuck on required reviewers,
53
+ configure an expiry window under Settings > Environments > [env] >
54
+ Deployment protection rules > Timeout.
55
+ fix_code:
56
+ - language: yaml
57
+ label: 'Set explicit per-job timeouts as a workaround'
58
+ code: |
59
+ jobs:
60
+ build:
61
+ runs-on: ubuntu-latest
62
+ timeout-minutes: 15 # Set per-job: build should not exceed 15 min
63
+ steps:
64
+ - uses: actions/checkout@v4
65
+ - run: npm ci && npm run build
66
+
67
+ test:
68
+ needs: build
69
+ runs-on: ubuntu-latest
70
+ timeout-minutes: 20 # Integration tests: 20 min max
71
+ steps:
72
+ - name: Run tests
73
+ timeout-minutes: 15 # Step-level: individual test run cap
74
+ run: npm run test:integration
75
+
76
+ deploy:
77
+ needs: test
78
+ runs-on: ubuntu-latest
79
+ timeout-minutes: 10 # Deployment itself should be fast
80
+ environment: production
81
+ steps:
82
+ - run: ./scripts/deploy.sh
83
+ prevention:
84
+ - 'Always set `timeout-minutes:` on every job — do not rely on the 360-minute default for normal CI workflows.'
85
+ - 'Add `timeout-minutes:` to individual steps that perform network I/O, external API calls, or any blocking operation.'
86
+ - 'Monitor unexpected Actions billing spikes: they often indicate a stuck workflow running against the 6-hour default job timeout.'
87
+ - 'Set deployment environment review expiry windows to prevent workflows from hanging indefinitely awaiting approval.'
88
+ docs:
89
+ - url: 'https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#jobsjob_idtimeout-minutes'
90
+ label: 'Workflow syntax: jobs.<job_id>.timeout-minutes'
91
+ - url: 'https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#jobsjob_idstepstimeout-minutes'
92
+ label: 'Workflow syntax: jobs.<job_id>.steps[*].timeout-minutes'
93
+ - url: 'https://github.com/orgs/community/discussions/16058'
94
+ label: 'GitHub Community: Workflow-level timeout-minutes (feature request)'
@@ -0,0 +1,97 @@
1
+ id: runner-environment-154
2
+ title: "macOS ARM64 runner: Rosetta 2 not pre-installed — x86_64 binaries fail"
3
+ category: runner-environment
4
+ severity: error
5
+ tags:
6
+ - macos
7
+ - arm64
8
+ - rosetta
9
+ - apple-silicon
10
+ - binary-compatibility
11
+ patterns:
12
+ - regex: 'Bad CPU type in executable'
13
+ flags: i
14
+ - regex: 'Exec format error'
15
+ flags: i
16
+ - regex: 'is not supported on this machine \(CPU type'
17
+ flags: i
18
+ - regex: 'rosetta.*not.*install|softwareupdate.*rosetta'
19
+ flags: i
20
+ error_messages:
21
+ - "zsh: bad CPU type in executable: /usr/local/bin/mytool"
22
+ - "Exec format error"
23
+ - "/usr/local/bin/node: Bad CPU type in executable"
24
+ - "The file '/path/to/binary' is not supported on this machine (CPU type 16777223)"
25
+ root_cause: |
26
+ GitHub-hosted macOS runners on Apple Silicon hardware (macos-14, macos-15, and the `macos-latest`
27
+ label when pointing to ARM64 images) do NOT have Rosetta 2 pre-installed. Rosetta 2 is Apple's
28
+ x86_64-to-ARM64 translation layer that allows Intel-compiled binaries to run on Apple Silicon.
29
+
30
+ Without Rosetta 2, any x86_64 binary executed on the ARM64 runner fails immediately with
31
+ "Bad CPU type in executable" or "Exec format error". Common sources of x86_64 binaries:
32
+ - Pre-compiled tool downloads targeting darwin-x64
33
+ - npm packages with native addons built for x86_64
34
+ - Homebrew formulae that only have x86_64 bottles
35
+ - Custom build scripts that hardcode `arch -x86_64`
36
+ - Docker images using `linux/amd64` platform
37
+
38
+ This is distinct from Linux ARM64 runners (ubuntu-24.04-arm) where the error manifests
39
+ differently and no Rosetta equivalent exists. On macOS, Rosetta 2 can be installed as a
40
+ one-time setup step.
41
+ fix: |
42
+ Option 1 — Install Rosetta 2 at job start (quick workaround):
43
+ Add `softwareupdate --install-rosetta --agree-to-license` as the first step. This allows
44
+ x86_64 binaries to run via translation.
45
+
46
+ Option 2 — Use ARM64-native binaries (preferred):
47
+ Update download scripts to detect `arch` and fetch the correct binary:
48
+ - Use `$(uname -m)` to branch between arm64 and x86_64 download URLs
49
+ - Use `arch -arm64 brew install` for Homebrew packages
50
+ - For npm: ensure native addons are rebuilt for the current architecture
51
+
52
+ Option 3 — Pin to Intel macOS runner:
53
+ Use `runs-on: macos-13` which is the last Intel-based macOS runner image. Note that
54
+ macos-13 is scheduled for deprecation; this is a temporary workaround only.
55
+ fix_code:
56
+ - language: yaml
57
+ label: "Install Rosetta 2 as first step (workaround)"
58
+ code: |
59
+ jobs:
60
+ build:
61
+ runs-on: macos-latest # ARM64 Apple Silicon
62
+ steps:
63
+ - name: Install Rosetta 2
64
+ run: softwareupdate --install-rosetta --agree-to-license
65
+ - uses: actions/checkout@v4
66
+ - name: Download tool
67
+ run: |
68
+ # x86_64 binary will now work via Rosetta translation
69
+ curl -L https://example.com/tool-darwin-x64 -o tool
70
+ chmod +x tool
71
+ ./tool
72
+ - language: yaml
73
+ label: "Detect architecture and fetch the correct binary (preferred)"
74
+ code: |
75
+ steps:
76
+ - name: Download architecture-appropriate binary
77
+ run: |
78
+ ARCH=$(uname -m)
79
+ if [ "$ARCH" = "arm64" ]; then
80
+ BINARY_URL="https://example.com/tool-darwin-arm64"
81
+ else
82
+ BINARY_URL="https://example.com/tool-darwin-x64"
83
+ fi
84
+ curl -L "$BINARY_URL" -o tool
85
+ chmod +x tool
86
+ ./tool
87
+ prevention:
88
+ - "Always test workflows on both `macos-13` (Intel) and `macos-14`+ (ARM64) runners"
89
+ - "Check download scripts for hardcoded `darwin-x64` or `darwin-amd64` architecture strings"
90
+ - "Prefer tools distributed via Homebrew — many formulae now have native ARM64 bottles"
91
+ - "Use `${{ runner.arch }}` in workflow expressions to branch on architecture (`X64` vs `ARM64`)"
92
+ - "Audit npm packages with native addons — they must support `darwin-arm64` or provide a WASM fallback"
93
+ docs:
94
+ - url: "https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources"
95
+ label: "GitHub Docs: Supported runners and hardware resources"
96
+ - url: "https://support.apple.com/en-us/102527"
97
+ label: "Apple: If you need to install Rosetta on your Mac"
@@ -0,0 +1,106 @@
1
+ id: runner-environment-155
2
+ title: "GitHub-hosted runner disk full — 'No space left on device' during large builds"
3
+ category: runner-environment
4
+ severity: error
5
+ tags:
6
+ - disk-space
7
+ - ubuntu
8
+ - docker
9
+ - large-builds
10
+ - runner-storage
11
+ patterns:
12
+ - regex: 'No space left on device'
13
+ flags: i
14
+ - regex: 'write.*error.*28|errno 28'
15
+ flags: i
16
+ - regex: 'disk.*full|filesystem.*full|out of disk'
17
+ flags: i
18
+ - regex: 'no space left'
19
+ flags: i
20
+ error_messages:
21
+ - "No space left on device"
22
+ - "Error: write /var/lib/docker/tmp/...: no space left on device"
23
+ - "tar: ./app: Cannot write: No space left on device"
24
+ - "error: failed to push some refs: No space left on device"
25
+ - "OSError: [Errno 28] No space left on device"
26
+ root_cause: |
27
+ GitHub-hosted Ubuntu runners have approximately 14 GB of usable disk space after the
28
+ pre-installed tool suite occupies the rest. The runner image includes a large set of
29
+ pre-installed software that consumes the majority of available disk:
30
+ - Android SDK: ~8.7 GB
31
+ - .NET SDKs: ~1.5 GB
32
+ - Haskell/GHC: ~5.4 GB
33
+ - CodeQL: ~5.4 GB
34
+ - Docker images cached on the runner: varies
35
+
36
+ Workflows that perform large Docker builds, pull multiple Docker images, build large
37
+ native packages, or accumulate many npm/cargo/maven dependencies can exhaust the
38
+ ~14 GB limit. Common triggers:
39
+ - `docker build` for large multi-stage images
40
+ - `docker pull` of several large base images
41
+ - Building and caching large Rust/C++ projects
42
+ - Downloading large ML models or datasets
43
+ - Generating large test fixtures or build artifacts
44
+
45
+ The error manifests in diverse ways: Docker build errors (errno 28), tar extraction
46
+ failures, git push failures writing pack files, or Python/Node crashes writing temp files.
47
+ fix: |
48
+ Free disk space before your build by removing pre-installed tools you don't need.
49
+ The community-maintained `jlumbroso/free-disk-space` action is the standard solution.
50
+
51
+ Manual removal commands for the largest consumers:
52
+ - Android SDK: `sudo rm -rf /usr/local/lib/android`
53
+ - .NET: `sudo rm -rf /usr/share/dotnet`
54
+ - Haskell/GHC: `sudo rm -rf /usr/local/.ghcup`
55
+ - Large packages: `sudo apt-get clean && sudo apt-get autoremove -y`
56
+ - Docker build cache: `docker builder prune -af`
57
+
58
+ Alternatively, upgrade to GitHub-hosted larger runners (4+ cores) which provide
59
+ more disk space, or use self-hosted runners.
60
+ fix_code:
61
+ - language: yaml
62
+ label: "Free disk space before large Docker build"
63
+ code: |
64
+ jobs:
65
+ build:
66
+ runs-on: ubuntu-latest
67
+ steps:
68
+ - name: Free disk space
69
+ uses: jlumbroso/free-disk-space@main
70
+ with:
71
+ tool-cache: false
72
+ android: true
73
+ dotnet: true
74
+ haskell: true
75
+ large-packages: true
76
+ docker-images: true
77
+ swap-storage: true
78
+ - uses: actions/checkout@v4
79
+ - name: Build Docker image
80
+ run: docker build -t myapp:latest .
81
+ - language: yaml
82
+ label: "Manual removal of largest pre-installed tools"
83
+ code: |
84
+ steps:
85
+ - name: Free disk space (manual)
86
+ run: |
87
+ df -h /
88
+ sudo rm -rf /usr/local/lib/android
89
+ sudo rm -rf /usr/share/dotnet
90
+ sudo rm -rf /usr/local/.ghcup
91
+ sudo apt-get clean
92
+ docker builder prune -af || true
93
+ df -h /
94
+ prevention:
95
+ - "Add a disk-space check step (`df -h /`) early in the workflow to detect capacity issues before they cause cryptic failures"
96
+ - "Run `jlumbroso/free-disk-space` before any Docker build or large compilation job"
97
+ - "Remove only tools you know you don't need — removing the tool-cache may break `actions/setup-*` steps"
98
+ - "Consider using `runs-on: ubuntu-latest-4-cores` (GitHub Teams) which provides more disk space"
99
+ - "Use Docker `--no-cache` flags cautiously — reusing layer cache can actually save disk vs rebuilding every layer"
100
+ docs:
101
+ - url: "https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources"
102
+ label: "GitHub Docs: Runner hardware resources"
103
+ - url: "https://github.com/jlumbroso/free-disk-space"
104
+ label: "jlumbroso/free-disk-space action"
105
+ - url: "https://github.com/actions/runner-images/issues/2840"
106
+ label: "runner-images#2840: Tracking disk space usage"
@@ -0,0 +1,90 @@
1
+ id: runner-environment-152
2
+ title: 'Organization "Require immutable actions" policy blocks tag-pinned action refs — must use full commit SHA'
3
+ category: runner-environment
4
+ severity: error
5
+ tags:
6
+ - immutable-actions
7
+ - sha-pinning
8
+ - security-policy
9
+ - organization-policy
10
+ - enterprise
11
+ - supply-chain
12
+ patterns:
13
+ - regex: 'not pinned to an immutable SHA'
14
+ flags: 'i'
15
+ - regex: 'Action.*is not pinned.*immutable'
16
+ flags: 'i'
17
+ - regex: 'immutable actions.*required'
18
+ flags: 'i'
19
+ - regex: 'Update the workflow to use the immutable reference'
20
+ flags: 'i'
21
+ error_messages:
22
+ - "Error: Action 'actions/checkout@v4' is not pinned to an immutable SHA. Update the workflow to use the immutable reference."
23
+ - "Actions must be pinned to an immutable commit SHA. Organization policy requires immutable actions."
24
+ - "Error: This action reference is not immutable. The organization requires all actions to be pinned by SHA."
25
+ root_cause: |
26
+ GitHub introduced an organization-level security policy called "Require immutable
27
+ actions" (available in GitHub Enterprise and GitHub Teams since late 2025). When
28
+ enabled by an organization admin, every `uses:` reference in every workflow within
29
+ that organization must point to a full commit SHA rather than a mutable tag (such
30
+ as `@v4`) or branch name (such as `@main`).
31
+
32
+ Tags and branches are mutable — they can be updated to point to a different commit
33
+ at any time. An attacker who compromises an upstream action repository can move a
34
+ widely used tag to point to malicious code. The SHA immutability policy protects
35
+ against this supply-chain attack vector by ensuring the exact code being run is
36
+ pinned and verifiable.
37
+
38
+ When the policy is active, the Actions runner validates every `uses:` reference
39
+ before execution and refuses to run any workflow containing mutable refs, even if
40
+ the referenced tag currently points to a trusted commit. This commonly surfaces
41
+ after an organization adopts the policy post-hoc, breaking all existing workflows.
42
+ fix: |
43
+ Replace every `uses:` tag or branch reference with the full 40-character commit SHA.
44
+ Add the human-readable tag as an inline comment for maintainability.
45
+
46
+ To find the SHA for a specific action version:
47
+ - Visit the action's GitHub releases page (e.g., github.com/actions/checkout/releases/tag/v4)
48
+ - Click the commit SHA link next to the tag
49
+
50
+ Tools that automate SHA pinning across all workflow files:
51
+ - `ratchet` (github.com/thepwagner/ratchet): `ratchet pin .github/workflows/`
52
+ - `pin-github-action` (Mend): available as a GitHub Action or CLI
53
+ - Dependabot with `package-ecosystem: github-actions` maintains pinned SHAs automatically
54
+ fix_code:
55
+ - language: yaml
56
+ label: 'Pin action refs to full commit SHA (with readable comment)'
57
+ code: |
58
+ # BEFORE (fails with immutable actions org policy)
59
+ steps:
60
+ - uses: actions/checkout@v4
61
+ - uses: actions/setup-node@v4
62
+ - uses: actions/upload-artifact@v4
63
+
64
+ # AFTER (SHA-pinned with human-readable tag comment)
65
+ steps:
66
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
67
+ - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
68
+ - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
69
+ - language: yaml
70
+ label: 'Dependabot config to keep SHA pins up to date automatically'
71
+ code: |
72
+ # .github/dependabot.yml
73
+ version: 2
74
+ updates:
75
+ - package-ecosystem: github-actions
76
+ directory: /
77
+ schedule:
78
+ interval: weekly
79
+ prevention:
80
+ - 'Audit all workflow files before enabling the org policy — run ratchet or pin-github-action across the entire .github/workflows/ directory first.'
81
+ - 'Enable the policy in a single pilot repository before rolling it out organization-wide to identify and fix all mutable refs.'
82
+ - 'Add actionlint with SHA-pinning rules to CI so new mutable refs are caught in PRs before reaching main.'
83
+ - 'Configure Dependabot for github-actions to automatically open PRs whenever a pinned SHA has a new upstream release.'
84
+ docs:
85
+ - url: 'https://docs.github.com/en/actions/security-for-github-actions/security-guides/security-hardening-for-github-actions#using-third-party-actions'
86
+ label: 'Security hardening for GitHub Actions: using third-party actions'
87
+ - url: 'https://docs.github.com/en/organizations/managing-organization-settings/disabling-or-limiting-github-actions-for-your-organization'
88
+ label: 'Requiring immutable action components (org policy settings)'
89
+ - url: 'https://github.com/thepwagner/ratchet'
90
+ label: 'ratchet — CLI tool to pin GitHub Actions refs to SHA'
@@ -0,0 +1,90 @@
1
+ id: runner-environment-156
2
+ title: "ubuntu runner: snap packages unavailable — snapd not running"
3
+ category: runner-environment
4
+ severity: error
5
+ tags:
6
+ - ubuntu
7
+ - snap
8
+ - snapd
9
+ - packages
10
+ - ubuntu-24
11
+ patterns:
12
+ - regex: 'cannot communicate with server.*snapd\.socket'
13
+ flags: i
14
+ - regex: 'snapd is not running'
15
+ flags: i
16
+ - regex: 'snap.*connect.*refused|dial unix.*snapd'
17
+ flags: i
18
+ - regex: 'snap: command not found'
19
+ flags: i
20
+ error_messages:
21
+ - "error: cannot communicate with server: Post \"http://localhost/v2/snaps/kubectl\": dial unix /run/snapd.socket: connect: no such file or directory"
22
+ - "error: cannot communicate with server: Post http://localhost/v2/snaps: dial unix /run/snapd.socket: connect: no such file or directory"
23
+ - "snapd is not running"
24
+ - "snap: command not found"
25
+ root_cause: |
26
+ GitHub-hosted Ubuntu runners do not run the snapd daemon. The snap socket
27
+ `/run/snapd.socket` is never created, so any `snap install` command immediately fails
28
+ when attempting to communicate with the snap store daemon.
29
+
30
+ While the `snap` binary may be present on the runner image, the background snapd service
31
+ is not started because GitHub-hosted runners use a minimal systemd-free environment.
32
+ Starting snapd manually is not practical — it requires systemd or a complex manual
33
+ daemon startup sequence, and snap packages are confined using AppArmor profiles that
34
+ may also be unavailable in the runner environment.
35
+
36
+ This is frequently encountered when workflows try to install tools distributed as snaps:
37
+ kubectl, microk8s, aws-cli, spotify, and many developer utilities.
38
+ fix: |
39
+ Replace `snap install` with an alternative package source for the tool you need:
40
+
41
+ - **kubectl**: Use `curl -LO https://dl.k8s.io/release/...` or the `azure/setup-kubectl` action
42
+ - **aws-cli v2**: Use `pip install awscli` or the official AWS install script via apt
43
+ - **Helm**: Use the `azure/setup-helm` action or the official install script
44
+ - **General tools**: Check for apt, pip, npm, or GitHub releases as alternatives
45
+
46
+ If you must install a snap, consider using a self-hosted runner with snapd enabled,
47
+ or a Docker container runner with snapd configured.
48
+ fix_code:
49
+ - language: yaml
50
+ label: "Install kubectl via apt instead of snap"
51
+ code: |
52
+ steps:
53
+ - name: Install kubectl
54
+ run: |
55
+ curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key \
56
+ | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
57
+ echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.30/deb/ /' \
58
+ | sudo tee /etc/apt/sources.list.d/kubernetes.list
59
+ sudo apt-get update
60
+ sudo apt-get install -y kubectl
61
+ - language: yaml
62
+ label: "Use dedicated setup actions instead of snap"
63
+ code: |
64
+ steps:
65
+ # Instead of: snap install kubectl --classic
66
+ - uses: azure/setup-kubectl@v4
67
+ with:
68
+ version: 'v1.30.0'
69
+
70
+ # Instead of: snap install helm --classic
71
+ - uses: azure/setup-helm@v4
72
+ with:
73
+ version: '3.14.0'
74
+
75
+ # Instead of: snap install aws-cli --classic
76
+ - name: Install AWS CLI v2
77
+ run: |
78
+ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
79
+ unzip awscliv2.zip
80
+ sudo ./aws/install
81
+ prevention:
82
+ - "Audit your workflow for any `snap install` commands — GitHub-hosted runners cannot run snap packages"
83
+ - "Check if the tool has an official GitHub Action (setup-kubectl, setup-helm, etc.) before writing a manual install step"
84
+ - "For tools not on apt, prefer GitHub Releases binary downloads with `curl` and `chmod +x` over snap"
85
+ - "Self-hosted runners with a full Ubuntu desktop/server installation do support snap if needed"
86
+ docs:
87
+ - url: "https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners#software-installed-on-github-hosted-runners"
88
+ label: "GitHub Docs: Software installed on GitHub-hosted runners"
89
+ - url: "https://github.com/actions/runner-images/issues/1769"
90
+ label: "runner-images#1769: snap is not supported"
@@ -0,0 +1,95 @@
1
+ id: runner-environment-153
2
+ title: "ubuntu runner systemctl fails — systemd not running as PID 1"
3
+ category: runner-environment
4
+ severity: error
5
+ tags:
6
+ - ubuntu
7
+ - systemd
8
+ - systemctl
9
+ - services
10
+ - daemon
11
+ patterns:
12
+ - regex: 'System has not been booted with systemd as init system \(PID 1\)\. Can''t operate\.'
13
+ flags: i
14
+ - regex: 'Failed to connect to bus: No such file or directory'
15
+ flags: i
16
+ - regex: 'systemctl: command not found'
17
+ flags: i
18
+ error_messages:
19
+ - "System has not been booted with systemd as init system (PID 1). Can't operate."
20
+ - "Failed to connect to bus: No such file or directory"
21
+ - "Failed to start postgresql.service: Unit not found."
22
+ - "System has not been booted with systemd"
23
+ root_cause: |
24
+ GitHub-hosted Ubuntu runners do not run systemd as the init system (PID 1). The runner
25
+ process starts directly inside a container-like environment where systemd is never initialized.
26
+ Any workflow step that calls `sudo systemctl start <service>`, `systemctl enable <service>`,
27
+ or `systemctl status <service>` will immediately fail because the D-Bus socket and systemd
28
+ unit system are not present.
29
+
30
+ This is a fundamental architectural constraint of GitHub-hosted runners — they are ephemeral
31
+ VMs (not containers) but systemd is disabled to reduce boot time and resource overhead. The
32
+ pattern is extremely common when devs copy-paste service startup commands from their local
33
+ Linux environment or documentation into GitHub Actions run: steps.
34
+
35
+ Common affected services: PostgreSQL, MySQL, Redis, MongoDB, Nginx, Apache, RabbitMQ.
36
+ fix: |
37
+ Replace `systemctl` calls with one of these approaches:
38
+
39
+ 1. **Use GitHub Actions `services:` containers** — the recommended approach for databases and
40
+ message queues. GitHub spins up Docker containers alongside your job.
41
+
42
+ 2. **Use direct daemon start commands** — start the service binary directly:
43
+ - PostgreSQL: `sudo -u postgres pg_ctl -D /etc/postgresql/*/main start`
44
+ - MySQL: `sudo mysqld_safe &`
45
+ - Redis: `redis-server --daemonize yes`
46
+
47
+ 3. **Use `service` SysV command** — on Ubuntu runners, SysV init `service` works even without
48
+ systemd: `sudo service postgresql start`
49
+
50
+ fix_code:
51
+ - language: yaml
52
+ label: "Use services: containers block (recommended for databases)"
53
+ code: |
54
+ jobs:
55
+ test:
56
+ runs-on: ubuntu-latest
57
+ services:
58
+ postgres:
59
+ image: postgres:16
60
+ env:
61
+ POSTGRES_PASSWORD: postgres
62
+ ports:
63
+ - 5432:5432
64
+ options: >-
65
+ --health-cmd pg_isready
66
+ --health-interval 10s
67
+ --health-timeout 5s
68
+ --health-retries 5
69
+ steps:
70
+ - uses: actions/checkout@v4
71
+ - name: Run tests
72
+ run: npm test
73
+ env:
74
+ DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test
75
+ - language: yaml
76
+ label: "Use SysV 'service' command as systemctl fallback"
77
+ code: |
78
+ steps:
79
+ - name: Start PostgreSQL
80
+ run: |
81
+ sudo service postgresql start
82
+ sudo service postgresql status
83
+ - name: Create test database
84
+ run: |
85
+ sudo -u postgres psql -c "CREATE DATABASE testdb;"
86
+ prevention:
87
+ - "Use the `services:` block in your workflow for databases and message queues — it's the GitHub Actions-native solution"
88
+ - "Replace `systemctl start X` with `sudo service X start` for SysV-compatible services"
89
+ - "For custom daemons, start them in the background with `&` and poll for readiness"
90
+ - "Never copy-paste `systemctl` commands from local Linux setup scripts into GitHub Actions without adaptation"
91
+ docs:
92
+ - url: "https://docs.github.com/en/actions/use-cases-and-examples/using-containerized-services/about-service-containers"
93
+ label: "GitHub Docs: About service containers"
94
+ - url: "https://docs.github.com/en/actions/use-cases-and-examples/using-containerized-services/creating-postgresql-service-containers"
95
+ label: "GitHub Docs: Creating PostgreSQL service containers"
@@ -0,0 +1,86 @@
1
+ id: silent-failures-081
2
+ title: '`needs.<job_id>.conclusion` does not exist — correct property is `result`; evaluates to empty string silently'
3
+ category: silent-failures
4
+ severity: silent-failure
5
+ tags:
6
+ - needs-context
7
+ - job-result
8
+ - downstream-jobs
9
+ - if-condition
10
+ - empty-string
11
+ - notification-job
12
+ patterns:
13
+ - regex: 'needs\.\w+\.conclusion'
14
+ flags: 'i'
15
+ error_messages:
16
+ - "needs.<job_id>.conclusion evaluates to empty string — condition using .conclusion never fires"
17
+ root_cause: |
18
+ The `needs` context exposes `.result` for each upstream job — NOT `.conclusion`.
19
+ Valid values for `needs.<job_id>.result` are: `success`, `failure`, `cancelled`,
20
+ and `skipped`.
21
+
22
+ The property `.conclusion` does not exist on the needs context object. Accessing
23
+ `needs.<job_id>.conclusion` silently evaluates to an empty string `""` with no
24
+ warning, error, or annotation in the workflow logs. The downstream job runs but the
25
+ `if:` condition never matches because `"" == 'failure'` is always false.
26
+
27
+ This confusion arises because the `steps` context exposes BOTH `.conclusion` and
28
+ `.outcome` for step results, leading developers to assume the needs context follows
29
+ the same property naming. The mismatch causes notification jobs, cleanup steps, and
30
+ failure-handler jobs to silently skip execution with no observable error.
31
+ fix: |
32
+ Replace `.conclusion` with `.result` in all `needs` context expressions.
33
+
34
+ WRONG: if: needs.build.conclusion == 'failure' # always empty string, never matches
35
+ RIGHT: if: needs.build.result == 'failure' # correct
36
+
37
+ For aggregate checks, prefer the built-in status functions over manual needs.result
38
+ comparisons — `failure()`, `success()`, `cancelled()`, `always()` — which evaluate
39
+ the combined result of all upstream jobs automatically.
40
+ fix_code:
41
+ - language: yaml
42
+ label: 'Correct: use needs.<job>.result not needs.<job>.conclusion'
43
+ code: |
44
+ jobs:
45
+ build:
46
+ runs-on: ubuntu-latest
47
+ steps:
48
+ - uses: actions/checkout@v4
49
+ - run: npm ci && npm test
50
+
51
+ notify-on-failure:
52
+ needs: [build]
53
+ # Use built-in failure() or explicit needs.<job>.result
54
+ if: failure()
55
+ runs-on: ubuntu-latest
56
+ steps:
57
+ - name: Send failure notification
58
+ run: |
59
+ echo "Build result: ${{ needs.build.result }}"
60
+ # .result values: success | failure | cancelled | skipped
61
+ - language: yaml
62
+ label: 'Multi-job downstream check using needs.result'
63
+ code: |
64
+ jobs:
65
+ deploy:
66
+ needs: [lint, test, build]
67
+ # Explicit per-job result check — use .result not .conclusion
68
+ if: >-
69
+ needs.lint.result == 'success' &&
70
+ needs.test.result == 'success' &&
71
+ needs.build.result == 'success'
72
+ runs-on: ubuntu-latest
73
+ steps:
74
+ - run: echo "All upstream jobs succeeded"
75
+ prevention:
76
+ - 'The needs context exposes `.result` only — `.conclusion` does not exist. Use `needs.<job>.result` for all downstream conditional checks.'
77
+ - 'Prefer the status check functions `failure()`, `success()`, `cancelled()`, `always()` in downstream job `if:` conditions — they aggregate all upstream job results automatically.'
78
+ - 'Add actionlint to CI — it reports references to undefined context properties including `needs.<job>.conclusion`, catching this mistake at review time.'
79
+ - 'When a notification or cleanup job silently skips, verify the `if:` condition uses `.result` and check the actual result value in the Actions run summary.'
80
+ docs:
81
+ - url: 'https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/accessing-contextual-information-about-workflow-runs#needs-context'
82
+ label: 'GitHub Actions: needs context — result property'
83
+ - url: 'https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/using-conditions-to-control-job-execution'
84
+ label: 'Using conditions to control job execution'
85
+ - url: 'https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/evaluate-expressions-in-workflows-and-actions#status-check-functions'
86
+ label: 'Status check functions: failure(), success(), cancelled(), always()'
@@ -0,0 +1,93 @@
1
+ id: silent-failures-082
2
+ title: "pull_request_target checkout defaults to base branch, not PR head"
3
+ category: silent-failures
4
+ severity: silent-failure
5
+ tags:
6
+ - pull_request_target
7
+ - checkout
8
+ - security
9
+ - fork
10
+ - base-branch
11
+ patterns:
12
+ - regex: 'on:\s*\n\s+pull_request_target'
13
+ flags: 'im'
14
+ - regex: 'pull_request_target'
15
+ flags: 'i'
16
+ error_messages:
17
+ - "Workflow runs on base branch code instead of PR contributor changes"
18
+ - "Tests pass on base but fail on PR code with no visible error in logs"
19
+ root_cause: |
20
+ When a workflow is triggered by `pull_request_target`, GitHub Actions runs the workflow
21
+ from the TARGET repository's base branch — not the contributor's PR head. This is
22
+ intentional: `pull_request_target` provides write-level token access (for labeling,
23
+ commenting, posting status checks), so GitHub protects secrets by refusing to run
24
+ untrusted fork code with elevated permissions.
25
+
26
+ As a result, `actions/checkout` checks out `github.sha`, which resolves to the merge
27
+ base commit on the target branch. Any tests, linting, or code analysis in this
28
+ workflow validate the base branch, not the contributor's changes. The workflow
29
+ succeeds silently while testing the wrong code.
30
+ fix: |
31
+ Option 1 (recommended — safe): Use `pull_request` (not `pull_request_target`) for
32
+ running PR code. `pull_request` triggers run with read-only tokens and check out the
33
+ PR head by default. Use `pull_request_target` only for privileged actions like posting
34
+ comments or labels.
35
+
36
+ Option 2 (explicit checkout — use with caution): Explicitly check out the PR head
37
+ using `github.event.pull_request.head.sha`. Only do this if you fully trust all
38
+ contributors and understand that fork code will execute with the repository write token.
39
+ fix_code:
40
+ - language: yaml
41
+ label: "Recommended: use pull_request for code execution, pull_request_target for privileged writes"
42
+ code: |
43
+ # Workflow 1: run tests on PR code (read-only, safe for forks)
44
+ on:
45
+ pull_request:
46
+ branches: [main]
47
+
48
+ jobs:
49
+ test:
50
+ runs-on: ubuntu-latest
51
+ steps:
52
+ - uses: actions/checkout@v4
53
+ # Checks out PR head automatically — no ref: override needed
54
+ - run: npm test
55
+
56
+ ---
57
+ # Workflow 2: post labels (write access via pull_request_target)
58
+ on:
59
+ pull_request_target:
60
+ types: [opened]
61
+
62
+ jobs:
63
+ label:
64
+ runs-on: ubuntu-latest
65
+ permissions:
66
+ pull-requests: write
67
+ steps:
68
+ - uses: actions/labeler@v5
69
+ # Never runs contributor code here — only labels the PR
70
+ - language: yaml
71
+ label: "If you must run PR code under pull_request_target (risky)"
72
+ code: |
73
+ on:
74
+ pull_request_target:
75
+ branches: [main]
76
+
77
+ jobs:
78
+ test:
79
+ runs-on: ubuntu-latest
80
+ steps:
81
+ - uses: actions/checkout@v4
82
+ with:
83
+ ref: ${{ github.event.pull_request.head.sha }}
84
+ # WARNING: executes untrusted fork code with write-level token
85
+ prevention:
86
+ - "Use pull_request (not pull_request_target) for workflows that run code — pull_request tokens are read-only and checkout the PR head correctly by default"
87
+ - "Reserve pull_request_target for privileged write-only actions: posting comments, applying labels, updating statuses — never checkout and execute untrusted PR code in these workflows"
88
+ - "If CI consistently passes but reviewers find bugs tests should catch, verify which commit your checkout step is using by printing github.sha vs github.event.pull_request.head.sha"
89
+ docs:
90
+ - url: "https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#pull_request_target"
91
+ label: "pull_request_target event — security considerations"
92
+ - url: "https://securitylab.github.com/research/github-actions-preventing-pwn-requests/"
93
+ label: "GitHub Security Lab: Preventing pwn requests (pull_request_target risks)"
@@ -0,0 +1,64 @@
1
+ id: silent-failures-083
2
+ title: "matrix strategy fail-fast true by default silently cancels all remaining jobs on first failure"
3
+ category: silent-failures
4
+ severity: silent-failure
5
+ tags:
6
+ - matrix
7
+ - fail-fast
8
+ - cancellation
9
+ - strategy
10
+ - parallel-jobs
11
+ patterns:
12
+ - regex: 'strategy:\s*\n\s+matrix:'
13
+ flags: 'im'
14
+ - regex: 'Some jobs were not executed because a previous required job failed'
15
+ flags: 'i'
16
+ error_messages:
17
+ - "Some jobs were not executed because a previous required job failed"
18
+ - "Skipping this step because a previous step failed or the workflow was cancelled"
19
+ - "This job was cancelled because another job in the workflow failed"
20
+ root_cause: |
21
+ GitHub Actions matrix strategy has `fail-fast: true` as the default. When any single
22
+ matrix job fails, GitHub immediately cancels all remaining in-progress and queued
23
+ matrix jobs from the same workflow run.
24
+
25
+ This means:
26
+ - You only see the failure from the first (or earliest) failing matrix combination
27
+ - All other combinations — whether they would pass or fail — are cancelled immediately
28
+ - The workflow summary shows cancelled jobs with no diagnostic information
29
+ - Developers may spend time fixing the first failure only to discover a second unrelated
30
+ failure in a different matrix combination afterward
31
+
32
+ Many developers set up matrix builds specifically to validate across multiple
33
+ OS/language version combinations and expect every combination to run to completion.
34
+ fix: |
35
+ Explicitly set `fail-fast: false` in your matrix strategy to allow all matrix jobs to
36
+ run to completion regardless of individual failures. This provides a complete picture
37
+ of which matrix combinations are broken.
38
+ fix_code:
39
+ - language: yaml
40
+ label: "Set fail-fast: false to run all matrix combinations to completion"
41
+ code: |
42
+ jobs:
43
+ test:
44
+ strategy:
45
+ fail-fast: false # default is true — set false for full matrix visibility
46
+ matrix:
47
+ os: [ubuntu-latest, windows-latest, macos-latest]
48
+ node: [18, 20, 22]
49
+ runs-on: ${{ matrix.os }}
50
+ steps:
51
+ - uses: actions/checkout@v4
52
+ - uses: actions/setup-node@v4
53
+ with:
54
+ node-version: ${{ matrix.node }}
55
+ - run: npm test
56
+ prevention:
57
+ - "Always explicitly set fail-fast: false when you want all matrix combinations to run — for example when building cross-platform or cross-version compatibility matrices"
58
+ - "The default fail-fast: true is intentional for workflows where you only care about any single failure (saves CI minutes), but must be changed when you need full failure visibility"
59
+ - "If matrix jobs are silently cancelled and show no error output, check whether fail-fast: true (or its absence — the default) is the cause"
60
+ docs:
61
+ - url: "https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#jobsjob_idstrategyfail-fast"
62
+ label: "jobs.<job_id>.strategy.fail-fast documentation"
63
+ - url: "https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#jobsjob_idstrategymatrix"
64
+ label: "Matrix strategy documentation"
@@ -0,0 +1,96 @@
1
+ id: silent-failures-084
2
+ title: "github.sha on pull_request event is the ephemeral merge commit SHA, not the PR head commit"
3
+ category: silent-failures
4
+ severity: silent-failure
5
+ tags:
6
+ - github-sha
7
+ - pull_request
8
+ - merge-commit
9
+ - docker
10
+ - tagging
11
+ - status-checks
12
+ patterns:
13
+ - regex: '\$\{\{\s*github\.sha\s*\}\}'
14
+ flags: 'i'
15
+ - regex: 'github\.sha'
16
+ flags: 'i'
17
+ error_messages:
18
+ - "Docker image tagged with SHA not found in git history"
19
+ - "Deployment status does not appear on the PR commit"
20
+ - "Commit status check not visible on pull request"
21
+ root_cause: |
22
+ On `pull_request` events, `github.sha` is NOT the PR branch's head commit SHA. It is
23
+ the SHA of a temporary merge commit that GitHub creates automatically to simulate
24
+ "what would happen if this PR were merged right now." This ephemeral merge commit:
25
+
26
+ - Does NOT appear in the repository's git history
27
+ - Changes every time the base branch advances, even with no new PR commits
28
+ - Is not accessible via normal git operations outside the workflow run
29
+
30
+ Consequences developers hit in the wild:
31
+ - Docker images tagged with `github.sha` have tags that don't correspond to any real
32
+ commit, making rollbacks and tracing impossible
33
+ - Commit status checks or deployment markers posted to `github.sha` don't appear on
34
+ any commit in the PR and are effectively invisible to reviewers
35
+ - Scripts that fetch the commit from the API using github.sha return 404
36
+
37
+ The actual PR head commit SHA is available via `github.event.pull_request.head.sha`.
38
+ fix: |
39
+ Use `github.event.pull_request.head.sha` to get the actual PR head commit on
40
+ pull_request events. For workflows triggered by both push and pull_request, use a
41
+ conditional to select the correct SHA per event type.
42
+ fix_code:
43
+ - language: yaml
44
+ label: "Get the correct SHA for both push and pull_request events"
45
+ code: |
46
+ jobs:
47
+ build:
48
+ runs-on: ubuntu-latest
49
+ steps:
50
+ - uses: actions/checkout@v4
51
+
52
+ - name: Resolve commit SHA
53
+ id: sha
54
+ run: |
55
+ if [ "${{ github.event_name }}" = "pull_request" ]; then
56
+ echo "value=${{ github.event.pull_request.head.sha }}" >> $GITHUB_OUTPUT
57
+ else
58
+ echo "value=${{ github.sha }}" >> $GITHUB_OUTPUT
59
+ fi
60
+
61
+ - name: Tag Docker image with correct SHA
62
+ run: |
63
+ docker build -t myapp:${{ steps.sha.outputs.value }} .
64
+ docker push myapp:${{ steps.sha.outputs.value }}
65
+ - language: yaml
66
+ label: "Post commit status to the correct PR head SHA"
67
+ code: |
68
+ on:
69
+ pull_request:
70
+
71
+ jobs:
72
+ status:
73
+ runs-on: ubuntu-latest
74
+ steps:
75
+ - name: Post status to actual PR commit
76
+ uses: actions/github-script@v7
77
+ with:
78
+ script: |
79
+ // Use PR head SHA, not github.sha (merge commit)
80
+ await github.rest.repos.createCommitStatus({
81
+ owner: context.repo.owner,
82
+ repo: context.repo.repo,
83
+ sha: context.payload.pull_request.head.sha,
84
+ state: 'success',
85
+ description: 'Build passed',
86
+ context: 'ci/build'
87
+ });
88
+ prevention:
89
+ - "Never tag Docker images or create commit statuses using github.sha on pull_request events — use github.event.pull_request.head.sha for the real PR head"
90
+ - "If deployment statuses or commit checks are missing from PR commits, verify you are not posting them to github.sha (the merge commit)"
91
+ - "The merge commit SHA changes every time the base branch gets new commits, even without new PR activity — this makes github.sha unstable for artifact tagging on PRs"
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: "pull_request event — note on github.sha merge commit"
95
+ - url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/accessing-contextual-information-about-workflow-runs#github-context"
96
+ label: "GitHub context — sha property"
@@ -0,0 +1,88 @@
1
+ id: yaml-syntax-055
2
+ title: '`on.workflow_call.outputs.value` references `steps.<id>.outputs` — steps context unavailable at workflow scope; must use `jobs.<job_id>.outputs`'
3
+ category: yaml-syntax
4
+ severity: error
5
+ tags:
6
+ - reusable-workflow
7
+ - workflow_call
8
+ - outputs
9
+ - steps-context
10
+ - jobs-context
11
+ - empty-string
12
+ - scope
13
+ patterns:
14
+ - regex: 'steps\.\w+\.outputs\.\w+'
15
+ flags: 'i'
16
+ error_messages:
17
+ - "Reusable workflow output is empty — steps context not accessible in on.workflow_call.outputs.value"
18
+ - "on.workflow_call.outputs value references steps context which is not available at workflow scope"
19
+ root_cause: |
20
+ In a reusable workflow, `on.workflow_call.outputs[*].value:` expressions are
21
+ evaluated at the WORKFLOW level, not within a job. The `steps` context is scoped to
22
+ a specific job and is only accessible inside that job's step expressions — it is
23
+ not visible at the top-level workflow scope where `on.workflow_call.outputs` lives.
24
+
25
+ Using `${{ steps.upload.outputs.artifact-id }}` in the `value:` field silently
26
+ evaluates to an empty string. No error, warning, or annotation is raised; the
27
+ caller simply receives an empty output value.
28
+
29
+ The correct pattern requires two explicit hops:
30
+ 1. Capture the step output at the JOB level using the job's `outputs:` block.
31
+ 2. Reference the JOB output at the WORKFLOW level using `${{ jobs.<job_id>.outputs.<key> }}`.
32
+
33
+ Note: this is distinct from yaml-syntax-032 (jobs.<id>.result empty in workflow_call
34
+ outputs) which covers the result property specifically, not step output propagation.
35
+ fix: |
36
+ Bridge step outputs up through the job's `outputs:` block first, then reference the
37
+ job output in `on.workflow_call.outputs.value`.
38
+
39
+ Pattern:
40
+ step writes to GITHUB_OUTPUT (or action output)
41
+ → job outputs: exposes it as jobs.<job_id>.outputs.<key>
42
+ → on.workflow_call.outputs.value references jobs.<job_id>.outputs.<key>
43
+ fix_code:
44
+ - language: yaml
45
+ label: 'Correct two-hop output propagation for reusable workflows'
46
+ code: |
47
+ on:
48
+ workflow_call:
49
+ outputs:
50
+ artifact-id:
51
+ description: 'ID of the uploaded build artifact'
52
+ # CORRECT: reference job-level output
53
+ value: ${{ jobs.build.outputs.artifact-id }}
54
+ # WRONG (silent empty string):
55
+ # value: ${{ steps.upload.outputs.artifact-id }}
56
+
57
+ jobs:
58
+ build:
59
+ runs-on: ubuntu-latest
60
+ outputs:
61
+ # Hop 1: expose step output at job level
62
+ artifact-id: ${{ steps.upload.outputs.artifact-id }}
63
+ steps:
64
+ - uses: actions/checkout@v4
65
+
66
+ - name: Build
67
+ run: npm ci && npm run build
68
+
69
+ - name: Upload artifact
70
+ id: upload
71
+ uses: actions/upload-artifact@v4
72
+ with:
73
+ name: build-output
74
+ path: dist/
75
+ # Hop 2: job outputs block above captures steps.upload.outputs.artifact-id
76
+ # Hop 3: on.workflow_call.outputs.value references jobs.build.outputs.artifact-id
77
+ prevention:
78
+ - 'The `steps` context is job-scoped. Always bridge step outputs through the job `outputs:` block before referencing them at workflow level in `on.workflow_call.outputs.value:`.'
79
+ - 'Use actionlint to statically analyze reusable workflow output expressions — it reports invalid context usage at workflow scope.'
80
+ - 'When a reusable workflow output is unexpectedly empty in the caller, check whether the `value:` expression uses `steps.` (wrong scope) vs `jobs.` (correct scope).'
81
+ - 'Each output needs both a job-level `outputs:` mapping AND a workflow-level `on.workflow_call.outputs[*].value:` reference — missing either hop silently returns empty string.'
82
+ docs:
83
+ - url: 'https://docs.github.com/en/actions/sharing-automations/reusing-workflows#using-outputs-from-a-reusable-workflow'
84
+ label: 'Reusable workflows: using outputs'
85
+ - url: 'https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/passing-information-between-jobs'
86
+ label: 'Passing information between jobs (job outputs)'
87
+ - url: 'https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/accessing-contextual-information-about-workflow-runs#steps-context'
88
+ label: 'Steps context — job-scoped, not available at workflow level'
@@ -0,0 +1,87 @@
1
+ id: yaml-syntax-056
2
+ title: "env context unavailable inside with: inputs of uses: steps"
3
+ category: yaml-syntax
4
+ severity: error
5
+ tags:
6
+ - env-context
7
+ - with-inputs
8
+ - uses
9
+ - expression-context
10
+ - action-inputs
11
+ patterns:
12
+ - regex: "Unrecognized named-value: 'env'"
13
+ flags: 'i'
14
+ - regex: 'Invalid workflow file.*Unrecognized named-value'
15
+ flags: 'i'
16
+ error_messages:
17
+ - "Unrecognized named-value: 'env'. Located at position 1 within expression: env.MY_VAR"
18
+ - "Invalid workflow file: .github/workflows/ci.yml (Line 14, Col 15): Unrecognized named-value: 'env'"
19
+ - "The workflow is not valid. .github/workflows/build.yml: Unrecognized named-value: 'env'"
20
+ root_cause: |
21
+ The `env` context is NOT available inside the `with:` input block of a `uses:` step.
22
+ GitHub Actions evaluates `uses:` step inputs using a restricted set of contexts, and
23
+ `env` is explicitly excluded because env var values may depend on previous step
24
+ outputs (which are also unavailable at `with:` evaluation time).
25
+
26
+ Contexts available in `with:` inputs: `github`, `needs`, `strategy`, `matrix`,
27
+ `secrets`, `inputs`, `vars`, and `steps` (but only from previously completed steps).
28
+ The `env` context, `runner` context, and job-level env vars are all unavailable.
29
+
30
+ This catches developers who define env vars at the workflow or job level and then try
31
+ to pass them as action inputs, which fails with "Unrecognized named-value: 'env'".
32
+ fix: |
33
+ Three options:
34
+ 1. Reference the value directly (hardcoded or via a different supported context)
35
+ 2. Use `vars` context (repository/org variables) — available in `with:` blocks
36
+ 3. Capture the env value in a prior step's GITHUB_OUTPUT and reference it via
37
+ `steps.<id>.outputs.<name>` in the subsequent `uses:` step
38
+ fix_code:
39
+ - language: yaml
40
+ label: "Wrong: env context in with: inputs (causes parse error)"
41
+ code: |
42
+ env:
43
+ API_URL: https://api.example.com
44
+
45
+ jobs:
46
+ deploy:
47
+ runs-on: ubuntu-latest
48
+ steps:
49
+ - uses: my-org/deploy-action@v1
50
+ with:
51
+ url: ${{ env.API_URL }} # ERROR: Unrecognized named-value: 'env'
52
+ - language: yaml
53
+ label: "Fix option A: use vars context (repository variable)"
54
+ code: |
55
+ # Set API_URL as a repository variable in Settings > Secrets and variables > Variables
56
+ jobs:
57
+ deploy:
58
+ runs-on: ubuntu-latest
59
+ steps:
60
+ - uses: my-org/deploy-action@v1
61
+ with:
62
+ url: ${{ vars.API_URL }} # vars context IS available in with:
63
+ - language: yaml
64
+ label: "Fix option B: capture in prior step output, reference via steps context"
65
+ code: |
66
+ env:
67
+ API_URL: https://api.example.com
68
+
69
+ jobs:
70
+ deploy:
71
+ runs-on: ubuntu-latest
72
+ steps:
73
+ - id: config
74
+ run: echo "api_url=$API_URL" >> $GITHUB_OUTPUT
75
+
76
+ - uses: my-org/deploy-action@v1
77
+ with:
78
+ url: ${{ steps.config.outputs.api_url }} # steps context IS available
79
+ prevention:
80
+ - "In with: inputs, only use: github, needs, strategy, matrix, secrets, inputs, vars, and steps (from prior completed steps) — never env or runner"
81
+ - "For static configuration values, prefer repository variables (vars context) over env — vars are available everywhere env is not"
82
+ - "If you need a dynamically computed value (from a script or env var) in a with: block, capture it to GITHUB_OUTPUT in a prior step and reference via steps.<id>.outputs"
83
+ docs:
84
+ - url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/accessing-contextual-information-about-workflow-runs#context-availability"
85
+ label: "Context availability table — which contexts are valid per syntax location"
86
+ - url: "https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#jobsjob_idstepswith"
87
+ label: "jobs.<job_id>.steps[*].with syntax documentation"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@htekdev/actions-debugger",
3
- "version": "1.0.87",
3
+ "version": "1.0.89",
4
4
  "description": "65+ real GitHub Actions errors, queryable by agents. CLI + MCP server + Copilot skills + error database.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",