@htekdev/actions-debugger 1.0.24 → 1.0.26
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/environment-deployment-false-custom-protection.yml +93 -0
- package/errors/permissions-auth/checkout-v6-cross-repo-token-override.yml +103 -0
- package/errors/runner-environment/macos-dotnet-root-env-var-removed.yml +90 -0
- package/errors/runner-environment/maven-gradle-403-cache-backend-outage.yml +116 -0
- package/errors/runner-environment/powershell-76-dotnet10-httpclient-breaking-changes.yml +109 -0
- package/errors/runner-environment/ubuntu-24-04-chrome-148-webdriverio-hang.yml +91 -0
- package/errors/runner-environment/ubuntu-24-04-kernel-read-ahead-kb-io-thrashing.yml +94 -0
- package/errors/silent-failures/undefined-env-expression-empty-string-silent.yml +1 -1
- package/errors/yaml-syntax/case-function-runner-version-too-old.yml +100 -0
- package/package.json +1 -1
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
id: known-unsolved-029
|
|
2
|
+
title: "deployment:false environment key incompatible with custom deployment protection rules"
|
|
3
|
+
category: known-unsolved
|
|
4
|
+
severity: limitation
|
|
5
|
+
tags:
|
|
6
|
+
- environment
|
|
7
|
+
- deployment
|
|
8
|
+
- protection-rules
|
|
9
|
+
- custom-deployment-protection
|
|
10
|
+
- no-fix
|
|
11
|
+
|
|
12
|
+
patterns:
|
|
13
|
+
- regex: "You cannot (use|disable) deployment.*custom deployment protection"
|
|
14
|
+
flags: "i"
|
|
15
|
+
- regex: "deployment: false.*is not supported.*protection rule"
|
|
16
|
+
flags: "i"
|
|
17
|
+
|
|
18
|
+
error_messages:
|
|
19
|
+
- "You cannot use deployment: false when a custom deployment protection rule is configured for this environment."
|
|
20
|
+
- "Environments with custom deployment protection rules require automatic deployment tracking. Remove deployment: false to proceed."
|
|
21
|
+
|
|
22
|
+
root_cause: |
|
|
23
|
+
GitHub Actions added deployment: false as a new key for environments in March 2026
|
|
24
|
+
(changelog 2026-03-19). This key lets workflows use environment secrets and variables
|
|
25
|
+
without creating a GitHub Deployment record, which was a long-requested feature for
|
|
26
|
+
teams who want secrets management without polluting the Deployments tab.
|
|
27
|
+
|
|
28
|
+
However, the deployment: false key is fundamentally incompatible with custom deployment
|
|
29
|
+
protection rules. Custom deployment protection rules (third-party apps registered via
|
|
30
|
+
the GitHub API to gate deployments) rely on GitHub Deployment events being created —
|
|
31
|
+
the protection rule callback fires when a deployment is created, approves or rejects it,
|
|
32
|
+
and the workflow proceeds based on the response.
|
|
33
|
+
|
|
34
|
+
When deployment: false is set, no Deployment record is created, so there is no event
|
|
35
|
+
to trigger the custom protection rule callback. GitHub therefore blocks the combination
|
|
36
|
+
entirely rather than silently skipping the protection rule check, which could create
|
|
37
|
+
a security bypass.
|
|
38
|
+
|
|
39
|
+
This is a platform-level design constraint with no workaround. Teams that need custom
|
|
40
|
+
deployment protection rules cannot use deployment: false and must keep auto-deployment
|
|
41
|
+
enabled.
|
|
42
|
+
|
|
43
|
+
fix: |
|
|
44
|
+
There is no workaround. If your environment uses a custom deployment protection rule
|
|
45
|
+
(a third-party app that approves or rejects deployments), you cannot use deployment: false.
|
|
46
|
+
|
|
47
|
+
Options:
|
|
48
|
+
1. Remove the custom deployment protection rule if it is no longer needed, then use
|
|
49
|
+
deployment: false to stop creating Deployment records.
|
|
50
|
+
2. Keep auto-deployment enabled (omit deployment: false) and accept that deployments
|
|
51
|
+
will appear in the Deployments tab.
|
|
52
|
+
3. Use a different secrets management strategy (repository secrets, organization secrets,
|
|
53
|
+
or HashiCorp Vault) if you want to avoid environment-scoped secrets entirely.
|
|
54
|
+
|
|
55
|
+
fix_code:
|
|
56
|
+
- language: yaml
|
|
57
|
+
label: "Valid: deployment:false without custom protection rules"
|
|
58
|
+
code: |
|
|
59
|
+
# Works only when the environment has NO custom deployment protection rules
|
|
60
|
+
jobs:
|
|
61
|
+
deploy:
|
|
62
|
+
environment:
|
|
63
|
+
name: staging
|
|
64
|
+
deployment: false # Suppresses Deployment record creation
|
|
65
|
+
runs-on: ubuntu-latest
|
|
66
|
+
steps:
|
|
67
|
+
- run: echo "Using ${{ secrets.STAGING_API_KEY }} without creating a deployment"
|
|
68
|
+
|
|
69
|
+
- language: yaml
|
|
70
|
+
label: "Required: keep deployment enabled when custom protection rules are configured"
|
|
71
|
+
code: |
|
|
72
|
+
# When a custom deployment protection rule (third-party app) is registered
|
|
73
|
+
# on the environment, omit deployment:false entirely
|
|
74
|
+
jobs:
|
|
75
|
+
deploy:
|
|
76
|
+
environment:
|
|
77
|
+
name: production # Has custom protection rule — must create deployment
|
|
78
|
+
runs-on: ubuntu-latest
|
|
79
|
+
steps:
|
|
80
|
+
- run: echo "Deployment record created; custom protection rule fires and must approve"
|
|
81
|
+
|
|
82
|
+
prevention:
|
|
83
|
+
- "Check environment settings in Settings > Environments before adding deployment: false to confirm no custom protection rules are registered."
|
|
84
|
+
- "Document which environments use custom protection rules so team members know deployment: false is unavailable for those environments."
|
|
85
|
+
- "If you need both secrets management and no deployment records, consider migrating secrets to organization-level secrets with repository access restrictions."
|
|
86
|
+
|
|
87
|
+
docs:
|
|
88
|
+
- url: "https://github.blog/changelog/2026-03-19-github-actions-late-march-2026-updates/"
|
|
89
|
+
label: "GitHub Changelog 2026-03-19: Environments without auto-deployment (deployment: false)"
|
|
90
|
+
- url: "https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment#using-an-environment-without-auto-deployment"
|
|
91
|
+
label: "GitHub Docs: Using an environment without auto-deployment"
|
|
92
|
+
- url: "https://docs.github.com/en/actions/deployment/protecting-deployments/creating-custom-deployment-protection-rules"
|
|
93
|
+
label: "GitHub Docs: Creating custom deployment protection rules"
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
id: permissions-auth-029
|
|
2
|
+
title: "checkout@v6 http.extraheader overrides inline token for cross-repository push"
|
|
3
|
+
category: permissions-auth
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- checkout
|
|
7
|
+
- v6
|
|
8
|
+
- cross-repo
|
|
9
|
+
- extraheader
|
|
10
|
+
- token
|
|
11
|
+
- push
|
|
12
|
+
- persist-credentials
|
|
13
|
+
|
|
14
|
+
patterns:
|
|
15
|
+
- regex: "remote: Permission to .+ denied to github-actions\\[bot\\]"
|
|
16
|
+
flags: "i"
|
|
17
|
+
- regex: "fatal: unable to access '.+': The requested URL returned error: 403"
|
|
18
|
+
flags: "i"
|
|
19
|
+
- regex: "The requested URL returned error: 403"
|
|
20
|
+
flags: "i"
|
|
21
|
+
|
|
22
|
+
error_messages:
|
|
23
|
+
- "remote: Permission to org/other-repo.git denied to github-actions[bot]."
|
|
24
|
+
- "fatal: unable to access 'https://github.com/org/other-repo.git/': The requested URL returned error: 403"
|
|
25
|
+
|
|
26
|
+
root_cause: |
|
|
27
|
+
checkout@v6 changed how credentials are stored compared to v4/v5. Instead of writing the
|
|
28
|
+
GITHUB_TOKEN directly into .git/config, v6 stores credentials in a separate file under
|
|
29
|
+
$RUNNER_TEMP and registers it via a git includeIf directive. This injects an
|
|
30
|
+
http.extraheader = Authorization: Bearer <GITHUB_TOKEN> for ALL https://github.com/ URLs.
|
|
31
|
+
|
|
32
|
+
When a workflow adds a second remote using an inline Personal Access Token (PAT) in the URL
|
|
33
|
+
(e.g., https://PAT@github.com/other-org/other-repo.git), git still sends the checkout-injected
|
|
34
|
+
Authorization header alongside the URL-embedded token. The injected GITHUB_TOKEN header takes
|
|
35
|
+
precedence over the URL-embedded PAT, and since GITHUB_TOKEN only has access to the current
|
|
36
|
+
repository, the push to the other repository is rejected with 403 Forbidden.
|
|
37
|
+
|
|
38
|
+
This regression is specific to workflows that push to repositories other than the one that
|
|
39
|
+
was checked out. Workflows that only interact with the current repository are unaffected.
|
|
40
|
+
|
|
41
|
+
fix: |
|
|
42
|
+
Option 1 (recommended): Set persist-credentials: false in the checkout step. This prevents
|
|
43
|
+
checkout@v6 from injecting the extraheader entirely. Configure authentication explicitly in
|
|
44
|
+
subsequent steps using the token in the remote URL or via GH_TOKEN environment variable.
|
|
45
|
+
|
|
46
|
+
Option 2 (targeted): Explicitly unset the http extraheader before performing cross-repo
|
|
47
|
+
operations. Add a step that clears the auth override for github.com URLs before pushing
|
|
48
|
+
to the other repository.
|
|
49
|
+
|
|
50
|
+
Option 3 (fallback): Pin to checkout@v5 for workflows that require cross-repo push
|
|
51
|
+
until a v6 upstream fix is available (actions/checkout#2424 is open).
|
|
52
|
+
|
|
53
|
+
fix_code:
|
|
54
|
+
- language: yaml
|
|
55
|
+
label: "Option 1: Disable persist-credentials to prevent extraheader injection"
|
|
56
|
+
code: |
|
|
57
|
+
steps:
|
|
58
|
+
- name: Checkout current repo
|
|
59
|
+
uses: actions/checkout@v6
|
|
60
|
+
with:
|
|
61
|
+
persist-credentials: false # No extraheader injected; manual auth required
|
|
62
|
+
|
|
63
|
+
- name: Push tag to target repository
|
|
64
|
+
env:
|
|
65
|
+
TARGET_PAT: ${{ secrets.TARGET_REPO_PAT }}
|
|
66
|
+
run: |
|
|
67
|
+
# Token embedded in remote URL; no competing extraheader present
|
|
68
|
+
TARGET_REMOTE="https://x-access-token:${TARGET_PAT}@github.com/org/target-repo.git"
|
|
69
|
+
git remote add target "${TARGET_REMOTE}"
|
|
70
|
+
git tag -f nightly
|
|
71
|
+
git push -f target nightly
|
|
72
|
+
|
|
73
|
+
- language: yaml
|
|
74
|
+
label: "Option 2: Clear the injected extraheader before cross-repo operations"
|
|
75
|
+
code: |
|
|
76
|
+
steps:
|
|
77
|
+
- uses: actions/checkout@v6
|
|
78
|
+
|
|
79
|
+
# ... build steps ...
|
|
80
|
+
|
|
81
|
+
- name: Unset checkout extraheader for cross-repo push
|
|
82
|
+
run: git config --unset-all "http.https://github.com/.extraheader" || true
|
|
83
|
+
|
|
84
|
+
- name: Push tag to target repository
|
|
85
|
+
env:
|
|
86
|
+
TARGET_PAT: ${{ secrets.TARGET_REPO_PAT }}
|
|
87
|
+
run: |
|
|
88
|
+
git remote add target "https://x-access-token:${TARGET_PAT}@github.com/org/target-repo.git"
|
|
89
|
+
git push -f target nightly
|
|
90
|
+
|
|
91
|
+
prevention:
|
|
92
|
+
- "Use persist-credentials: false on all checkout steps in workflows that interact with multiple repositories."
|
|
93
|
+
- "Avoid embedding tokens directly in remote URLs when checkout@v6 is used without persist-credentials:false."
|
|
94
|
+
- "Test cross-repo operations in a staging branch after upgrading from checkout@v4 or v5 to v6."
|
|
95
|
+
- "Check actions/checkout release notes for credential storage changes when upgrading major versions."
|
|
96
|
+
|
|
97
|
+
docs:
|
|
98
|
+
- url: "https://github.com/actions/checkout/issues/2424"
|
|
99
|
+
label: "actions/checkout#2424: Unable to create tags in another repo with v6"
|
|
100
|
+
- url: "https://github.com/actions/checkout/releases/tag/v6.0.0"
|
|
101
|
+
label: "checkout@v6.0.0 release notes — persist-credentials storage change"
|
|
102
|
+
- url: "https://docs.github.com/en/actions/security-for-github-actions/security-guides/automatic-token-authentication"
|
|
103
|
+
label: "GitHub Docs: Automatic token authentication and GITHUB_TOKEN scopes"
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
id: runner-environment-078
|
|
2
|
+
title: "macOS Runner DOTNET_ROOT Environment Variable Removed — .NET SDK Path Discovery Fails"
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- macos
|
|
7
|
+
- dotnet
|
|
8
|
+
- dotnet-root
|
|
9
|
+
- environment-variable
|
|
10
|
+
- sdk-discovery
|
|
11
|
+
- breaking-change
|
|
12
|
+
- runner-images
|
|
13
|
+
patterns:
|
|
14
|
+
- regex: 'DOTNET_ROOT.*not set|DOTNET_ROOT.*undefined|DOTNET_ROOT.*empty'
|
|
15
|
+
flags: "i"
|
|
16
|
+
- regex: 'A compatible \.NET SDK was not found|It was not possible to find any installed \.NET'
|
|
17
|
+
flags: "i"
|
|
18
|
+
- regex: 'dotnet.*not found|No \.NET SDKs were found'
|
|
19
|
+
flags: "i"
|
|
20
|
+
error_messages:
|
|
21
|
+
- "A compatible .NET SDK was not found."
|
|
22
|
+
- "It was not possible to find any installed .NET Core SDKs."
|
|
23
|
+
- "No .NET SDKs were found."
|
|
24
|
+
- "DOTNET_ROOT is not set."
|
|
25
|
+
root_cause: |
|
|
26
|
+
Starting January 12, 2026, GitHub removed the DOTNET_ROOT environment variable from
|
|
27
|
+
all macOS runner images: macOS-14, macOS-14-arm64, macOS-15, macOS-15-arm64,
|
|
28
|
+
macOS-26, and macOS-26-arm64 (runner-images#13470, driven by #13365).
|
|
29
|
+
|
|
30
|
+
The variable was previously predefined in the runner image environment to help
|
|
31
|
+
.NET tooling locate installed SDKs. It was removed because modern .NET SDK versions
|
|
32
|
+
can discover installations without it, and keeping the hardcoded path caused
|
|
33
|
+
inconsistent behavior when multiple .NET versions were installed side-by-side.
|
|
34
|
+
|
|
35
|
+
Workflows affected:
|
|
36
|
+
1. Custom scripts that use $DOTNET_ROOT or $env:DOTNET_ROOT to invoke the dotnet CLI
|
|
37
|
+
without first running actions/setup-dotnet.
|
|
38
|
+
2. Docker containers started from the runner that inherit the host environment
|
|
39
|
+
and previously relied on DOTNET_ROOT being present.
|
|
40
|
+
3. Third-party .NET tools or build scripts that call into the .NET host resolver
|
|
41
|
+
and expect the environment to provide a root path.
|
|
42
|
+
|
|
43
|
+
Note: Windows and Ubuntu runner images are NOT affected by this change — only macOS.
|
|
44
|
+
Workflows using actions/setup-dotnet are unaffected as it sets DOTNET_ROOT itself.
|
|
45
|
+
fix: |
|
|
46
|
+
Set DOTNET_ROOT manually in the job env block, OR use actions/setup-dotnet which
|
|
47
|
+
sets it correctly as part of its own setup. For most GitHub Actions workflows that
|
|
48
|
+
install .NET via setup-dotnet, no change is needed. Custom scripts that reference
|
|
49
|
+
$DOTNET_ROOT directly must set it explicitly.
|
|
50
|
+
|
|
51
|
+
The canonical path for user-scoped .NET installs is $HOME/.dotnet (Unix) or
|
|
52
|
+
$env:USERPROFILE\.dotnet (Windows). actions/setup-dotnet uses $RUNNER_TOOL_CACHE.
|
|
53
|
+
fix_code:
|
|
54
|
+
- language: yaml
|
|
55
|
+
label: "Set DOTNET_ROOT manually in the job env block"
|
|
56
|
+
code: |
|
|
57
|
+
jobs:
|
|
58
|
+
build:
|
|
59
|
+
runs-on: macos-latest
|
|
60
|
+
env:
|
|
61
|
+
DOTNET_ROOT: ${{ runner.home }}/.dotnet
|
|
62
|
+
steps:
|
|
63
|
+
- uses: actions/checkout@v4
|
|
64
|
+
- name: Build
|
|
65
|
+
run: dotnet build src/MyApp.csproj
|
|
66
|
+
- language: yaml
|
|
67
|
+
label: "Use actions/setup-dotnet — sets DOTNET_ROOT automatically"
|
|
68
|
+
code: |
|
|
69
|
+
jobs:
|
|
70
|
+
build:
|
|
71
|
+
runs-on: macos-latest
|
|
72
|
+
steps:
|
|
73
|
+
- uses: actions/checkout@v4
|
|
74
|
+
- uses: actions/setup-dotnet@v4
|
|
75
|
+
with:
|
|
76
|
+
dotnet-version: '9.x'
|
|
77
|
+
# DOTNET_ROOT is now set by setup-dotnet automatically
|
|
78
|
+
- run: dotnet test --configuration Release
|
|
79
|
+
prevention:
|
|
80
|
+
- "Use actions/setup-dotnet in all .NET workflows on macOS — it sets DOTNET_ROOT and handles version management."
|
|
81
|
+
- "Audit scripts for direct $DOTNET_ROOT or $env:DOTNET_ROOT references and add explicit env: blocks for macOS jobs."
|
|
82
|
+
- "Test .NET workflows on macOS runner versions after image update cycles."
|
|
83
|
+
- "Subscribe to runner-images pinned announcements to stay ahead of environment variable removals."
|
|
84
|
+
docs:
|
|
85
|
+
- url: "https://github.com/actions/runner-images/issues/13470"
|
|
86
|
+
label: "runner-images#13470: DOTNET_ROOT environment variable will be removed from macOS on January 12th, 2026"
|
|
87
|
+
- url: "https://github.com/actions/setup-dotnet"
|
|
88
|
+
label: "actions/setup-dotnet: Installs .NET SDK and sets DOTNET_ROOT correctly"
|
|
89
|
+
- url: "https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-environment-variables#dotnet_root-dotnet_rootx86"
|
|
90
|
+
label: "Microsoft Docs: DOTNET_ROOT environment variable reference"
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
id: runner-environment-075
|
|
2
|
+
title: "Maven/Gradle 403 Forbidden when GitHub Actions cache backend is degraded"
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- maven
|
|
7
|
+
- gradle
|
|
8
|
+
- 403
|
|
9
|
+
- cache-backend
|
|
10
|
+
- outage
|
|
11
|
+
- rate-limit
|
|
12
|
+
- sonatype
|
|
13
|
+
- dependency-download
|
|
14
|
+
|
|
15
|
+
patterns:
|
|
16
|
+
- regex: "Received status code 403 from server"
|
|
17
|
+
flags: "i"
|
|
18
|
+
- regex: "Could not transfer artifact .+ from .+ Forbidden"
|
|
19
|
+
flags: "i"
|
|
20
|
+
- regex: "Our services aren't available right now"
|
|
21
|
+
flags: "i"
|
|
22
|
+
- regex: "Received HTTP 403 from Maven Repository"
|
|
23
|
+
flags: "i"
|
|
24
|
+
|
|
25
|
+
error_messages:
|
|
26
|
+
- "Could not transfer artifact org.springframework:spring-core:jar:6.1.0 from/to central (https://repo.maven.apache.org/maven2): Received status code 403 from server: Forbidden"
|
|
27
|
+
- "Received status code 403 from server: Forbidden"
|
|
28
|
+
- "Our services aren't available right now\nWe're working to restore all services as soon as possible. Please check back soon."
|
|
29
|
+
- "Exception in thread \"main\" org.gradle.api.UncheckedIOException: com.amazonaws.SdkClientException: Unable to execute HTTP request: The target server failed to respond"
|
|
30
|
+
|
|
31
|
+
root_cause: |
|
|
32
|
+
GitHub Actions cache backend (actions/cache) is an eventually-consistent distributed storage
|
|
33
|
+
system. During degradation incidents, cache restore operations fail with the message
|
|
34
|
+
"Our services aren't available right now" and exit 0 (the job continues). Maven and Gradle
|
|
35
|
+
builds that normally cache artifacts under .m2/repository or .gradle/caches fall through
|
|
36
|
+
to downloading all dependencies directly from Maven Central (repo.maven.apache.org).
|
|
37
|
+
|
|
38
|
+
GitHub-hosted runners share IP address ranges across thousands of concurrent workflow runs.
|
|
39
|
+
During a cache backend outage, every affected build simultaneously requests artifacts
|
|
40
|
+
from Maven Central. Sonatype (which operates Maven Central) rate-limits abusive traffic
|
|
41
|
+
patterns from shared IP ranges, returning HTTP 403 Forbidden. This creates a cascading
|
|
42
|
+
failure: one cache service incident causes all Java/Kotlin/Scala CI pipelines to fail
|
|
43
|
+
until the cache backend recovers.
|
|
44
|
+
|
|
45
|
+
The failure is misleading because the error comes from Maven Central, not GitHub, so
|
|
46
|
+
developers often suspect repository permissions, network configuration, or Sonatype policy
|
|
47
|
+
changes rather than GitHub infrastructure.
|
|
48
|
+
|
|
49
|
+
fix: |
|
|
50
|
+
Short-term: Check GitHub Status (githubstatus.com) for cache service incidents before
|
|
51
|
+
debugging Maven/Gradle configuration. Retry the workflow after the incident resolves.
|
|
52
|
+
|
|
53
|
+
Medium-term: Add Maven retry configuration to pom.xml or build.gradle to tolerate
|
|
54
|
+
transient 403/429 responses. Configure a secondary mirror as a fallback to reduce
|
|
55
|
+
direct Maven Central dependency.
|
|
56
|
+
|
|
57
|
+
Long-term: Host a private artifact cache (Nexus, Artifactory, or AWS CodeArtifact)
|
|
58
|
+
that proxies Maven Central. This prevents GitHub runner IP ranges from hitting Maven
|
|
59
|
+
Central directly and provides a stable fallback during GitHub cache outages.
|
|
60
|
+
|
|
61
|
+
fix_code:
|
|
62
|
+
- language: yaml
|
|
63
|
+
label: "Workflow: Add retry wrapper step for Maven builds during cache degradation"
|
|
64
|
+
code: |
|
|
65
|
+
steps:
|
|
66
|
+
- uses: actions/cache@v4
|
|
67
|
+
id: maven-cache
|
|
68
|
+
with:
|
|
69
|
+
path: ~/.m2/repository
|
|
70
|
+
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
|
71
|
+
restore-keys: |
|
|
72
|
+
${{ runner.os }}-maven-
|
|
73
|
+
|
|
74
|
+
- name: Check cache status and set retry flag
|
|
75
|
+
if: steps.maven-cache.outputs.cache-hit != 'true'
|
|
76
|
+
run: echo "MAVEN_OPTS=-Dmaven.artifact.threads=5" >> $GITHUB_ENV
|
|
77
|
+
|
|
78
|
+
- name: Build with Maven
|
|
79
|
+
run: mvn --batch-mode --no-transfer-progress -T 1C verify
|
|
80
|
+
|
|
81
|
+
- language: yaml
|
|
82
|
+
label: "Maven settings.xml: Add mirror fallback to reduce direct Maven Central load"
|
|
83
|
+
code: |
|
|
84
|
+
# .github/maven-settings.xml — add to repository root
|
|
85
|
+
# Reference in workflow: mvn -s .github/maven-settings.xml ...
|
|
86
|
+
#
|
|
87
|
+
# <settings>
|
|
88
|
+
# <mirrors>
|
|
89
|
+
# <mirror>
|
|
90
|
+
# <id>central-mirror</id>
|
|
91
|
+
# <mirrorOf>central</mirrorOf>
|
|
92
|
+
# <url>https://repo1.maven.org/maven2/</url>
|
|
93
|
+
# </mirror>
|
|
94
|
+
# </mirrors>
|
|
95
|
+
# </settings>
|
|
96
|
+
#
|
|
97
|
+
# Then in workflow:
|
|
98
|
+
- name: Build with Maven (mirror fallback)
|
|
99
|
+
run: mvn -s .github/maven-settings.xml --batch-mode verify
|
|
100
|
+
|
|
101
|
+
prevention:
|
|
102
|
+
- "Monitor githubstatus.com/history for GitHub Actions cache incidents before assuming build failures are configuration errors."
|
|
103
|
+
- "Add --no-transfer-progress to Maven commands to reduce output noise; add -Dmaven.artifact.threads=3 to reduce concurrent Central requests."
|
|
104
|
+
- "Configure restore-keys fallback in actions/cache so partial cache hits reduce Maven Central traffic."
|
|
105
|
+
- "Consider self-hosted Nexus or AWS CodeArtifact as a Maven Central proxy for production CI pipelines."
|
|
106
|
+
- "Add 'if: always()' or cache-miss detection to skip cache restore wait during known outages."
|
|
107
|
+
|
|
108
|
+
docs:
|
|
109
|
+
- url: "https://github.com/actions/runner/issues/4180"
|
|
110
|
+
label: "actions/runner#4180: CI Runners Failing with 403 Forbidden for Maven/Gradle (75 reactions)"
|
|
111
|
+
- url: "https://www.githubstatus.com/"
|
|
112
|
+
label: "GitHub Status — check for Actions cache service incidents"
|
|
113
|
+
- url: "https://central.sonatype.org/faq/rate-limiting/"
|
|
114
|
+
label: "Sonatype Maven Central: Rate limiting and fair use policy"
|
|
115
|
+
- url: "https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows"
|
|
116
|
+
label: "GitHub Docs: Caching dependencies to speed up workflows"
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
id: runner-environment-079
|
|
2
|
+
title: "PowerShell 7.6 on Runners Ships .NET 10 Runtime — HttpWebRequest and WebClient Throw NotSupportedException"
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- powershell
|
|
7
|
+
- powershell-76
|
|
8
|
+
- dotnet-10
|
|
9
|
+
- dotnet-8
|
|
10
|
+
- runner-images
|
|
11
|
+
- breaking-change
|
|
12
|
+
- httpclient
|
|
13
|
+
- webclient
|
|
14
|
+
patterns:
|
|
15
|
+
- regex: 'NotSupportedException.*HttpWebRequest|WebClient.*NotSupportedException'
|
|
16
|
+
flags: "i"
|
|
17
|
+
- regex: 'ServicePointManager.*SecurityProtocol.*not supported|The method or operation is not implemented'
|
|
18
|
+
flags: "i"
|
|
19
|
+
- regex: 'MissingMethodException.*ServicePointManager|System\.Net\.WebException.*NotSupported'
|
|
20
|
+
flags: "i"
|
|
21
|
+
- regex: 'WildcardPattern\.Escape.*backtick|Join-Path.*ChildPath.*string\[\]'
|
|
22
|
+
flags: "i"
|
|
23
|
+
error_messages:
|
|
24
|
+
- "System.NotSupportedException: WebClient has been removed from .NET"
|
|
25
|
+
- "System.NotSupportedException: HttpWebRequest is not supported on this platform"
|
|
26
|
+
- "System.MissingMethodException: Method not found: 'Void System.Net.ServicePointManager.set_SecurityProtocol'"
|
|
27
|
+
root_cause: |
|
|
28
|
+
PowerShell 7.4 was built on .NET 8. PowerShell 7.6 is built on .NET 10.
|
|
29
|
+
Beginning June 8-15, 2026, all GitHub-hosted runner images upgraded from PS 7.4
|
|
30
|
+
to PS 7.6 LTS (runner-images#14150). This introduces several .NET 10 breaking changes:
|
|
31
|
+
|
|
32
|
+
1. HttpWebRequest and WebClient have been fully removed in .NET 10.
|
|
33
|
+
Any PowerShell script that uses New-Object System.Net.WebClient or
|
|
34
|
+
[System.Net.HttpWebRequest]::Create() now throws NotSupportedException.
|
|
35
|
+
Both classes were deprecated in .NET 5 and are gone in .NET 10.
|
|
36
|
+
|
|
37
|
+
2. ServicePointManager.SecurityProtocol setter is not supported in .NET 10.
|
|
38
|
+
Workflows that manually set TLS protocol versions with
|
|
39
|
+
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
|
|
40
|
+
now throw MissingMethodException. .NET 10 negotiates TLS automatically.
|
|
41
|
+
|
|
42
|
+
3. WildcardPattern.Escape now correctly escapes lone backtick characters (PS #25211).
|
|
43
|
+
Scripts that relied on the previous (incorrect) unescaped behavior may match
|
|
44
|
+
different patterns than expected.
|
|
45
|
+
|
|
46
|
+
4. Join-Path -ChildPath parameter changed from string to string[]. Code that relied
|
|
47
|
+
on positional argument behavior for this parameter may bind differently.
|
|
48
|
+
|
|
49
|
+
This is distinct from the ThreadJob module rename (runner-environment-075 entry).
|
|
50
|
+
These are .NET runtime-level breaking changes, not module renames.
|
|
51
|
+
fix: |
|
|
52
|
+
Replace HttpWebRequest / WebClient with Invoke-RestMethod or Invoke-WebRequest,
|
|
53
|
+
which are the PowerShell-native HTTP clients backed by HttpClient (supported in all
|
|
54
|
+
.NET versions). Remove ServicePointManager.SecurityProtocol assignments entirely;
|
|
55
|
+
.NET 10 negotiates TLS 1.2/1.3 automatically and no longer accepts manual overrides.
|
|
56
|
+
fix_code:
|
|
57
|
+
- language: yaml
|
|
58
|
+
label: "Replace WebClient (removed in .NET 10) with Invoke-WebRequest"
|
|
59
|
+
code: |
|
|
60
|
+
steps:
|
|
61
|
+
- name: Download file
|
|
62
|
+
shell: pwsh
|
|
63
|
+
run: |
|
|
64
|
+
# BEFORE (.NET 10 throws NotSupportedException):
|
|
65
|
+
# $wc = New-Object System.Net.WebClient
|
|
66
|
+
# $wc.DownloadFile($env:URL, $env:DEST)
|
|
67
|
+
|
|
68
|
+
# AFTER — use Invoke-WebRequest (works across .NET 6/8/10)
|
|
69
|
+
Invoke-WebRequest -Uri $env:ARTIFACT_URL -OutFile $env:DEST_PATH -UseBasicParsing
|
|
70
|
+
env:
|
|
71
|
+
ARTIFACT_URL: 'https://example.com/artifact.zip'
|
|
72
|
+
DEST_PATH: 'artifact.zip'
|
|
73
|
+
- language: yaml
|
|
74
|
+
label: "Remove ServicePointManager.SecurityProtocol (not needed in .NET 10)"
|
|
75
|
+
code: |
|
|
76
|
+
steps:
|
|
77
|
+
- name: Call API
|
|
78
|
+
shell: pwsh
|
|
79
|
+
run: |
|
|
80
|
+
# BEFORE (.NET 10 throws MissingMethodException):
|
|
81
|
+
# [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
|
|
82
|
+
|
|
83
|
+
# AFTER — .NET 10 negotiates TLS 1.3/1.2 automatically, no manual override needed
|
|
84
|
+
$response = Invoke-RestMethod -Uri 'https://api.example.com/data' -Method Get
|
|
85
|
+
$response | ConvertTo-Json
|
|
86
|
+
- language: yaml
|
|
87
|
+
label: "Check PowerShell version in workflow to detect the upgrade"
|
|
88
|
+
code: |
|
|
89
|
+
steps:
|
|
90
|
+
- name: Verify PowerShell version and .NET runtime
|
|
91
|
+
shell: pwsh
|
|
92
|
+
run: |
|
|
93
|
+
$PSVersionTable
|
|
94
|
+
[System.Environment]::Version
|
|
95
|
+
prevention:
|
|
96
|
+
- "Audit all PowerShell scripts in workflows for WebClient and HttpWebRequest usage before the June 8-15 image rollout."
|
|
97
|
+
- "Replace New-Object System.Net.WebClient with Invoke-WebRequest or Invoke-RestMethod throughout."
|
|
98
|
+
- "Remove all [System.Net.ServicePointManager]::SecurityProtocol assignments — they are no-ops at best in .NET 10."
|
|
99
|
+
- "Test workflows locally with PowerShell 7.6 (winget install Microsoft.PowerShell) before the image rollout completes."
|
|
100
|
+
- "The ThreadJob module rename is a separate issue — see runner-environment-075 entry for that breaking change."
|
|
101
|
+
docs:
|
|
102
|
+
- url: "https://github.com/actions/runner-images/issues/14150"
|
|
103
|
+
label: "runner-images#14150: PowerShell will be updated from 7.4 to 7.6 LTS on all runner images"
|
|
104
|
+
- url: "https://learn.microsoft.com/en-us/powershell/scripting/whats-new/what-s-new-in-powershell-76"
|
|
105
|
+
label: "Microsoft Docs: What's new in PowerShell 7.6"
|
|
106
|
+
- url: "https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-10/overview"
|
|
107
|
+
label: "Microsoft Docs: Breaking changes in .NET 10"
|
|
108
|
+
- url: "https://github.com/PowerShell/PowerShell/releases/tag/v7.6.0"
|
|
109
|
+
label: "PowerShell 7.6.0 Release Notes"
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
id: runner-environment-077
|
|
2
|
+
title: "Chrome 148.0.7778.178 on Ubuntu 24.04 Causes WebdriverIO and Browser Tests to Hang"
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- ubuntu-24.04
|
|
7
|
+
- chrome
|
|
8
|
+
- chromium
|
|
9
|
+
- webdriverio
|
|
10
|
+
- browser-testing
|
|
11
|
+
- regression
|
|
12
|
+
- selenium
|
|
13
|
+
- playwright
|
|
14
|
+
patterns:
|
|
15
|
+
- regex: 'Failed to create session|chrome not reachable|connect ECONNREFUSED.*9515'
|
|
16
|
+
flags: "i"
|
|
17
|
+
- regex: 'ChromeDriver.*unable to receive message|WebDriver.*timed out'
|
|
18
|
+
flags: "i"
|
|
19
|
+
- regex: 'google-chrome.*148\.0\.7778\.17[89]|148\.0\.7778\.17[89]'
|
|
20
|
+
flags: "i"
|
|
21
|
+
error_messages:
|
|
22
|
+
- "Error: Failed to create session."
|
|
23
|
+
- "Error: chrome not reachable"
|
|
24
|
+
- "Error: connect ECONNREFUSED 127.0.0.1:9515"
|
|
25
|
+
- "DevTools protocol message timeout"
|
|
26
|
+
root_cause: |
|
|
27
|
+
Chrome 148.0.7778.178 was shipped in ubuntu-24.04 runner image 20260525.161.1
|
|
28
|
+
(May 25, 2026). This build introduced an upstream regression that causes WebdriverIO,
|
|
29
|
+
Selenium, and other CDP-based browser automation frameworks to hang indefinitely
|
|
30
|
+
when launching Chrome. The Chrome process starts but the DevTools Protocol endpoint
|
|
31
|
+
never becomes reachable, causing session creation to time out.
|
|
32
|
+
|
|
33
|
+
GitHub installs Chrome from the official stable channel on each image build and does
|
|
34
|
+
not pin versions. The previous image (20260518.149.1) shipped Chrome 148.0.7778.167
|
|
35
|
+
which was unaffected. GitHub confirmed they will not roll back the image and are
|
|
36
|
+
waiting for an upstream Google Chrome fix (tracked as Chromium issue #517079992).
|
|
37
|
+
|
|
38
|
+
WebdriverIO tests that previously ran reliably on GitHub-hosted ubuntu-24.04 runners
|
|
39
|
+
will hang silently or time out after this image version update. Switching to
|
|
40
|
+
ubuntu-22.04 does not guarantee relief as it also installs stable Chrome.
|
|
41
|
+
fix: |
|
|
42
|
+
Pin Chrome to version 148.0.7778.167 (the last known-good stable build) using
|
|
43
|
+
browser-actions/setup-chrome, which installs from Chrome for Testing CDN — an
|
|
44
|
+
immutable, version-pinned registry that does not auto-update. Point WebdriverIO at
|
|
45
|
+
the pinned Chrome binary via environment variables rather than using system Chrome.
|
|
46
|
+
fix_code:
|
|
47
|
+
- language: yaml
|
|
48
|
+
label: "Pin Chrome to last known-good build (runner-images#14169 workaround)"
|
|
49
|
+
code: |
|
|
50
|
+
jobs:
|
|
51
|
+
e2e:
|
|
52
|
+
runs-on: ubuntu-24.04
|
|
53
|
+
steps:
|
|
54
|
+
- uses: actions/checkout@v4
|
|
55
|
+
|
|
56
|
+
- name: Install pinned Chrome (workaround for runner-images#14169)
|
|
57
|
+
id: setup-chrome
|
|
58
|
+
uses: browser-actions/setup-chrome@v1
|
|
59
|
+
with:
|
|
60
|
+
chrome-version: '148.0.7778.167'
|
|
61
|
+
install-dependencies: true
|
|
62
|
+
install-chromedriver: true
|
|
63
|
+
|
|
64
|
+
- name: Run E2E tests with pinned Chrome
|
|
65
|
+
env:
|
|
66
|
+
CHROME_BIN: ${{ steps.setup-chrome.outputs.chrome-path }}
|
|
67
|
+
CHROMEWEBDRIVER: ${{ steps.setup-chrome.outputs.chromedriver-path }}
|
|
68
|
+
run: npx wdio run wdio.conf.js
|
|
69
|
+
- language: yaml
|
|
70
|
+
label: "WebdriverIO capability config pointing to pinned Chrome binary"
|
|
71
|
+
code: |
|
|
72
|
+
# wdio.conf.js — use CHROME_BIN from the setup-chrome step, not system Chrome
|
|
73
|
+
capabilities: [{
|
|
74
|
+
browserName: 'chrome',
|
|
75
|
+
'goog:chromeOptions': {
|
|
76
|
+
binary: process.env.CHROME_BIN,
|
|
77
|
+
args: ['--headless=new', '--no-sandbox', '--disable-dev-shm-usage'],
|
|
78
|
+
},
|
|
79
|
+
}]
|
|
80
|
+
prevention:
|
|
81
|
+
- "Never rely on the system Chrome version in CI — pin via browser-actions/setup-chrome for reproducible builds."
|
|
82
|
+
- "Configure WebdriverIO to use CHROME_BIN environment variable instead of auto-detecting /usr/bin/google-chrome."
|
|
83
|
+
- "Subscribe to actions/runner-images#14169 to learn when a fixed Chrome stable is shipped."
|
|
84
|
+
- "Consider Playwright (brings its own browser binaries) as a long-term alternative to avoid runner image Chrome updates."
|
|
85
|
+
docs:
|
|
86
|
+
- url: "https://github.com/actions/runner-images/issues/14169"
|
|
87
|
+
label: "runner-images#14169: Ubuntu 24.04 image update causes WebdriverIO tests with updated Chrome to hang"
|
|
88
|
+
- url: "https://github.com/browser-actions/setup-chrome"
|
|
89
|
+
label: "browser-actions/setup-chrome: Install pinned Chrome for Testing builds"
|
|
90
|
+
- url: "https://googlechromelabs.github.io/chrome-for-testing/"
|
|
91
|
+
label: "Chrome for Testing: Immutable Chrome binaries by version (CDN)"
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
id: runner-environment-076
|
|
2
|
+
title: "Ubuntu 24.04 Kernel read_ahead_kb Regression Causes I/O Thrashing and Workflow Hangs"
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- ubuntu-24.04
|
|
7
|
+
- kernel
|
|
8
|
+
- io-thrashing
|
|
9
|
+
- memory
|
|
10
|
+
- docker
|
|
11
|
+
- read-ahead
|
|
12
|
+
- performance
|
|
13
|
+
patterns:
|
|
14
|
+
- regex: 'The hosted runner lost communication with the server'
|
|
15
|
+
flags: "i"
|
|
16
|
+
- regex: 'Free memory is lower than 5%|Currently used: 9[0-9]\.[0-9]+%'
|
|
17
|
+
flags: "i"
|
|
18
|
+
- regex: 'Out of memory, malloc failed|fatal: the remote end hung up unexpectedly'
|
|
19
|
+
flags: "i"
|
|
20
|
+
error_messages:
|
|
21
|
+
- "The hosted runner lost communication with the server. Anything in your workflow that terminates the runner process, starves it for CPU/Memory, or blocks its network access can cause this error."
|
|
22
|
+
- "##[warning]Free memory is lower than 5%; Currently used: 95.55%"
|
|
23
|
+
- "fatal: Out of memory, malloc failed (tried to allocate 217 bytes)"
|
|
24
|
+
- "fatal: the remote end hung up unexpectedly"
|
|
25
|
+
root_cause: |
|
|
26
|
+
Starting with kernel 6.14.0-1017-azure (shipped in ubuntu-24.04 image 20260224.36.1
|
|
27
|
+
and continuing with 6.17.0-1008-azure in 20260302.42.1 through current), the default
|
|
28
|
+
read_ahead_kb block device value was changed from 128 KB to 4096 KB. This causes
|
|
29
|
+
the Linux page cache to speculatively read 32x more data from disk for each I/O
|
|
30
|
+
operation, flooding available RAM with unused prefetched data.
|
|
31
|
+
|
|
32
|
+
The effect is severe for workloads with large files accessed non-sequentially
|
|
33
|
+
(many build systems, compilation), Docker-in-Docker setups, database integration
|
|
34
|
+
tests (Postgres, MySQL, Redis) under I/O load, and large repository operations.
|
|
35
|
+
|
|
36
|
+
The page cache exhaustion triggers OOM conditions, process starvation, and eventually
|
|
37
|
+
causes the Actions runner process to lose connectivity to the GitHub Actions broker,
|
|
38
|
+
manifesting as "The hosted runner lost communication with the server."
|
|
39
|
+
|
|
40
|
+
GitHub confirmed this is a kernel-level change they do not control and cannot roll
|
|
41
|
+
back. The fix must be applied in the workflow. Independently documented by the
|
|
42
|
+
RavenDB team for the same Azure kernel change.
|
|
43
|
+
fix: |
|
|
44
|
+
Add a step at the beginning of the job to reset read_ahead_kb to 128 KB (the
|
|
45
|
+
safe pre-regression value). This must run before any I/O-intensive steps.
|
|
46
|
+
The step requires sudo access, which is available on all GitHub-hosted runners.
|
|
47
|
+
fix_code:
|
|
48
|
+
- language: yaml
|
|
49
|
+
label: "Reset read_ahead_kb before I/O-intensive steps (kernel regression workaround)"
|
|
50
|
+
code: |
|
|
51
|
+
jobs:
|
|
52
|
+
build:
|
|
53
|
+
runs-on: ubuntu-24.04
|
|
54
|
+
steps:
|
|
55
|
+
- name: Reset block device read-ahead (kernel regression workaround for runner-images#13770)
|
|
56
|
+
run: |
|
|
57
|
+
for dev in /sys/block/sd*/queue/read_ahead_kb; do
|
|
58
|
+
echo 128 | sudo tee "$dev" > /dev/null
|
|
59
|
+
done
|
|
60
|
+
echo "read_ahead_kb reset to 128 on all block devices"
|
|
61
|
+
|
|
62
|
+
- uses: actions/checkout@v4
|
|
63
|
+
- name: Build
|
|
64
|
+
run: make
|
|
65
|
+
- language: yaml
|
|
66
|
+
label: "Diagnose memory pressure before applying the workaround"
|
|
67
|
+
code: |
|
|
68
|
+
jobs:
|
|
69
|
+
build:
|
|
70
|
+
runs-on: ubuntu-24.04
|
|
71
|
+
steps:
|
|
72
|
+
- name: Show current read_ahead_kb and available memory
|
|
73
|
+
run: |
|
|
74
|
+
cat /sys/block/sda/queue/read_ahead_kb || true
|
|
75
|
+
free -h
|
|
76
|
+
|
|
77
|
+
- name: Reset read_ahead_kb to safe value
|
|
78
|
+
run: |
|
|
79
|
+
for dev in /sys/block/sd*/queue/read_ahead_kb; do
|
|
80
|
+
echo 128 | sudo tee "$dev" > /dev/null
|
|
81
|
+
done
|
|
82
|
+
cat /sys/block/sda/queue/read_ahead_kb
|
|
83
|
+
prevention:
|
|
84
|
+
- "Always reset read_ahead_kb to 128 on ubuntu-24.04 runners for workflows with Docker containers or database integration tests."
|
|
85
|
+
- "Use ubuntu-22.04 as a temporary mitigation — kernel 6.8.0 is unaffected by this regression."
|
|
86
|
+
- "Add memory diagnostics (free -h) before heavy build steps to catch exhaustion early."
|
|
87
|
+
- "Monitor actions/runner-images#13770 for a permanent kernel fix from Canonical and GitHub."
|
|
88
|
+
docs:
|
|
89
|
+
- url: "https://github.com/actions/runner-images/issues/13770"
|
|
90
|
+
label: "runner-images#13770: ubuntu-latest builds hanging in 20260302.42.1 runner image (kernel regression)"
|
|
91
|
+
- url: "https://github.com/ravendb/ravendb/discussions/22410"
|
|
92
|
+
label: "RavenDB: Azure kernel read_ahead_kb change causing I/O thrashing"
|
|
93
|
+
- url: "https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners"
|
|
94
|
+
label: "GitHub Docs: GitHub-hosted runner hardware resources"
|
|
@@ -12,7 +12,7 @@ tags:
|
|
|
12
12
|
patterns:
|
|
13
13
|
- regex: '\$\{\{\s*env\.[A-Za-z_][A-Za-z0-9_]*\s*\}\}'
|
|
14
14
|
flags: "i"
|
|
15
|
-
- regex:
|
|
15
|
+
- regex: 'expression.*evaluates.*empty.*string|undefined.*variable.*no.*error'
|
|
16
16
|
flags: "i"
|
|
17
17
|
error_messages:
|
|
18
18
|
- "(no error shown -- undefined env/context variables produce empty strings silently)"
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
id: yaml-syntax-031
|
|
2
|
+
title: "case() expression function fails with 'Unrecognized function' on runners older than 2.329.0"
|
|
3
|
+
category: yaml-syntax
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- case-function
|
|
7
|
+
- expressions
|
|
8
|
+
- runner-version
|
|
9
|
+
- self-hosted
|
|
10
|
+
- composite-action
|
|
11
|
+
- if-condition
|
|
12
|
+
|
|
13
|
+
patterns:
|
|
14
|
+
- regex: "Unrecognized function: 'case'"
|
|
15
|
+
flags: "i"
|
|
16
|
+
- regex: "The workflow is not valid.*Unrecognized function.*case"
|
|
17
|
+
flags: "i"
|
|
18
|
+
|
|
19
|
+
error_messages:
|
|
20
|
+
- "Unrecognized function: 'case'. Located at position 1 within expression: case(github.event_name == 'push', 'deploy', github.event_name == 'pull_request', 'review', 'skip')"
|
|
21
|
+
- "The workflow is not valid. .github/workflows/deploy.yml (Line: 24, Col: 16): Unrecognized function: 'case'"
|
|
22
|
+
|
|
23
|
+
root_cause: |
|
|
24
|
+
GitHub introduced the case() expression function in runner version 2.329.0 (January 2026,
|
|
25
|
+
announced in the GitHub Actions changelog on 2026-01-29). The case() function enables
|
|
26
|
+
conditional branching similar to SQL CASE expressions, supporting if-else and switch-case
|
|
27
|
+
patterns in workflow expressions.
|
|
28
|
+
|
|
29
|
+
Self-hosted runners that have not been updated to version 2.329.0 or later do not recognize
|
|
30
|
+
case() as a valid function. When any workflow step, job-level if: condition, output mapping,
|
|
31
|
+
or composite action uses ${{ case(...) }}, the runner throws "Unrecognized function: 'case'"
|
|
32
|
+
and the job fails immediately.
|
|
33
|
+
|
|
34
|
+
GitHub-hosted runners (ubuntu-latest, windows-latest, macos-latest) receive runner updates
|
|
35
|
+
automatically and are not affected. Only self-hosted runners with version pinning or delayed
|
|
36
|
+
update policies encounter this error.
|
|
37
|
+
|
|
38
|
+
A secondary regression occurred in runner 2.333.0 (March 2026) where case() was temporarily
|
|
39
|
+
broken for composite actions specifically, producing the same error. This was resolved in
|
|
40
|
+
2.333.1.
|
|
41
|
+
|
|
42
|
+
fix: |
|
|
43
|
+
For self-hosted runners: Update the runner to version 2.329.0 or later. Runner updates
|
|
44
|
+
can be applied via the GitHub Actions runner update script or by re-registering the runner
|
|
45
|
+
with the latest version from the GitHub Actions runner releases page.
|
|
46
|
+
|
|
47
|
+
To verify your runner version: check Settings > Actions > Runners in your repository or
|
|
48
|
+
organization, or inspect the runner binary with ./actions-runner/config.sh --version.
|
|
49
|
+
|
|
50
|
+
Temporary workaround: Rewrite case() expressions using nested ternary-style expressions
|
|
51
|
+
that work on all runner versions, then migrate to case() once runners are updated.
|
|
52
|
+
|
|
53
|
+
fix_code:
|
|
54
|
+
- language: yaml
|
|
55
|
+
label: "New (requires runner 2.329.0+): using case() for conditional output"
|
|
56
|
+
code: |
|
|
57
|
+
jobs:
|
|
58
|
+
determine-env:
|
|
59
|
+
runs-on: self-hosted
|
|
60
|
+
outputs:
|
|
61
|
+
environment: ${{ steps.set-env.outputs.env }}
|
|
62
|
+
steps:
|
|
63
|
+
- id: set-env
|
|
64
|
+
run: echo "env=${{ case(github.ref == 'refs/heads/main', 'production', github.ref == 'refs/heads/staging', 'staging', 'development') }}" >> $GITHUB_OUTPUT
|
|
65
|
+
|
|
66
|
+
- language: yaml
|
|
67
|
+
label: "Fallback for runners older than 2.329.0 (works on all versions)"
|
|
68
|
+
code: |
|
|
69
|
+
jobs:
|
|
70
|
+
determine-env:
|
|
71
|
+
runs-on: self-hosted
|
|
72
|
+
outputs:
|
|
73
|
+
environment: ${{ steps.set-env.outputs.env }}
|
|
74
|
+
steps:
|
|
75
|
+
- id: set-env
|
|
76
|
+
run: |
|
|
77
|
+
REF="${{ github.ref }}"
|
|
78
|
+
if [[ "$REF" == "refs/heads/main" ]]; then
|
|
79
|
+
echo "env=production" >> $GITHUB_OUTPUT
|
|
80
|
+
elif [[ "$REF" == "refs/heads/staging" ]]; then
|
|
81
|
+
echo "env=staging" >> $GITHUB_OUTPUT
|
|
82
|
+
else
|
|
83
|
+
echo "env=development" >> $GITHUB_OUTPUT
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
prevention:
|
|
87
|
+
- "Pin runner version in self-hosted runner documentation and set up automated update notifications."
|
|
88
|
+
- "Add a workflow step that logs the runner version (echo $ACTIONS_RUNNER_VERSION) to surface version mismatches early."
|
|
89
|
+
- "Test new expression functions on GitHub-hosted runners first; then roll out to self-hosted after confirming the runner version."
|
|
90
|
+
- "Configure runner auto-update policies — GitHub recommends keeping self-hosted runners within 2 major versions of the latest."
|
|
91
|
+
|
|
92
|
+
docs:
|
|
93
|
+
- url: "https://github.blog/changelog/2026-01-29-github-actions-smarter-editing-clearer-debugging-and-a-new-case-function/"
|
|
94
|
+
label: "GitHub Changelog 2026-01-29: New case() function introduction"
|
|
95
|
+
- url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/evaluate-expressions-in-workflows-and-actions"
|
|
96
|
+
label: "GitHub Docs: Expressions — case() function reference"
|
|
97
|
+
- url: "https://github.com/actions/runner/issues/4315"
|
|
98
|
+
label: "actions/runner#4315: Runner v2.333.0 breaks case function (regression)"
|
|
99
|
+
- url: "https://github.com/actions/runner/releases"
|
|
100
|
+
label: "GitHub Actions Runner releases — version history"
|
package/package.json
CHANGED