@htekdev/actions-debugger 1.0.117 → 1.0.119
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/errors/caching-artifacts/caching-artifacts-069.yml +133 -0
- package/errors/caching-artifacts/caching-artifacts-070.yml +94 -0
- package/errors/concurrency-timing/concurrency-timing-056.yml +127 -0
- package/errors/concurrency-timing/concurrency-timing-057.yml +115 -0
- package/errors/concurrency-timing/workflow-run-head-branch-null-schedule-dispatch-concurrency.yml +135 -0
- package/errors/known-unsolved/known-unsolved-067.yml +117 -0
- package/errors/known-unsolved/known-unsolved-068.yml +124 -0
- package/errors/known-unsolved/node-action-post-step-wrong-inputs-nested-composite.yml +133 -0
- package/errors/known-unsolved/ubuntu-24-04-arm64-missing-binder-ashmem-kernel-modules.yml +149 -0
- package/errors/permissions-auth/permissions-auth-069.yml +161 -0
- package/errors/runner-environment/arc-autoscalinglistener-ephemeralrunnerset-stale-after-upgrade.yml +134 -0
- package/errors/runner-environment/broker-server-socket-exception-nat-timeout-linux.yml +114 -0
- package/errors/runner-environment/runner-environment-210.yml +105 -0
- package/errors/runner-environment/runner-environment-213.yml +142 -0
- package/errors/runner-environment/runner-environment-214.yml +107 -0
- package/errors/runner-environment/runner-environment-215.yml +93 -0
- package/errors/runner-environment/runner-environment-216.yml +82 -0
- package/errors/runner-environment/runner-environment-217.yml +99 -0
- package/errors/runner-environment/runner-environment-218.yml +111 -0
- package/errors/runner-environment/ubuntu-24-man-db-dpkg-trigger-apt-install-stall.yml +94 -0
- package/errors/runner-environment/ubuntu-26-04-missing-preinstalled-tools.yml +178 -0
- package/errors/runner-environment/upload-artifact-v6-proxy-headers-leak-strict-proxy-fail.yml +101 -0
- package/errors/silent-failures/silent-failures-108.yml +108 -0
- package/errors/silent-failures/silent-failures-109.yml +119 -0
- package/errors/silent-failures/silent-failures-110.yml +91 -0
- package/errors/silent-failures/silent-failures-111.yml +107 -0
- package/errors/triggers/pull-request-labeled-fires-all-labels-no-name-filter.yml +110 -0
- package/errors/yaml-syntax/duplicate-step-id-within-job-scope-validation-error.yml +130 -0
- package/errors/yaml-syntax/yaml-syntax-072.yml +93 -0
- package/errors/yaml-syntax/yaml-syntax-073.yml +103 -0
- package/package.json +1 -1
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
id: known-unsolved-067
|
|
2
|
+
title: 'ubuntu-24.04 Runner df Reports 12-15 GB Ghost Disk Usage — Invisible to du/lsof'
|
|
3
|
+
category: known-unsolved
|
|
4
|
+
severity: silent-failure
|
|
5
|
+
tags:
|
|
6
|
+
- ubuntu-24
|
|
7
|
+
- disk-space
|
|
8
|
+
- enospc
|
|
9
|
+
- runner-agent
|
|
10
|
+
- diagnostics
|
|
11
|
+
- phantom-disk
|
|
12
|
+
- playwright
|
|
13
|
+
- hosted-runner
|
|
14
|
+
patterns:
|
|
15
|
+
- regex: 'ENOSPC:\s*no space left on device'
|
|
16
|
+
flags: 'i'
|
|
17
|
+
- regex: 'df\s+/\s+.*\d{4,5}M\s+.*\d+%'
|
|
18
|
+
flags: 'i'
|
|
19
|
+
- regex: 'No space left on device'
|
|
20
|
+
flags: 'i'
|
|
21
|
+
error_messages:
|
|
22
|
+
- 'ENOSPC: no space left on device, write'
|
|
23
|
+
- 'No space left on device'
|
|
24
|
+
- 'df: cannot read table of mounted file systems: No space left on device'
|
|
25
|
+
root_cause: |
|
|
26
|
+
On ubuntu-24.04 hosted runners, `df /` can report 12–15 GB of disk used
|
|
27
|
+
during heavy test runs (particularly those spawning many short-lived child
|
|
28
|
+
processes or producing large volumes of stdout, such as Playwright WebKit /
|
|
29
|
+
WPE test suites). This usage CANNOT be accounted for by:
|
|
30
|
+
|
|
31
|
+
- `du -shx /` (sum of all directories does not grow)
|
|
32
|
+
- `lsof +L1` (deleted-but-open files show only kernel /memfd:* entries)
|
|
33
|
+
- /proc/<PID>/maps (only kernel memfd entries)
|
|
34
|
+
- /proc/<PID>/io write_bytes (single-digit MB cumulative)
|
|
35
|
+
|
|
36
|
+
The ghost usage RECOVERS fully ~40 seconds after the job's main process
|
|
37
|
+
exits — gradually, over ~10 seconds — even though all child processes are
|
|
38
|
+
already reaped at recovery start. This rules out lingering processes holding
|
|
39
|
+
mmap'd files.
|
|
40
|
+
|
|
41
|
+
Best-guess root cause (unconfirmed by GitHub team as of June 2026): the
|
|
42
|
+
runner agent's diagnostic/log buffers are flushed periodically on the host
|
|
43
|
+
and the flushed bytes are counted in the container's `df` view but are not
|
|
44
|
+
visible from inside the runner's PID namespace. The ~40-second recovery delay
|
|
45
|
+
is consistent with a periodic flush cycle on the agent side.
|
|
46
|
+
|
|
47
|
+
This issue is non-deterministic and tied to the state of the underlying host
|
|
48
|
+
VM. The same workload run locally on ubuntu-24.04 does not reproduce.
|
|
49
|
+
|
|
50
|
+
Affected environments:
|
|
51
|
+
- Native `ubuntu-24.04` hosted runner
|
|
52
|
+
- Containers running on the `ubuntu-24.04` runner (which share the host's /)
|
|
53
|
+
- Does NOT reproduce on self-hosted ubuntu-24.04 VM locally
|
|
54
|
+
|
|
55
|
+
Tracked upstream: https://github.com/actions/runner/issues/4448 (open, May 2026)
|
|
56
|
+
fix: |
|
|
57
|
+
There is NO user-side fix for the phantom disk usage itself — this is
|
|
58
|
+
infrastructure-level behaviour outside the workflow's control.
|
|
59
|
+
|
|
60
|
+
Mitigations to prevent ENOSPC failures:
|
|
61
|
+
|
|
62
|
+
1. Use a larger runner (8-core or 16-core) — larger runner classes have
|
|
63
|
+
more disk allocated on different host hardware.
|
|
64
|
+
|
|
65
|
+
2. Reduce stdout volume by adding --quiet / --silent flags to test runners
|
|
66
|
+
and package managers (npm ci --quiet, pytest -q, etc.).
|
|
67
|
+
|
|
68
|
+
3. Pre-clean the runner's docker layer cache and tool downloads that are
|
|
69
|
+
not needed:
|
|
70
|
+
- name: Free disk space
|
|
71
|
+
run: |
|
|
72
|
+
sudo rm -rf /usr/share/dotnet
|
|
73
|
+
sudo rm -rf /opt/ghc
|
|
74
|
+
sudo rm -rf /usr/local/lib/android
|
|
75
|
+
docker system prune -af
|
|
76
|
+
|
|
77
|
+
4. Split the job into smaller parallel matrix jobs to reduce per-job output.
|
|
78
|
+
|
|
79
|
+
5. Monitor disk in a background step to detect the ghost spike early and
|
|
80
|
+
correlate it with failures.
|
|
81
|
+
fix_code:
|
|
82
|
+
- language: yaml
|
|
83
|
+
label: 'Pre-clean unused runner tools to reclaim disk headroom'
|
|
84
|
+
code: |
|
|
85
|
+
steps:
|
|
86
|
+
- name: Free runner disk space
|
|
87
|
+
run: |
|
|
88
|
+
sudo rm -rf /usr/share/dotnet /opt/ghc /usr/local/lib/android
|
|
89
|
+
sudo apt-get clean
|
|
90
|
+
docker system prune -af --volumes || true
|
|
91
|
+
df -h / # confirm headroom before heavy tests
|
|
92
|
+
|
|
93
|
+
- name: Run Playwright tests
|
|
94
|
+
run: npx playwright test
|
|
95
|
+
- language: yaml
|
|
96
|
+
label: 'Use a larger runner with more disk allocation'
|
|
97
|
+
code: |
|
|
98
|
+
jobs:
|
|
99
|
+
test:
|
|
100
|
+
runs-on: ubuntu-latest-8-cores # or ubuntu-24.04-x64-8-cores
|
|
101
|
+
steps:
|
|
102
|
+
- run: npx playwright test
|
|
103
|
+
prevention:
|
|
104
|
+
- 'Add `df -h /` before and after heavy test steps to measure actual disk
|
|
105
|
+
consumption and detect when the ghost spike occurs.'
|
|
106
|
+
- 'Reduce test output verbosity — the agent diagnostic buffer hypothesis
|
|
107
|
+
correlates large stdout volumes with larger phantom disk readings.'
|
|
108
|
+
- 'For Playwright/WebKit CI that regularly sees ENOSPC: switch to
|
|
109
|
+
`ubuntu-24.04` larger runners or use `--reporter=dot` to minimise output.'
|
|
110
|
+
- 'Do not rely on `du -shx /` for disk capacity planning on hosted runners —
|
|
111
|
+
`df /` may show significantly more usage than du can account for during
|
|
112
|
+
heavy-output jobs.'
|
|
113
|
+
docs:
|
|
114
|
+
- url: 'https://github.com/actions/runner/issues/4448'
|
|
115
|
+
label: 'runner #4448 — df reports 12-15 GB ghost disk usage on ubuntu-24.04 runner (open, May 2026)'
|
|
116
|
+
- url: 'https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources'
|
|
117
|
+
label: 'GitHub Docs — Hosted runner hardware resources (disk sizes per runner class)'
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
id: known-unsolved-068
|
|
2
|
+
title: "Step outcome cannot distinguish timeout from failure — both report as 'failure' in steps context"
|
|
3
|
+
category: known-unsolved
|
|
4
|
+
severity: limitation
|
|
5
|
+
tags:
|
|
6
|
+
- timeout-minutes
|
|
7
|
+
- outcome
|
|
8
|
+
- conclusion
|
|
9
|
+
- continue-on-error
|
|
10
|
+
- steps-context
|
|
11
|
+
- retry
|
|
12
|
+
- known-limitation
|
|
13
|
+
- no-fix
|
|
14
|
+
patterns:
|
|
15
|
+
- regex: 'steps\.\w+\.outcome\s*==\s*.failure.'
|
|
16
|
+
flags: 'i'
|
|
17
|
+
- regex: 'timeout-minutes.*continue-on-error|continue-on-error.*timeout-minutes'
|
|
18
|
+
flags: 'im'
|
|
19
|
+
- regex: 'The process.*timed out after \d+ minutes'
|
|
20
|
+
flags: 'i'
|
|
21
|
+
error_messages:
|
|
22
|
+
- "Error: The process '/usr/bin/bash' failed with exit code 1"
|
|
23
|
+
- 'Error: Process completed with exit code 1'
|
|
24
|
+
root_cause: |
|
|
25
|
+
GitHub Actions exposes two result fields for completed steps in the steps context:
|
|
26
|
+
|
|
27
|
+
- steps.<id>.outcome: the raw result before continue-on-error is applied.
|
|
28
|
+
Possible values: success, failure, cancelled, skipped.
|
|
29
|
+
- steps.<id>.conclusion: the final result after continue-on-error is applied.
|
|
30
|
+
When continue-on-error: true is set on a failed step, conclusion becomes 'success'
|
|
31
|
+
even if outcome is 'failure'.
|
|
32
|
+
|
|
33
|
+
Neither field distinguishes between a step that failed because the process exited with a
|
|
34
|
+
non-zero code and a step that failed because it hit its timeout-minutes limit. Both
|
|
35
|
+
scenarios set outcome to 'failure'. There is no 'timed_out' value, no
|
|
36
|
+
steps.<id>.timed_out boolean, and no built-in expression function to query the reason
|
|
37
|
+
for failure.
|
|
38
|
+
|
|
39
|
+
This means workflows cannot natively:
|
|
40
|
+
- Retry only on timeout while failing fast on real errors
|
|
41
|
+
- Alert with different severity for timeouts vs application failures
|
|
42
|
+
- Auto-escalate timeout-minutes only when a timeout (not a logic error) occurred
|
|
43
|
+
|
|
44
|
+
The limitation has been a known open request in the GitHub Actions community since at
|
|
45
|
+
least 2022 with no current implementation timeline from GitHub.
|
|
46
|
+
fix: |
|
|
47
|
+
No native fix exists within GitHub Actions expressions. Two manual workarounds are
|
|
48
|
+
available in bash-based steps:
|
|
49
|
+
|
|
50
|
+
1. Record start time and compute elapsed duration at the next step to infer timeout:
|
|
51
|
+
Compare elapsed seconds against the timeout-minutes threshold. A step that used
|
|
52
|
+
approximately 100% of its time budget likely timed out.
|
|
53
|
+
|
|
54
|
+
2. Write a sentinel file just before the critical work; check for its absence afterward.
|
|
55
|
+
A timed-out step never reaches the sentinel-write line after the long-running command,
|
|
56
|
+
while a normally-failing step (which exits immediately on error) may or may not.
|
|
57
|
+
|
|
58
|
+
Neither workaround is exact — both have race conditions and edge cases. The most
|
|
59
|
+
reliable approach is to implement timeout detection inside the script itself using
|
|
60
|
+
shell signals or test-framework timeout flags.
|
|
61
|
+
fix_code:
|
|
62
|
+
- language: yaml
|
|
63
|
+
label: 'Workaround 1: Infer timeout via elapsed time'
|
|
64
|
+
code: |
|
|
65
|
+
- name: Start timer
|
|
66
|
+
id: timer
|
|
67
|
+
run: echo "start=$(date +%s)" >> "$GITHUB_OUTPUT"
|
|
68
|
+
|
|
69
|
+
- name: Run slow tests
|
|
70
|
+
id: tests
|
|
71
|
+
timeout-minutes: 10
|
|
72
|
+
continue-on-error: true
|
|
73
|
+
run: npm test
|
|
74
|
+
|
|
75
|
+
- name: Classify failure type
|
|
76
|
+
if: steps.tests.outcome == 'failure'
|
|
77
|
+
env:
|
|
78
|
+
START: ${{ steps.timer.outputs.start }}
|
|
79
|
+
run: |
|
|
80
|
+
elapsed=$(( $(date +%s) - START ))
|
|
81
|
+
timeout_secs=600 # 10 minutes in seconds
|
|
82
|
+
threshold=$(( timeout_secs - 30 )) # within 30s of limit → likely timeout
|
|
83
|
+
if [ "$elapsed" -ge "$threshold" ]; then
|
|
84
|
+
echo "::warning::Step likely timed out (elapsed ${elapsed}s, limit ${timeout_secs}s)"
|
|
85
|
+
# Handle timeout-specific logic here (e.g., don't fail, just warn)
|
|
86
|
+
else
|
|
87
|
+
echo "::error::Step failed (exit code, not timeout — elapsed ${elapsed}s)"
|
|
88
|
+
exit 1
|
|
89
|
+
fi
|
|
90
|
+
- language: yaml
|
|
91
|
+
label: 'Workaround 2: Sentinel file to detect timeout vs normal failure'
|
|
92
|
+
code: |
|
|
93
|
+
- name: Run tests with sentinel
|
|
94
|
+
id: tests
|
|
95
|
+
timeout-minutes: 10
|
|
96
|
+
continue-on-error: true
|
|
97
|
+
run: |
|
|
98
|
+
# The long-running command:
|
|
99
|
+
npm test
|
|
100
|
+
# Only reached on clean exit (not timeout, not error):
|
|
101
|
+
touch /tmp/test-completed
|
|
102
|
+
|
|
103
|
+
- name: Check failure reason
|
|
104
|
+
if: steps.tests.outcome == 'failure'
|
|
105
|
+
run: |
|
|
106
|
+
if [ ! -f /tmp/test-completed ]; then
|
|
107
|
+
echo "Step timed out or failed before completing"
|
|
108
|
+
# Inspect logs for timeout keyword:
|
|
109
|
+
# If the runner log shows "The process timed out after N minutes" → it was timeout
|
|
110
|
+
else
|
|
111
|
+
echo "Step completed but exited non-zero — application failure"
|
|
112
|
+
exit 1
|
|
113
|
+
fi
|
|
114
|
+
prevention:
|
|
115
|
+
- 'Log test durations inside the script itself; test framework flags like --testTimeout (Jest) or --timeout (Mocha) provide per-test granularity inside logs.'
|
|
116
|
+
- 'Use separate jobs for steps with different timeout characteristics — a dedicated integration-test job with a high timeout-minutes and a unit-test job with a low one makes failures easier to categorize.'
|
|
117
|
+
- 'If the step runs a single long command, wrap it in a shell timeout with a slightly shorter duration than timeout-minutes; the shell timeout exit code (124) is detectable inside the same step.'
|
|
118
|
+
docs:
|
|
119
|
+
- url: 'https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/accessing-contextual-information-about-workflow-runs#steps-context'
|
|
120
|
+
label: 'GitHub Docs: steps context — outcome and conclusion fields'
|
|
121
|
+
- url: 'https://stackoverflow.com/questions/78233438/github-action-cannot-get-timeout-status-from-previous-step'
|
|
122
|
+
label: 'SO: Cannot get timeout status from previous step (Mar 2024)'
|
|
123
|
+
- url: 'https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/using-conditions-to-control-job-execution'
|
|
124
|
+
label: 'GitHub Docs: Status check functions (failure, success, cancelled, always)'
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
id: known-unsolved-066
|
|
2
|
+
title: 'Node Action Post Step Receives Wrong INPUT_* Env Vars When Called Through Nested Composite Action'
|
|
3
|
+
category: known-unsolved
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- composite-actions
|
|
7
|
+
- post-step
|
|
8
|
+
- node-action
|
|
9
|
+
- nested
|
|
10
|
+
- inputs
|
|
11
|
+
- runner-bug
|
|
12
|
+
- savestate
|
|
13
|
+
patterns:
|
|
14
|
+
- regex: 'Input required and not supplied:\s*\S+'
|
|
15
|
+
flags: 'i'
|
|
16
|
+
- regex: 'Post job cleanup\.\s*\n.*Input required'
|
|
17
|
+
flags: 'im'
|
|
18
|
+
- regex: 'post.*wrong.*input|INPUT_.*post.*ancestor'
|
|
19
|
+
flags: 'i'
|
|
20
|
+
error_messages:
|
|
21
|
+
- 'Input required and not supplied: token'
|
|
22
|
+
- 'Input required and not supplied: test'
|
|
23
|
+
- 'Error: Input required and not supplied: <input-name>'
|
|
24
|
+
- 'Post job cleanup.'
|
|
25
|
+
root_cause: |
|
|
26
|
+
Runner bug (actions/runner#3514, actions/runner#2030, open since 2022): when a Node.js
|
|
27
|
+
action that has a `post:` step is invoked through one or more composite action layers,
|
|
28
|
+
the runner restores the wrong `INPUT_*` environment variables for the post step execution.
|
|
29
|
+
|
|
30
|
+
At post-step execution time, the runner sets environment variables from the nearest
|
|
31
|
+
ancestor composite action's inputs, not from the inputs actually passed to the Node
|
|
32
|
+
action itself. For example:
|
|
33
|
+
|
|
34
|
+
Workflow → outer-composite (inputs: image-tag: "foo") → inner-composite
|
|
35
|
+
→ node-action (inputs: image-tag: "foo")
|
|
36
|
+
|
|
37
|
+
The node action's main step correctly sees INPUT_IMAGE_TAG=foo.
|
|
38
|
+
In the post step, INPUT_IMAGE_TAG is absent or overwritten by the outer composite's
|
|
39
|
+
INPUT_IMAGE_TAG value (or another ancestor composite's value), causing:
|
|
40
|
+
- Required inputs to appear missing → visible error in post cleanup
|
|
41
|
+
- Optional inputs to resolve to wrong values → silent wrong behavior (e.g.,
|
|
42
|
+
devcontainers/ci pushes image with wrong tag; codeql-action uploads SARIF with
|
|
43
|
+
wrong token)
|
|
44
|
+
|
|
45
|
+
This affects ANY Node action with a post step that is called through composite
|
|
46
|
+
action nesting (depth ≥ 2). First-party actions affected include github/codeql-action
|
|
47
|
+
(fixed via workaround in codeql-action#2557) and pnpm/action-setup (issue #253).
|
|
48
|
+
fix: |
|
|
49
|
+
GitHub has not fixed the runner bug. The canonical workaround is to persist inputs
|
|
50
|
+
in the action's main step using `core.saveState()` and read them back in the post
|
|
51
|
+
step using `core.getState()` instead of `core.getInput()`.
|
|
52
|
+
|
|
53
|
+
Actions consuming this workaround pattern:
|
|
54
|
+
- github/codeql-action (PR #2557): saveState for upload inputs
|
|
55
|
+
- Any action that reads inputs in its post step
|
|
56
|
+
|
|
57
|
+
If you maintain a Node action with a post step, add to your main.ts:
|
|
58
|
+
core.saveState('my-input', core.getInput('my-input'));
|
|
59
|
+
And in your post.ts:
|
|
60
|
+
const val = core.getState('my-input'); // use this instead of core.getInput
|
|
61
|
+
|
|
62
|
+
If you are a workflow author calling a third-party action through composite layers
|
|
63
|
+
and seeing wrong post-step behavior, check whether the action uses `core.getInput`
|
|
64
|
+
in its post step. If so, file an issue with the action maintainer referencing
|
|
65
|
+
actions/runner#3514 and the saveState workaround.
|
|
66
|
+
fix_code:
|
|
67
|
+
- language: typescript
|
|
68
|
+
label: 'Action main.ts — persist inputs to state before post step runs'
|
|
69
|
+
code: |
|
|
70
|
+
import * as core from '@actions/core';
|
|
71
|
+
|
|
72
|
+
async function run() {
|
|
73
|
+
// Read inputs normally in main
|
|
74
|
+
const token = core.getInput('token', { required: true });
|
|
75
|
+
const imageName = core.getInput('image-name');
|
|
76
|
+
|
|
77
|
+
// Persist for post step (workaround for runner#3514)
|
|
78
|
+
core.saveState('token', token);
|
|
79
|
+
core.saveState('image-name', imageName);
|
|
80
|
+
|
|
81
|
+
// ... rest of main logic
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
run();
|
|
85
|
+
- language: typescript
|
|
86
|
+
label: 'Action post.ts — read from state, NOT core.getInput'
|
|
87
|
+
code: |
|
|
88
|
+
import * as core from '@actions/core';
|
|
89
|
+
|
|
90
|
+
async function runPost() {
|
|
91
|
+
// Use getState, NOT getInput — inputs are wrong in post step
|
|
92
|
+
// when called through nested composite action (runner#3514)
|
|
93
|
+
const token = core.getState('token');
|
|
94
|
+
const imageName = core.getState('image-name');
|
|
95
|
+
|
|
96
|
+
// ... post step logic using state values
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
runPost();
|
|
100
|
+
- language: yaml
|
|
101
|
+
label: 'action.yml — declare post step'
|
|
102
|
+
code: |
|
|
103
|
+
name: 'My Action'
|
|
104
|
+
inputs:
|
|
105
|
+
token:
|
|
106
|
+
required: true
|
|
107
|
+
image-name:
|
|
108
|
+
required: false
|
|
109
|
+
runs:
|
|
110
|
+
using: 'node20'
|
|
111
|
+
main: 'dist/main.js'
|
|
112
|
+
post: 'dist/post.js'
|
|
113
|
+
post-if: always()
|
|
114
|
+
prevention:
|
|
115
|
+
- 'In any Node action with a post: step, always use core.saveState/core.getState for
|
|
116
|
+
inputs consumed in post, never core.getInput — this is defensive programming regardless
|
|
117
|
+
of nesting depth'
|
|
118
|
+
- 'Test your action in a composite action wrapper (at least 2 layers deep) to catch
|
|
119
|
+
this bug before publishing'
|
|
120
|
+
- 'Check release notes of actions/runner for fixes to this bug before assuming
|
|
121
|
+
the built-in behavior is fixed'
|
|
122
|
+
- 'When using actions with known post-step input bugs through composite layers,
|
|
123
|
+
consider calling them directly from the workflow (not nested in a composite) as
|
|
124
|
+
a temporary workaround'
|
|
125
|
+
docs:
|
|
126
|
+
- url: 'https://github.com/actions/runner/issues/3514'
|
|
127
|
+
label: 'actions/runner#3514 — Wrong environment passed to node post when called by composite called by composite'
|
|
128
|
+
- url: 'https://github.com/actions/runner/issues/2030'
|
|
129
|
+
label: 'actions/runner#2030 — Composite: Nested actions post steps have the wrong context (open since 2022)'
|
|
130
|
+
- url: 'https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/workflow-commands-for-github-actions#sending-values-to-the-pre-and-post-actions'
|
|
131
|
+
label: 'GitHub Docs — Sending values to pre and post actions (saveState/getState)'
|
|
132
|
+
- url: 'https://github.com/github/codeql-action/pull/2557'
|
|
133
|
+
label: 'codeql-action#2557 — Fix: persist inputs between upload action and post step (reference implementation)'
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
id: known-unsolved-065
|
|
2
|
+
title: 'ubuntu-24.04-arm64 Hosted Runner Kernel Missing binder_linux and ashmem_linux Modules — Android Container Tests Fail'
|
|
3
|
+
category: known-unsolved
|
|
4
|
+
severity: limitation
|
|
5
|
+
tags:
|
|
6
|
+
- ubuntu-24.04-arm64
|
|
7
|
+
- arm64
|
|
8
|
+
- kernel-modules
|
|
9
|
+
- android
|
|
10
|
+
- binder
|
|
11
|
+
- ashmem
|
|
12
|
+
- container
|
|
13
|
+
- known-limitation
|
|
14
|
+
patterns:
|
|
15
|
+
- regex: 'modprobe: FATAL: Module binder_linux not found|modprobe.*binder_linux.*not found'
|
|
16
|
+
flags: 'i'
|
|
17
|
+
- regex: 'modprobe: FATAL: Module ashmem_linux not found|modprobe.*ashmem_linux.*not found'
|
|
18
|
+
flags: 'i'
|
|
19
|
+
- regex: '/dev/binder: No such file or directory|/dev/ashmem: No such file or directory'
|
|
20
|
+
flags: 'i'
|
|
21
|
+
- regex: 'CONFIG_ANDROID_BINDER_IPC.*not set|binder_linux.*absent.*kernel'
|
|
22
|
+
flags: 'i'
|
|
23
|
+
error_messages:
|
|
24
|
+
- 'modprobe: FATAL: Module binder_linux not found in directory /lib/modules/<kernel>'
|
|
25
|
+
- 'modprobe: FATAL: Module ashmem_linux not found in directory /lib/modules/<kernel>'
|
|
26
|
+
- '/dev/binder: No such file or directory'
|
|
27
|
+
- '/dev/ashmem: No such file or directory'
|
|
28
|
+
- 'modprobe binder_linux exited with code 1'
|
|
29
|
+
root_cause: |
|
|
30
|
+
The ubuntu-24.04-arm64 GitHub Actions hosted runner kernel is compiled WITHOUT
|
|
31
|
+
`CONFIG_ANDROID_BINDER_IPC=m` and `CONFIG_ANDROID_BINDERFS=m`. This means the
|
|
32
|
+
`binder_linux` and `ashmem_linux` kernel modules do not exist in
|
|
33
|
+
`/lib/modules/$(uname -r)/` on ARM64 runners.
|
|
34
|
+
|
|
35
|
+
Attempting `modprobe binder_linux` fails silently (exits 1) on ARM64 because
|
|
36
|
+
the module is simply absent from the kernel tree — it cannot be loaded even
|
|
37
|
+
as a privileged container.
|
|
38
|
+
|
|
39
|
+
**Why x86_64 hosted runners DO have these modules:**
|
|
40
|
+
The x86_64 ubuntu-24.04 hosted runners expose `binder` and `ashmem` because
|
|
41
|
+
they support the [GitHub Actions KVM Android hardware acceleration feature](https://github.blog/changelog/2024-04-02-github-actions-hardware-accelerated-android-virtualization-now-available/)
|
|
42
|
+
(released April 2024). The x86_64 kernel was explicitly built with Android
|
|
43
|
+
IPC support to enable this feature. The ARM64 kernel image is compiled
|
|
44
|
+
separately and was not built with these modules.
|
|
45
|
+
|
|
46
|
+
**Affected use cases:**
|
|
47
|
+
- Running [ReDroid](https://github.com/remote-android/redroid-doc) (GPU-enabled
|
|
48
|
+
Android-in-Docker) on native ARM64 CI for ARM-native app testing
|
|
49
|
+
- Running [Waydroid](https://waydro.id/) in ARM64 CI containers
|
|
50
|
+
- Any workflow that requires `/dev/binder` or `/dev/ashmem` devices
|
|
51
|
+
|
|
52
|
+
**Confirmed on:**
|
|
53
|
+
- ubuntu-24.04-arm64 image 20260531.15.1 (kernel aarch64, Azure westus2)
|
|
54
|
+
- Source: actions/runner-images#14184 (feature request, June 2026, open)
|
|
55
|
+
|
|
56
|
+
**No current workaround exists** — the module cannot be compiled from source
|
|
57
|
+
against the runner's kernel headers without the kernel source tree, and the
|
|
58
|
+
azure-linux kernel for ARM64 is not shipped with headers for out-of-tree
|
|
59
|
+
`binder_linux` builds. A request to add the modules to the ubuntu-24.04-arm64
|
|
60
|
+
image is tracked at runner-images#14184 and is currently open with no ETA.
|
|
61
|
+
fix: |
|
|
62
|
+
**No complete fix is currently available for native ARM64 hosted runners.**
|
|
63
|
+
|
|
64
|
+
**Option 1 (Recommended): Use ubuntu-24.04 x86_64 runners for Android tests**
|
|
65
|
+
|
|
66
|
+
The x86_64 ubuntu-24.04 runner has `binder_linux` and `ashmem_linux` and
|
|
67
|
+
supports Android container tests via KVM acceleration. ARM-native testing can
|
|
68
|
+
be approximated via the Android native bridge, at the cost of some overhead:
|
|
69
|
+
|
|
70
|
+
```yaml
|
|
71
|
+
android-test:
|
|
72
|
+
runs-on: ubuntu-24.04 # x86_64 — has binder_linux/ashmem_linux
|
|
73
|
+
steps:
|
|
74
|
+
- uses: actions/checkout@v6
|
|
75
|
+
- run: |
|
|
76
|
+
sudo modprobe binder_linux # succeeds on x86_64
|
|
77
|
+
sudo modprobe ashmem_linux
|
|
78
|
+
# ... run ReDroid or Waydroid Android container tests
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Option 2: Use real ARM hardware (Firebase Test Lab, self-hosted)**
|
|
82
|
+
|
|
83
|
+
For true ARM64 profiling (power/wakelock, native execution) use Firebase
|
|
84
|
+
Test Lab with physical Pixel hardware, or a self-hosted ARM64 runner on
|
|
85
|
+
hardware/VMs that expose binder devices.
|
|
86
|
+
|
|
87
|
+
**Option 3: Compile binder_linux from source (complex, unreliable)**
|
|
88
|
+
|
|
89
|
+
Without kernel headers matching the runner kernel, this is not practical
|
|
90
|
+
on GitHub-hosted runners.
|
|
91
|
+
|
|
92
|
+
**Track for a platform fix:** Follow actions/runner-images#14184 for progress
|
|
93
|
+
on adding `binder_linux`/`ashmem_linux` to the ubuntu-24.04-arm64 runner image.
|
|
94
|
+
fix_code:
|
|
95
|
+
- language: yaml
|
|
96
|
+
label: 'Route Android container tests to x86_64 runner which has binder_linux/ashmem_linux'
|
|
97
|
+
code: |
|
|
98
|
+
jobs:
|
|
99
|
+
android-container-test:
|
|
100
|
+
# ubuntu-24.04-arm64 runner kernel is compiled without CONFIG_ANDROID_BINDER_IPC=m
|
|
101
|
+
# Use x86_64 runner which has binder_linux/ashmem_linux for KVM Android acceleration.
|
|
102
|
+
# Track runner-images#14184 for ARM64 kernel module support.
|
|
103
|
+
runs-on: ubuntu-24.04 # x86_64 — binder_linux available
|
|
104
|
+
container:
|
|
105
|
+
image: redroid/redroid:15.0.0-latest
|
|
106
|
+
options: --privileged
|
|
107
|
+
steps:
|
|
108
|
+
- uses: actions/checkout@v6
|
|
109
|
+
- name: Verify binder device
|
|
110
|
+
run: ls -la /dev/binder /dev/ashmem
|
|
111
|
+
- name: Run instrumented tests
|
|
112
|
+
run: ./gradlew connectedAndroidTest
|
|
113
|
+
- language: yaml
|
|
114
|
+
label: 'Guard ARM64 jobs against missing kernel modules'
|
|
115
|
+
code: |
|
|
116
|
+
jobs:
|
|
117
|
+
android-test:
|
|
118
|
+
runs-on: ${{ matrix.runner }}
|
|
119
|
+
strategy:
|
|
120
|
+
matrix:
|
|
121
|
+
runner: [ubuntu-24.04, ubuntu-24.04-arm64]
|
|
122
|
+
steps:
|
|
123
|
+
- uses: actions/checkout@v6
|
|
124
|
+
- name: Check binder_linux availability
|
|
125
|
+
id: binder-check
|
|
126
|
+
run: |
|
|
127
|
+
if modprobe binder_linux 2>/dev/null; then
|
|
128
|
+
echo "available=true" >> "$GITHUB_OUTPUT"
|
|
129
|
+
else
|
|
130
|
+
echo "available=false" >> "$GITHUB_OUTPUT"
|
|
131
|
+
echo "::warning::binder_linux not available on $(uname -m) runner. Skipping Android container tests."
|
|
132
|
+
fi
|
|
133
|
+
- name: Run Android container tests
|
|
134
|
+
if: steps.binder-check.outputs.available == 'true'
|
|
135
|
+
run: ./run-android-tests.sh
|
|
136
|
+
prevention:
|
|
137
|
+
- 'Do not assume binder_linux or ashmem_linux are available on ubuntu-24.04-arm64 hosted runners — the kernel was not built with CONFIG_ANDROID_BINDER_IPC=m.'
|
|
138
|
+
- 'Route Android container (ReDroid/Waydroid) CI tests to x86_64 ubuntu-24.04 runners until runner-images#14184 is resolved.'
|
|
139
|
+
- 'Always guard binder_linux/ashmem_linux modprobe calls with an availability check so ARM64 jobs fail gracefully rather than unexpectedly.'
|
|
140
|
+
- 'Track the ARM64 runner image feature request at actions/runner-images#14184 to know when the modules are added.'
|
|
141
|
+
docs:
|
|
142
|
+
- url: 'https://github.com/actions/runner-images/issues/14184'
|
|
143
|
+
label: 'runner-images #14184 — Add binder_linux and ashmem_linux kernel modules to ubuntu-24.04-arm image (open Jun 2026)'
|
|
144
|
+
- url: 'https://github.com/remote-android/redroid-doc/issues/928'
|
|
145
|
+
label: 'redroid-doc #928 — GitHub Actions ubuntu-24.04-arm runners lack binder/ashmem kernel modules'
|
|
146
|
+
- url: 'https://github.blog/changelog/2024-04-02-github-actions-hardware-accelerated-android-virtualization-now-available/'
|
|
147
|
+
label: 'GitHub Changelog — Hardware-accelerated Android virtualization on x86_64 Actions runners'
|
|
148
|
+
- url: 'https://github.com/actions/runner-images/releases/tag/ubuntu24-arm64%2F20260531.15'
|
|
149
|
+
label: 'ubuntu-24.04-arm64 image 20260531.15.1 release notes'
|