@htekdev/actions-debugger 1.0.20 → 1.0.22
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/homebrew-transitive-dependency-not-guaranteed.yml +133 -0
- package/errors/runner-environment/android-sdk-api37-hash-mismatch.yml +97 -0
- package/errors/runner-environment/android-sdk-platforms-v33-removed.yml +120 -0
- package/errors/runner-environment/force-node24-env-persistent-node20-annotation.yml +127 -0
- package/errors/runner-environment/macos-26-homebrew-llvm-version-hardcoded.yml +158 -0
- package/errors/runner-environment/node24-action-self-hosted-runner-too-old.yml +93 -0
- package/errors/runner-environment/python39-removed-runner-images.yml +97 -0
- package/errors/silent-failures/setup-python-pip-cache-macos26-annotation.yml +110 -0
- package/package.json +1 -1
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
id: known-unsolved-020
|
|
2
|
+
title: "Homebrew Transitive Dependency Silently Removed — Only Documented Formulas Are Guaranteed"
|
|
3
|
+
category: known-unsolved
|
|
4
|
+
severity: limitation
|
|
5
|
+
tags:
|
|
6
|
+
- macos
|
|
7
|
+
- homebrew
|
|
8
|
+
- transitive-dependency
|
|
9
|
+
- runner-image
|
|
10
|
+
- brew
|
|
11
|
+
- silent-removal
|
|
12
|
+
- limitation
|
|
13
|
+
patterns:
|
|
14
|
+
- regex: "No such file or directory.*homebrew.*opt.*\\b(libevent|libiconv|libffi|gettext)\\b"
|
|
15
|
+
flags: "i"
|
|
16
|
+
- regex: "Library not loaded.*homebrew.*opt.*\\.dylib.*image not found"
|
|
17
|
+
flags: "i"
|
|
18
|
+
- regex: "brew.*error.*([a-z0-9_-]+): No available formula"
|
|
19
|
+
flags: "i"
|
|
20
|
+
- regex: "dyld.*Library not loaded.*/opt/homebrew/opt/[a-z0-9_-]+/lib"
|
|
21
|
+
flags: "i"
|
|
22
|
+
error_messages:
|
|
23
|
+
- "Error: No such file or directory - /opt/homebrew/opt/libevent/lib/libevent.dylib"
|
|
24
|
+
- "dyld[80]: Library not loaded: /opt/homebrew/opt/libevent/lib/libevent.dylib"
|
|
25
|
+
- "pkg-config: Package 'libevent', required by 'virtual:world', not found"
|
|
26
|
+
- "CMake Error: Could not find a package configuration file provided by 'libevent'"
|
|
27
|
+
root_cause: |
|
|
28
|
+
GitHub-hosted macOS runner images include a curated list of Homebrew formulae that are
|
|
29
|
+
**officially documented and guaranteed** (listed in the image README, e.g.
|
|
30
|
+
`images/macos/macos-15-Readme.md`). Any Homebrew package that is present on the image
|
|
31
|
+
only as a **transitive dependency** of another formula — not explicitly documented — can
|
|
32
|
+
silently disappear between image updates when the parent formula's dependency chain changes.
|
|
33
|
+
|
|
34
|
+
**What happens:**
|
|
35
|
+
When a documented formula is upgraded (e.g., `tmux`, `openssl@3`, `ffmpeg`), its new
|
|
36
|
+
version may no longer depend on the same set of transitive packages as the previous
|
|
37
|
+
version. The transitive dependency is removed from the image automatically in the next
|
|
38
|
+
image release, with no announcement, no deprecation notice, and no entry in the image
|
|
39
|
+
changelog.
|
|
40
|
+
|
|
41
|
+
**Real example:** `libevent` was present on `macos-15` images as a transitive dependency
|
|
42
|
+
of another documented formula. When that formula's dependency chain changed in the
|
|
43
|
+
`20260525.0142.1` image, `libevent` was removed. Workflows depending on `libevent`
|
|
44
|
+
(for building tmux from source, libevent-based C++ servers, etc.) began failing with
|
|
45
|
+
"No such file or directory" errors without any changes to the workflow itself.
|
|
46
|
+
|
|
47
|
+
GitHub's response (confirmed in runner-images#14170):
|
|
48
|
+
> "libevent has never been part of the documented Homebrew Formulae list. It was only
|
|
49
|
+
> present incidentally as a transitive dependency of another formula, and that
|
|
50
|
+
> dependency chain has changed in the newer image. Since libevent is not an officially
|
|
51
|
+
> preinstalled tool on the image, its presence is not guaranteed across image versions
|
|
52
|
+
> and we don't plan to pin it."
|
|
53
|
+
|
|
54
|
+
**This is by design and will not be fixed.** The GitHub runner-images team will not
|
|
55
|
+
guarantee transitive dependencies — only the explicitly documented formula list is stable.
|
|
56
|
+
|
|
57
|
+
Source: actions/runner-images#14170 (closed as `wontfix / not_planned`, May 2026).
|
|
58
|
+
fix: |
|
|
59
|
+
The only reliable fix is to **explicitly install every library your workflow needs**,
|
|
60
|
+
regardless of whether it "happens to be there" on the current image.
|
|
61
|
+
|
|
62
|
+
**Immediate fix:** Add `brew install <missing-package>` as a workflow step before
|
|
63
|
+
any step that requires the package:
|
|
64
|
+
|
|
65
|
+
**Long-term fix:** Audit ALL your workflow's Homebrew dependencies and cross-reference
|
|
66
|
+
each one against the official runner image README. Any package NOT listed there must be
|
|
67
|
+
explicitly installed in your workflow.
|
|
68
|
+
|
|
69
|
+
**Finding the image README:**
|
|
70
|
+
- macOS 15: https://github.com/actions/runner-images/blob/main/images/macos/macos-15-Readme.md
|
|
71
|
+
- macOS 26: https://github.com/actions/runner-images/blob/main/images/macos/macos-26-Readme.md
|
|
72
|
+
If your package isn't in the "Homebrew Packages" section of the README, install it
|
|
73
|
+
explicitly — it's not guaranteed.
|
|
74
|
+
fix_code:
|
|
75
|
+
- language: yaml
|
|
76
|
+
label: "Explicitly install transitive dependencies before use"
|
|
77
|
+
code: |
|
|
78
|
+
jobs:
|
|
79
|
+
build:
|
|
80
|
+
runs-on: macos-latest
|
|
81
|
+
steps:
|
|
82
|
+
- uses: actions/checkout@v4
|
|
83
|
+
|
|
84
|
+
# Explicitly install ALL required libraries — even ones that "used to be there"
|
|
85
|
+
- name: Install dependencies
|
|
86
|
+
run: |
|
|
87
|
+
brew install libevent libffi gettext
|
|
88
|
+
# Do NOT rely on transitive deps from other formulae
|
|
89
|
+
|
|
90
|
+
- name: Build
|
|
91
|
+
run: make
|
|
92
|
+
- language: yaml
|
|
93
|
+
label: "Audit step — verify dependencies are explicitly documented"
|
|
94
|
+
code: |
|
|
95
|
+
# Check if your dependency is in the official image README:
|
|
96
|
+
# curl -s https://raw.githubusercontent.com/actions/runner-images/main/images/macos/macos-15-Readme.md \
|
|
97
|
+
# | grep -i "libevent"
|
|
98
|
+
# If no output → the package is NOT guaranteed → add brew install
|
|
99
|
+
|
|
100
|
+
- name: Ensure all dependencies are installed
|
|
101
|
+
run: |
|
|
102
|
+
# Install everything your build actually needs
|
|
103
|
+
brew install libevent tmux pkg-config
|
|
104
|
+
- language: yaml
|
|
105
|
+
label: "Cache explicit brew installs to reduce per-job overhead"
|
|
106
|
+
code: |
|
|
107
|
+
- name: Cache Homebrew packages
|
|
108
|
+
uses: actions/cache@v4
|
|
109
|
+
with:
|
|
110
|
+
path: |
|
|
111
|
+
~/Library/Caches/Homebrew
|
|
112
|
+
/opt/homebrew/Cellar
|
|
113
|
+
key: ${{ runner.os }}-brew-${{ hashFiles('Brewfile') }}
|
|
114
|
+
restore-keys: |
|
|
115
|
+
${{ runner.os }}-brew-
|
|
116
|
+
|
|
117
|
+
- name: Install dependencies from Brewfile
|
|
118
|
+
run: brew bundle
|
|
119
|
+
prevention:
|
|
120
|
+
- "Never rely on a Homebrew package being preinstalled unless it is explicitly listed in the runner image's official README (linked below)."
|
|
121
|
+
- "Maintain a `Brewfile` in your repository and use `brew bundle` to install all macOS dependencies explicitly — this documents and enforces your true dependency set."
|
|
122
|
+
- "When a workflow starts failing on macOS runners after an image update, check the runner-images release notes for formula removals and cross-reference against the image README."
|
|
123
|
+
- "Subscribe to runner-images releases (GitHub → Watch → Releases) to get notified when the image README changes and transitive deps may be affected."
|
|
124
|
+
- "Run `brew deps --tree <your-installed-formula>` locally to identify which transitive deps your workflow relies on, then add explicit `brew install` calls for each."
|
|
125
|
+
docs:
|
|
126
|
+
- url: "https://github.com/actions/runner-images/issues/14170"
|
|
127
|
+
label: "runner-images#14170: macos-15 libevent removed as transitive dep (closed wontfix)"
|
|
128
|
+
- url: "https://github.com/actions/runner-images/blob/main/images/macos/macos-15-Readme.md"
|
|
129
|
+
label: "macOS 15 runner image README — official guaranteed software list"
|
|
130
|
+
- url: "https://github.com/actions/runner-images/blob/main/images/macos/macos-26-Readme.md"
|
|
131
|
+
label: "macOS 26 runner image README — official guaranteed software list"
|
|
132
|
+
- url: "https://docs.brew.sh/Manpage#bundle-subcommand"
|
|
133
|
+
label: "Homebrew Bundle subcommand — manage dependencies via Brewfile"
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
id: runner-environment-055
|
|
2
|
+
title: "Android SDK Platform 37 Installed as 'android-37.0' — Builds Fail Looking for 'android-37'"
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- android
|
|
7
|
+
- android-sdk
|
|
8
|
+
- gradle
|
|
9
|
+
- ubuntu-2404
|
|
10
|
+
- sdk-platform
|
|
11
|
+
- hash-string
|
|
12
|
+
patterns:
|
|
13
|
+
- regex: "Failed to find target with hash string 'android-37'"
|
|
14
|
+
flags: "i"
|
|
15
|
+
- regex: "Failed to find target.*android-37[^\\d]"
|
|
16
|
+
flags: "i"
|
|
17
|
+
- regex: "Could not determine.*dependencies.*android-37[^\\d]"
|
|
18
|
+
flags: "i"
|
|
19
|
+
- regex: "platforms/android-37\\.0.*android-37[^\\.]"
|
|
20
|
+
flags: "i"
|
|
21
|
+
error_messages:
|
|
22
|
+
- "Failed to find target with hash string 'android-37' in: /usr/local/lib/android/sdk"
|
|
23
|
+
- "Could not determine the dependencies of task ':app:compileDebugJavaWithJavac'."
|
|
24
|
+
- "> Failed to find target with hash string 'android-37'"
|
|
25
|
+
root_cause: |
|
|
26
|
+
On the Ubuntu 24.04 runner image (from approximately image version 20260323), the
|
|
27
|
+
Android SDK Platform 37 is installed under the directory name `android-37.0` rather
|
|
28
|
+
than the expected `android-37`. Gradle and the Android Gradle Plugin (AGP) look up
|
|
29
|
+
platform targets by their hash string (`android-37`), which must exactly match the
|
|
30
|
+
subdirectory name inside `$ANDROID_SDK_ROOT/platforms/`.
|
|
31
|
+
|
|
32
|
+
When `sdkmanager` installs `platforms;android-37.0`, it creates:
|
|
33
|
+
`/usr/local/lib/android/sdk/platforms/android-37.0/`
|
|
34
|
+
|
|
35
|
+
But AGP resolves `compileSdk = 37` (or `compileSdkVersion 37`) to hash string
|
|
36
|
+
`android-37`, not `android-37.0`. The lookup fails even though the SDK is physically
|
|
37
|
+
present on the runner (runner-images#13859).
|
|
38
|
+
|
|
39
|
+
Root cause in the runner image: the `platforms;android-37.0` package name was published
|
|
40
|
+
by Google with a `.0` version suffix in the SDK package path, causing a naming
|
|
41
|
+
inconsistency between the package identifier and the installed directory name expected
|
|
42
|
+
by build tools.
|
|
43
|
+
fix: |
|
|
44
|
+
Add a workaround step that creates a symlink from `android-37` → `android-37.0` before
|
|
45
|
+
the Gradle build. This resolves the hash lookup without any source code changes.
|
|
46
|
+
|
|
47
|
+
Alternatively, pin `compileSdk` to 36 (which is installed normally) until the runner
|
|
48
|
+
image is fixed, or install `platforms;android-37` explicitly via sdkmanager — but note
|
|
49
|
+
that as of the time of writing the `android-37` (non-.0) package may not yet be
|
|
50
|
+
published to the official SDK registry.
|
|
51
|
+
fix_code:
|
|
52
|
+
- language: yaml
|
|
53
|
+
label: "Symlink workaround — link android-37 to android-37.0 before build"
|
|
54
|
+
code: |
|
|
55
|
+
steps:
|
|
56
|
+
- uses: actions/checkout@v4
|
|
57
|
+
|
|
58
|
+
- name: Fix Android SDK 37 directory name mismatch
|
|
59
|
+
run: |
|
|
60
|
+
SDK_PLATFORMS="$ANDROID_SDK_ROOT/platforms"
|
|
61
|
+
if [ -d "$SDK_PLATFORMS/android-37.0" ] && [ ! -d "$SDK_PLATFORMS/android-37" ]; then
|
|
62
|
+
ln -s "$SDK_PLATFORMS/android-37.0" "$SDK_PLATFORMS/android-37"
|
|
63
|
+
echo "Symlinked android-37 -> android-37.0"
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
- name: Build APK
|
|
67
|
+
run: ./gradlew assembleDebug
|
|
68
|
+
- language: yaml
|
|
69
|
+
label: "Pin compileSdk to 36 as temporary workaround"
|
|
70
|
+
code: |
|
|
71
|
+
# In app/build.gradle or build.gradle.kts:
|
|
72
|
+
android {
|
|
73
|
+
compileSdk = 36 # Use 36 until android-37 symlink issue is resolved
|
|
74
|
+
# compileSdk = 37 # <- caused 'android-37' hash mismatch
|
|
75
|
+
}
|
|
76
|
+
- language: yaml
|
|
77
|
+
label: "Install android-37 explicitly via sdkmanager"
|
|
78
|
+
code: |
|
|
79
|
+
steps:
|
|
80
|
+
- name: Install Android SDK Platform 37
|
|
81
|
+
run: |
|
|
82
|
+
echo "y" | $ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager \
|
|
83
|
+
"platforms;android-37" \
|
|
84
|
+
"build-tools;37.0.0"
|
|
85
|
+
- name: Build
|
|
86
|
+
run: ./gradlew assembleDebug
|
|
87
|
+
prevention:
|
|
88
|
+
- "When upgrading `compileSdk` to a newly released Android API level, test against ubuntu-24.04 runners in a feature branch first before rolling out to all jobs."
|
|
89
|
+
- "Subscribe to runner-images releases for `ubuntu-24.04` to catch SDK directory naming changes early."
|
|
90
|
+
- "Add an explicit `sdkmanager` install step for the exact platform and build-tools version your project requires instead of relying on pre-installed SDKs."
|
|
91
|
+
docs:
|
|
92
|
+
- url: "https://github.com/actions/runner-images/issues/13859"
|
|
93
|
+
label: "runner-images#13859 — Ubuntu 24.04 installs API 37 as android-37.0; builds fail looking for android-37"
|
|
94
|
+
- url: "https://developer.android.com/studio/releases/platforms"
|
|
95
|
+
label: "Android SDK Platform releases — official platform package naming"
|
|
96
|
+
- url: "https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources"
|
|
97
|
+
label: "GitHub Docs — GitHub-hosted runner software"
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
id: runner-environment-056
|
|
2
|
+
title: "Android SDK Platforms and Build Tools < v34 Removed from Runner Images (Jan 2026)"
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- android
|
|
7
|
+
- android-sdk
|
|
8
|
+
- gradle
|
|
9
|
+
- runner-images
|
|
10
|
+
- ubuntu-2204
|
|
11
|
+
- macos-14
|
|
12
|
+
- windows-2022
|
|
13
|
+
- compile-sdk
|
|
14
|
+
patterns:
|
|
15
|
+
- regex: "Failed to find target with hash string 'android-3[0-3]'"
|
|
16
|
+
flags: "i"
|
|
17
|
+
- regex: "Failed to find Build Tools revision 3[0-3]\\."
|
|
18
|
+
flags: "i"
|
|
19
|
+
- regex: "Build Tools revision.*not installed|not installed.*Build Tools"
|
|
20
|
+
flags: "i"
|
|
21
|
+
- regex: "compileSdkVersion.*3[0-3].*not found|SDK Platform.*3[0-3].*not installed"
|
|
22
|
+
flags: "i"
|
|
23
|
+
error_messages:
|
|
24
|
+
- "Failed to find target with hash string 'android-33' in: /usr/local/lib/android/sdk"
|
|
25
|
+
- "Failed to find Build Tools revision 33.0.2"
|
|
26
|
+
- "SDK Platform '33' is not installed."
|
|
27
|
+
- "Failed to find target with hash string 'android-32'"
|
|
28
|
+
root_cause: |
|
|
29
|
+
Starting January 12, 2026, GitHub removed pre-installed Android SDK platforms and build
|
|
30
|
+
tools older than version 34 from the following runner images (runner-images#13469):
|
|
31
|
+
|
|
32
|
+
- Ubuntu 22.04
|
|
33
|
+
- macOS 14 (and macOS 14 Arm64)
|
|
34
|
+
- Windows Server 2022
|
|
35
|
+
|
|
36
|
+
Affected toolchain components:
|
|
37
|
+
- SDK Platforms: android-33 and older (Android 13 / API 33, API 32, etc.)
|
|
38
|
+
- Build Tools: versions older than 34.0.0
|
|
39
|
+
|
|
40
|
+
The removal was motivated by freeing up disk space. Projects that reference
|
|
41
|
+
`compileSdkVersion 33` (or lower) in their Gradle configuration, or that install
|
|
42
|
+
specific old build-tools versions, fail immediately because the expected directories are
|
|
43
|
+
absent from `$ANDROID_SDK_ROOT/platforms/` and `$ANDROID_SDK_ROOT/build-tools/`.
|
|
44
|
+
|
|
45
|
+
Note: Ubuntu 24.04, macOS 15, and Windows Server 2025 images were not affected because
|
|
46
|
+
they never carried the older SDK platforms.
|
|
47
|
+
fix: |
|
|
48
|
+
Option A — Upgrade compileSdk and targetSdk to 34 or higher (recommended):
|
|
49
|
+
Updating to a supported API level removes the dependency on removed SDK packages.
|
|
50
|
+
API 34 (Android 14) is widely available and well-tested.
|
|
51
|
+
|
|
52
|
+
Option B — Install the required SDK platform at runtime:
|
|
53
|
+
Use `sdkmanager` in a workflow step to download and install the exact platform and
|
|
54
|
+
build tools version before the Gradle build runs. This adds ~30-60 seconds to the job.
|
|
55
|
+
fix_code:
|
|
56
|
+
- language: yaml
|
|
57
|
+
label: "Upgrade compileSdk to 35 (recommended long-term fix)"
|
|
58
|
+
code: |
|
|
59
|
+
# In app/build.gradle.kts:
|
|
60
|
+
android {
|
|
61
|
+
compileSdk = 35 # upgraded from 33 — no SDK install step needed
|
|
62
|
+
targetSdk = 35
|
|
63
|
+
minSdk = 21
|
|
64
|
+
}
|
|
65
|
+
- language: yaml
|
|
66
|
+
label: "Install removed SDK platform at runtime (keeps compileSdk 33)"
|
|
67
|
+
code: |
|
|
68
|
+
steps:
|
|
69
|
+
- uses: actions/checkout@v4
|
|
70
|
+
|
|
71
|
+
- name: Install Android SDK Platform 33 and Build Tools 33.0.2
|
|
72
|
+
run: |
|
|
73
|
+
echo "y" | $ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager \
|
|
74
|
+
"platforms;android-33" \
|
|
75
|
+
"build-tools;33.0.2"
|
|
76
|
+
|
|
77
|
+
- name: Build
|
|
78
|
+
run: ./gradlew assembleDebug
|
|
79
|
+
- language: yaml
|
|
80
|
+
label: "Install SDK using android-actions/setup-android"
|
|
81
|
+
code: |
|
|
82
|
+
steps:
|
|
83
|
+
- uses: actions/checkout@v4
|
|
84
|
+
- uses: android-actions/setup-android@v3
|
|
85
|
+
with:
|
|
86
|
+
packages: >
|
|
87
|
+
platforms;android-33
|
|
88
|
+
build-tools;33.0.2
|
|
89
|
+
- run: ./gradlew assembleRelease
|
|
90
|
+
- language: yaml
|
|
91
|
+
label: "Matrix build: validate migration to newer API level"
|
|
92
|
+
code: |
|
|
93
|
+
jobs:
|
|
94
|
+
build:
|
|
95
|
+
strategy:
|
|
96
|
+
matrix:
|
|
97
|
+
compile-sdk: [33, 34, 35]
|
|
98
|
+
runs-on: ubuntu-22.04
|
|
99
|
+
steps:
|
|
100
|
+
- uses: actions/checkout@v4
|
|
101
|
+
- name: Install required SDK (only needed for API < 34)
|
|
102
|
+
if: matrix.compile-sdk < 34
|
|
103
|
+
run: |
|
|
104
|
+
echo "y" | $ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager \
|
|
105
|
+
"platforms;android-${{ matrix.compile-sdk }}"
|
|
106
|
+
- run: ./gradlew assembleDebug
|
|
107
|
+
env:
|
|
108
|
+
COMPILE_SDK_VERSION: ${{ matrix.compile-sdk }}
|
|
109
|
+
prevention:
|
|
110
|
+
- "Target `compileSdk` and `targetSdk` at API 34 or higher; Google Play requires API 35+ for new app submissions as of August 2025."
|
|
111
|
+
- "Audit your `build.gradle` files for hard-coded old `compileSdkVersion` values and migrate proactively during the announcement window."
|
|
112
|
+
- "Subscribe to runner-images GitHub Issues to see SDK removal announcements before they hit production workflows."
|
|
113
|
+
- "Add an explicit `sdkmanager` install step for any SDK version your build requires so the workflow is portable regardless of what's pre-installed."
|
|
114
|
+
docs:
|
|
115
|
+
- url: "https://github.com/actions/runner-images/issues/13469"
|
|
116
|
+
label: "runner-images#13469 — Android SDK platforms and build tools < v34 removed on Jan 12, 2026"
|
|
117
|
+
- url: "https://developer.android.com/tools/sdkmanager"
|
|
118
|
+
label: "Android Docs — sdkmanager command-line tool"
|
|
119
|
+
- url: "https://developer.android.com/google/play/requirements/target-sdk"
|
|
120
|
+
label: "Google Play — target API level requirements"
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
id: runner-environment-057
|
|
2
|
+
title: "FORCE_JAVASCRIPT_ACTIONS_TO_NODE24 Still Emits Node 20 Deprecation Annotation"
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: warning
|
|
5
|
+
tags:
|
|
6
|
+
- node20
|
|
7
|
+
- node24
|
|
8
|
+
- deprecation
|
|
9
|
+
- annotation
|
|
10
|
+
- force-node24
|
|
11
|
+
- javascript-actions
|
|
12
|
+
patterns:
|
|
13
|
+
- regex: "Node\\.js 20 is deprecated.*following actions target Node\\.js 20 but are being forced to run on Node\\.js 24"
|
|
14
|
+
flags: "i"
|
|
15
|
+
- regex: "The following actions target Node\\.?20 but are being forced to run on Node\\.?24"
|
|
16
|
+
flags: "i"
|
|
17
|
+
- regex: "following actions are running on Node\\.js 20 and may not work as expected"
|
|
18
|
+
flags: "i"
|
|
19
|
+
error_messages:
|
|
20
|
+
- "Node.js 20 is deprecated. The following actions target Node.js 20 but are being forced to run on Node.js 24: some-action@v1"
|
|
21
|
+
- "The following actions are running on Node.js 20 and may not work as expected: actions/cache@v3, custom-org/deploy@v2"
|
|
22
|
+
- "Node.js 20 actions are deprecated. The following actions are running on Node.js 20"
|
|
23
|
+
root_cause: |
|
|
24
|
+
Setting `FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"` in a workflow's `env:` section
|
|
25
|
+
successfully redirects JavaScript actions that declare `using: node20` to execute on
|
|
26
|
+
Node.js 24 at runtime. However, the runner still emits a deprecation annotation at
|
|
27
|
+
the end of every job listing those actions.
|
|
28
|
+
|
|
29
|
+
**Two distinct annotation messages depending on runner version:**
|
|
30
|
+
|
|
31
|
+
- **Pre-runner v2.326 (before PR#4303):** Inaccurate message — "The following actions
|
|
32
|
+
are **running on** Node.js 20 and may not work as expected" — even though they are
|
|
33
|
+
actually executing on Node 24. This is a bug in the runner's deprecation tracking
|
|
34
|
+
which recorded actions before the `FORCE_` env var was resolved.
|
|
35
|
+
|
|
36
|
+
- **Post-runner v2.326 (after PR#4303 fix):** Accurate but still present message —
|
|
37
|
+
"Node.js 20 is deprecated. The following actions **target** Node.js 20 but are
|
|
38
|
+
being forced to run on Node.js 24" — this annotation correctly describes the
|
|
39
|
+
situation but continues to appear as long as any action declares `using: node20`.
|
|
40
|
+
|
|
41
|
+
**Why this matters:** The annotation appears as a warning in GitHub's UI, turning
|
|
42
|
+
affected jobs "yellow" or showing red annotation badges, causing developer confusion
|
|
43
|
+
about whether `FORCE_JAVASCRIPT_ACTIONS_TO_NODE24` is working. CI dashboards that
|
|
44
|
+
treat any annotation as a failure (strict mode) will block PRs.
|
|
45
|
+
|
|
46
|
+
**Root cause of persistence:** The annotation fires based on the action's *declared*
|
|
47
|
+
`using` field in `action.yml` (`node20`), not the *actual runtime* used. Even with
|
|
48
|
+
the force env var, the declaration still exists until the action author updates and
|
|
49
|
+
publishes a new release with `using: node24`.
|
|
50
|
+
|
|
51
|
+
Source: actions/runner#4295 (9 reactions, April 2026), fixed partially in runner PR#4303.
|
|
52
|
+
fix: |
|
|
53
|
+
The only permanent fix is to eliminate the `using: node20` declaration from every
|
|
54
|
+
action listed in the annotation.
|
|
55
|
+
|
|
56
|
+
**If you control the action:**
|
|
57
|
+
Update `action.yml` to declare `runs.using: 'node24'`, recompile with Node 24, and
|
|
58
|
+
publish a new release. Downstream consumers must update their `uses:` pin.
|
|
59
|
+
|
|
60
|
+
**If you use a third-party action:**
|
|
61
|
+
Update to a newer version of the action that already ships `using: node24`. Check the
|
|
62
|
+
action's GitHub releases or `action.yml` on the latest tag.
|
|
63
|
+
|
|
64
|
+
**Temporary suppression (not recommended for long-term):**
|
|
65
|
+
Continue using `FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"` — the action *does* run
|
|
66
|
+
on Node 24 despite the annotation. The annotation is informational. If you need
|
|
67
|
+
annotation-clean builds, the only path is action upgrades.
|
|
68
|
+
|
|
69
|
+
**Audit all actions in your workflow:**
|
|
70
|
+
Run this to find actions still declaring node20 in their action.yml:
|
|
71
|
+
```bash
|
|
72
|
+
find . -name 'action.yml' -o -name 'action.yaml' | xargs grep -l 'using.*node20'
|
|
73
|
+
```
|
|
74
|
+
fix_code:
|
|
75
|
+
- language: yaml
|
|
76
|
+
label: "Upgrade pinned actions to node24-compatible major versions"
|
|
77
|
+
code: |
|
|
78
|
+
# Before: actions declaring using: node20 → emits annotation even with FORCE_ var
|
|
79
|
+
steps:
|
|
80
|
+
- uses: actions/checkout@v3 # node20 → upgrade to @v4
|
|
81
|
+
- uses: actions/cache@v3 # node20 → upgrade to @v4
|
|
82
|
+
- uses: actions/upload-artifact@v3 # node20 → upgrade to @v4
|
|
83
|
+
|
|
84
|
+
# After: actions declaring using: node24 → no annotation
|
|
85
|
+
steps:
|
|
86
|
+
- uses: actions/checkout@v4 # node24 ✅
|
|
87
|
+
- uses: actions/cache@v4 # node24 ✅
|
|
88
|
+
- uses: actions/upload-artifact@v4 # node24 ✅
|
|
89
|
+
- language: yaml
|
|
90
|
+
label: "For your own action.yml — update to node24"
|
|
91
|
+
code: |
|
|
92
|
+
# action.yml — before
|
|
93
|
+
runs:
|
|
94
|
+
using: 'node20'
|
|
95
|
+
main: 'dist/index.js'
|
|
96
|
+
|
|
97
|
+
# action.yml — after
|
|
98
|
+
runs:
|
|
99
|
+
using: 'node24'
|
|
100
|
+
main: 'dist/index.js'
|
|
101
|
+
# Also recompile: ncc build src/index.ts --license licenses.txt
|
|
102
|
+
- language: yaml
|
|
103
|
+
label: "Temporary escape hatch — FORCE env var (annotation still appears)"
|
|
104
|
+
code: |
|
|
105
|
+
jobs:
|
|
106
|
+
build:
|
|
107
|
+
runs-on: ubuntu-latest
|
|
108
|
+
env:
|
|
109
|
+
# Actions run on Node 24 but annotation still fires for node20 declarations
|
|
110
|
+
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: 'true'
|
|
111
|
+
steps:
|
|
112
|
+
- uses: actions/checkout@v4
|
|
113
|
+
prevention:
|
|
114
|
+
- "Pin to the latest major version of all official `actions/*` actions — they already ship `using: node24` in current releases."
|
|
115
|
+
- "Search your workflow files for `uses:` pins older than the current major version and update them in batch before Node 20 enforcement completes."
|
|
116
|
+
- "For private/internal actions, add a CI check that fails if any `action.yml` in the monorepo still declares `using: node20`."
|
|
117
|
+
- "Use `FORCE_JAVASCRIPT_ACTIONS_TO_NODE24=true` only as a bridge, not a permanent solution — the annotation is a reminder that action.yml still needs updating."
|
|
118
|
+
- "Run periodic audits: `gh api /repos/ORG/REPO/contents/action.yml | jq .content | base64 -d | grep using`."
|
|
119
|
+
docs:
|
|
120
|
+
- url: "https://github.com/actions/runner/issues/4295"
|
|
121
|
+
label: "actions/runner#4295: Node 20 deprecation warning fires even with FORCE_JAVASCRIPT_ACTIONS_TO_NODE24"
|
|
122
|
+
- url: "https://github.com/actions/runner/pull/4303"
|
|
123
|
+
label: "actions/runner#4303: Node 24 enforcement + Linux ARM32 deprecation support (fix)"
|
|
124
|
+
- url: "https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/"
|
|
125
|
+
label: "GitHub Changelog: Deprecation of Node 20 on GitHub Actions runners"
|
|
126
|
+
- url: "https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions#runs-for-javascript-actions"
|
|
127
|
+
label: "Metadata syntax: runs.using for JavaScript actions"
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
id: runner-environment-058
|
|
2
|
+
title: "macOS 26 Homebrew LLVM Jumps 18 → 20 — Hardcoded llvm@18 Paths Fail"
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- macos-26
|
|
7
|
+
- macos-latest
|
|
8
|
+
- llvm
|
|
9
|
+
- clang
|
|
10
|
+
- homebrew
|
|
11
|
+
- runner-image
|
|
12
|
+
- breaking-change
|
|
13
|
+
- cpp
|
|
14
|
+
- cmake
|
|
15
|
+
patterns:
|
|
16
|
+
- regex: "no such file or directory.*homebrew.*opt.*llvm@(17|18)/bin"
|
|
17
|
+
flags: "i"
|
|
18
|
+
- regex: "clang(\\+\\+)?-(17|18).*command not found|No such file.*clang-(17|18)"
|
|
19
|
+
flags: "i"
|
|
20
|
+
- regex: "brew.*prefix.*llvm@(17|18).*Error.*no such keg"
|
|
21
|
+
flags: "i"
|
|
22
|
+
- regex: "Could not find.*LLVM (17|18).*Config\\.cmake"
|
|
23
|
+
flags: "i"
|
|
24
|
+
- regex: "llvm-config-(17|18).*not found"
|
|
25
|
+
flags: "i"
|
|
26
|
+
error_messages:
|
|
27
|
+
- "zsh: no such file or directory: /opt/homebrew/opt/llvm@18/bin/clang++"
|
|
28
|
+
- "Error: clang-18: command not found"
|
|
29
|
+
- "Error: No such keg: /opt/homebrew/Cellar/llvm@18"
|
|
30
|
+
- "CMake Error at /opt/homebrew/lib/cmake/llvm/LLVMConfig.cmake: LLVM 18.1 required but 20.1 found"
|
|
31
|
+
- "llvm-config-18: not found"
|
|
32
|
+
root_cause: |
|
|
33
|
+
When the `macos-latest` label migrated to macOS 26 Tahoe (beginning June 15, 2026),
|
|
34
|
+
the Homebrew-installed LLVM major version changed from **18.1.8** (on macOS 15) to
|
|
35
|
+
**20.1.8** (on macOS 26). This is a two-major-version jump that silently breaks any
|
|
36
|
+
workflow that hardcodes LLVM version numbers in paths, environment variables, or
|
|
37
|
+
CMake configuration.
|
|
38
|
+
|
|
39
|
+
**Affected patterns:**
|
|
40
|
+
- Shell scripts using `$(brew --prefix llvm@18)/bin/clang++` — the `llvm@18` keg no
|
|
41
|
+
longer exists on macOS 26; Homebrew returns "Error: No such keg"
|
|
42
|
+
- Workflows setting `CC=clang-18` or `CXX=clang++-18` — these binaries aren't
|
|
43
|
+
installed; the available binaries are `clang-20` and `clang++-20`
|
|
44
|
+
- CMake `find_package(LLVM 18 REQUIRED)` — succeeds on macOS 15 because Homebrew
|
|
45
|
+
LLVM 18 is present; fails on macOS 26 because only LLVM 20 is available
|
|
46
|
+
- `llvm-config-18 --version` in build scripts — the versioned binary doesn't exist
|
|
47
|
+
- `pkg-config --libs llvm-18` — the pkg-config file for llvm-18 is absent
|
|
48
|
+
|
|
49
|
+
**macOS 26 image ships with:**
|
|
50
|
+
- `llvm` formula → installs LLVM 20.x (unversioned `llvm` formula always tracks latest)
|
|
51
|
+
- `llvm@20` → available for explicit `brew install llvm@20`
|
|
52
|
+
- No `llvm@18` keg in the default image
|
|
53
|
+
|
|
54
|
+
Note: Workflows using the *unversioned* `llvm` or `clang` commands (e.g., `CC=clang`,
|
|
55
|
+
`$(brew --prefix llvm)/bin/clang++`) are NOT affected — they pick up the default
|
|
56
|
+
LLVM version on each image automatically.
|
|
57
|
+
|
|
58
|
+
Source: runner-images#14167 release diff table (Clang/LLVM 18.1.8 → 20.1.8);
|
|
59
|
+
community migration example: POCO C++ Libraries commit ff8174d (April 2026).
|
|
60
|
+
fix: |
|
|
61
|
+
Replace all hardcoded `llvm@18` / `clang-18` references with either the unversioned
|
|
62
|
+
`llvm` formula path or the explicit `llvm@20` path on macOS 26.
|
|
63
|
+
|
|
64
|
+
**Option 1 — Use the unversioned Homebrew prefix (recommended):**
|
|
65
|
+
Replace `$(brew --prefix llvm@18)` with `$(brew --prefix llvm)` — this always resolves
|
|
66
|
+
to the current default LLVM, making the workflow future-proof.
|
|
67
|
+
|
|
68
|
+
**Option 2 — Explicit llvm@20 for reproducibility:**
|
|
69
|
+
Install `llvm@20` explicitly and reference it by version. This avoids future surprises
|
|
70
|
+
when `llvm` bumps to 21+.
|
|
71
|
+
|
|
72
|
+
**Option 3 — Pin to macos-15 temporarily:**
|
|
73
|
+
If the migration is not immediately feasible, pin to `macos-15` while updating your
|
|
74
|
+
build system to use the unversioned LLVM path.
|
|
75
|
+
|
|
76
|
+
**For CMake projects:** Remove the version constraint from `find_package(LLVM X REQUIRED)`
|
|
77
|
+
or use `find_package(LLVM REQUIRED)` and check the found version at configure time.
|
|
78
|
+
fix_code:
|
|
79
|
+
- language: yaml
|
|
80
|
+
label: "Use unversioned llvm prefix — works across all macOS runner versions"
|
|
81
|
+
code: |
|
|
82
|
+
jobs:
|
|
83
|
+
build:
|
|
84
|
+
runs-on: macos-latest
|
|
85
|
+
steps:
|
|
86
|
+
- uses: actions/checkout@v4
|
|
87
|
+
|
|
88
|
+
- name: Install LLVM
|
|
89
|
+
run: brew install llvm # installs current default (llvm@20 on macOS 26)
|
|
90
|
+
|
|
91
|
+
- name: Build
|
|
92
|
+
run: |
|
|
93
|
+
# Use unversioned prefix — future-proof across LLVM major bumps
|
|
94
|
+
LLVM_PREFIX=$(brew --prefix llvm)
|
|
95
|
+
export CC="$LLVM_PREFIX/bin/clang"
|
|
96
|
+
export CXX="$LLVM_PREFIX/bin/clang++"
|
|
97
|
+
export LDFLAGS="-L$LLVM_PREFIX/lib"
|
|
98
|
+
export CPPFLAGS="-I$LLVM_PREFIX/include"
|
|
99
|
+
make -j$(sysctl -n hw.logicalcpu)
|
|
100
|
+
- language: yaml
|
|
101
|
+
label: "Explicit llvm@20 for reproducible macOS 26 builds"
|
|
102
|
+
code: |
|
|
103
|
+
jobs:
|
|
104
|
+
build:
|
|
105
|
+
runs-on: macos-latest # macOS 26
|
|
106
|
+
steps:
|
|
107
|
+
- uses: actions/checkout@v4
|
|
108
|
+
|
|
109
|
+
- name: Install LLVM 20
|
|
110
|
+
run: brew install llvm@20
|
|
111
|
+
|
|
112
|
+
- name: Configure and build
|
|
113
|
+
run: |
|
|
114
|
+
export CC="$(brew --prefix llvm@20)/bin/clang"
|
|
115
|
+
export CXX="$(brew --prefix llvm@20)/bin/clang++"
|
|
116
|
+
cmake -B build \
|
|
117
|
+
-DCMAKE_C_COMPILER="$CC" \
|
|
118
|
+
-DCMAKE_CXX_COMPILER="$CXX" \
|
|
119
|
+
-DLLVM_DIR="$(brew --prefix llvm@20)/lib/cmake/llvm"
|
|
120
|
+
cmake --build build --parallel
|
|
121
|
+
- language: yaml
|
|
122
|
+
label: "CMake: remove version constraint from find_package(LLVM)"
|
|
123
|
+
code: |
|
|
124
|
+
# CMakeLists.txt — before
|
|
125
|
+
find_package(LLVM 18 REQUIRED CONFIG)
|
|
126
|
+
|
|
127
|
+
# CMakeLists.txt — after (accepts any version)
|
|
128
|
+
find_package(LLVM REQUIRED CONFIG)
|
|
129
|
+
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
|
|
130
|
+
# Optionally enforce a minimum version:
|
|
131
|
+
if(LLVM_VERSION_MAJOR LESS 18)
|
|
132
|
+
message(FATAL_ERROR "LLVM >= 18 required, got ${LLVM_PACKAGE_VERSION}")
|
|
133
|
+
endif()
|
|
134
|
+
- language: yaml
|
|
135
|
+
label: "Pin to macos-15 as temporary rollback while migrating"
|
|
136
|
+
code: |
|
|
137
|
+
jobs:
|
|
138
|
+
build:
|
|
139
|
+
# Temporary: macOS 15 still has llvm@18 via Homebrew
|
|
140
|
+
# TODO: migrate to unversioned llvm and switch back to macos-latest
|
|
141
|
+
runs-on: macos-15
|
|
142
|
+
steps:
|
|
143
|
+
- uses: actions/checkout@v4
|
|
144
|
+
prevention:
|
|
145
|
+
- "Never hardcode LLVM version numbers in Homebrew prefix paths. Use `$(brew --prefix llvm)` for the current default or `$(brew --prefix llvm@XX)` with an explicit install step for reproducibility."
|
|
146
|
+
- "In CMakeLists.txt, use `find_package(LLVM REQUIRED CONFIG)` without a version constraint, and validate the found version at configure time instead."
|
|
147
|
+
- "Test your macOS CI against `macos-26` (or `macos-latest` after it transitions) before the migration completes — use a matrix build to run both images in parallel."
|
|
148
|
+
- "Audit all workflow files for hardcoded `clang-XX`, `llvm@XX`, or `llvm-config-XX` strings when macOS runner images announce major tool version changes."
|
|
149
|
+
- "Subscribe to runner-images releases to monitor Homebrew LLVM version changes in the release diff tables."
|
|
150
|
+
docs:
|
|
151
|
+
- url: "https://github.com/actions/runner-images/issues/14167"
|
|
152
|
+
label: "runner-images#14167: macos-latest will use macos-26 in June 2026 (diff table shows LLVM 18 → 20)"
|
|
153
|
+
- url: "https://github.com/actions/runner-images/blob/main/images/macos/macos-26-arm64-Readme.md"
|
|
154
|
+
label: "macOS 26 arm64 image README — full software list including LLVM version"
|
|
155
|
+
- url: "https://docs.brew.sh/Versions"
|
|
156
|
+
label: "Homebrew Docs: Versioned formulae (llvm@18, llvm@20, etc.)"
|
|
157
|
+
- url: "https://cmake.org/cmake/help/latest/command/find_package.html"
|
|
158
|
+
label: "CMake find_package documentation"
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
id: runner-environment-053
|
|
2
|
+
title: "Node 24 Action Fails on Self-Hosted Runner — 'using: node24 is not supported'"
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- node24
|
|
7
|
+
- self-hosted-runner
|
|
8
|
+
- runner-version
|
|
9
|
+
- node-runtime
|
|
10
|
+
- actions-checkout
|
|
11
|
+
- actions-cache
|
|
12
|
+
patterns:
|
|
13
|
+
- regex: "'using: node24' is not supported"
|
|
14
|
+
flags: "i"
|
|
15
|
+
- regex: "Parameter.*using.*node24.*is not supported"
|
|
16
|
+
flags: "i"
|
|
17
|
+
- regex: "node24.*not supported.*use.*node12.*node16.*node20"
|
|
18
|
+
flags: "i"
|
|
19
|
+
- regex: "This version of the Actions runner is too old to run node24"
|
|
20
|
+
flags: "i"
|
|
21
|
+
error_messages:
|
|
22
|
+
- "Specified argument was out of the range of valid values. (Parameter ''using: node24' is not supported, use 'docker', 'node12', 'node16' or 'node20' instead.')"
|
|
23
|
+
- "'using: node24' is not supported, use 'docker', 'node12', 'node16' or 'node20' instead."
|
|
24
|
+
root_cause: |
|
|
25
|
+
GitHub Actions runner v2.327.1 (released July 25, 2025) was the first version to add
|
|
26
|
+
support for the `node24` runtime. Actions that bumped their major version to run on
|
|
27
|
+
Node.js 24 (including `actions/checkout@v5`, `actions/cache@v5`,
|
|
28
|
+
`actions/upload-artifact@v6`, and `actions/setup-node@v5`) specify `using: node24` in
|
|
29
|
+
their `action.yml`. When one of these actions runs on a self-hosted runner older than
|
|
30
|
+
v2.327.1, the runner's `ActionManifestManager` throws a `System.ArgumentOutOfRangeException`
|
|
31
|
+
because it does not recognise `node24` as a valid runtime identifier — it only knows
|
|
32
|
+
`docker`, `node12`, `node16`, and `node20`.
|
|
33
|
+
|
|
34
|
+
Common scenarios:
|
|
35
|
+
- Bumping a pinned `actions/checkout@v4` → `actions/checkout@v5` without first updating
|
|
36
|
+
the self-hosted runner.
|
|
37
|
+
- Relying on automatic runner self-update: runners sometimes auto-update the agent binary
|
|
38
|
+
but the worker process still runs under the old version, causing a mismatch
|
|
39
|
+
(actions/runner#4064).
|
|
40
|
+
- Using Dependabot or Renovate to auto-bump action versions across a repo.
|
|
41
|
+
fix: |
|
|
42
|
+
Update all self-hosted runners to version 2.327.1 or later before upgrading any action
|
|
43
|
+
to a version that requires `node24`. Steps:
|
|
44
|
+
|
|
45
|
+
1. Download and install the latest runner from:
|
|
46
|
+
https://github.com/actions/runner/releases/latest
|
|
47
|
+
2. Verify the version with: `./run.sh --version` (Linux/macOS) or `.\run.cmd --version`
|
|
48
|
+
(Windows).
|
|
49
|
+
3. If automatic self-update is enabled but stuck, stop the runner service, delete the
|
|
50
|
+
cached `_work/_update` directory, and restart — or manually install the new version.
|
|
51
|
+
4. For containerised runners (ARC, summerwind/actions-runner-dind), update the base image
|
|
52
|
+
tag to a version that ships runner ≥ 2.327.1.
|
|
53
|
+
|
|
54
|
+
If you cannot update the runner immediately, pin the actions back to the last v4/v5
|
|
55
|
+
compatible release and schedule the runner upgrade.
|
|
56
|
+
fix_code:
|
|
57
|
+
- language: yaml
|
|
58
|
+
label: "Pin to node24-compatible action versions — requires runner ≥ 2.327.1"
|
|
59
|
+
code: |
|
|
60
|
+
steps:
|
|
61
|
+
- uses: actions/checkout@v5 # node24 — runner must be ≥ 2.327.1
|
|
62
|
+
- uses: actions/cache@v5 # node24 — runner must be ≥ 2.327.1
|
|
63
|
+
- uses: actions/upload-artifact@v6 # node24 — runner must be ≥ 2.327.1
|
|
64
|
+
- uses: actions/setup-node@v5 # node24 — runner must be ≥ 2.327.1
|
|
65
|
+
- language: yaml
|
|
66
|
+
label: "Temporary pin to node20 versions while runner is being updated"
|
|
67
|
+
code: |
|
|
68
|
+
steps:
|
|
69
|
+
- uses: actions/checkout@v4 # still node20, compatible with older runners
|
|
70
|
+
- uses: actions/cache@v4 # still node20
|
|
71
|
+
- uses: actions/upload-artifact@v4 # still node20
|
|
72
|
+
- uses: actions/setup-node@v4 # still node20
|
|
73
|
+
- language: yaml
|
|
74
|
+
label: "Verify runner version in workflow (diagnostic)"
|
|
75
|
+
code: |
|
|
76
|
+
steps:
|
|
77
|
+
- name: Print runner version
|
|
78
|
+
run: echo "Runner version ${{ runner.version }}"
|
|
79
|
+
# runner.version must be >= 2.327.1 for node24 actions
|
|
80
|
+
prevention:
|
|
81
|
+
- "Before bumping any action to a node24 major version, check all self-hosted runner versions and update them first."
|
|
82
|
+
- "Add a minimum runner version check step or GitHub Actions required runner version policy for your organisation."
|
|
83
|
+
- "Subscribe to runner-images and actions/runner release announcements to learn about node runtime changes in advance."
|
|
84
|
+
- "For Dependabot/Renovate auto-bumps, add a CI gate that blocks merging action version upgrades until runner compatibility is confirmed."
|
|
85
|
+
docs:
|
|
86
|
+
- url: "https://github.com/actions/checkout/issues/2240"
|
|
87
|
+
label: "actions/checkout#2240 — Breaking change with v5: 'using: node24 is not supported' (27 reactions)"
|
|
88
|
+
- url: "https://github.com/actions/runner/releases/tag/v2.327.1"
|
|
89
|
+
label: "actions/runner v2.327.1 — First release with Node.js 24 support"
|
|
90
|
+
- url: "https://github.com/actions/runner/issues/4064"
|
|
91
|
+
label: "actions/runner#4064 — Auto-update doesn't take node20 → node24 into account, cascading failures"
|
|
92
|
+
- url: "https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/"
|
|
93
|
+
label: "GitHub Changelog — Deprecation of Node 20 on GitHub Actions runners"
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
id: runner-environment-054
|
|
2
|
+
title: "Python 3.9 Removed from Runner Images — Version Not Found in Local Cache"
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- python
|
|
7
|
+
- python-39
|
|
8
|
+
- runner-images
|
|
9
|
+
- toolcache
|
|
10
|
+
- setup-python
|
|
11
|
+
- eol
|
|
12
|
+
patterns:
|
|
13
|
+
- regex: "Version '3\\.9[^']*' was not found in the local cache"
|
|
14
|
+
flags: "i"
|
|
15
|
+
- regex: "python.*3\\.9.*not found.*cache|not found.*python.*3\\.9"
|
|
16
|
+
flags: "i"
|
|
17
|
+
- regex: "Unable to find python version.*3\\.9"
|
|
18
|
+
flags: "i"
|
|
19
|
+
- regex: "Couldn't find a version that satisfies.*python.*3\\.9"
|
|
20
|
+
flags: "i"
|
|
21
|
+
error_messages:
|
|
22
|
+
- "Version '3.9.x' was not found in the local cache"
|
|
23
|
+
- "Unable to find the requested Python version (3.9.x) in the local tool cache"
|
|
24
|
+
- "Error: Version 3.9 with arch x64 not found"
|
|
25
|
+
root_cause: |
|
|
26
|
+
Python 3.9 reached end-of-life on October 5, 2025. Starting January 12, 2026, GitHub
|
|
27
|
+
removed the pre-cached Python 3.9 toolchain from all runner images (ubuntu-22.04,
|
|
28
|
+
ubuntu-24.04, macOS-14, macOS-15, Windows Server 2022/2025). Additionally, on
|
|
29
|
+
Windows-based images Python 3.12 replaced 3.9 as the default version
|
|
30
|
+
(runner-images#13468).
|
|
31
|
+
|
|
32
|
+
Workflows are affected when:
|
|
33
|
+
1. `actions/setup-python` is used with `python-version: '3.9'` without a fallback —
|
|
34
|
+
the action tries the local toolcache first and fails when the pre-cached entry is gone.
|
|
35
|
+
2. A workflow assumes the system `python` or `python3` binary is 3.9 on Windows
|
|
36
|
+
(where it was the previous default).
|
|
37
|
+
3. A workflow calls `python3.9` directly (e.g. `python3.9 manage.py …`) without
|
|
38
|
+
installing it first.
|
|
39
|
+
fix: |
|
|
40
|
+
Option A — Install Python 3.9 at runtime via actions/setup-python (recommended):
|
|
41
|
+
Add `actions/setup-python` with a specific version. The action will download and
|
|
42
|
+
install Python 3.9 from the GitHub-managed toolcache CDN even though it is no longer
|
|
43
|
+
pre-cached on the image.
|
|
44
|
+
|
|
45
|
+
Option B — Migrate to a supported Python version:
|
|
46
|
+
Python 3.9 is EOL. Migrate to Python 3.11, 3.12, or 3.13 to benefit from active
|
|
47
|
+
security patches. Test your dependency set against the newer version.
|
|
48
|
+
|
|
49
|
+
Option C — Pin a newer default for Windows:
|
|
50
|
+
If you relied on the system default `python` being 3.9 on Windows, add an explicit
|
|
51
|
+
`actions/setup-python` step to pin the exact version you need.
|
|
52
|
+
fix_code:
|
|
53
|
+
- language: yaml
|
|
54
|
+
label: "Install Python 3.9 at runtime (works despite toolcache removal)"
|
|
55
|
+
code: |
|
|
56
|
+
steps:
|
|
57
|
+
- uses: actions/checkout@v4
|
|
58
|
+
- uses: actions/setup-python@v5
|
|
59
|
+
with:
|
|
60
|
+
python-version: '3.9' # downloaded from CDN — no longer pre-cached
|
|
61
|
+
- run: python --version
|
|
62
|
+
- language: yaml
|
|
63
|
+
label: "Migrate to Python 3.12 (recommended — actively supported)"
|
|
64
|
+
code: |
|
|
65
|
+
steps:
|
|
66
|
+
- uses: actions/checkout@v4
|
|
67
|
+
- uses: actions/setup-python@v5
|
|
68
|
+
with:
|
|
69
|
+
python-version: '3.12'
|
|
70
|
+
- run: pip install -r requirements.txt
|
|
71
|
+
- language: yaml
|
|
72
|
+
label: "Matrix across multiple Python versions"
|
|
73
|
+
code: |
|
|
74
|
+
jobs:
|
|
75
|
+
test:
|
|
76
|
+
strategy:
|
|
77
|
+
matrix:
|
|
78
|
+
python-version: ['3.11', '3.12', '3.13']
|
|
79
|
+
runs-on: ubuntu-latest
|
|
80
|
+
steps:
|
|
81
|
+
- uses: actions/checkout@v4
|
|
82
|
+
- uses: actions/setup-python@v5
|
|
83
|
+
with:
|
|
84
|
+
python-version: ${{ matrix.python-version }}
|
|
85
|
+
- run: pip install -r requirements.txt && pytest
|
|
86
|
+
prevention:
|
|
87
|
+
- "Always use `actions/setup-python` with an explicit `python-version` — never rely on the system pre-cached version."
|
|
88
|
+
- "Subscribe to runner-images EOL announcements to plan Python version migrations before removal dates."
|
|
89
|
+
- "Add Python version to `.python-version` or `pyproject.toml` and let `actions/setup-python` read it via `python-version-file`."
|
|
90
|
+
- "Avoid hard-coding EOL Python versions; use `~3.12` or `>=3.11` range specifiers where the toolchain supports them."
|
|
91
|
+
docs:
|
|
92
|
+
- url: "https://github.com/actions/runner-images/issues/13468"
|
|
93
|
+
label: "runner-images#13468 — Python 3.9 removed; Python 3.12 becomes default on Windows (Jan 12, 2026)"
|
|
94
|
+
- url: "https://github.com/actions/setup-python"
|
|
95
|
+
label: "actions/setup-python — installs any Python version at runtime from CDN"
|
|
96
|
+
- url: "https://devguide.python.org/versions/"
|
|
97
|
+
label: "Python Developer's Guide — supported versions and EOL dates"
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
id: silent-failures-027
|
|
2
|
+
title: "actions/setup-python pip Cache on macOS 26 Emits False Error Annotation"
|
|
3
|
+
category: silent-failures
|
|
4
|
+
severity: warning
|
|
5
|
+
tags:
|
|
6
|
+
- setup-python
|
|
7
|
+
- pip
|
|
8
|
+
- cache
|
|
9
|
+
- macos-26
|
|
10
|
+
- annotation
|
|
11
|
+
- false-positive
|
|
12
|
+
- python310
|
|
13
|
+
patterns:
|
|
14
|
+
- regex: "ERROR.*WARNING.*Cache entry deserialization failed.*entry ignored"
|
|
15
|
+
flags: "i"
|
|
16
|
+
- regex: "Cache entry deserialization failed.*entry ignored"
|
|
17
|
+
flags: "i"
|
|
18
|
+
- regex: "Error: WARNING:.*cache.*deserialization"
|
|
19
|
+
flags: "i"
|
|
20
|
+
error_messages:
|
|
21
|
+
- "Error: WARNING: Cache entry deserialization failed, entry ignored."
|
|
22
|
+
- "WARNING: Cache entry deserialization failed, entry ignored"
|
|
23
|
+
root_cause: |
|
|
24
|
+
When using `actions/setup-python@v6` with `cache: 'pip'` and an older Python version
|
|
25
|
+
(notably Python 3.10) on `macos-26` runners, the action succeeds but emits a false
|
|
26
|
+
error annotation in the GitHub Actions UI, turning the job "yellow" or showing a red
|
|
27
|
+
annotation badge.
|
|
28
|
+
|
|
29
|
+
**What happens:**
|
|
30
|
+
1. `setup-python@v6` restores the pip cache from a previous run.
|
|
31
|
+
2. pip on the current macOS 26 runner (with a newer pip version) encounters a pip
|
|
32
|
+
wheel cache entry written by an older pip version using a different serialization
|
|
33
|
+
format or metadata schema.
|
|
34
|
+
3. pip emits: `WARNING: Cache entry deserialization failed, entry ignored` to stderr.
|
|
35
|
+
4. The GitHub Actions runner's annotation parser sees the word "Error" at the start
|
|
36
|
+
of the output (because the line is rendered as `Error: WARNING: ...` in GitHub's
|
|
37
|
+
log viewer) and creates an annotation treating it as a job error.
|
|
38
|
+
5. The job itself succeeds — the dependency install works fine — but the annotation
|
|
39
|
+
makes the job appear failed or degraded in the GitHub UI.
|
|
40
|
+
|
|
41
|
+
**Platform specificity:** This is reproducible specifically on `macos-26` (ARM), not
|
|
42
|
+
on Ubuntu, Windows, or `macos-15`. The combination of macOS 26's newer system Python
|
|
43
|
+
environment and the `macos-26` Arm64 pip wheel cache schema causes the deserialization
|
|
44
|
+
mismatch.
|
|
45
|
+
|
|
46
|
+
Source: actions/setup-python#1317 (open bug, May 20 2026 — under investigation by
|
|
47
|
+
actions/setup-python maintainers).
|
|
48
|
+
fix: |
|
|
49
|
+
**Option 1 — Clear the stale pip cache (immediate fix):**
|
|
50
|
+
Purge the GitHub Actions cache for the affected key via the UI or API, forcing a cache
|
|
51
|
+
rebuild on the next run. The fresh cache will be written by the current pip version on
|
|
52
|
+
macOS 26 and will deserialize cleanly on subsequent runs.
|
|
53
|
+
|
|
54
|
+
**Option 2 — Disable pip caching for macOS 26 until resolved:**
|
|
55
|
+
Use a conditional `cache` input based on the runner OS:
|
|
56
|
+
|
|
57
|
+
**Option 3 — Pin to a Python version not affected:**
|
|
58
|
+
Python 3.12 and 3.14 have not been reported to exhibit this issue on macOS 26 — only
|
|
59
|
+
3.10 is confirmed. Test whether upgrading your target Python version resolves the annotation.
|
|
60
|
+
|
|
61
|
+
**Option 4 — Wait for the upstream fix:**
|
|
62
|
+
This is an open bug in `actions/setup-python` being investigated (issue #1317). A fix
|
|
63
|
+
in `setup-python@v6` will resolve this without workflow changes.
|
|
64
|
+
fix_code:
|
|
65
|
+
- language: yaml
|
|
66
|
+
label: "Disable pip cache on macOS to avoid false error annotation"
|
|
67
|
+
code: |
|
|
68
|
+
- name: Set up Python
|
|
69
|
+
uses: actions/setup-python@v6
|
|
70
|
+
with:
|
|
71
|
+
python-version: "3.10"
|
|
72
|
+
# Disable cache on macOS 26 until setup-python#1317 is resolved
|
|
73
|
+
cache: ${{ runner.os != 'macOS' && 'pip' || '' }}
|
|
74
|
+
- language: yaml
|
|
75
|
+
label: "Clear the stale cache via GitHub API (one-time fix)"
|
|
76
|
+
code: |
|
|
77
|
+
# Delete the stale pip cache key via gh CLI (run once)
|
|
78
|
+
gh cache list --repo owner/repo --key 'setup-python-*macos-26*'
|
|
79
|
+
gh cache delete <CACHE_ID> --repo owner/repo
|
|
80
|
+
# Or delete all pip caches for macOS 26:
|
|
81
|
+
gh cache list --repo owner/repo --json id,key --jq \
|
|
82
|
+
'.[] | select(.key | test("macos-26")) | .id' \
|
|
83
|
+
| xargs -I{} gh cache delete {} --repo owner/repo
|
|
84
|
+
- language: yaml
|
|
85
|
+
label: "Matrix build: cache only on platforms where it works cleanly"
|
|
86
|
+
code: |
|
|
87
|
+
jobs:
|
|
88
|
+
test:
|
|
89
|
+
strategy:
|
|
90
|
+
matrix:
|
|
91
|
+
os: [ubuntu-latest, windows-latest, macos-26]
|
|
92
|
+
runs-on: ${{ matrix.os }}
|
|
93
|
+
steps:
|
|
94
|
+
- uses: actions/setup-python@v6
|
|
95
|
+
with:
|
|
96
|
+
python-version: "3.10"
|
|
97
|
+
# macOS 26 pip cache has deserialization issue (setup-python#1317)
|
|
98
|
+
cache: ${{ matrix.os != 'macos-26' && 'pip' || '' }}
|
|
99
|
+
prevention:
|
|
100
|
+
- "Watch for `actions/setup-python` releases fixing issue #1317 — once resolved, re-enable caching on macOS 26."
|
|
101
|
+
- "When a new macOS runner label becomes `macos-latest`, clear pip caches from the old image version to avoid deserialization mismatches on the first run."
|
|
102
|
+
- "Test your workflows on new macOS runner labels before `macos-latest` transitions — catch cache format incompatibilities before they affect production CI."
|
|
103
|
+
- "Use GitHub's cache eviction API or `actions/cache@v4` with `fail-on-cache-miss: false` to gracefully handle deserialization failures."
|
|
104
|
+
docs:
|
|
105
|
+
- url: "https://github.com/actions/setup-python/issues/1317"
|
|
106
|
+
label: "actions/setup-python#1317: Cache entry deserialization failed on macOS 26 (open bug)"
|
|
107
|
+
- url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/caching-dependencies-to-speed-up-workflows#managing-caches"
|
|
108
|
+
label: "GitHub Docs: Managing GitHub Actions caches"
|
|
109
|
+
- url: "https://github.com/actions/setup-python"
|
|
110
|
+
label: "actions/setup-python — official action repository"
|
package/package.json
CHANGED