@htekdev/actions-debugger 1.0.32 → 1.0.34
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/known-unsolved/bulk-tag-push-over-three-silent-drop.yml +115 -0
- package/errors/runner-environment/checkout-detached-head-git-push-fail.yml +104 -0
- package/errors/runner-environment/macos-15-arm64-homebrew-rustup-init-argv-rejected.yml +114 -0
- package/errors/runner-environment/ubuntu-24-04-iproute2-kernel-614-vxlan-segfault.yml +102 -0
- package/errors/runner-environment/ubuntu-slim-setup-node-semver-range-toolcache-miss.yml +108 -0
- package/errors/silent-failures/cache-restore-fail-on-cache-miss-silent-bug.yml +115 -0
- package/errors/silent-failures/step-summary-content-silently-dropped-near-limit.yml +115 -0
- package/errors/triggers/pull-request-ready-for-review-type-not-listed.yml +101 -0
- package/package.json +1 -1
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
id: 'known-unsolved-031'
|
|
2
|
+
title: 'Pushing more than 3 tags simultaneously silently drops workflow runs for excess tags — GitHub platform limit'
|
|
3
|
+
category: known-unsolved
|
|
4
|
+
severity: silent-failure
|
|
5
|
+
tags:
|
|
6
|
+
- push
|
|
7
|
+
- tags
|
|
8
|
+
- bulk-push
|
|
9
|
+
- webhook
|
|
10
|
+
- workflow-trigger
|
|
11
|
+
- limitation
|
|
12
|
+
- monorepo
|
|
13
|
+
patterns:
|
|
14
|
+
- regex: 'push\s+--tags'
|
|
15
|
+
flags: 'i'
|
|
16
|
+
- regex: 'on:\s*\n\s*push:\s*\n\s*tags:'
|
|
17
|
+
flags: 'im'
|
|
18
|
+
error_messages:
|
|
19
|
+
- 'No workflow runs created for some tags in bulk tag push'
|
|
20
|
+
root_cause: |
|
|
21
|
+
GitHub's webhook delivery system has a documented hard limit: when more than 3 tags
|
|
22
|
+
are pushed simultaneously in a single push operation, push webhook events are only
|
|
23
|
+
created for the first 3 matching tags. Workflows for the remaining tags are silently
|
|
24
|
+
never triggered — no warning, no error, no failed run.
|
|
25
|
+
|
|
26
|
+
From the GitHub webhook events and payloads documentation:
|
|
27
|
+
"Events will not be created for tags when more than three tags are pushed at once."
|
|
28
|
+
(A similar limit of 5000 applies to branch pushes in a single operation, making the
|
|
29
|
+
3-tag threshold unexpectedly low by comparison.)
|
|
30
|
+
|
|
31
|
+
This is a platform-level constraint with no opt-out or configuration setting.
|
|
32
|
+
|
|
33
|
+
Common use cases affected:
|
|
34
|
+
- Monorepo release pipelines that tag multiple packages simultaneously
|
|
35
|
+
(e.g., package-a/v1.2.0, package-b/v1.0.0, package-c/v2.0.0, package-d/v0.5.0)
|
|
36
|
+
- Automated tooling that creates and pushes several version tags in one batch
|
|
37
|
+
- Release scripts using bulk push operations after creating several release tags
|
|
38
|
+
- Any CI pipeline where batch tagging is a normal part of the release flow
|
|
39
|
+
|
|
40
|
+
Source: actions/runner#3644 (7 reactions, Jan 2025, open), GitHub Docs push event.
|
|
41
|
+
fix: |
|
|
42
|
+
No native fix — the 3-tag limit is a GitHub platform constraint. Workarounds:
|
|
43
|
+
|
|
44
|
+
Option 1: Push tags individually one at a time in a loop (slower but reliable).
|
|
45
|
+
|
|
46
|
+
Option 2: After a bulk tag operation, use the GitHub CLI to manually trigger
|
|
47
|
+
workflows for the tags that were silently skipped:
|
|
48
|
+
gh workflow run release.yml --ref tag-name
|
|
49
|
+
|
|
50
|
+
Option 3 (recommended for monorepos): Switch from push:tags triggered workflows to
|
|
51
|
+
repository_dispatch triggered release workflows. Use a coordination script that
|
|
52
|
+
pushes tags and then dispatches one workflow event per tag. This removes the
|
|
53
|
+
3-tag webhook constraint entirely.
|
|
54
|
+
|
|
55
|
+
Option 4: Use workflow_dispatch with a tag name input parameter and invoke it once
|
|
56
|
+
per tag from a release coordination script.
|
|
57
|
+
fix_code:
|
|
58
|
+
- language: yaml
|
|
59
|
+
label: 'repository_dispatch-based release trigger bypassing the 3-tag limit'
|
|
60
|
+
code: |
|
|
61
|
+
# Release coordination script (run in CI or locally):
|
|
62
|
+
#
|
|
63
|
+
# For each tag you want to release, dispatch a repository_dispatch event:
|
|
64
|
+
#
|
|
65
|
+
# for tag in package-a/v1.2.0 package-b/v1.0.0 package-c/v2.0.0; do
|
|
66
|
+
# gh api repos/{owner}/{repo}/dispatches \
|
|
67
|
+
# --field event_type=release \
|
|
68
|
+
# --field "client_payload[tag]=$tag"
|
|
69
|
+
# done
|
|
70
|
+
|
|
71
|
+
# Workflow triggered per tag via repository_dispatch:
|
|
72
|
+
on:
|
|
73
|
+
repository_dispatch:
|
|
74
|
+
types: [release]
|
|
75
|
+
|
|
76
|
+
jobs:
|
|
77
|
+
release:
|
|
78
|
+
runs-on: ubuntu-latest
|
|
79
|
+
steps:
|
|
80
|
+
- uses: actions/checkout@v4
|
|
81
|
+
with:
|
|
82
|
+
ref: ${{ github.event.client_payload.tag }}
|
|
83
|
+
|
|
84
|
+
- name: Build and publish
|
|
85
|
+
run: |
|
|
86
|
+
echo "Releasing ${{ github.event.client_payload.tag }}"
|
|
87
|
+
# add actual release steps here
|
|
88
|
+
- language: yaml
|
|
89
|
+
label: 'workflow_dispatch with tag input — invoke once per tag from release script'
|
|
90
|
+
code: |
|
|
91
|
+
on:
|
|
92
|
+
workflow_dispatch:
|
|
93
|
+
inputs:
|
|
94
|
+
tag:
|
|
95
|
+
description: 'Tag to release (e.g. package-a/v1.2.0)'
|
|
96
|
+
required: true
|
|
97
|
+
type: string
|
|
98
|
+
|
|
99
|
+
jobs:
|
|
100
|
+
release:
|
|
101
|
+
runs-on: ubuntu-latest
|
|
102
|
+
steps:
|
|
103
|
+
- uses: actions/checkout@v4
|
|
104
|
+
with:
|
|
105
|
+
ref: ${{ inputs.tag }}
|
|
106
|
+
- run: echo "Releasing ${{ inputs.tag }}"
|
|
107
|
+
prevention:
|
|
108
|
+
- 'Never rely on bulk push operations to trigger per-tag workflows in monorepos — push tags individually or use repository_dispatch/workflow_dispatch patterns'
|
|
109
|
+
- 'Audit your release pipeline: if bulk tag operations are used and more than 3 tags are pushed at once, some workflow runs are silently missing'
|
|
110
|
+
- 'Add a post-release verification step that confirms a workflow run exists for each expected tag, alerting if any are missing'
|
|
111
|
+
docs:
|
|
112
|
+
- url: 'https://docs.github.com/en/webhooks/webhook-events-and-payloads#push'
|
|
113
|
+
label: 'GitHub Docs: push webhook — 3-tag limit for simultaneous bulk tag pushes'
|
|
114
|
+
- url: 'https://github.com/actions/runner/issues/3644'
|
|
115
|
+
label: 'actions/runner#3644: Workflow fails to trigger on multiple tags push simultaneously (Jan 2025, open)'
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
id: 'runner-environment-089'
|
|
2
|
+
title: '`actions/checkout` leaves repository in detached HEAD state — subsequent `push` operations fail with "You are not currently on a branch"'
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- checkout
|
|
7
|
+
- detached-head
|
|
8
|
+
- push
|
|
9
|
+
- pull-request
|
|
10
|
+
- branch
|
|
11
|
+
- git-operations
|
|
12
|
+
patterns:
|
|
13
|
+
- regex: 'fatal: You are not currently on a branch\.'
|
|
14
|
+
flags: 'i'
|
|
15
|
+
- regex: 'To push the history leading to the current \(detached HEAD\)'
|
|
16
|
+
flags: 'i'
|
|
17
|
+
- regex: 'detached HEAD.*\d+\].*fatal'
|
|
18
|
+
flags: 'i'
|
|
19
|
+
error_messages:
|
|
20
|
+
- 'fatal: You are not currently on a branch.'
|
|
21
|
+
- 'To push the history leading to the current (detached HEAD) state now, use'
|
|
22
|
+
- ' git push origin HEAD:<name-of-remote-branch>'
|
|
23
|
+
- 'Process completed with exit code 128.'
|
|
24
|
+
root_cause: |
|
|
25
|
+
actions/checkout performs a detached HEAD checkout by default for pull_request events.
|
|
26
|
+
For pull_request triggers, GitHub provides a synthetic merge ref
|
|
27
|
+
(refs/pull/N/merge) rather than a real branch ref, so the action checks out
|
|
28
|
+
this merge commit without creating or tracking a local branch.
|
|
29
|
+
|
|
30
|
+
When subsequent workflow steps attempt to commit and push changes back to the
|
|
31
|
+
repository — for example, auto-formatting, documentation builds, coverage report
|
|
32
|
+
generation, or generated file updates — the operation fails because no remote
|
|
33
|
+
branch can be determined from a detached HEAD state.
|
|
34
|
+
|
|
35
|
+
This affects any workflow step that:
|
|
36
|
+
- Runs push operations after making commits in the workflow
|
|
37
|
+
- Uses tools that internally run push operations (e.g., auto-commit, changelog tools,
|
|
38
|
+
version bumpers)
|
|
39
|
+
- Expects to push back to the PR branch after making modifications
|
|
40
|
+
|
|
41
|
+
On push events, the checkout is also detached if ref: is not specified with the
|
|
42
|
+
branch name, because the default ref is github.sha (a commit SHA, not a branch name).
|
|
43
|
+
|
|
44
|
+
Tracked: actions/checkout#317 (44 reactions, ongoing since 2020, still receiving
|
|
45
|
+
comments in 2025).
|
|
46
|
+
fix: |
|
|
47
|
+
Specify ref: in the checkout step to check out the branch name rather than a
|
|
48
|
+
commit SHA or merge ref. Once on a named branch, push-back operations work normally.
|
|
49
|
+
|
|
50
|
+
For pull_request events: use github.event.pull_request.head.ref
|
|
51
|
+
For push events: use github.ref_name (available since Runner 2.294.0)
|
|
52
|
+
For workflows triggered by multiple event types: branch the ref selection by
|
|
53
|
+
event name as shown in the third example below.
|
|
54
|
+
fix_code:
|
|
55
|
+
- language: yaml
|
|
56
|
+
label: 'Fix for pull_request-triggered workflows that push back to the PR branch'
|
|
57
|
+
code: |
|
|
58
|
+
jobs:
|
|
59
|
+
build:
|
|
60
|
+
runs-on: ubuntu-latest
|
|
61
|
+
steps:
|
|
62
|
+
- uses: actions/checkout@v4
|
|
63
|
+
with:
|
|
64
|
+
# Check out the actual PR branch, not the detached merge ref
|
|
65
|
+
ref: ${{ github.event.pull_request.head.ref }}
|
|
66
|
+
- language: yaml
|
|
67
|
+
label: 'Fix for push-triggered workflows that commit and push back'
|
|
68
|
+
code: |
|
|
69
|
+
jobs:
|
|
70
|
+
build:
|
|
71
|
+
runs-on: ubuntu-latest
|
|
72
|
+
steps:
|
|
73
|
+
- uses: actions/checkout@v4
|
|
74
|
+
with:
|
|
75
|
+
# Checks out the branch name (e.g. main) instead of the commit SHA
|
|
76
|
+
ref: ${{ github.ref_name }}
|
|
77
|
+
- language: yaml
|
|
78
|
+
label: 'Universal fix for workflows triggered by multiple event types'
|
|
79
|
+
code: |
|
|
80
|
+
jobs:
|
|
81
|
+
build:
|
|
82
|
+
runs-on: ubuntu-latest
|
|
83
|
+
steps:
|
|
84
|
+
- name: Checkout (pull_request)
|
|
85
|
+
if: github.event_name == 'pull_request'
|
|
86
|
+
uses: actions/checkout@v4
|
|
87
|
+
with:
|
|
88
|
+
ref: ${{ github.event.pull_request.head.ref }}
|
|
89
|
+
|
|
90
|
+
- name: Checkout (push or workflow_dispatch)
|
|
91
|
+
if: github.event_name != 'pull_request'
|
|
92
|
+
uses: actions/checkout@v4
|
|
93
|
+
with:
|
|
94
|
+
ref: ${{ github.ref_name }}
|
|
95
|
+
prevention:
|
|
96
|
+
- 'Always specify ref: in checkout steps for workflows that push changes back to the repository'
|
|
97
|
+
- 'Use github.ref_name (not github.sha) for push-triggered workflows to get the branch name rather than a detached commit SHA'
|
|
98
|
+
- 'Test push-back workflows on both pull_request and push triggers to detect detached HEAD issues before they reach production'
|
|
99
|
+
- 'If using actions/checkout@v4, prefer explicit ref: values over relying on defaults when the workflow modifies and pushes files'
|
|
100
|
+
docs:
|
|
101
|
+
- url: 'https://github.com/actions/checkout/issues/317'
|
|
102
|
+
label: 'actions/checkout#317: fatal: You are not currently on a branch (44 reactions, 2020–2025)'
|
|
103
|
+
- url: 'https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#pull_request'
|
|
104
|
+
label: 'GitHub Docs: pull_request event — uses synthetic merge ref by default'
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
id: 'runner-environment-086'
|
|
2
|
+
title: 'macOS 15 arm64 Homebrew `rustup-init` rejects `+stable` toolchain specifier and subcommands — Rust builds fail with ~50% probability'
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- macos
|
|
7
|
+
- arm64
|
|
8
|
+
- homebrew
|
|
9
|
+
- rust
|
|
10
|
+
- rustup
|
|
11
|
+
- maturin
|
|
12
|
+
- napi-rs
|
|
13
|
+
- image-regression
|
|
14
|
+
patterns:
|
|
15
|
+
- regex: 'error: unexpected argument .+stable. found'
|
|
16
|
+
flags: 'i'
|
|
17
|
+
- regex: 'error: unexpected argument .metadata. found'
|
|
18
|
+
flags: 'i'
|
|
19
|
+
- regex: 'Usage: rustup-init\[EXE\] \[OPTIONS\]'
|
|
20
|
+
flags: 'i'
|
|
21
|
+
- regex: 'macos-15-arm64.*20260511'
|
|
22
|
+
flags: 'i'
|
|
23
|
+
error_messages:
|
|
24
|
+
- "Error: error: error: unexpected argument '+stable' found"
|
|
25
|
+
- "error: error: unexpected argument 'metadata' found"
|
|
26
|
+
- "Usage: rustup-init[EXE] [OPTIONS]"
|
|
27
|
+
- "info: self-update is disabled for this build of rustup"
|
|
28
|
+
- "Could not parse the Cargo.toml: Error: Command failed: cargo metadata"
|
|
29
|
+
root_cause: |
|
|
30
|
+
The macos-15-arm64 runner image version 20260511.0048 ships a broken Homebrew rustup
|
|
31
|
+
formula at /opt/homebrew/bin/rustup (version 1.29.0) whose bundled rustup-init binary
|
|
32
|
+
rejects standard argv that the outer rustup CLI forwards internally.
|
|
33
|
+
|
|
34
|
+
When rustup receives a command like `rustup component add llvm-tools-preview` or when
|
|
35
|
+
cargo shims invoke `cargo metadata`, the outer rustup binary calls rustup-init with
|
|
36
|
+
forwarded arguments (+stable, metadata, etc.). On this image version, rustup-init
|
|
37
|
+
treats these as unknown positional arguments and immediately exits with an error.
|
|
38
|
+
|
|
39
|
+
The failure is intermittent because GitHub's runner scheduler assigns jobs to different
|
|
40
|
+
image versions: 20260511.0048 (broken) and 20260427.0018 (working). A single workflow
|
|
41
|
+
run with multiple matrix entries can produce a mix of passing and failing jobs depending
|
|
42
|
+
on which image version each job lands on. Reruns do not reliably fix the issue because
|
|
43
|
+
rerun jobs may again be scheduled on the broken image version.
|
|
44
|
+
|
|
45
|
+
Affected downstream tools (all work on 20260427.0018, all fail on 20260511.0048):
|
|
46
|
+
- PyO3/maturin-action@v1 — calls `rustup component add llvm-tools-preview`
|
|
47
|
+
- @napi-rs/cli — calls `cargo metadata --format-version 1`
|
|
48
|
+
- Any workflow that calls `rustup component add` with a toolchain specifier
|
|
49
|
+
- Any Rust build that uses the Homebrew rustup shim for internal rustup-init calls
|
|
50
|
+
|
|
51
|
+
Tracked in actions/runner-images#14097 (May 2026, open).
|
|
52
|
+
fix: |
|
|
53
|
+
Option 1 (recommended): Install rustup from the upstream installer (sh.rustup.rs)
|
|
54
|
+
before any Rust build steps. This replaces the broken Homebrew binary at
|
|
55
|
+
/opt/homebrew/bin/rustup with the upstream version and resolves the argv issue.
|
|
56
|
+
|
|
57
|
+
Option 2: Pin the runner to macos-15-arm64 explicitly and avoid the image lottery.
|
|
58
|
+
Note: this only temporarily avoids the issue; broken images will eventually be the
|
|
59
|
+
only version served.
|
|
60
|
+
|
|
61
|
+
Option 3: Use the dtolnay/rust-toolchain action before any Rust operations to
|
|
62
|
+
install or update rustup via the upstream installer, bypassing the Homebrew version.
|
|
63
|
+
fix_code:
|
|
64
|
+
- language: yaml
|
|
65
|
+
label: 'Replace Homebrew rustup with upstream installer before Rust build steps'
|
|
66
|
+
code: |
|
|
67
|
+
jobs:
|
|
68
|
+
build:
|
|
69
|
+
runs-on: macos-latest # or macos-15-arm64
|
|
70
|
+
steps:
|
|
71
|
+
- uses: actions/checkout@v6
|
|
72
|
+
|
|
73
|
+
- name: Replace Homebrew rustup with upstream installer
|
|
74
|
+
run: |
|
|
75
|
+
# Remove Homebrew rustup to avoid the broken rustup-init binary
|
|
76
|
+
brew uninstall rustup-init rustup 2>/dev/null || true
|
|
77
|
+
# Install from upstream — stable, no Homebrew dependency
|
|
78
|
+
curl https://sh.rustup.rs -sSf | sh -s -- -y --no-modify-path
|
|
79
|
+
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
|
|
80
|
+
|
|
81
|
+
- name: Install Rust target
|
|
82
|
+
run: rustup target add aarch64-apple-darwin
|
|
83
|
+
|
|
84
|
+
- uses: PyO3/maturin-action@v1
|
|
85
|
+
with:
|
|
86
|
+
target: aarch64-apple-darwin
|
|
87
|
+
- language: yaml
|
|
88
|
+
label: 'Use dtolnay/rust-toolchain to install a clean rustup before builds'
|
|
89
|
+
code: |
|
|
90
|
+
jobs:
|
|
91
|
+
build:
|
|
92
|
+
runs-on: macos-latest
|
|
93
|
+
steps:
|
|
94
|
+
- uses: actions/checkout@v6
|
|
95
|
+
|
|
96
|
+
- name: Install Rust toolchain (upstream, not Homebrew)
|
|
97
|
+
uses: dtolnay/rust-toolchain@stable
|
|
98
|
+
with:
|
|
99
|
+
components: llvm-tools-preview
|
|
100
|
+
|
|
101
|
+
- name: Build
|
|
102
|
+
run: cargo build --release
|
|
103
|
+
prevention:
|
|
104
|
+
- 'Prefer dtolnay/rust-toolchain or rustup-toolchain-install-master for cross-platform Rust toolchain management rather than relying on the pre-installed Homebrew rustup'
|
|
105
|
+
- 'Test macOS ARM64 jobs on both arm64 and x86-via-Rosetta matrix entries to detect image-lottery regressions early'
|
|
106
|
+
- 'Watch actions/runner-images#14097 for the fix and the image version that resolves the broken rustup-init'
|
|
107
|
+
- 'Avoid using the Homebrew rustup binary directly; upstream rustup at ~/.cargo/bin/rustup is more stable across image updates'
|
|
108
|
+
docs:
|
|
109
|
+
- url: 'https://github.com/actions/runner-images/issues/14097'
|
|
110
|
+
label: 'actions/runner-images#14097: macos-15-arm64/20260511.0048 ships broken Homebrew rustup-init (May 2026)'
|
|
111
|
+
- url: 'https://rustup.rs/'
|
|
112
|
+
label: 'rustup.rs: Official upstream rustup installer'
|
|
113
|
+
- url: 'https://github.com/PyO3/maturin-action'
|
|
114
|
+
label: 'PyO3/maturin-action: Affected action that calls rustup component add'
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
id: 'runner-environment-087'
|
|
2
|
+
title: '`ip -d link show` segfaults (exit 139 / SIGSEGV) on VXLAN interfaces on ubuntu-24.04 after kernel 6.14 upgrade'
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- ubuntu-24-04
|
|
7
|
+
- networking
|
|
8
|
+
- vxlan
|
|
9
|
+
- iproute2
|
|
10
|
+
- kernel
|
|
11
|
+
- segfault
|
|
12
|
+
- regression
|
|
13
|
+
- container-networking
|
|
14
|
+
patterns:
|
|
15
|
+
- regex: 'Segmentation fault.*ip.*link'
|
|
16
|
+
flags: 'i'
|
|
17
|
+
- regex: 'ip -d link show.*exit.*139'
|
|
18
|
+
flags: 'i'
|
|
19
|
+
- regex: 'ip\s+-d\s+link\s+show'
|
|
20
|
+
flags: 'i'
|
|
21
|
+
error_messages:
|
|
22
|
+
- 'Segmentation fault (core dumped)'
|
|
23
|
+
- 'Process completed with exit code 139.'
|
|
24
|
+
- 'ip: Segmentation fault'
|
|
25
|
+
root_cause: |
|
|
26
|
+
On ubuntu-24.04 runner image 20260209.23 and later, the kernel was upgraded to
|
|
27
|
+
6.14.0-1017-azure while the iproute2 package remained at version 6.1.0-1ubuntu6.2.
|
|
28
|
+
|
|
29
|
+
Linux kernel 6.14 introduced a new VXLAN netlink attribute (IFLA_VXLAN_FAN_MAP) in
|
|
30
|
+
the rtnetlink interface. When iproute2 6.1 receives a netlink response containing this
|
|
31
|
+
unrecognized attribute and parses it with the -d (details) flag, it dereferences an
|
|
32
|
+
unexpected attribute structure, triggering a SIGSEGV.
|
|
33
|
+
|
|
34
|
+
The crash occurs specifically when:
|
|
35
|
+
1. A VXLAN network interface exists on the runner (e.g., created with `ip link add ... type vxlan`)
|
|
36
|
+
2. `ip -d link show dev <vxlan-interface>` is executed to inspect its details
|
|
37
|
+
|
|
38
|
+
Without the -d flag, `ip link show` succeeds. The regression was confirmed by comparing:
|
|
39
|
+
- Working image: 20260201.15.1 (kernel 6.11.0-1018-azure, iproute2 6.1.0-1ubuntu6.2)
|
|
40
|
+
- Broken image: 20260209.23.1 (kernel 6.14.0-1017-azure, iproute2 6.1.0-1ubuntu6.2)
|
|
41
|
+
|
|
42
|
+
Affected workflows: any CI that creates VXLAN interfaces for network simulation, overlay
|
|
43
|
+
networking tests, or Kubernetes-in-CI scenarios (e.g., containerlab, kind with custom
|
|
44
|
+
network topologies, network protocol testing).
|
|
45
|
+
|
|
46
|
+
Tracked in actions/runner-images#13669 (February 2026, open).
|
|
47
|
+
fix: |
|
|
48
|
+
Option 1: Upgrade iproute2 to a version compatible with kernel 6.14 at the start of
|
|
49
|
+
the job. Install a newer iproute2 from a backport PPA or compile from source.
|
|
50
|
+
|
|
51
|
+
Option 2: Avoid the -d flag when only basic VXLAN interface information is needed.
|
|
52
|
+
`ip link show dev <vxlan-interface>` (without -d) does not trigger the crash.
|
|
53
|
+
|
|
54
|
+
Option 3: Pin to ubuntu-22.04, which uses an older kernel/iproute2 combination that
|
|
55
|
+
does not exhibit this issue.
|
|
56
|
+
|
|
57
|
+
Option 4: Parse VXLAN interface details via /sys/class/net/ sysfs entries instead of
|
|
58
|
+
relying on `ip -d link show`.
|
|
59
|
+
fix_code:
|
|
60
|
+
- language: yaml
|
|
61
|
+
label: 'Upgrade iproute2 before creating VXLAN interfaces to avoid segfault'
|
|
62
|
+
code: |
|
|
63
|
+
jobs:
|
|
64
|
+
network-test:
|
|
65
|
+
runs-on: ubuntu-24.04
|
|
66
|
+
steps:
|
|
67
|
+
- name: Upgrade iproute2 to kernel-6.14-compatible version
|
|
68
|
+
run: |
|
|
69
|
+
sudo apt-get update -qq
|
|
70
|
+
sudo apt-get install -y --only-upgrade iproute2
|
|
71
|
+
ip -V # Verify new version
|
|
72
|
+
|
|
73
|
+
- name: Create and inspect VXLAN interface
|
|
74
|
+
run: |
|
|
75
|
+
sudo ip link add vxlan-test type vxlan id 100 \
|
|
76
|
+
local 10.0.0.1 remote 10.0.0.2 dev eth0 dstport 4789
|
|
77
|
+
ip -d link show dev vxlan-test # Safe with upgraded iproute2
|
|
78
|
+
|
|
79
|
+
- language: yaml
|
|
80
|
+
label: 'Avoid -d flag as workaround on ubuntu-24.04 without iproute2 upgrade'
|
|
81
|
+
code: |
|
|
82
|
+
jobs:
|
|
83
|
+
network-test:
|
|
84
|
+
runs-on: ubuntu-24.04
|
|
85
|
+
steps:
|
|
86
|
+
- name: Create VXLAN interface
|
|
87
|
+
run: |
|
|
88
|
+
sudo ip link add vxlan-test type vxlan id 100 dstport 4789
|
|
89
|
+
# Use ip link show WITHOUT -d flag to avoid SIGSEGV on kernel 6.14
|
|
90
|
+
ip link show dev vxlan-test
|
|
91
|
+
# VXLAN-specific attributes via sysfs instead of iproute2 -d output:
|
|
92
|
+
cat /sys/class/net/vxlan-test/carrier || true
|
|
93
|
+
prevention:
|
|
94
|
+
- 'Add an iproute2 upgrade step when workflows inspect VXLAN or other advanced interface types with `ip -d link show`'
|
|
95
|
+
- 'Watch actions/runner-images#13669 for a fix that aligns iproute2 with the kernel 6.14 netlink attributes'
|
|
96
|
+
- 'Test network-intensive CI on both ubuntu-22.04 and ubuntu-24.04 to detect kernel/iproute2 mismatch regressions'
|
|
97
|
+
- 'Consider ubuntu-22.04 for VXLAN-dependent workflows until the iproute2 package is updated on ubuntu-24.04 images'
|
|
98
|
+
docs:
|
|
99
|
+
- url: 'https://github.com/actions/runner-images/issues/13669'
|
|
100
|
+
label: 'actions/runner-images#13669: ip -d link show segfaults on vxlan interfaces — iproute2/kernel 6.14 mismatch'
|
|
101
|
+
- url: 'https://manpages.ubuntu.com/manpages/noble/man8/ip-link.8.html'
|
|
102
|
+
label: 'Ubuntu ip-link manpage: ip link show options'
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
id: 'runner-environment-088'
|
|
2
|
+
title: '`ubuntu-slim` runner has empty Node.js toolcache — `setup-node` with semver range downloads latest patch instead of using cached version'
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- ubuntu-slim
|
|
7
|
+
- setup-node
|
|
8
|
+
- toolcache
|
|
9
|
+
- semver
|
|
10
|
+
- caching
|
|
11
|
+
- node
|
|
12
|
+
- version-mismatch
|
|
13
|
+
patterns:
|
|
14
|
+
- regex: 'evaluating 0 versions'
|
|
15
|
+
flags: 'i'
|
|
16
|
+
- regex: 'Attempting to download.*\.\.\.'
|
|
17
|
+
flags: 'i'
|
|
18
|
+
- regex: 'ubuntu-slim.*setup-node'
|
|
19
|
+
flags: 'i'
|
|
20
|
+
error_messages:
|
|
21
|
+
- '##[debug]evaluating 0 versions'
|
|
22
|
+
- '##[debug]match not found'
|
|
23
|
+
- 'Attempting to download 24.x...'
|
|
24
|
+
- 'Acquiring 24.13.1 - x64 from https://github.com/actions/node-versions/releases/download/'
|
|
25
|
+
root_cause: |
|
|
26
|
+
The ubuntu-slim runner image ships with an empty or absent Node.js toolcache manifest.
|
|
27
|
+
When actions/setup-node evaluates a semver range (e.g., 24, 24.x, 22.x) it first
|
|
28
|
+
inspects the local toolcache versions manifest. On ubuntu-slim, the manifest contains
|
|
29
|
+
zero cached versions (log line: "evaluating 0 versions"), so setup-node falls through
|
|
30
|
+
to download the latest matching version from GitHub releases at runtime.
|
|
31
|
+
|
|
32
|
+
On ubuntu-24.04 and ubuntu-latest, setup-node finds the cached version (e.g., 24.13.0)
|
|
33
|
+
and logs "Found tool in cache". The same workflow on ubuntu-slim downloads a newer
|
|
34
|
+
patch release (e.g., 24.13.1) because the remote versions API returns the freshest
|
|
35
|
+
available release.
|
|
36
|
+
|
|
37
|
+
This causes three distinct problems:
|
|
38
|
+
1. Slower CI: every job downloads Node.js from the network instead of using the cache
|
|
39
|
+
2. Version drift: ubuntu-slim jobs may use a different Node.js version than ubuntu-24.04
|
|
40
|
+
jobs in the same matrix, silently breaking cross-platform consistency checks
|
|
41
|
+
3. Test failures: libraries that cache built binaries keyed on Node.js version will
|
|
42
|
+
produce cache misses across ubuntu-slim and ubuntu-latest jobs in the same run
|
|
43
|
+
|
|
44
|
+
Reproduced on ubuntu-slim image version 20260120.46.1.
|
|
45
|
+
Tracked in actions/runner-images#13671 and actions/setup-node#1492 (February 2026).
|
|
46
|
+
fix: |
|
|
47
|
+
Option 1: Pin an explicit Node.js version (e.g., 24.13.0) instead of a semver range.
|
|
48
|
+
setup-node downloads this version on ubuntu-slim, but the result is deterministic and
|
|
49
|
+
matches any version you also pin on ubuntu-latest or ubuntu-24.04.
|
|
50
|
+
|
|
51
|
+
Option 2: Use a .node-version or .nvmrc file with an exact version. setup-node reads
|
|
52
|
+
the file and pins to that version on all runner images.
|
|
53
|
+
|
|
54
|
+
Option 3: Use actions/cache to manually cache the Node.js installation directory on
|
|
55
|
+
ubuntu-slim jobs.
|
|
56
|
+
|
|
57
|
+
Option 4: Avoid ubuntu-slim for workflows that require a specific Node.js toolcache
|
|
58
|
+
version. Use ubuntu-24.04 or ubuntu-latest which ship pre-cached Node.js versions.
|
|
59
|
+
fix_code:
|
|
60
|
+
- language: yaml
|
|
61
|
+
label: 'Pin exact Node.js version to avoid toolcache miss on ubuntu-slim'
|
|
62
|
+
code: |
|
|
63
|
+
jobs:
|
|
64
|
+
build:
|
|
65
|
+
runs-on: ubuntu-slim # empty toolcache
|
|
66
|
+
steps:
|
|
67
|
+
- uses: actions/checkout@v6
|
|
68
|
+
|
|
69
|
+
# WRONG: semver range downloads latest patch on ubuntu-slim
|
|
70
|
+
# - uses: actions/setup-node@v6
|
|
71
|
+
# with:
|
|
72
|
+
# node-version: '24' # evaluating 0 versions → downloads 24.13.1
|
|
73
|
+
|
|
74
|
+
# CORRECT: explicit version is deterministic on all images
|
|
75
|
+
- uses: actions/setup-node@v6
|
|
76
|
+
with:
|
|
77
|
+
node-version: '24.13.0' # exact — no toolcache lookup needed
|
|
78
|
+
|
|
79
|
+
- language: yaml
|
|
80
|
+
label: 'Use .node-version file for consistent version across all runner images'
|
|
81
|
+
code: |
|
|
82
|
+
# .node-version (at repo root):
|
|
83
|
+
# 24.13.0
|
|
84
|
+
|
|
85
|
+
jobs:
|
|
86
|
+
build:
|
|
87
|
+
runs-on: ${{ matrix.os }}
|
|
88
|
+
strategy:
|
|
89
|
+
matrix:
|
|
90
|
+
os: [ubuntu-slim, ubuntu-24.04, macos-latest]
|
|
91
|
+
steps:
|
|
92
|
+
- uses: actions/checkout@v6
|
|
93
|
+
|
|
94
|
+
- uses: actions/setup-node@v6
|
|
95
|
+
with:
|
|
96
|
+
node-version-file: '.node-version' # same version on all images
|
|
97
|
+
prevention:
|
|
98
|
+
- 'Use exact Node.js versions (not semver ranges like 24.x) when running on ubuntu-slim to ensure deterministic toolcache behavior'
|
|
99
|
+
- 'Add a .node-version or .nvmrc file at the repo root and reference it with node-version-file: for consistent versions across all runner images'
|
|
100
|
+
- 'In matrix builds mixing ubuntu-slim with ubuntu-24.04, verify that node --version outputs match to detect silent version drift'
|
|
101
|
+
- 'Watch actions/runner-images#13671 for a fix that pre-populates the ubuntu-slim toolcache with a Node.js manifest'
|
|
102
|
+
docs:
|
|
103
|
+
- url: 'https://github.com/actions/runner-images/issues/13671'
|
|
104
|
+
label: 'actions/runner-images#13671: setup-node incorrectly downloads latest on ubuntu-slim'
|
|
105
|
+
- url: 'https://github.com/actions/setup-node/issues/1492'
|
|
106
|
+
label: 'actions/setup-node#1492: ubuntu-slim toolcache manifest missing'
|
|
107
|
+
- url: 'https://github.com/actions/setup-node#usage'
|
|
108
|
+
label: 'actions/setup-node documentation: node-version-file option'
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
id: 'silent-failures-040'
|
|
2
|
+
title: '`actions/cache/restore` `fail-on-cache-miss: true` silently does not halt the workflow in v3.3.2–v3.3.3 — subsequent steps execute despite cache miss'
|
|
3
|
+
category: silent-failures
|
|
4
|
+
severity: silent-failure
|
|
5
|
+
tags:
|
|
6
|
+
- cache
|
|
7
|
+
- fail-on-cache-miss
|
|
8
|
+
- cache-restore
|
|
9
|
+
- silent-failure
|
|
10
|
+
- regression
|
|
11
|
+
- cache-v3
|
|
12
|
+
- cache-v4
|
|
13
|
+
patterns:
|
|
14
|
+
- regex: 'Failed to restore cache entry\. Exiting as fail-on-cache-miss is set\.'
|
|
15
|
+
flags: 'i'
|
|
16
|
+
- regex: 'fail-on-cache-miss.*true'
|
|
17
|
+
flags: 'i'
|
|
18
|
+
error_messages:
|
|
19
|
+
- 'Error: Failed to restore cache entry. Exiting as fail-on-cache-miss is set.'
|
|
20
|
+
- 'Warning: Cache not found for keys:'
|
|
21
|
+
root_cause: |
|
|
22
|
+
actions/cache@v3.3.2 and v3.3.3 contain a bug in the actions/cache/restore sub-action
|
|
23
|
+
where fail-on-cache-miss: true does not actually halt the workflow when no cache entry
|
|
24
|
+
is found.
|
|
25
|
+
|
|
26
|
+
The bug has two components (tracked in PR#1327):
|
|
27
|
+
|
|
28
|
+
1. Logic error: restoreImpl.ts initializes earlyExit to undefined (falsy) regardless
|
|
29
|
+
of whether fail-on-cache-miss is set. The conditional `if (earlyExit)` check always
|
|
30
|
+
evaluates to false, so process.exit(1) is never called on a miss.
|
|
31
|
+
|
|
32
|
+
2. Exit code conflict: even when process.exit(1) is called, it overwrites the exit
|
|
33
|
+
code previously set by core.setFailed(), causing the runner to record the step
|
|
34
|
+
outcome as 'success' despite the logged error message.
|
|
35
|
+
|
|
36
|
+
Observable behavior in affected versions:
|
|
37
|
+
- The step log shows: "Error: Failed to restore cache entry. Exiting as
|
|
38
|
+
fail-on-cache-miss is set."
|
|
39
|
+
- The step is marked with a red X in the UI but step.outcome is 'success'
|
|
40
|
+
- All subsequent steps execute normally as if no error occurred
|
|
41
|
+
- Jobs that should have stopped at the cache guard proceed to completion
|
|
42
|
+
|
|
43
|
+
This silently undermines workflows that use fail-on-cache-miss to enforce a
|
|
44
|
+
warm-cache-required pattern (e.g., a build artifact must exist from a prior job).
|
|
45
|
+
|
|
46
|
+
Fixed in: actions/cache@v3.3.4 and actions/cache@v4.0.2+ via PR#1327 (merged March 2024).
|
|
47
|
+
Affected: actions/cache@v3.3.2, v3.3.3 and the corresponding actions/cache/restore versions.
|
|
48
|
+
|
|
49
|
+
Source: actions/cache#1265 (11 reactions), actions/cache PR#1327 (merged March 2024).
|
|
50
|
+
fix: |
|
|
51
|
+
Option 1 (recommended): Update to actions/cache@v4 (v4.0.2+) or actions/cache@v3.3.4+
|
|
52
|
+
where the earlyExit logic and exit code handling are corrected.
|
|
53
|
+
|
|
54
|
+
Option 2: Roll back to actions/cache@v3.3.1 — the last version before the regression
|
|
55
|
+
was introduced.
|
|
56
|
+
|
|
57
|
+
Option 3 (belt-and-suspenders, any version): Add an explicit guard step after the
|
|
58
|
+
restore that checks the cache-hit output and exits manually. This works regardless
|
|
59
|
+
of the action version and is the most robust approach.
|
|
60
|
+
fix_code:
|
|
61
|
+
- language: yaml
|
|
62
|
+
label: 'Upgrade to fixed actions/cache version (v3.3.4+ or v4.0.2+)'
|
|
63
|
+
code: |
|
|
64
|
+
jobs:
|
|
65
|
+
downstream:
|
|
66
|
+
needs: build
|
|
67
|
+
runs-on: ubuntu-latest
|
|
68
|
+
steps:
|
|
69
|
+
- uses: actions/checkout@v4
|
|
70
|
+
|
|
71
|
+
# v4.0.2+ correctly fails the step AND stops the job on cache miss
|
|
72
|
+
- name: Restore build artifacts
|
|
73
|
+
uses: actions/cache/restore@v4
|
|
74
|
+
with:
|
|
75
|
+
path: dist/
|
|
76
|
+
key: build-${{ github.sha }}
|
|
77
|
+
fail-on-cache-miss: true
|
|
78
|
+
|
|
79
|
+
- name: Run tests against build
|
|
80
|
+
run: make test-dist
|
|
81
|
+
- language: yaml
|
|
82
|
+
label: 'Belt-and-suspenders explicit guard (works on all cache versions)'
|
|
83
|
+
code: |
|
|
84
|
+
jobs:
|
|
85
|
+
downstream:
|
|
86
|
+
needs: build
|
|
87
|
+
runs-on: ubuntu-latest
|
|
88
|
+
steps:
|
|
89
|
+
- uses: actions/checkout@v4
|
|
90
|
+
|
|
91
|
+
- name: Restore build artifacts
|
|
92
|
+
id: cache-restore
|
|
93
|
+
uses: actions/cache/restore@v4
|
|
94
|
+
with:
|
|
95
|
+
path: dist/
|
|
96
|
+
key: build-${{ github.sha }}
|
|
97
|
+
fail-on-cache-miss: false # Do not rely on this alone
|
|
98
|
+
|
|
99
|
+
- name: Abort if build cache missing
|
|
100
|
+
if: steps.cache-restore.outputs.cache-hit != 'true'
|
|
101
|
+
run: |
|
|
102
|
+
echo "::error::Build artifacts not found in cache — run the build job first."
|
|
103
|
+
exit 1
|
|
104
|
+
|
|
105
|
+
- name: Run tests against build
|
|
106
|
+
run: make test-dist
|
|
107
|
+
prevention:
|
|
108
|
+
- 'Pin actions/cache and actions/cache/restore to v3.3.4+ or v4.0.2+ when using fail-on-cache-miss'
|
|
109
|
+
- 'Add an explicit guard step checking steps.ID.outputs.cache-hit alongside fail-on-cache-miss for critical cache gates'
|
|
110
|
+
- 'Verify that a failed cache restore truly stops downstream steps by running a workflow with a known cache miss before relying on fail-on-cache-miss in production'
|
|
111
|
+
docs:
|
|
112
|
+
- url: 'https://github.com/actions/cache/issues/1265'
|
|
113
|
+
label: 'actions/cache#1265: fail-on-cache-miss not failing the workflow (11 reactions, Oct 2023)'
|
|
114
|
+
- url: 'https://github.com/actions/cache/pull/1327'
|
|
115
|
+
label: 'actions/cache PR#1327: Fix fail-on-cache-miss not working (merged March 2024)'
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
id: 'silent-failures-039'
|
|
2
|
+
title: '`GITHUB_STEP_SUMMARY` content silently discarded when write size approaches the 1 MiB per-step limit'
|
|
3
|
+
category: silent-failures
|
|
4
|
+
severity: silent-failure
|
|
5
|
+
tags:
|
|
6
|
+
- step-summary
|
|
7
|
+
- github-step-summary
|
|
8
|
+
- silent-discard
|
|
9
|
+
- 1mib-limit
|
|
10
|
+
- job-summary
|
|
11
|
+
- reporting
|
|
12
|
+
patterns:
|
|
13
|
+
- regex: 'GITHUB_STEP_SUMMARY'
|
|
14
|
+
flags: 'i'
|
|
15
|
+
- regex: '\$env:GITHUB_STEP_SUMMARY'
|
|
16
|
+
flags: 'i'
|
|
17
|
+
error_messages:
|
|
18
|
+
- 'Summary content written to /home/runner/work/_temp/_github_workflow/step_summary_*.md'
|
|
19
|
+
- 'Summary content written to C:\Users\runneradmin\AppData\Local\Temp\_github_workflow\step_summary_*.md'
|
|
20
|
+
root_cause: |
|
|
21
|
+
The GitHub Actions runner enforces a 1 MiB (1,048,576 bytes) per-step size limit on
|
|
22
|
+
GITHUB_STEP_SUMMARY content. When a step writes content that is within approximately
|
|
23
|
+
2 bytes of this limit, the runner silently discards the entire summary with no error
|
|
24
|
+
message, no warning, and no non-zero exit code.
|
|
25
|
+
|
|
26
|
+
Two distinct bugs are present (both observed on runner 2.333.1+):
|
|
27
|
+
|
|
28
|
+
Bug 1 — Off-by-one at the limit boundary: Content that is exactly (1 MiB - 1) bytes
|
|
29
|
+
is rejected as "too long" even though it is one byte below the documented limit.
|
|
30
|
+
The effective hard limit is (1 MiB - 2) bytes, not 1 MiB.
|
|
31
|
+
|
|
32
|
+
Bug 2 — Silent discard near the boundary: Content written when the running total is
|
|
33
|
+
within ~2 bytes of the effective limit is silently dropped. The write succeeds (no
|
|
34
|
+
error), the step exits 0, but the summary does not appear in the GitHub Actions UI.
|
|
35
|
+
There is no log line, annotation, or job-level error indicating the drop occurred.
|
|
36
|
+
|
|
37
|
+
This is particularly dangerous for CI workflows that rely on step summary for:
|
|
38
|
+
- Test result tables (many failed tests → large HTML tables)
|
|
39
|
+
- Build logs written to summary for easy access
|
|
40
|
+
- Deployment manifests or diff outputs
|
|
41
|
+
- Security scan results
|
|
42
|
+
|
|
43
|
+
The content is lost at job execution time; there is no way to recover it after the fact.
|
|
44
|
+
The only indication is that the summary section in the GitHub UI appears blank or shows
|
|
45
|
+
less content than expected.
|
|
46
|
+
|
|
47
|
+
Tracked in actions/runner#4337 (April 2026, open).
|
|
48
|
+
fix: |
|
|
49
|
+
Truncate summary content to a safe size before writing to GITHUB_STEP_SUMMARY.
|
|
50
|
+
Leave a margin of ~5 KB below the 1 MiB limit to account for multi-step accumulation
|
|
51
|
+
and the off-by-one bug.
|
|
52
|
+
|
|
53
|
+
For multi-step workflows, track cumulative size: each step's contribution adds to the
|
|
54
|
+
total step summary for the job. The 1 MiB limit applies per step, not per job.
|
|
55
|
+
|
|
56
|
+
Always validate that critical summary content was written by checking the file size
|
|
57
|
+
after the write, not by relying on exit code alone.
|
|
58
|
+
fix_code:
|
|
59
|
+
- language: yaml
|
|
60
|
+
label: 'Truncate step summary to safe size before writing (bash)'
|
|
61
|
+
code: |
|
|
62
|
+
jobs:
|
|
63
|
+
test:
|
|
64
|
+
runs-on: ubuntu-latest
|
|
65
|
+
steps:
|
|
66
|
+
- name: Run tests and write summary
|
|
67
|
+
run: |
|
|
68
|
+
# Generate potentially large summary content
|
|
69
|
+
content=$(cat test-results.md 2>/dev/null || echo "No results")
|
|
70
|
+
|
|
71
|
+
# Enforce safe limit: 1 MiB minus 10 KB buffer
|
|
72
|
+
max_bytes=$(( 1048576 - 10240 ))
|
|
73
|
+
content_bytes=${#content}
|
|
74
|
+
|
|
75
|
+
if [ "$content_bytes" -gt "$max_bytes" ]; then
|
|
76
|
+
content="${content:0:$max_bytes}"
|
|
77
|
+
content="${content}"$'\n\n> **Note:** Summary truncated — exceeded safe 1 MiB limit.'
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
printf '%s' "$content" >> "$GITHUB_STEP_SUMMARY"
|
|
81
|
+
- language: yaml
|
|
82
|
+
label: 'Truncate step summary to safe size before writing (PowerShell)'
|
|
83
|
+
code: |
|
|
84
|
+
jobs:
|
|
85
|
+
test:
|
|
86
|
+
runs-on: windows-latest
|
|
87
|
+
steps:
|
|
88
|
+
- name: Write test summary with size guard
|
|
89
|
+
shell: pwsh
|
|
90
|
+
run: |
|
|
91
|
+
$content = Get-Content test-results.md -Raw -ErrorAction SilentlyContinue
|
|
92
|
+
if (-not $content) { $content = "No test results found." }
|
|
93
|
+
|
|
94
|
+
# Safe limit: 1 MiB minus 10 KB buffer (accounts for off-by-one bug)
|
|
95
|
+
$maxBytes = 1048576 - 10240
|
|
96
|
+
$bytes = [System.Text.Encoding]::UTF8.GetByteCount($content)
|
|
97
|
+
|
|
98
|
+
if ($bytes -gt $maxBytes) {
|
|
99
|
+
# Truncate and add warning marker
|
|
100
|
+
$truncated = $content.Substring(0, [Math]::Min($content.Length, $maxBytes / 2))
|
|
101
|
+
$content = $truncated + "`n`n> **Note:** Summary truncated — exceeded safe 1 MiB limit."
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
$content | Out-File -Append -FilePath $env:GITHUB_STEP_SUMMARY -Encoding utf8
|
|
105
|
+
prevention:
|
|
106
|
+
- 'Always apply a size guard before writing to GITHUB_STEP_SUMMARY — use (1 MiB - 10 KB) as a safe upper bound'
|
|
107
|
+
- 'For test result summaries, limit to the N most-recent or most-critical failures rather than dumping all output'
|
|
108
|
+
- 'Verify critical summary writes by checking file size after the write step, not by relying on exit code 0'
|
|
109
|
+
- 'Track actions/runner#4337 for a runner fix that either raises the limit or surfaces an error when content is discarded'
|
|
110
|
+
- 'Split large summaries across multiple steps — but note each step has its own 1 MiB budget, not a shared pool'
|
|
111
|
+
docs:
|
|
112
|
+
- url: 'https://github.com/actions/runner/issues/4337'
|
|
113
|
+
label: 'actions/runner#4337: GITHUB_STEP_SUMMARY content silently dropped when size approaches 1 MiB limit (April 2026)'
|
|
114
|
+
- url: 'https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/workflow-commands-for-github-actions#adding-a-job-summary'
|
|
115
|
+
label: 'GitHub Docs: Adding a job summary — GITHUB_STEP_SUMMARY documentation and limits'
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
id: 'triggers-028'
|
|
2
|
+
title: 'Converting a draft PR to ready-for-review does not trigger `pull_request` workflow unless `ready_for_review` is explicitly listed in `types:`'
|
|
3
|
+
category: triggers
|
|
4
|
+
severity: silent-failure
|
|
5
|
+
tags:
|
|
6
|
+
- pull-request
|
|
7
|
+
- draft
|
|
8
|
+
- ready-for-review
|
|
9
|
+
- types
|
|
10
|
+
- trigger
|
|
11
|
+
- silent-failure
|
|
12
|
+
patterns:
|
|
13
|
+
- regex: 'ready_for_review'
|
|
14
|
+
flags: 'i'
|
|
15
|
+
- regex: 'pull_request\.draft\s*==\s*false'
|
|
16
|
+
flags: 'i'
|
|
17
|
+
error_messages:
|
|
18
|
+
- 'Workflow not triggered when draft PR converted to ready for review'
|
|
19
|
+
- 'No workflow runs appeared after marking PR as ready for review'
|
|
20
|
+
root_cause: |
|
|
21
|
+
GitHub fires a distinct pull_request event type — ready_for_review — when a draft PR
|
|
22
|
+
is converted to ready. This event type is NOT included in the default types list
|
|
23
|
+
of [opened, synchronize, reopened].
|
|
24
|
+
|
|
25
|
+
Two common misconfigured patterns that silently fail:
|
|
26
|
+
|
|
27
|
+
Pattern 1 — draft filter with default types:
|
|
28
|
+
A workflow uses `if: github.event.pull_request.draft == false` with default types.
|
|
29
|
+
The if: condition filters jobs correctly on synchronize/opened events, but the
|
|
30
|
+
ready_for_review conversion event is never fired because ready_for_review is not
|
|
31
|
+
in the types list. Result: a PR opened as draft, then converted to ready, will
|
|
32
|
+
never have had CI run against its commits.
|
|
33
|
+
|
|
34
|
+
Pattern 2 — only ready_for_review type:
|
|
35
|
+
A workflow lists only `types: [ready_for_review]`. This fires once when the draft
|
|
36
|
+
is converted, but never on subsequent commits to the PR (synchronize is not listed).
|
|
37
|
+
|
|
38
|
+
The correct pattern combines all four types AND adds the draft check condition so
|
|
39
|
+
that draft-state pushes are skipped while draft-to-ready conversion and subsequent
|
|
40
|
+
synchronize events all trigger the workflow.
|
|
41
|
+
|
|
42
|
+
Source: Stack Overflow #73948443 (score 8, 4,466 views), GitHub Docs pull_request
|
|
43
|
+
event types documentation.
|
|
44
|
+
fix: |
|
|
45
|
+
Combine all required event types including ready_for_review in the types: list, and
|
|
46
|
+
add a job-level if: condition to skip workflow runs while the PR is still in draft.
|
|
47
|
+
|
|
48
|
+
This ensures:
|
|
49
|
+
- Draft PRs do not run CI (filtered by the if: condition)
|
|
50
|
+
- Converting a draft to ready fires the workflow against the current HEAD commit
|
|
51
|
+
- Subsequent commits to a ready PR trigger the workflow via synchronize events
|
|
52
|
+
fix_code:
|
|
53
|
+
- language: yaml
|
|
54
|
+
label: 'Correct configuration: all four types plus draft guard condition'
|
|
55
|
+
code: |
|
|
56
|
+
on:
|
|
57
|
+
pull_request:
|
|
58
|
+
types:
|
|
59
|
+
- opened
|
|
60
|
+
- synchronize
|
|
61
|
+
- reopened
|
|
62
|
+
- ready_for_review # Must be explicit — not included in default types
|
|
63
|
+
|
|
64
|
+
jobs:
|
|
65
|
+
ci:
|
|
66
|
+
# Skip while PR is in draft state — fires for all non-draft PR events above
|
|
67
|
+
if: '! github.event.pull_request.draft'
|
|
68
|
+
runs-on: ubuntu-latest
|
|
69
|
+
steps:
|
|
70
|
+
- uses: actions/checkout@v4
|
|
71
|
+
- run: echo "CI running on non-draft PR"
|
|
72
|
+
- language: yaml
|
|
73
|
+
label: 'Alternative: run on all PR events, annotate draft runs as informational'
|
|
74
|
+
code: |
|
|
75
|
+
on:
|
|
76
|
+
pull_request:
|
|
77
|
+
types:
|
|
78
|
+
- opened
|
|
79
|
+
- synchronize
|
|
80
|
+
- reopened
|
|
81
|
+
- ready_for_review
|
|
82
|
+
|
|
83
|
+
jobs:
|
|
84
|
+
ci:
|
|
85
|
+
runs-on: ubuntu-latest
|
|
86
|
+
steps:
|
|
87
|
+
- name: Annotate draft status
|
|
88
|
+
if: github.event.pull_request.draft == true
|
|
89
|
+
run: echo "::notice::Running on draft PR — results are informational"
|
|
90
|
+
|
|
91
|
+
- uses: actions/checkout@v4
|
|
92
|
+
- run: make test
|
|
93
|
+
prevention:
|
|
94
|
+
- 'Always explicitly list all four pull_request types when your workflow must run on draft-to-ready conversions'
|
|
95
|
+
- 'Validate your trigger configuration by: opening a draft PR, pushing a commit to it, then converting to ready — all three events should behave as expected'
|
|
96
|
+
- 'Use github.event.pull_request.draft in job-level if: conditions rather than filtering by type alone, so the same workflow handles draft and non-draft PRs correctly'
|
|
97
|
+
docs:
|
|
98
|
+
- url: 'https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#pull_request'
|
|
99
|
+
label: 'GitHub Docs: pull_request event types including ready_for_review'
|
|
100
|
+
- url: 'https://stackoverflow.com/questions/73948443/github-actions-running-a-workflow-on-non-draft-prs'
|
|
101
|
+
label: 'Stack Overflow #73948443: Running a workflow on non-draft PRs (score 8, 4,466 views)'
|
package/package.json
CHANGED