@htekdev/actions-debugger 1.0.126 → 1.0.127

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,172 @@
1
+ id: caching-artifacts-075
2
+ title: '`actions/cache` entries saved by GitHub-hosted runners are not accessible from self-hosted runners — cache lookup returns miss despite matching key'
3
+ category: caching-artifacts
4
+ severity: error
5
+ tags:
6
+ - actions-cache
7
+ - self-hosted
8
+ - github-hosted
9
+ - cache-miss
10
+ - cross-runner
11
+ - ACTIONS_CACHE_URL
12
+ - cache-backend
13
+ patterns:
14
+ - regex: 'Cache not found for input keys'
15
+ flags: 'i'
16
+ - regex: 'No cache found.*self.hosted'
17
+ flags: 'i'
18
+ - regex: 'ACTIONS_CACHE_URL.*self.hosted'
19
+ flags: 'i'
20
+ - regex: 'cache.*miss.*self.hosted|self.hosted.*cache.*miss'
21
+ flags: 'i'
22
+ error_messages:
23
+ - "Cache not found for input keys: my-cache-key-abc123"
24
+ - "Warning: Cache restore failed."
25
+ - "No cache found for key my-cache-key on self-hosted runner"
26
+ root_cause: |
27
+ `actions/cache` stores and retrieves cache entries via a **runner-specific
28
+ `ACTIONS_CACHE_URL` endpoint** that is injected into each job by the Actions
29
+ infrastructure. The cache URL for a GitHub-hosted runner points to GitHub's
30
+ hosted cache service, while the cache URL for a self-hosted runner may point to
31
+ a different endpoint (e.g., GHES cache, Actions Runner Controller cache proxy,
32
+ or a completely different ACTIONS_CACHE_URL configured by the runner operator).
33
+
34
+ When a GitHub-hosted runner saves a cache entry:
35
+ - The entry is stored at GitHub's hosted cache service endpoint.
36
+ - The entry IS visible via the GitHub Cache REST API and the repository's
37
+ Actions → Caches UI.
38
+
39
+ When a self-hosted runner tries to restore the same key:
40
+ - The runner uses its own `ACTIONS_CACHE_URL`, which may point to a different
41
+ service.
42
+ - The cache lookup returns "Cache not found" even though the entry is visible
43
+ in the UI.
44
+ - No error is surfaced — the action silently reports a cache miss and the job
45
+ continues.
46
+
47
+ This is commonly encountered when:
48
+ 1. **ARC (Actions Runner Controller) on Kubernetes** — ARC runners use a
49
+ `gha-cache-server` proxy sidecar that fronts GitHub's cache API; the proxy's
50
+ cache scope or URL differs from the GitHub-hosted ACTIONS_CACHE_URL.
51
+ 2. **GHES (GitHub Enterprise Server)** — On-prem GHES cache is a separate
52
+ service from github.com hosted cache.
53
+ 3. **Mixed runner pools** — Some jobs run on GitHub-hosted (`ubuntu-latest`)
54
+ and others on self-hosted runners; they do not share cache entries.
55
+ 4. **Self-hosted runners with custom ACTIONS_CACHE_URL** — Operators configure
56
+ a custom cache backend (e.g., Artifactory, Nexus) that doesn't contain entries
57
+ from GitHub's hosted cache.
58
+
59
+ Related: actions/cache#1595 (open since April 2025).
60
+
61
+ The cache entries ARE there (visible via REST API) but are stored at a different
62
+ cache service endpoint than the one the self-hosted runner queries.
63
+ fix: |
64
+ **Option 1 (Recommended) — Ensure all cache-sharing jobs use the same runner type:**
65
+ If a job saves a cache on a GitHub-hosted runner, ensure the job that needs to
66
+ restore it also runs on a GitHub-hosted runner. Do not rely on cross-runner-type
67
+ cache sharing.
68
+
69
+ **Option 2 — Configure a shared external cache backend:**
70
+ For mixed runner environments, configure all runners (GitHub-hosted and self-hosted)
71
+ to use a shared external cache backend. This requires customizing `ACTIONS_CACHE_URL`
72
+ on your self-hosted runners to point to the same service.
73
+
74
+ **Option 3 — Re-populate cache from self-hosted runners:**
75
+ Have the self-hosted runner job save its own cache entry with the same key on first
76
+ miss. Subsequent self-hosted runner runs will hit this entry. The GitHub-hosted and
77
+ self-hosted entries may diverge if they have different paths.
78
+
79
+ **Option 4 — Use artifact-based sharing instead of cache:**
80
+ If the data must cross runner types, use `actions/upload-artifact` and
81
+ `actions/download-artifact` instead of cache. Artifacts are stored and retrieved
82
+ via the same GitHub API endpoint regardless of runner type.
83
+ fix_code:
84
+ - language: yaml
85
+ label: 'Broken — cache saved by GitHub-hosted runner, restored by self-hosted (misses)'
86
+ code: |
87
+ jobs:
88
+ build:
89
+ runs-on: ubuntu-latest # GitHub-hosted runner saves cache
90
+ steps:
91
+ - uses: actions/checkout@v4
92
+ - uses: actions/cache@v4
93
+ with:
94
+ path: ~/.npm
95
+ key: npm-${{ hashFiles('**/package-lock.json') }}
96
+ - run: npm ci
97
+
98
+ test:
99
+ runs-on: self-hosted # ✗ Self-hosted runner cannot access
100
+ needs: build # github-hosted runner's cache entry
101
+ steps:
102
+ - uses: actions/cache@v4
103
+ with:
104
+ path: ~/.npm
105
+ key: npm-${{ hashFiles('**/package-lock.json') }}
106
+ # → Always "Cache not found for input keys: npm-..."
107
+ - run: npm test
108
+
109
+ - language: yaml
110
+ label: 'Fixed — both jobs on the same runner type share cache entries'
111
+ code: |
112
+ jobs:
113
+ build:
114
+ runs-on: ubuntu-latest # ✓ Both jobs use GitHub-hosted runners
115
+ steps:
116
+ - uses: actions/checkout@v4
117
+ - uses: actions/cache@v4
118
+ with:
119
+ path: ~/.npm
120
+ key: npm-${{ hashFiles('**/package-lock.json') }}
121
+ - run: npm ci
122
+
123
+ test:
124
+ runs-on: ubuntu-latest # ✓ Same runner type = same cache backend
125
+ needs: build
126
+ steps:
127
+ - uses: actions/cache@v4
128
+ with:
129
+ path: ~/.npm
130
+ key: npm-${{ hashFiles('**/package-lock.json') }}
131
+ # ✓ Cache hit — saved by github-hosted, restored by github-hosted
132
+ - run: npm test
133
+
134
+ - language: yaml
135
+ label: 'Alternative — use upload-artifact / download-artifact for cross-runner sharing'
136
+ code: |
137
+ jobs:
138
+ build:
139
+ runs-on: ubuntu-latest # GitHub-hosted builds the artifacts
140
+ steps:
141
+ - uses: actions/checkout@v4
142
+ - run: npm ci && npm run build
143
+ - uses: actions/upload-artifact@v4
144
+ with:
145
+ name: build-output
146
+ path: dist/
147
+
148
+ test:
149
+ runs-on: self-hosted # ✓ Artifacts are accessible from any runner type
150
+ needs: build
151
+ steps:
152
+ - uses: actions/download-artifact@v4
153
+ with:
154
+ name: build-output
155
+ path: dist/
156
+ - run: npm test
157
+
158
+ prevention:
159
+ - 'Treat `actions/cache` entries as scoped to the runner type that created them — GitHub-hosted and self-hosted runners do not share a cache backend by default.'
160
+ - 'Design workflows so that cache-save and cache-restore jobs run on the same runner type (both GitHub-hosted or both self-hosted).'
161
+ - 'When mixing runner types, use `actions/upload-artifact` + `actions/download-artifact` for data that must cross the runner boundary.'
162
+ - 'Verify cache access in ARC (Actions Runner Controller) setups: ARC uses a gha-cache-server proxy that may have different scope from the GitHub-hosted cache.'
163
+ - 'Inspect `ACTIONS_CACHE_URL` in debug logs (`ACTIONS_RUNNER_DEBUG=true`) to confirm both runners are pointing to the same cache endpoint.'
164
+ docs:
165
+ - url: 'https://github.com/actions/cache/issues/1595'
166
+ label: 'actions/cache#1595: GitHub-hosted runner cache not found from self-hosted runner (open 2025)'
167
+ - url: 'https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#restrictions-for-accessing-a-cache'
168
+ label: 'GitHub Docs: Cache access restrictions'
169
+ - url: 'https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows'
170
+ label: 'GitHub Docs: Caching dependencies to speed up workflows'
171
+ - url: 'https://github.com/actions/actions-runner-controller/blob/main/docs/gha-runner-scale-set-controller/README.md'
172
+ label: 'ARC docs: Runner Scale Set — cache proxy configuration'
@@ -0,0 +1,141 @@
1
+ id: known-unsolved-074
2
+ title: '`hashFiles()` has a hardcoded 120-second timeout — fails silently on large repos with many files'
3
+ category: known-unsolved
4
+ severity: limitation
5
+ tags:
6
+ - hashFiles
7
+ - timeout
8
+ - cache-key
9
+ - large-repo
10
+ - actions-cache
11
+ - 120-seconds
12
+ - known-limitation
13
+ patterns:
14
+ - regex: 'hashFiles\(.+\) couldn''t finish within 120 seconds'
15
+ flags: 'i'
16
+ - regex: 'hashFiles.*couldn''t finish'
17
+ flags: 'i'
18
+ - regex: 'The template is not valid.*hashFiles.*couldn''t finish'
19
+ flags: 'i'
20
+ error_messages:
21
+ - "Error: The template is not valid. .github/workflows/ci.yml (Line: N, Col: M): hashFiles('Assets/**', 'Packages/**', 'ProjectSettings/**') couldn't finish within 120 seconds."
22
+ - "hashFiles('**/pom.xml') couldn't finish within 120 seconds."
23
+ - "hashFiles('**/Podfile.lock') couldn't finish within 120 seconds."
24
+ root_cause: |
25
+ The `hashFiles()` expression function has a **hardcoded 120-second timeout** inside the
26
+ GitHub Actions runner. When hashing many files — large game projects, monorepos with
27
+ thousands of dependencies, or deeply nested directory trees — the hash process (a separate
28
+ Node.js subprocess) can exceed this limit.
29
+
30
+ The timeout is set in the runner source:
31
+ `src/Runner.Worker/Expressions/HashFilesFunction.cs` as a fixed constant. There is no
32
+ workflow-level configuration to extend or remove it. Pull Request actions/runner#1844,
33
+ opened in April 2022 to make the timeout configurable, has remained unmerged for years.
34
+
35
+ **Common triggers:**
36
+ - Unity game projects hashing `Assets/**`, `Packages/**`, `ProjectSettings/**` (tens of
37
+ thousands of binary and text assets).
38
+ - Java monorepos hashing `**/pom.xml` across hundreds of modules.
39
+ - iOS projects hashing `**/Podfile.lock` where CocoaPods creates large lock files.
40
+ - `actions/cache` Post step re-computing `hashFiles()` at the **end** of the job (to
41
+ check whether the cache should be saved), by which point many new files may exist in
42
+ the hashed path, making the second hash slower than the first.
43
+ - Self-hosted Windows runners, which tend to have slower file system scan speeds than
44
+ Linux GitHub-hosted runners for large directory trees.
45
+
46
+ The error surfaces as a YAML template evaluation failure before any step runs, so the
47
+ entire job fails immediately with no useful diagnostic beyond the 120-second error.
48
+
49
+ Related: actions/runner#1840 (12 reactions, open since April 2022, last active May 2024).
50
+ fix: |
51
+ There is **no native fix** — `hashFiles()` timeout is hardcoded and cannot be increased
52
+ in workflow YAML.
53
+
54
+ **Workaround 1 — Pre-compute the hash in a shell step:**
55
+ Run a shell command to hash the target files and write the result to a single file, then
56
+ use `hashFiles()` on only that single file. The shell command runs without the 120-second
57
+ runner constraint, and hashing one file is nearly instant.
58
+
59
+ **Workaround 2 — Use the last Git commit hash for the target directory:**
60
+ `git log` is much faster than file-content hashing. If cache invalidation on the last
61
+ commit touching the directory is acceptable (rather than on file-content change), use
62
+ `git log -1 --pretty=format:%H -- <directory>` to generate the key.
63
+
64
+ **Workaround 3 — Narrow the glob pattern:**
65
+ Instead of `Assets/**`, narrow to a specific file type:
66
+ `Assets/**/*.meta` or `Assets/**/*.asset`. Fewer files = faster hash = less chance of
67
+ timeout. Acceptable when only certain file types are meaningful for cache invalidation.
68
+
69
+ **Workaround 4 — Reduce what goes in the hashed path:**
70
+ If you control the directory structure, move frequently-updated large binary files out
71
+ of the hashed path so the glob matches fewer files.
72
+ fix_code:
73
+ - language: yaml
74
+ label: 'Broken — hashFiles() times out on large directory tree'
75
+ code: |
76
+ - uses: actions/cache@v4
77
+ with:
78
+ path: Library
79
+ # ✗ hashFiles() will time out if Assets/**, Packages/**, ProjectSettings/**
80
+ # contains thousands of files (e.g. large Unity project)
81
+ key: Library-${{ hashFiles('Assets/**', 'Packages/**', 'ProjectSettings/**') }}
82
+
83
+ - language: yaml
84
+ label: 'Fixed — pre-compute hash in a shell step, then hashFiles() on single file'
85
+ code: |
86
+ - name: Generate cache key from directory contents
87
+ run: |
88
+ find Assets Packages ProjectSettings \
89
+ -type f | sort | xargs sha256sum > /tmp/unity-hash-input.txt
90
+ # On Windows self-hosted runner, use PowerShell instead:
91
+ # Get-ChildItem -Recurse Assets,Packages,ProjectSettings |
92
+ # Where-Object { !$_.PSIsContainer } |
93
+ # Sort-Object FullName |
94
+ # ForEach-Object { sha256sum $_.FullName } |
95
+ # Out-File /tmp/unity-hash-input.txt -Encoding utf8
96
+
97
+ - uses: actions/cache@v4
98
+ with:
99
+ path: Library
100
+ # ✓ hashFiles() on a single pre-computed file is nearly instant
101
+ key: Library-${{ hashFiles('/tmp/unity-hash-input.txt') }}
102
+
103
+ - language: yaml
104
+ label: 'Alternative — use last Git commit hash touching the cached directory'
105
+ code: |
106
+ - name: Get cache key from last commit touching packages
107
+ run: |
108
+ echo "PKG_HASH=$(git log -1 --pretty=format:%H -- packages/)" >> $GITHUB_ENV
109
+
110
+ - uses: actions/cache@v4
111
+ with:
112
+ path: ~/.m2/repository
113
+ # ✓ git log is instant regardless of how many files are in packages/
114
+ # Note: invalidates on commit, not on file-content change
115
+ key: maven-${{ runner.os }}-${{ env.PKG_HASH }}
116
+
117
+ - language: yaml
118
+ label: 'Alternative — narrow glob to only meaningful file types'
119
+ code: |
120
+ - uses: actions/cache@v4
121
+ with:
122
+ path: Library
123
+ # ✓ Narrow glob: only hash .meta files instead of all assets
124
+ # Fewer matched files = faster hash = less risk of timeout
125
+ key: Library-${{ hashFiles('Assets/**/*.meta', 'Packages/**/package.json') }}
126
+
127
+ prevention:
128
+ - 'For any project with more than ~10,000 files in the hashed path, pre-compute the hash in a shell step instead of using `hashFiles()` directly in the cache key expression.'
129
+ - 'Test `hashFiles()` locally by adding a step that logs the evaluation time: the timeout occurs during expression evaluation, before the step executes.'
130
+ - 'On Windows self-hosted runners, file system scan is slower — lower the threshold for when to switch to a pre-computed hash (≥5,000 files).'
131
+ - 'Watch the `actions/cache` Post step — it re-evaluates `hashFiles()` at job end to decide whether to save. If you add files to the hashed path during the job, the Post step can time out even when the Pre step succeeded.'
132
+ - 'Upvote actions/runner#1844 — the PR to make the timeout configurable. No merge timeline as of June 2026.'
133
+ docs:
134
+ - url: 'https://github.com/actions/runner/issues/1840'
135
+ label: 'actions/runner#1840: hashFiles() couldn''t finish within 120 seconds (12 reactions, open since 2022)'
136
+ - url: 'https://github.com/actions/runner/pull/1844'
137
+ label: 'actions/runner#1844: PR to make hashFiles() timeout configurable (unmerged)'
138
+ - url: 'https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/evaluate-expressions-in-workflows-and-actions#hashfiles'
139
+ label: 'GitHub Docs: hashFiles() expression function'
140
+ - url: 'https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows'
141
+ label: 'GitHub Docs: Caching dependencies to speed up workflows'
@@ -0,0 +1,146 @@
1
+ id: runner-environment-236
2
+ title: '`ubuntu-slim` runner has Docker CLI but no Docker daemon — docker build/pull and Dockerfile container actions fail'
3
+ category: runner-environment
4
+ severity: error
5
+ tags:
6
+ - ubuntu-slim
7
+ - docker
8
+ - docker-daemon
9
+ - container-action
10
+ - docker-build
11
+ - dockerfile
12
+ - lightweight-runner
13
+ patterns:
14
+ - regex: 'Cannot connect to the Docker daemon at unix:///var/run/docker\.sock'
15
+ flags: 'i'
16
+ - regex: 'docker\.sock.*no such file or directory'
17
+ flags: 'i'
18
+ - regex: 'ERROR: Cannot connect to the Docker daemon'
19
+ flags: 'i'
20
+ - regex: 'ubuntu-slim.*docker|docker.*ubuntu-slim'
21
+ flags: 'i'
22
+ error_messages:
23
+ - "Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?"
24
+ - "ERROR: Cannot connect to the Docker daemon at unix:///var/run/docker.sock: connect: no such file or directory"
25
+ - "Docker build failed with exit code 1, back off 3.588 seconds before retry."
26
+ - "failed to connect to the docker API at unix:///var/run/docker.sock; check if the path is correct and if the daemon is running: dial unix /var/run/docker.sock: connect: no such file or directory"
27
+ - "/usr/bin/docker build ... ERROR: Cannot connect to the Docker daemon"
28
+ root_cause: |
29
+ The `ubuntu-slim` GitHub-hosted runner image (added January 2026 via runner-images
30
+ PR#13542) is a **lightweight Ubuntu image intentionally stripped of the Docker daemon**.
31
+ It is designed for fast, low-overhead CI jobs (linting, unit tests, scripting) that
32
+ do not need container tooling.
33
+
34
+ **What ubuntu-slim DOES have:**
35
+ - Docker CLI (`docker` command is on `PATH`)
36
+ - Standard shell tooling, git, curl, Node.js, Python
37
+
38
+ **What ubuntu-slim does NOT have:**
39
+ - Docker daemon (no `/var/run/docker.sock` socket)
40
+ - Docker daemon service (not running — not even stopped, just not installed)
41
+ - BuildKit / buildx (requires daemon)
42
+
43
+ This affects several common patterns:
44
+ 1. **`docker build` / `docker run` / `docker pull` in `run:` steps** — All fail
45
+ immediately because there is no daemon to dispatch commands to.
46
+ 2. **Container actions** (`uses: some-org/docker-action@v1` where the action has a
47
+ `Dockerfile`) — The Actions runner tries to build the action's `Dockerfile` using
48
+ the host Docker daemon before executing the step. On `ubuntu-slim`, this fails during
49
+ job setup with "Cannot connect to the Docker daemon."
50
+ 3. **`docker/setup-buildx-action`** — Fails because BuildKit requires a Docker daemon.
51
+ 4. **Service containers** (`services:` block using Docker images) — Fail because
52
+ pulling and starting service containers requires the Docker daemon.
53
+
54
+ GitHub has closed requests to add Docker daemon to ubuntu-slim as "not_planned"
55
+ (runner-images#13583 Feb 2026), confirming this is **by design**.
56
+
57
+ This is distinct from `runner-environment-030` (ubuntu-arm64-docker-not-preinstalled),
58
+ which covers ARM64 partner runners where Docker CLI itself is missing. On ubuntu-slim,
59
+ Docker CLI IS present — only the daemon is absent.
60
+ fix: |
61
+ **Option 1 (Recommended) — Switch to `ubuntu-latest` or `ubuntu-24.04`:**
62
+ If your workflow uses Docker in any form (docker build, container actions, service
63
+ containers), use a full Ubuntu image. Docker daemon is pre-installed and running
64
+ on `ubuntu-latest` and `ubuntu-24.04`.
65
+
66
+ **Option 2 — Conditionally skip Docker-dependent steps:**
67
+ If you want to use ubuntu-slim for most of a workflow but have one Docker step, you
68
+ cannot run that step on ubuntu-slim. Restructure into two jobs: one on ubuntu-slim for
69
+ fast non-Docker steps, one on ubuntu-latest for Docker steps.
70
+
71
+ **Option 3 — Use a Docker-in-Docker container (advanced, not recommended):**
72
+ You can run a `dind` (Docker-in-Docker) container as a service and set `DOCKER_HOST`
73
+ to point to it, but this is complex, slow, and defeats the purpose of ubuntu-slim.
74
+
75
+ **Option 4 — Replace Dockerfile container actions with JS/composite alternatives:**
76
+ Some Docker-based third-party actions have JavaScript equivalents that don't require
77
+ a daemon. Check if the action you're using has a non-Docker version.
78
+ fix_code:
79
+ - language: yaml
80
+ label: 'Broken — docker commands and container actions fail on ubuntu-slim'
81
+ code: |
82
+ jobs:
83
+ build:
84
+ runs-on: ubuntu-slim # ✗ No Docker daemon available
85
+
86
+ steps:
87
+ - uses: actions/checkout@v4
88
+
89
+ # ✗ Fails: "Cannot connect to the Docker daemon at unix:///var/run/docker.sock"
90
+ - name: Build Docker image
91
+ run: docker build -t myapp:latest .
92
+
93
+ # ✗ Also fails: action uses Dockerfile, requires Docker daemon to build
94
+ - name: Run Docker-based action
95
+ uses: some-org/docker-based-action@v2
96
+
97
+ - language: yaml
98
+ label: 'Fixed — use ubuntu-latest for any workflow that needs Docker'
99
+ code: |
100
+ jobs:
101
+ build:
102
+ runs-on: ubuntu-latest # ✓ Docker daemon pre-installed and running
103
+
104
+ steps:
105
+ - uses: actions/checkout@v4
106
+
107
+ # ✓ Works: Docker daemon available on ubuntu-latest
108
+ - name: Build Docker image
109
+ run: docker build -t myapp:latest .
110
+
111
+ # ✓ Works: container actions can build their Dockerfiles
112
+ - name: Run Docker-based action
113
+ uses: some-org/docker-based-action@v2
114
+
115
+ - language: yaml
116
+ label: 'Pattern — split jobs to use ubuntu-slim for fast steps, ubuntu-latest for Docker'
117
+ code: |
118
+ jobs:
119
+ lint:
120
+ runs-on: ubuntu-slim # ✓ Fast, no Docker needed for lint
121
+ steps:
122
+ - uses: actions/checkout@v4
123
+ - run: npm run lint
124
+
125
+ docker-build:
126
+ runs-on: ubuntu-latest # ✓ Docker available for build/push steps
127
+ needs: lint
128
+ steps:
129
+ - uses: actions/checkout@v4
130
+ - run: docker build -t myapp:latest .
131
+ - run: docker push myregistry/myapp:latest
132
+
133
+ prevention:
134
+ - 'Before switching to `ubuntu-slim`, audit your workflow for `docker` commands, Dockerfile-based `uses:` steps, and `services:` blocks — any of these require a Docker daemon.'
135
+ - 'Container actions (actions with a `Dockerfile`) silently fail during job setup on ubuntu-slim, making the error appear before any step runs — check the "Set up job" section of the logs.'
136
+ - 'Check the ubuntu-slim software list at https://github.com/actions/runner-images to confirm Docker daemon is not present before migrating workflows.'
137
+ - '`service containers` defined in the `services:` block also require the Docker daemon — they will also fail on ubuntu-slim.'
138
+ docs:
139
+ - url: 'https://github.com/actions/runner-images/issues/13583'
140
+ label: 'runner-images#13583: Docker pull failed on ubuntu-slim (closed as not_planned — by design)'
141
+ - url: 'https://github.com/actions/runner-images/pull/13542'
142
+ label: 'runner-images PR#13542: Add ubuntu-slim image (Jan 2026)'
143
+ - url: 'https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners'
144
+ label: 'GitHub Docs: About GitHub-hosted runners'
145
+ - url: 'https://docs.github.com/en/actions/creating-actions/creating-a-docker-container-action'
146
+ label: 'GitHub Docs: Creating a Docker container action'
@@ -0,0 +1,173 @@
1
+ id: triggers-073
2
+ title: '`on: workflow_run: branches:` filter matches head_branch of triggering run — PR merge triggers are silently skipped when head_branch is the PR branch, not the merge target'
3
+ category: triggers
4
+ severity: silent-failure
5
+ tags:
6
+ - workflow_run
7
+ - branches-filter
8
+ - head-branch
9
+ - pr-merge
10
+ - silent-skip
11
+ - trigger-not-firing
12
+ - deploy-workflow
13
+ patterns:
14
+ - regex: 'workflow_run:[\s\S]{0,200}branches:'
15
+ flags: 'im'
16
+ - regex: 'github\.event\.workflow_run\.head_branch'
17
+ flags: 'i'
18
+ - regex: 'workflow_run.*branches.*\[.*main.*\]'
19
+ flags: 'i'
20
+ error_messages:
21
+ - "workflow not triggering after PR merge"
22
+ - "workflow_run with branches filter not firing on merge to main"
23
+ root_cause: |
24
+ The `branches:` filter in an `on: workflow_run:` trigger compares against
25
+ `github.event.workflow_run.head_branch` — the branch the **source workflow** ran on.
26
+
27
+ When a pull request is opened, the source workflow (e.g., CI) runs with
28
+ `head_branch` = the feature branch name (e.g., `feat/my-change`). When GitHub
29
+ handles the PR merge, it creates a push to `main`, but it **reuses the PR's existing
30
+ check suite** rather than creating a new check run for the merge commit. As a result,
31
+ the `workflow_run` event that fires after the merge has:
32
+
33
+ ```
34
+ github.event.workflow_run.head_branch = "feat/my-change" # PR branch, not "main"
35
+ github.event.workflow_run.head_sha = "<merge-commit-sha>"
36
+ ```
37
+
38
+ If a downstream workflow has `branches: [main]`, this filter is evaluated against
39
+ `head_branch` = `"feat/my-change"`. The filter does NOT match — the downstream
40
+ workflow **silently never runs** after the PR merge.
41
+
42
+ This is counterintuitive because developers expect `branches: [main]` to mean
43
+ "trigger my deployment workflow only when CI ran on the main branch," not "only
44
+ when the source workflow's head_branch exactly equals main." The distinction matters
45
+ specifically for PR merges, where the push IS to main but the check run is attributed
46
+ to the PR branch.
47
+
48
+ **Who is affected:**
49
+ - Any deploy-on-merge pattern using `workflow_run` with `branches: [main]` or
50
+ `branches: [master]`
51
+ - Workflows that use `workflow_run` to chain CI → deploy only for the default branch
52
+
53
+ **Note:** Workflows triggered by a direct push to `main` (not a PR merge) DO have
54
+ `head_branch = "main"` and ARE correctly triggered by the `branches: [main]` filter.
55
+ The problem is specific to PR merges that go through the PR check-suite flow.
56
+
57
+ Source: observed in production deployments (commit Skretzo/shortest-path@8254fb4),
58
+ GitHub docs issue github/docs#42813 (Feb 2026).
59
+ fix: |
60
+ **Remove `branches:` from the `workflow_run` trigger** and instead enforce the branch
61
+ restriction in a **job-level `if:` condition** that explicitly checks
62
+ `github.event.workflow_run.head_branch`:
63
+
64
+ ```yaml
65
+ on:
66
+ workflow_run:
67
+ workflows: ["CI"]
68
+ types: [completed]
69
+ # ✗ Remove: branches: [main]
70
+
71
+ jobs:
72
+ deploy:
73
+ # ✓ Check head_branch here instead — this sees the actual branch
74
+ if: >-
75
+ github.event.workflow_run.conclusion == 'success' &&
76
+ github.event.workflow_run.head_branch == 'main'
77
+ ```
78
+
79
+ This approach works for both direct pushes to main AND PR merges to main,
80
+ because the `if:` condition is evaluated at job execution time with the full
81
+ `workflow_run` event payload, while the `branches:` filter is evaluated at
82
+ trigger time and uses different matching semantics.
83
+
84
+ Alternatively, use the `workflow_run` trigger WITHOUT a branches filter and
85
+ rely entirely on job conditions to control which branches proceed to deployment.
86
+ fix_code:
87
+ - language: yaml
88
+ label: 'Broken — branches: [main] silently blocks PR merge triggers'
89
+ code: |
90
+ # .github/workflows/deploy.yml
91
+ on:
92
+ workflow_run:
93
+ workflows: ["CI"]
94
+ types: [completed]
95
+ branches: [main] # ✗ Matches head_branch of triggering run
96
+ # PR merges have head_branch = PR branch name
97
+ # → deploy never fires after PR merges to main
98
+
99
+ jobs:
100
+ deploy:
101
+ runs-on: ubuntu-latest
102
+ if: github.event.workflow_run.conclusion == 'success'
103
+ steps:
104
+ - run: ./deploy.sh
105
+
106
+ - language: yaml
107
+ label: 'Fixed — remove branches filter; check head_branch in job condition'
108
+ code: |
109
+ # .github/workflows/deploy.yml
110
+ on:
111
+ workflow_run:
112
+ workflows: ["CI"]
113
+ types: [completed]
114
+ # ✓ No branches filter — let all workflow_run events through
115
+
116
+ jobs:
117
+ deploy:
118
+ runs-on: ubuntu-latest
119
+ # ✓ Check head_branch in the if: condition
120
+ # head_branch == 'main' correctly identifies merges to main
121
+ if: >-
122
+ github.event.workflow_run.conclusion == 'success' &&
123
+ github.event.workflow_run.head_branch == 'main'
124
+ steps:
125
+ - uses: actions/checkout@v4
126
+ with:
127
+ ref: ${{ github.event.workflow_run.head_sha }}
128
+ - run: ./deploy.sh
129
+
130
+ - language: yaml
131
+ label: 'Pattern — full deploy-on-merge via workflow_run with branch guard'
132
+ code: |
133
+ # .github/workflows/deploy.yml
134
+ # Runs after CI completes successfully on any branch,
135
+ # but only deploys when it ran on main (direct push OR PR merge)
136
+ name: Deploy
137
+
138
+ on:
139
+ workflow_run:
140
+ workflows: ["CI"]
141
+ types: [completed]
142
+
143
+ jobs:
144
+ deploy:
145
+ name: Deploy to production
146
+ runs-on: ubuntu-latest
147
+ if: >-
148
+ github.event.workflow_run.conclusion == 'success' &&
149
+ github.event.workflow_run.head_branch == 'main'
150
+
151
+ steps:
152
+ - uses: actions/checkout@v4
153
+ with:
154
+ # ✓ Check out the exact commit that CI ran on
155
+ ref: ${{ github.event.workflow_run.head_sha }}
156
+
157
+ - name: Deploy
158
+ run: |
159
+ echo "Deploying commit ${{ github.event.workflow_run.head_sha }}"
160
+ ./deploy.sh
161
+
162
+ prevention:
163
+ - 'Never use `branches:` in `on: workflow_run:` if your deployment pattern relies on PR merges — always enforce branch restrictions in `jobs.<id>.if` conditions instead.'
164
+ - 'Test the pattern by creating a PR, merging it, and checking the Actions tab — the `workflow_run` event should appear even without a `branches` filter.'
165
+ - 'Use `github.event.workflow_run.head_branch` in the `if:` condition to distinguish deploy-worthy runs from feature-branch CI runs.'
166
+ - 'Document this behavior in your workflow comments so future contributors understand why the `branches:` filter is not used.'
167
+ docs:
168
+ - url: 'https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#workflow_run'
169
+ label: 'GitHub Docs: workflow_run trigger — branches filter behavior'
170
+ - url: 'https://github.com/github/docs/issues/42813'
171
+ label: 'github/docs#42813: Clarify branches filter on workflow_run (Feb 2026)'
172
+ - url: 'https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#using-data-from-the-triggering-workflow'
173
+ label: 'GitHub Docs: Using data from the triggering workflow'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@htekdev/actions-debugger",
3
- "version": "1.0.126",
3
+ "version": "1.0.127",
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",