@htekdev/actions-debugger 1.0.1 → 1.0.3

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.
@@ -0,0 +1,118 @@
1
+ id: caching-artifacts-010
2
+ title: "Artifact Download Fails — Unable to Find Any Artifacts for Run"
3
+ category: caching-artifacts
4
+ severity: error
5
+ tags:
6
+ - artifact
7
+ - download
8
+ - run-id
9
+ - cross-workflow
10
+ - upload-artifact
11
+ - download-artifact
12
+ patterns:
13
+ - regex: "Unable to find any artifacts for the associated workflow"
14
+ flags: "i"
15
+ - regex: "No artifacts found for run"
16
+ flags: "i"
17
+ - regex: "Error: Unable to find any artifacts"
18
+ flags: "i"
19
+ error_messages:
20
+ - "Unable to find any artifacts for the associated workflow"
21
+ - "Error: Unable to find any artifacts for the associated workflow"
22
+ - "No artifacts were found with the provided name and filters."
23
+ root_cause: |
24
+ GitHub Actions artifacts are scoped to a specific workflow run. The
25
+ `actions/download-artifact@v4` action (and v3 with `run-id:`) will fail with
26
+ "Unable to find any artifacts" when:
27
+
28
+ 1. **Wrong or stale run-id** — The run ID is hard-coded or fetched from a
29
+ prior run that no longer has the expected artifact (artifacts expire after
30
+ the configured retention period, default 90 days).
31
+
32
+ 2. **Upload step never ran** — The producing workflow job was cancelled, the
33
+ upload step was skipped due to a failed prior step, or the `if:` condition
34
+ on the upload step evaluated to false.
35
+
36
+ 3. **Name mismatch** — The `name:` specified in `download-artifact` doesn't
37
+ exactly match the name used in `upload-artifact` (case-sensitive).
38
+
39
+ 4. **Cross-workflow download without explicit run-id** — In v4, downloading
40
+ artifacts from a different workflow run requires an explicit `run-id:`.
41
+ Omitting it defaults to the current run, which may not have those artifacts.
42
+
43
+ Documented in GitHub Community discussion #109905.
44
+ fix: |
45
+ For cross-workflow artifact sharing:
46
+ 1. Capture the producing workflow's run-id dynamically using the GitHub REST
47
+ API or by passing it as a workflow_dispatch input or repository_dispatch payload.
48
+ 2. Verify the upload step ran successfully in the producer workflow before
49
+ downloading in a consumer workflow.
50
+ 3. Ensure `name:` matches exactly (case-sensitive) between upload and download.
51
+ 4. For same-workflow jobs, omit `run-id:` — download-artifact v4 defaults to
52
+ the current run automatically.
53
+ fix_code:
54
+ - language: yaml
55
+ label: "WRONG — hard-coded run-id that may be stale"
56
+ code: |
57
+ - uses: actions/download-artifact@v4
58
+ with:
59
+ name: build-output
60
+ run-id: 12345678 # ❌ hard-coded run ID — stale if re-run or wrong workflow
61
+ - language: yaml
62
+ label: "RIGHT — same-workflow, no run-id needed"
63
+ code: |
64
+ # Job A (producer)
65
+ jobs:
66
+ build:
67
+ runs-on: ubuntu-latest
68
+ steps:
69
+ - run: make build
70
+ - uses: actions/upload-artifact@v4
71
+ with:
72
+ name: build-output # ✅ exact name matters
73
+ path: dist/
74
+
75
+ test:
76
+ needs: build
77
+ runs-on: ubuntu-latest
78
+ steps:
79
+ - uses: actions/download-artifact@v4
80
+ with:
81
+ name: build-output # ✅ same name, no run-id needed for current run
82
+ - language: yaml
83
+ label: "RIGHT — cross-workflow download, run-id from API"
84
+ code: |
85
+ - name: Get latest successful run ID
86
+ id: get-run
87
+ env:
88
+ GH_TOKEN: ${{ github.token }}
89
+ run: |
90
+ RUN_ID=$(gh run list \
91
+ --workflow=build.yml \
92
+ --branch=main \
93
+ --status=success \
94
+ --limit=1 \
95
+ --json databaseId \
96
+ --jq '.[0].databaseId')
97
+ echo "run_id=$RUN_ID" >> $GITHUB_OUTPUT
98
+
99
+ - uses: actions/download-artifact@v4
100
+ with:
101
+ name: build-output
102
+ run-id: ${{ steps.get-run.outputs.run_id }} # ✅ dynamic run ID
103
+ github-token: ${{ github.token }}
104
+ prevention:
105
+ - "Never hard-code run-id values — always fetch them dynamically via the GitHub API or pass them as workflow inputs."
106
+ - "Always verify artifact upload completed successfully before writing a consuming workflow that depends on it."
107
+ - "Use exact case-matching artifact names — `build-output` and `Build-Output` are different artifacts."
108
+ - "For same-workflow artifact sharing between jobs, omit `run-id:` entirely — it defaults to the current run."
109
+ - "Check artifact retention settings — artifacts expire after 90 days (public) or 400 days (private) by default."
110
+ docs:
111
+ - url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/storing-and-sharing-data-from-a-workflow"
112
+ label: "Storing and sharing data from a workflow"
113
+ - url: "https://github.com/actions/download-artifact"
114
+ label: "actions/download-artifact — README and cross-run download docs"
115
+ - url: "https://github.com/orgs/community/discussions/109905"
116
+ label: "GitHub Community #109905 — Unable to find any artifacts troubleshooting"
117
+ - url: "https://stackoverflow.com/questions/78238187/unable-to-find-any-artifacts-for-the-associated-workflow-github-actions"
118
+ label: "Stack Overflow — Unable to find any artifacts for the associated workflow"
@@ -0,0 +1,101 @@
1
+ id: known-unsolved-007
2
+ title: "Workflow Rerun Limit: 50 Reruns Maximum Per Workflow Run"
3
+ category: known-unsolved
4
+ severity: limitation
5
+ tags:
6
+ - rerun
7
+ - retry
8
+ - automation
9
+ - limits
10
+ - check-suite
11
+ patterns:
12
+ - regex: "exceeded.*maximum.*rerun.*limit"
13
+ flags: "i"
14
+ - regex: "rerun limit.*50"
15
+ flags: "i"
16
+ - regex: "This workflow has been rerun too many times"
17
+ flags: "i"
18
+ - regex: "maximum rerun limit.*exceeded"
19
+ flags: "i"
20
+ error_messages:
21
+ - "This workflow has exceeded the maximum rerun limit of 50."
22
+ - "You have exceeded the maximum rerun limit for this workflow run."
23
+ - "Failed check suite: exceeded maximum rerun limit."
24
+ root_cause: |
25
+ In April 2026 GitHub introduced a hard cap of 50 reruns per workflow run (combining
26
+ full re-runs and partial job re-runs). When the limit is hit, any subsequent rerun
27
+ attempt results in a failed check suite with an annotation — no partial or full rerun
28
+ is permitted on that run ever again.
29
+
30
+ The limit was introduced because some automation scripts were issuing hundreds of retry
31
+ attempts on a single workflow run, adding significant load to GitHub's infrastructure.
32
+
33
+ Common triggers of this limit:
34
+ - Automated retry bots (e.g. flaky-test detection scripts) that loop on `gh run rerun`
35
+ - CI platforms that aggressively requeue failed runs
36
+ - Scheduled maintenance pipelines that retry indefinitely on runner-level transient failures
37
+ - GitHub Apps polling and re-triggering stale check suites on long-lived PRs
38
+ fix: |
39
+ There is no way to raise the 50-rerun cap — it is a hard platform limit with no bypass.
40
+
41
+ Recommended approaches:
42
+ 1. **Fix the root cause instead of retrying** — identify and address flaky tests, network
43
+ timeouts, or runner instability rather than masking them with reruns.
44
+ 2. **Create a new workflow run instead of rerunning** — close and reopen the PR, push a
45
+ no-op commit, or trigger `workflow_dispatch` to start a fresh run with its own 50-run
46
+ budget.
47
+ 3. **Implement retry logic inside the step** — use a step-level retry loop (`for i in 1 2 3`)
48
+ rather than whole-workflow reruns so flakiness is contained within a single run.
49
+ 4. **Limit automation rerun budgets** — if you operate a retry bot, add a counter check
50
+ (`gh run view --json runAttempt`) and stop retrying once `runAttempt >= 40` to leave
51
+ headroom before the limit hits.
52
+ fix_code:
53
+ - language: yaml
54
+ label: "Step-level retry instead of whole-workflow rerun"
55
+ code: |
56
+ steps:
57
+ - name: Run flaky integration test (with built-in retry)
58
+ shell: bash
59
+ run: |
60
+ for attempt in 1 2 3; do
61
+ echo "Attempt $attempt of 3"
62
+ if npm run test:integration; then
63
+ echo "Tests passed on attempt $attempt"
64
+ exit 0
65
+ fi
66
+ echo "Attempt $attempt failed, retrying..."
67
+ sleep 10
68
+ done
69
+ echo "All 3 attempts failed"
70
+ exit 1
71
+ - language: yaml
72
+ label: "Check rerun count before auto-retrying in a workflow automation"
73
+ code: |
74
+ steps:
75
+ - name: Guard against rerun limit
76
+ shell: bash
77
+ run: |
78
+ RUN_ATTEMPT="${{ github.run_attempt }}"
79
+ if [ "$RUN_ATTEMPT" -ge 40 ]; then
80
+ echo "::error::Run attempt $RUN_ATTEMPT is near the 50-rerun limit. Stopping auto-retry."
81
+ exit 1
82
+ fi
83
+ echo "Run attempt $RUN_ATTEMPT — within safe retry budget"
84
+ - language: yaml
85
+ label: "Trigger a fresh run instead of rerunning (workflow_dispatch)"
86
+ code: |
87
+ # Instead of gh run rerun <run-id>, dispatch a fresh run:
88
+ # gh workflow run my-workflow.yml --ref main
89
+ # This creates a new run ID with its own 50-rerun budget.
90
+ prevention:
91
+ - "Build retry logic inside steps using shell loops rather than whole-workflow reruns."
92
+ - "Monitor `github.run_attempt` context value; alert or stop automation at 40+ attempts."
93
+ - "Fix flaky tests rather than relying on reruns as the primary reliability mechanism."
94
+ - "If a run regularly hits >10 reruns, treat it as a reliability incident, not a normal CI pattern."
95
+ docs:
96
+ - url: "https://github.blog/changelog/2026-04-10-actions-workflows-are-limited-to-50-reruns/"
97
+ label: "GitHub Changelog: Actions workflows are limited to 50 reruns"
98
+ - url: "https://docs.github.com/en/actions/managing-workflow-runs-and-deployments/managing-workflow-runs/re-running-workflows-and-jobs"
99
+ label: "Re-running workflows and jobs"
100
+ - url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/workflow-commands-for-github-actions"
101
+ label: "Workflow commands for GitHub Actions"
@@ -0,0 +1,130 @@
1
+ id: permissions-auth-008
2
+ title: "GCP OIDC Workload Identity: Pool Path vs Provider Path / Project ID vs Number"
3
+ category: permissions-auth
4
+ severity: error
5
+ tags:
6
+ - oidc
7
+ - gcp
8
+ - google-cloud
9
+ - workload-identity
10
+ - auth
11
+ patterns:
12
+ - regex: "Invalid value for [\"']?audience[\"']?"
13
+ flags: "i"
14
+ - regex: "Error code invalid_request.*Invalid value for.*audience"
15
+ flags: "i"
16
+ - regex: "workloadIdentityPools.*not.*providers"
17
+ flags: "i"
18
+ - regex: "project.*number.*not.*project.*id"
19
+ flags: "i"
20
+ - regex: "OAuthError.*Invalid value for.*audience"
21
+ flags: "i"
22
+ - regex: "Error parsing credentials.*workload_identity_provider"
23
+ flags: "i"
24
+ error_messages:
25
+ - "ERROR: gcloud crashed (OAuthError): Error code invalid_request: Invalid value for \"audience\"."
26
+ - "Error: google-github-actions/auth failed with: Error code invalid_request: Invalid value for \"audience\"."
27
+ - "The workload_identity_provider must be the full provider resource name, not the pool resource name."
28
+ root_cause: |
29
+ `google-github-actions/auth` OIDC authentication fails with "Invalid value for audience"
30
+ when either of two common misconfiguration patterns is present:
31
+
32
+ **Mistake 1 — Pool path instead of Provider path**
33
+ The `workload_identity_provider` input requires the full *Provider* resource name:
34
+ `projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID`
35
+
36
+ Many developers mistakenly supply only the *Pool* path (omitting `/providers/PROVIDER_ID`):
37
+ `projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID`
38
+
39
+ GCP's STS token endpoint rejects the audience because it expects the provider URI, not the pool URI.
40
+
41
+ **Mistake 2 — Project ID (string) instead of Project Number (integer)**
42
+ The path requires the numeric GCP project number (e.g. `123456789012`), NOT the human-readable
43
+ project ID (e.g. `my-gcp-project`). Workload Identity Federation does not accept project IDs.
44
+ Using a project ID causes the STS endpoint to return "Invalid value for audience" because the
45
+ resource path does not resolve to a valid identity provider.
46
+
47
+ **Mistake 3 — Missing `id-token: write` permission**
48
+ If `permissions.id-token` is not explicitly set to `write` at the job or workflow level,
49
+ GitHub will not mint an OIDC token and the auth step fails with a permissions error rather
50
+ than a token exchange error.
51
+ fix: |
52
+ Verify the `workload_identity_provider` value against the exact format required:
53
+ `projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL/providers/PROVIDER`
54
+
55
+ Retrieve the correct value:
56
+ gcloud iam workload-identity-pools providers describe PROVIDER_ID \
57
+ --project=PROJECT_ID \
58
+ --location=global \
59
+ --workload-identity-pool=POOL_ID \
60
+ --format='value(name)'
61
+
62
+ Ensure `id-token: write` is set in the job permissions block.
63
+
64
+ Wait at least 5 minutes after changes to Workload Identity Pool / Provider / IAM bindings
65
+ before testing — these resources are eventually consistent.
66
+ fix_code:
67
+ - language: yaml
68
+ label: "Correct workload_identity_provider format (provider path + project number)"
69
+ code: |
70
+ jobs:
71
+ deploy:
72
+ runs-on: ubuntu-latest
73
+ permissions:
74
+ id-token: write # REQUIRED — grants GitHub the right to mint an OIDC token
75
+ contents: read
76
+
77
+ steps:
78
+ - uses: actions/checkout@v4
79
+
80
+ - id: auth
81
+ uses: google-github-actions/auth@v2
82
+ with:
83
+ # CORRECT: full provider path with numeric project number
84
+ workload_identity_provider: >-
85
+ projects/123456789012/locations/global/workloadIdentityPools/my-pool/providers/my-provider
86
+ service_account: my-service-account@my-project.iam.gserviceaccount.com
87
+ - language: yaml
88
+ label: "Common mistake — pool path (missing /providers/...) causes audience error"
89
+ code: |
90
+ # WRONG: pool path only — gcloud crashes with "Invalid value for audience"
91
+ # workload_identity_provider: >-
92
+ # projects/123456789012/locations/global/workloadIdentityPools/my-pool
93
+
94
+ # ALSO WRONG: project ID string instead of project number
95
+ # workload_identity_provider: >-
96
+ # projects/my-gcp-project/locations/global/workloadIdentityPools/my-pool/providers/my-provider
97
+
98
+ # CORRECT:
99
+ # workload_identity_provider: >-
100
+ # projects/123456789012/locations/global/workloadIdentityPools/my-pool/providers/my-provider
101
+ - language: yaml
102
+ label: "Store provider path in a repository variable to avoid typos"
103
+ code: |
104
+ jobs:
105
+ deploy:
106
+ runs-on: ubuntu-latest
107
+ permissions:
108
+ id-token: write
109
+ contents: read
110
+ steps:
111
+ - uses: google-github-actions/auth@v2
112
+ with:
113
+ # Store full provider path as a repository variable to avoid typos
114
+ workload_identity_provider: ${{ vars.GCP_WIF_PROVIDER }}
115
+ service_account: ${{ vars.GCP_SERVICE_ACCOUNT }}
116
+ prevention:
117
+ - "Always use `gcloud iam workload-identity-pools providers describe` to copy the exact provider path."
118
+ - "Store the full provider path in a GitHub Actions variable (`vars.GCP_WIF_PROVIDER`) to prevent manual typos."
119
+ - "Use numeric project number — retrieve it with `gcloud projects describe PROJECT_ID --format='value(projectNumber)'`."
120
+ - "After changing Workload Identity Pool config, wait 5 minutes before testing (eventual consistency)."
121
+ - "Confirm `id-token: write` permission is present at job (not just workflow) level."
122
+ docs:
123
+ - url: "https://github.com/google-github-actions/auth#setup"
124
+ label: "google-github-actions/auth: Setup and configuration"
125
+ - url: "https://github.com/google-github-actions/auth/blob/main/docs/TROUBLESHOOTING.md"
126
+ label: "google-github-actions/auth: Troubleshooting guide"
127
+ - url: "https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/configuring-openid-connect-in-google-cloud-platform"
128
+ label: "Configuring OIDC in Google Cloud Platform"
129
+ - url: "https://cloud.google.com/iam/docs/workload-identity-federation-with-deployment-pipelines"
130
+ label: "GCP: Workload Identity Federation with deployment pipelines"
@@ -0,0 +1,89 @@
1
+ id: runner-environment-018
2
+ title: "macOS 14 Sonoma Runner Deprecation — EOL November 2026"
3
+ category: runner-environment
4
+ severity: warning
5
+ tags:
6
+ - macos
7
+ - deprecation
8
+ - runner-image
9
+ - eol
10
+ - migration
11
+ patterns:
12
+ - regex: "##\\[error\\]This request was rejected because.*macos-14"
13
+ flags: "i"
14
+ - regex: "Image.*macos-14.*deprecated|macos-14.*no longer supported"
15
+ flags: "i"
16
+ - regex: "The requested image.*macos-14.*not available"
17
+ flags: "i"
18
+ error_messages:
19
+ - "##[error]This request was rejected because the runner label 'macos-14' is no longer supported."
20
+ - "The macOS 14 image has been retired. Please update to macos-15 or macos-latest."
21
+ root_cause: |
22
+ GitHub announced the deprecation of `macOS 14 Sonoma` runner images on the following schedule:
23
+ - **Deprecation begins**: July 6, 2026 — longer queue times during peak hours, brownout periods
24
+ - **Full retirement**: November 2, 2026 — jobs using `macos-14` will fail permanently
25
+
26
+ GitHub maintains only the latest two stable macOS major versions. Since macOS 26 Tahoe is now
27
+ GA on GitHub Actions, macOS 14 is the oldest and must retire.
28
+
29
+ **Brownout schedule** (jobs deliberately failed during these windows to force migration):
30
+ - October 5, 14:00 UTC – October 6, 00:00 UTC
31
+ - October 12, 14:00 UTC – October 13, 00:00 UTC
32
+ - October 16–30, 14:00 UTC – next day 00:00 UTC (escalating weekly)
33
+
34
+ Affected labels: `macos-14`, `macos-14-large`, `macos-14-xlarge`.
35
+ fix: |
36
+ Update your workflow's `runs-on` label to a supported macOS version:
37
+
38
+ | Old label | Replace with |
39
+ |-----------|--------------|
40
+ | `macos-14` | `macos-latest` or `macos-15` or `macos-26` |
41
+ | `macos-14-large` | `macos-latest-large` or `macos-15-large` |
42
+ | `macos-14-xlarge` | `macos-latest-xlarge` or `macos-15-xlarge` or `macos-26-xlarge` |
43
+
44
+ If your workflow depends on macOS 14-specific software versions (e.g., Xcode 15, older
45
+ Python/Ruby), test carefully against macOS 15 before switching `macos-latest`.
46
+ See runner-environment-017 for macOS 15 → 26 migration notes if moving to `macos-latest`.
47
+ fix_code:
48
+ - language: yaml
49
+ label: "Migrate from macos-14 to macos-15 (conservative) or macos-latest"
50
+ code: |
51
+ jobs:
52
+ build:
53
+ # Before:
54
+ # runs-on: macos-14
55
+
56
+ # Conservative: macos-15 (similar software stack, no OpenSSL jump)
57
+ runs-on: macos-15
58
+
59
+ # OR accept latest (currently macos-26 after June 15 2026):
60
+ # runs-on: macos-latest
61
+
62
+ steps:
63
+ - uses: actions/checkout@v4
64
+ - language: yaml
65
+ label: "Strategy matrix: test across multiple macOS versions during migration"
66
+ code: |
67
+ jobs:
68
+ build:
69
+ strategy:
70
+ matrix:
71
+ os: [macos-15, macos-26]
72
+ runs-on: ${{ matrix.os }}
73
+ steps:
74
+ - uses: actions/checkout@v4
75
+ - name: Build and test
76
+ run: make test
77
+ prevention:
78
+ - "Subscribe to actions/runner-images GitHub Issues announcements label to receive deprecation notices well in advance."
79
+ - "Avoid pinning to specific macOS point versions (`macos-14`, `macos-15`) in long-lived workflows — use `macos-latest` and test proactively against the next version."
80
+ - "Run a matrix strategy against `macos-latest` and your pinned version to detect incompatibilities before they cause production failures."
81
+ - "Search your organization's workflows periodically for deprecated runner labels using: `gh search code 'runs-on: macos-14' --owner YOUR_ORG`."
82
+ docs:
83
+ - url: "https://github.com/actions/runner-images/issues/13518"
84
+ label: "GitHub Announcement: macOS 14 Sonoma deprecation timeline"
85
+ - url: "https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources"
86
+ label: "Supported GitHub-hosted runner labels"
87
+ source:
88
+ article: "https://htek.dev/articles/github-actions-debugging-guide"
89
+ section: "Runner deprecation and EOL"
@@ -0,0 +1,127 @@
1
+ id: runner-environment-017
2
+ title: "macos-latest Label Now Points to macOS 26 Tahoe"
3
+ category: runner-environment
4
+ severity: error
5
+ tags:
6
+ - macos
7
+ - runner-image
8
+ - breaking-change
9
+ - openssl
10
+ - xcode
11
+ - migration
12
+ patterns:
13
+ - regex: "Error opening configuration file.*openssl"
14
+ flags: "i"
15
+ - regex: "SSL_CTX_new.*failed|SSL_connect.*SYSCALL error"
16
+ flags: "i"
17
+ - regex: "Could not find Xcode.*version.*16\\.\\d"
18
+ flags: "i"
19
+ - regex: "ruby.*requires.*Ruby (2|3\\.0|3\\.1|3\\.2|3\\.3)"
20
+ flags: "i"
21
+ - regex: "dyld.*Library not loaded.*libssl\\.1\\.1"
22
+ flags: "i"
23
+ error_messages:
24
+ - "dyld[]: Library not loaded: /usr/local/opt/openssl@1.1/lib/libssl.1.1.dylib"
25
+ - "Could not find Xcode version '16.4'"
26
+ - "SSL_connect returned=1 errno=0 state=error: certificate verify failed"
27
+ - "Your Ruby version is 3.3.x, but your Gemfile specified ~> 3.3"
28
+ - "npm warn old lockfile"
29
+ root_cause: |
30
+ The `macos-latest` label in GitHub Actions was migrated to point to macOS 26 Tahoe
31
+ beginning June 15, 2026 (completing by July 15, 2026). Previously it pointed to macOS 15
32
+ Sequoia. This migration includes several major software version changes that silently break
33
+ workflows:
34
+
35
+ - **OpenSSL**: 1.1.1w → 3.6.2 — The biggest breaking change. Many C/C++ projects,
36
+ Ruby gems (openssl), and Python packages that link against the system OpenSSL dynamically
37
+ will fail at runtime because libssl.1.1.dylib no longer ships with macOS 26.
38
+ - **Xcode**: Default changes from 16.4 to 26.4.1 (Xcode 26 series). Workflows pinning
39
+ `xcode-version: '16.4'` or relying on Clang 17 will break — Clang/LLVM jumps from 17 → 21.
40
+ - **Ruby**: 3.3.x → 3.4.x — Minor version bump can cause Gemfile constraint failures and
41
+ gem native extension compilation issues.
42
+ - **Node.js**: Default moves from 22 → 24 (though both images include Node 24 in cached tools).
43
+ - **npm**: 10.x → 11.x — Major npm version. Package-lock.json format changes possible.
44
+ - **Homebrew LLVM**: 18 → 20 (major version jump for workflows using `llvm@18` explicitly).
45
+ fix: |
46
+ **Immediate mitigation:** Pin to `macos-15` to restore previous behavior while you migrate:
47
+
48
+ ```yaml
49
+ runs-on: macos-15
50
+ ```
51
+
52
+ **Proper fix** — address each breaking dependency:
53
+
54
+ 1. **OpenSSL**: Brew-install a pinned OpenSSL version and set library paths:
55
+ ```bash
56
+ brew install openssl@1.1
57
+ export LDFLAGS="-L$(brew --prefix openssl@1.1)/lib"
58
+ export CPPFLAGS="-I$(brew --prefix openssl@1.1)/include"
59
+ ```
60
+ Or migrate to OpenSSL 3.x compatible code.
61
+
62
+ 2. **Xcode**: Pin the Xcode version explicitly using `maxim-lobanov/setup-xcode`:
63
+ ```yaml
64
+ - uses: maxim-lobanov/setup-xcode@v1
65
+ with:
66
+ xcode-version: '16.4'
67
+ ```
68
+ Or migrate your project to Xcode 26.
69
+
70
+ 3. **Ruby**: Update your Gemfile to accept 3.4.x (`~> 3.4`) or use `ruby/setup-ruby` to
71
+ pin a specific version:
72
+ ```yaml
73
+ - uses: ruby/setup-ruby@v1
74
+ with:
75
+ ruby-version: '3.3'
76
+ ```
77
+ fix_code:
78
+ - language: yaml
79
+ label: "Pin to macos-15 for immediate rollback"
80
+ code: |
81
+ jobs:
82
+ build:
83
+ runs-on: macos-15 # pinned until macos-26 migration complete
84
+ steps:
85
+ - uses: actions/checkout@v4
86
+ - language: yaml
87
+ label: "Full macos-26 compatible workflow — pin Xcode, Ruby, and OpenSSL"
88
+ code: |
89
+ jobs:
90
+ build:
91
+ runs-on: macos-latest # now macos-26
92
+ steps:
93
+ - uses: actions/checkout@v4
94
+
95
+ # Pin Xcode version explicitly
96
+ - uses: maxim-lobanov/setup-xcode@v1
97
+ with:
98
+ xcode-version: '26.4'
99
+
100
+ # Pin Ruby if needed
101
+ - uses: ruby/setup-ruby@v1
102
+ with:
103
+ ruby-version: '3.3'
104
+ bundler-cache: true
105
+
106
+ # If OpenSSL 1.1 is needed, install and export paths
107
+ - name: Install OpenSSL 1.1
108
+ run: |
109
+ brew install openssl@1.1
110
+ echo "LDFLAGS=-L$(brew --prefix openssl@1.1)/lib" >> $GITHUB_ENV
111
+ echo "CPPFLAGS=-I$(brew --prefix openssl@1.1)/include" >> $GITHUB_ENV
112
+ prevention:
113
+ - "Avoid relying on `macos-latest` for builds that depend on specific system library versions (OpenSSL, LLVM). Pin to a concrete label like `macos-15`."
114
+ - "Subscribe to the actions/runner-images repository announcements to get advance notice of `macos-latest` label migrations."
115
+ - "Use `ruby/setup-ruby`, `actions/setup-node`, and `actions/setup-python` to pin language runtimes instead of relying on runner image defaults."
116
+ - "Test your macOS workflows against the new image early by substituting `macos-26` before the `macos-latest` migration completes."
117
+ - "Audit all dylib/framework dependencies — anything linking to libssl.1.1 must be migrated to OpenSSL 3.x or brew-pinned."
118
+ docs:
119
+ - url: "https://github.com/actions/runner-images/issues/14167"
120
+ label: "GitHub Announcement: macos-latest will use macos-26 in June 2026"
121
+ - url: "https://github.com/actions/runner-images/blob/main/images/macos/macos-26-arm64-Readme.md"
122
+ label: "macOS 26 arm64 image README — full software list"
123
+ - url: "https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners"
124
+ label: "About GitHub-hosted runners — supported runner labels"
125
+ source:
126
+ article: "https://htek.dev/articles/github-actions-debugging-guide"
127
+ section: "Runner image migrations"