@htekdev/actions-debugger 1.0.24 → 1.0.25
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/maven-gradle-403-cache-backend-outage.yml +116 -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,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"
|
|
@@ -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