@htekdev/actions-debugger 1.0.100 → 1.0.101

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,113 @@
1
+ id: caching-artifacts-056
2
+ title: 'actions/cache v1 and v2 deprecated — workflows fail hard with "automatically failed" error'
3
+ category: caching-artifacts
4
+ severity: error
5
+ tags:
6
+ - actions/cache
7
+ - deprecated
8
+ - v1
9
+ - v2
10
+ - hard-failure
11
+ - breaking-change
12
+ - upgrade
13
+ patterns:
14
+ - regex: 'automatically failed.*deprecated version.*actions/cache'
15
+ flags: 'i'
16
+ - regex: 'deprecated version of.{0,30}actions/cache'
17
+ flags: 'i'
18
+ - regex: 'actions/cache@v[12]\b'
19
+ flags: 'i'
20
+ error_messages:
21
+ - "This request has been automatically failed because it uses a deprecated version of `actions/cache: 6849a6489940f00c2f30c0fb92c6274307ccb58a`"
22
+ - "Error: This request has been automatically failed because it uses a deprecated version of `actions/cache`"
23
+ root_cause: |
24
+ GitHub announced in December 2024 (GitHub Changelog) that `actions/cache` versions 1 and 2
25
+ were deprecated and would be hard-failed starting February 1, 2025. Any workflow still
26
+ pinned to `actions/cache@v1` or `actions/cache@v2` (or to a full SHA that resolves to
27
+ those versions) now fails immediately with a hard error — no cache operation is attempted
28
+ and the entire step fails.
29
+
30
+ The error message includes the SHA of the deprecated action version:
31
+ "This request has been automatically failed because it uses a deprecated version
32
+ of `actions/cache: <SHA>`"
33
+
34
+ This is a hard failure, not a graceful degradation — the step exit code is non-zero and
35
+ causes the job to fail unless `continue-on-error: true` is set on the step (which is
36
+ not a recommended fix).
37
+
38
+ Common reasons workflows are still on v1/v2:
39
+ 1. The workflow was written years ago and never updated
40
+ 2. The action is referenced by a full commit SHA from before v3 was released
41
+ 3. A reusable workflow or composite action calls an outdated dependency that pins v1/v2
42
+ 4. `Dependabot` is not enabled on the repo for GitHub Actions
43
+
44
+ Note: `actions/cache@v3` and `actions/cache@v4` are both supported. V4 is the current
45
+ recommended version.
46
+ fix: |
47
+ Upgrade all `actions/cache` references from v1 or v2 to v4 (recommended) or v3.
48
+ Search your repository for `actions/cache@v1` and `actions/cache@v2` references,
49
+ including in nested composite actions and reusable workflows.
50
+
51
+ If you are migrating from v3 to v4, note the breaking changes documented in the
52
+ v3-to-v4 migration guide (see caching-artifacts-009). The v1/v2 to v4 migration
53
+ follows the same v3-to-v4 guidance since v3 and v4 share the same input API except
54
+ for `save-always`.
55
+
56
+ Enable Dependabot for GitHub Actions updates to automatically receive future
57
+ deprecation PRs.
58
+ fix_code:
59
+ - language: yaml
60
+ label: 'Problem: workflow pinned to deprecated actions/cache v1 or v2'
61
+ code: |
62
+ steps:
63
+ - uses: actions/checkout@v4
64
+
65
+ # FAILS: v1 and v2 are deprecated — hard failure since Feb 1, 2025
66
+ - uses: actions/cache@v1
67
+ with:
68
+ path: ~/.npm
69
+ key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
70
+
71
+ # Also fails — v2 is deprecated
72
+ - uses: actions/cache@v2
73
+ with:
74
+ path: ~/.npm
75
+ key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
76
+ - language: yaml
77
+ label: 'Fix: upgrade to actions/cache v4 (recommended)'
78
+ code: |
79
+ steps:
80
+ - uses: actions/checkout@v4
81
+
82
+ # CORRECT: use v4 (or v3 if v3-to-v4 migration is not yet done)
83
+ - uses: actions/cache@v4
84
+ with:
85
+ path: ~/.npm
86
+ key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
87
+ restore-keys: |
88
+ ${{ runner.os }}-npm-
89
+ - language: yaml
90
+ label: 'Dependabot config to automatically receive Actions version updates'
91
+ code: |
92
+ # .github/dependabot.yml
93
+ version: 2
94
+ updates:
95
+ - package-ecosystem: github-actions
96
+ directory: /
97
+ schedule:
98
+ interval: weekly
99
+ # Dependabot will open PRs to upgrade actions/cache@v1/v2 → v4 automatically
100
+ prevention:
101
+ - "Enable Dependabot for GitHub Actions in `.github/dependabot.yml` to receive automated upgrade PRs."
102
+ - "Search your `.github/workflows/` directory for `actions/cache@v1` and `actions/cache@v2` before the deprecation deadline."
103
+ - "Check composite actions and reusable workflows — they may internally call deprecated cache versions."
104
+ - "Audit SHA-pinned action references to ensure the SHA does not point to a v1/v2 release."
105
+ docs:
106
+ - url: 'https://github.blog/changelog/2024-12-05-notice-of-upcoming-releases-and-breaking-changes-for-github-actions/#actions-cache-v1-v2-and-actions-toolkit-cache-package-closing-down'
107
+ label: 'GitHub Changelog Dec 2024: actions/cache v1/v2 deprecation notice'
108
+ - url: 'https://github.com/actions/cache/discussions/1510'
109
+ label: 'actions/cache Discussion #1510: deprecated version hard failure reports'
110
+ - url: 'https://github.com/actions/cache'
111
+ label: 'actions/cache repository — upgrade instructions'
112
+ - url: 'https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot'
113
+ label: 'GitHub Docs: Keeping your actions up to date with Dependabot'
@@ -0,0 +1,98 @@
1
+ id: caching-artifacts-057
2
+ title: '`actions/cache` Never Refreshes Cached Content — Cache Keys Are Immutable Once Stored'
3
+ category: caching-artifacts
4
+ severity: silent-failure
5
+ tags:
6
+ - cache
7
+ - stale
8
+ - immutable
9
+ - cache-hit
10
+ - refresh
11
+ - node-modules
12
+ patterns:
13
+ - regex: 'cache-hit.*true.*post.*skip'
14
+ flags: 'i'
15
+ error_messages:
16
+ - "Cache hit occurred on the primary key, not saving cache."
17
+ - "Cache hit occurred on the primary key runner-os-node-"
18
+ root_cause: |
19
+ `actions/cache` uses immutable cache keys. Once a cache entry is stored for a given
20
+ key, it cannot be updated or overwritten — any subsequent run that produces an exact
21
+ key match will restore the cached content and the post step will NOT save a new cache
22
+ entry because one already exists for that key.
23
+
24
+ This means cached content (node_modules, pip packages, Maven artifacts, etc.) is
25
+ frozen at the point of first creation and will not reflect package updates until:
26
+ - The cache entry expires (GitHub-hosted caches expire after 7 days of no access)
27
+ - The cache key changes (e.g., lockfile hash changes)
28
+ - The cache entry is manually deleted via the GitHub UI or API
29
+
30
+ Common misconception: developers expect that running `npm ci` inside a cached
31
+ node_modules hit will update the cache if packages changed. It won't. The cache key
32
+ (usually `${{ hashFiles('package-lock.json') }}`) must change for a new cache to be
33
+ saved.
34
+
35
+ Related gotcha: if restore-keys produce a partial hit (different key prefix), the
36
+ post step DOES save a new cache — but for the full key, not the partial restore key.
37
+ This creates unexpected cache churn from the developer's perspective where cache hit
38
+ rate is high but actual content is outdated.
39
+
40
+ This is intentional GitHub design but frequently misunderstood, leading to:
41
+ - Stale node_modules with old transitive dependencies
42
+ - pip packages that don't receive security patches within 7 days
43
+ - Build artifacts compiled against old toolchain versions
44
+ fix: |
45
+ To force periodic cache refresh without changing your lockfile, use one of these patterns:
46
+
47
+ 1. Include a date-based component in the cache key (weekly rotation).
48
+ 2. Use `actions/cache/restore` + `actions/cache/save` with explicit control of when
49
+ to save (allows saving even on hits).
50
+ 3. Delete the cache manually via GitHub UI (Actions > Caches) or the API when you
51
+ need an immediate refresh.
52
+ fix_code:
53
+ - language: yaml
54
+ label: "Weekly-rotating cache key to prevent indefinitely stale caches"
55
+ code: |
56
+ - name: Get week number for cache rotation
57
+ id: date
58
+ run: echo "week=$(date +'%Y-%U')" >> "$GITHUB_OUTPUT"
59
+
60
+ - name: Cache node_modules (refreshes weekly)
61
+ uses: actions/cache@v4
62
+ with:
63
+ path: ~/.npm
64
+ key: ${{ runner.os }}-node-${{ steps.date.outputs.week }}-${{ hashFiles('**/package-lock.json') }}
65
+ restore-keys: |
66
+ ${{ runner.os }}-node-${{ steps.date.outputs.week }}-
67
+ ${{ runner.os }}-node-
68
+ - language: yaml
69
+ label: "Separate restore + save for explicit cache update control"
70
+ code: |
71
+ - name: Restore cache
72
+ id: cache-restore
73
+ uses: actions/cache/restore@v4
74
+ with:
75
+ path: ~/.npm
76
+ key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
77
+ restore-keys: ${{ runner.os }}-node-
78
+
79
+ - run: npm ci
80
+
81
+ - name: Save updated cache (always saves, even on hit)
82
+ uses: actions/cache/save@v4
83
+ if: always()
84
+ with:
85
+ path: ~/.npm
86
+ key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}-${{ github.run_id }}
87
+ prevention:
88
+ - "Understand that GitHub cache keys are immutable — a key that already exists in the cache will never be overwritten"
89
+ - "Use time-based or run-id-based cache key suffixes when cached content must be refreshed more frequently than lockfile changes"
90
+ - "Monitor cache age in the GitHub UI (Actions > Caches) and manually purge entries that appear stale"
91
+ - "For security-sensitive dependencies, prefer short cache TTLs via run-id keys or disable caching entirely"
92
+ docs:
93
+ - url: "https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows"
94
+ label: "GitHub Docs — Caching dependencies to speed up workflows"
95
+ - url: "https://github.com/actions/cache/blob/main/tips-and-workarounds.md"
96
+ label: "actions/cache tips and workarounds"
97
+ - url: "https://github.com/actions/cache/issues/1380"
98
+ label: "actions/cache #1380 — cache never updates on key hit"
@@ -0,0 +1,136 @@
1
+ id: permissions-auth-059
2
+ title: 'GITHUB_TOKEN expires after 24 hours on self-hosted runners — long-running jobs fail with "GITHUB_TOKEN has expired"'
3
+ category: permissions-auth
4
+ severity: error
5
+ tags:
6
+ - GITHUB_TOKEN
7
+ - token-expiry
8
+ - self-hosted-runner
9
+ - long-running-jobs
10
+ - 24-hour-limit
11
+ - authentication
12
+ patterns:
13
+ - regex: 'GITHUB_TOKEN has expired'
14
+ flags: 'i'
15
+ - regex: 'Unable to extend GITHUB_TOKEN expiration'
16
+ flags: 'i'
17
+ - regex: 'token.*expired.*self.hosted'
18
+ flags: 'i'
19
+ error_messages:
20
+ - "Unable to extend GITHUB_TOKEN expiration time due to: GITHUB_TOKEN has expired."
21
+ - "Error: fatal: unable to access 'https://github.com/...': The requested URL returned error: 403"
22
+ root_cause: |
23
+ `GITHUB_TOKEN` is an installation access token issued at the START of each job. Its
24
+ lifetime is tied to the job execution, with a hard cap determined by the runner type:
25
+
26
+ - **GitHub-hosted runners**: `GITHUB_TOKEN` lives for up to 6 hours (matching the maximum
27
+ job execution time). On hosted runners this limit is never the issue because the job
28
+ itself can't run longer than 6 hours.
29
+
30
+ - **Self-hosted runners**: Jobs can run for up to 5 days, but `GITHUB_TOKEN` can only be
31
+ refreshed for up to **24 hours**. If a job on a self-hosted runner exceeds 24 hours of
32
+ runtime, any subsequent GitHub API call, `git push`, `gh` CLI invocation, or action that
33
+ uses `${{ github.token }}` or `${{ secrets.GITHUB_TOKEN }}` will fail with a 401/403
34
+ authentication error.
35
+
36
+ The specific error message is:
37
+ "Unable to extend GITHUB_TOKEN expiration time due to: GITHUB_TOKEN has expired."
38
+
39
+ This is particularly common in:
40
+ - Large test suites or build pipelines that process massive monorepos
41
+ - ML/data pipelines that process large datasets sequentially
42
+ - Long-running deployment or migration jobs that need GitHub API access at the end
43
+ - Jobs with retries that collectively exceed 24 hours
44
+
45
+ Note: `actions/create-github-app-token` GitHub App tokens have a similar but shorter
46
+ 1-hour expiry — see permissions-auth-046 for that pattern.
47
+ fix: |
48
+ Several approaches, in order of recommendation:
49
+
50
+ 1. **Split the job into smaller jobs** — Break the long-running job into multiple shorter
51
+ jobs connected by `needs:` dependencies. Each job gets its own fresh `GITHUB_TOKEN`.
52
+
53
+ 2. **Use a GitHub App token** — Use `actions/create-github-app-token` to generate tokens
54
+ mid-job as needed, or generate a fresh token at the point in the job where you need it.
55
+
56
+ 3. **Use a PAT (Personal Access Token)** — Store a long-lived PAT in repository or
57
+ organization secrets and use it in place of `GITHUB_TOKEN` for the API calls at the
58
+ end of the long-running job. PATs do not expire in 24 hours (they expire based on the
59
+ PAT expiration date you set). Drawback: PATs are tied to a specific user account.
60
+
61
+ 4. **Use a machine user PAT** — Create a dedicated machine account and use its PAT.
62
+ This decouples the secret from any individual developer's account.
63
+ fix_code:
64
+ - language: yaml
65
+ label: 'Problem: long-running self-hosted job uses GITHUB_TOKEN after 24+ hours'
66
+ code: |
67
+ jobs:
68
+ long-build:
69
+ runs-on: [self-hosted, large-runner]
70
+ steps:
71
+ - uses: actions/checkout@v4
72
+ - name: Run 26-hour data processing
73
+ run: ./scripts/process_all_data.sh # takes ~26 hours
74
+
75
+ # FAILS: GITHUB_TOKEN has expired by the time this step runs
76
+ - name: Upload results to GitHub
77
+ env:
78
+ GH_TOKEN: ${{ github.token }}
79
+ run: gh release upload v1.0 ./output/*.tar.gz
80
+ - language: yaml
81
+ label: 'Fix: split into jobs so each gets a fresh GITHUB_TOKEN'
82
+ code: |
83
+ jobs:
84
+ process-data:
85
+ runs-on: [self-hosted, large-runner]
86
+ steps:
87
+ - uses: actions/checkout@v4
88
+ - run: ./scripts/process_all_data.sh
89
+ - uses: actions/upload-artifact@v4
90
+ with:
91
+ name: output-files
92
+ path: ./output/
93
+
94
+ upload-release:
95
+ needs: process-data
96
+ runs-on: ubuntu-latest # hosted runner with fresh token
97
+ permissions:
98
+ contents: write
99
+ steps:
100
+ - uses: actions/download-artifact@v4
101
+ with:
102
+ name: output-files
103
+ path: ./output/
104
+ # GITHUB_TOKEN is fresh — just issued for this new job
105
+ - name: Upload to release
106
+ env:
107
+ GH_TOKEN: ${{ github.token }}
108
+ run: gh release upload v1.0 ./output/*.tar.gz
109
+ - language: yaml
110
+ label: 'Fix: use stored PAT when splitting jobs is not feasible'
111
+ code: |
112
+ jobs:
113
+ long-build:
114
+ runs-on: [self-hosted, large-runner]
115
+ steps:
116
+ - uses: actions/checkout@v4
117
+ - run: ./scripts/process_all_data.sh
118
+
119
+ # Use a PAT stored in secrets — does not expire in 24 hours
120
+ - name: Upload results (using PAT)
121
+ env:
122
+ GH_TOKEN: ${{ secrets.MACHINE_USER_PAT }} # PAT, not github.token
123
+ run: gh release upload v1.0 ./output/*.tar.gz
124
+ prevention:
125
+ - "Design self-hosted runner jobs to complete within 24 hours, or split them into smaller jobs connected by `needs:`."
126
+ - "If a job genuinely requires >24 hours of runtime, use a PAT or GitHub App token for API calls instead of `GITHUB_TOKEN`."
127
+ - "Add a monitoring step that logs elapsed job time — alert if a job approaches 20+ hours."
128
+ - "Avoid using `GITHUB_TOKEN` for API calls near the end of jobs that are known to run close to the 24-hour limit."
129
+ - "For GitHub-hosted runners this is not an issue — the job execution limit (6 hours) is shorter than the token lifetime."
130
+ docs:
131
+ - url: 'https://docs.github.com/en/actions/security-for-github-actions/security-guides/automatic-token-authentication#about-the-github_token-secret'
132
+ label: 'GitHub Docs: GITHUB_TOKEN — effective maximum lifetime'
133
+ - url: 'https://stackoverflow.com/questions/75602556/how-can-i-use-a-github-token-for-more-than-24-hours'
134
+ label: 'Stack Overflow: How to use GITHUB_TOKEN for more than 24 hours'
135
+ - url: 'https://docs.github.com/en/actions/hosting-your-own-runners/managing-self-hosted-runners/about-self-hosted-runners#usage-limits'
136
+ label: 'GitHub Docs: Self-hosted runner usage limits (5-day job limit)'
@@ -0,0 +1,115 @@
1
+ id: permissions-auth-060
2
+ title: 'Fork Pull Request Workflows Cannot Access Repository Secrets — Secrets Context Is Empty'
3
+ category: permissions-auth
4
+ severity: silent-failure
5
+ tags:
6
+ - fork
7
+ - pull-request
8
+ - secrets
9
+ - security
10
+ - workflow-permissions
11
+ patterns:
12
+ - regex: 'secrets\.[\w_]+.*empty|secrets context.*fork'
13
+ flags: 'i'
14
+ error_messages:
15
+ - "Error: Input required and not supplied: token"
16
+ - "HttpError: Bad credentials"
17
+ - "Error: Resource not accessible by integration"
18
+ root_cause: |
19
+ GitHub's security model prevents workflows triggered by `pull_request` events from
20
+ fork repositories from accessing repository secrets. This applies to ALL non-Dependabot
21
+ external contributor forks — not just Dependabot.
22
+
23
+ When a fork PR workflow runs:
24
+ - All `secrets.*` values resolve to empty string `''`
25
+ - `secrets.GITHUB_TOKEN` is replaced with a read-only token scoped only to the fork
26
+ repository (cannot write to the upstream repo, cannot access packages, etc.)
27
+ - Environment secrets are also unavailable
28
+ - Fine-grained PATs stored as secrets are unavailable
29
+
30
+ This is intentional — allowing forks to read secrets would enable malicious PRs to
31
+ exfiltrate credentials.
32
+
33
+ Common failure patterns:
34
+ - `actions/setup-node` with `registry-url` + `NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}` → 401 Unauthorized
35
+ - `docker/login-action` with `${{ secrets.DOCKERHUB_TOKEN }}` → login fails silently, image push 403
36
+ - `aws-actions/configure-aws-credentials` with role ARN from secrets → empty role, OIDC fallback
37
+ - Custom actions reading a `token:` input wired to `${{ secrets.MY_TOKEN }}` → action receives ''
38
+ and may throw "Input required and not supplied: token"
39
+
40
+ The fork PR restriction also applies to `workflow_dispatch` when triggered from a fork,
41
+ and to `check_suite`/`check_run` events from fork PRs.
42
+
43
+ Note: `pull_request_target` DOES have access to secrets because it runs in the context
44
+ of the BASE repository — but this introduces a different security risk (running untrusted
45
+ code with secret access) that requires careful mitigation.
46
+ fix: |
47
+ For CI checks that don't need secrets (lint, unit tests, build validation), no change
48
+ is needed — the read-only GITHUB_TOKEN is sufficient.
49
+
50
+ For steps that require secrets:
51
+
52
+ 1. Gate secret-requiring steps on `github.event.pull_request.head.repo.fork == false`
53
+ to skip them on fork PRs gracefully.
54
+ 2. Use `pull_request_target` + a separate privileged job for publishing/deploying,
55
+ but ALWAYS check out from `github.event.pull_request.head.sha` explicitly and
56
+ never run untrusted code in the same job.
57
+ 3. For package publishing, only publish from base branch pushes (not from PRs at all).
58
+ fix_code:
59
+ - language: yaml
60
+ label: "Skip secret-requiring steps on fork PRs gracefully"
61
+ code: |
62
+ jobs:
63
+ build:
64
+ runs-on: ubuntu-latest
65
+ steps:
66
+ - uses: actions/checkout@v4
67
+
68
+ - name: Run tests (works on fork PRs)
69
+ run: npm test
70
+
71
+ - name: Publish coverage report (skip on fork PRs)
72
+ if: github.event.pull_request.head.repo.fork == false
73
+ env:
74
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
75
+ run: npx codecov
76
+ - language: yaml
77
+ label: "Split fork-safe CI from privileged deployment using workflow_run"
78
+ code: |
79
+ # workflow: ci.yml — runs on all PRs including forks (no secrets needed)
80
+ on:
81
+ pull_request:
82
+ jobs:
83
+ test:
84
+ runs-on: ubuntu-latest
85
+ steps:
86
+ - uses: actions/checkout@v4
87
+ - run: npm ci && npm test
88
+
89
+ ---
90
+ # workflow: publish-coverage.yml — runs after ci.yml completes (has secrets)
91
+ on:
92
+ workflow_run:
93
+ workflows: ['CI']
94
+ types: [completed]
95
+ jobs:
96
+ coverage:
97
+ if: github.event.workflow_run.conclusion == 'success'
98
+ runs-on: ubuntu-latest
99
+ steps:
100
+ - name: Publish coverage
101
+ env:
102
+ CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
103
+ run: echo "Publishing coverage for run ${{ github.event.workflow_run.id }}"
104
+ prevention:
105
+ - "Design CI workflows to not require secrets for the build/test steps — secrets should only be needed for publish/deploy"
106
+ - "Check `github.event.pull_request.head.repo.fork` before any step that uses secrets to provide a clear skip message"
107
+ - "Do not use `pull_request_target` as a shortcut to get secrets — it runs untrusted fork code with base repo privileges, creating a severe injection risk"
108
+ - "Use `workflow_run` to chain a privileged follow-up workflow that runs in base repo context after fork CI succeeds"
109
+ docs:
110
+ - url: "https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#understanding-the-risk-of-script-injections"
111
+ label: "GitHub Docs — Security hardening: fork PR and secret access"
112
+ - url: "https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request"
113
+ label: "GitHub Docs — pull_request event: fork limitations"
114
+ - url: "https://securitylab.github.com/research/github-actions-preventing-pwn-requests/"
115
+ label: "GitHub Security Lab — Preventing pwn requests (pull_request_target risks)"
@@ -0,0 +1,93 @@
1
+ id: runner-environment-170
2
+ title: 'windows-latest Migration to Windows Server 2025 Removes MSVC v142 (VS 2019) Toolchain'
3
+ category: runner-environment
4
+ severity: error
5
+ tags:
6
+ - windows
7
+ - msvc
8
+ - cmake
9
+ - msbuild
10
+ - toolchain
11
+ - migration
12
+ patterns:
13
+ - regex: 'MSB8020.*v142.*cannot be found'
14
+ flags: 'i'
15
+ - regex: 'build tools for v142.*Platform Toolset.*v142.*cannot be found'
16
+ flags: 'i'
17
+ - regex: 'CMAKE_GENERATOR_TOOLSET.*v142.*not found'
18
+ flags: 'i'
19
+ error_messages:
20
+ - "MSBUILD : error MSB8020: The build tools for v142 (Platform Toolset = 'v142') cannot be found."
21
+ - "CMake Error: The CMAKE_CXX_COMPILER: cl.exe is not able to compile a simple test program."
22
+ - "error MSB8020: The build tools for v142 (Platform Toolset = 'v142') cannot be found."
23
+ root_cause: |
24
+ Starting November 2024, `windows-latest` was migrated to Windows Server 2025 with
25
+ Visual Studio 2022 17.12 as the default build environment. Windows Server 2025 runner
26
+ images do not include the Visual Studio 2019 build tools (MSVC v142 / toolset 14.2).
27
+
28
+ Projects that explicitly request the VS 2019 toolchain via any of these mechanisms fail:
29
+ - MSBuild `<PlatformToolset>v142</PlatformToolset>` in .vcxproj files
30
+ - CMake `-T v142` flag or `set(CMAKE_GENERATOR_TOOLSET v142)` in CMakeLists.txt
31
+ - MSBuild command-line flag `/p:PlatformToolset=v142`
32
+ - Visual Studio solution files pinned to VS 2019 (toolset version 142)
33
+
34
+ Windows Server 2022 runners (`windows-2022`) continue to offer both VS 2019
35
+ (v142) and VS 2022 (v143) toolchains in parallel. After the `windows-latest`
36
+ migration, workflows that did not pin to `windows-2022` and relied on v142
37
+ break silently on runners already migrated while appearing to work in older
38
+ runner pools.
39
+
40
+ The migration timeline:
41
+ - Nov 2024: windows-latest begins pointing to Windows Server 2025 (partial rollout)
42
+ - Early 2025: Full rollout; all new `windows-latest` queue jobs use WS 2025
43
+
44
+ Reference: https://github.com/actions/runner-images/issues/10751
45
+ fix: |
46
+ Choose one of the following approaches:
47
+
48
+ 1. Upgrade to the v143 (VS 2022) toolchain — recommended for long-term compatibility.
49
+ 2. Pin to `windows-2022` runner if you cannot migrate immediately.
50
+ 3. Install the VS 2019 build tools component manually (slow, increases job time).
51
+ fix_code:
52
+ - language: yaml
53
+ label: "Option A: upgrade toolchain to v143 (VS 2022) in CMakeLists.txt"
54
+ code: |
55
+ # In CMakeLists.txt — remove explicit toolset pinning
56
+ # cmake_minimum_required(VERSION 3.20)
57
+ # project(MyProject)
58
+ # Previously had: set(CMAKE_GENERATOR_TOOLSET "v142")
59
+ # Remove or update to:
60
+ # set(CMAKE_GENERATOR_TOOLSET "v143") # or omit to use default
61
+ - language: yaml
62
+ label: "Option B: pin to windows-2022 to keep v142 support"
63
+ code: |
64
+ jobs:
65
+ build:
66
+ runs-on: windows-2022 # has both v142 and v143 available
67
+ steps:
68
+ - uses: actions/checkout@v4
69
+ - name: Build with CMake
70
+ run: cmake -B build -T v142 && cmake --build build
71
+ - language: yaml
72
+ label: "Option C: install VS 2019 build tools on windows-latest (slow)"
73
+ code: |
74
+ jobs:
75
+ build:
76
+ runs-on: windows-latest
77
+ steps:
78
+ - uses: actions/checkout@v4
79
+ - name: Install VS 2019 Build Tools
80
+ run: |
81
+ choco install visualstudio2019buildtools --package-parameters "--add Microsoft.VisualStudio.Component.VC.v142.x86.x64" -y
82
+ prevention:
83
+ - "Audit all .vcxproj and CMakeLists.txt files for explicit v142 toolset references before migrating to windows-latest"
84
+ - "Pin to `windows-2022` in CI to preserve VS 2019 toolchain availability while planning an upgrade"
85
+ - "Watch https://github.com/actions/runner-images/blob/main/images/windows/Windows2025-Readme.md for current pre-installed toolchain versions"
86
+ - "Use `vswhere` in a pre-build step to detect installed VS components and fail fast with a descriptive error"
87
+ docs:
88
+ - url: "https://github.com/actions/runner-images/issues/10751"
89
+ label: "runner-images #10751 — windows-latest migration to Windows Server 2025"
90
+ - url: "https://github.com/actions/runner-images/blob/main/images/windows/Windows2025-Readme.md"
91
+ label: "Windows Server 2025 runner image README — pre-installed software"
92
+ - url: "https://learn.microsoft.com/en-us/cpp/build/cmake-presets-vs?view=msvc-170"
93
+ label: "Microsoft Docs — CMake toolset configuration"
@@ -0,0 +1,94 @@
1
+ id: silent-failures-091
2
+ title: '`github.ref_name` Returns Ephemeral Merge Ref (`123/merge`) on `pull_request` Trigger, Not Branch Name'
3
+ category: silent-failures
4
+ severity: silent-failure
5
+ tags:
6
+ - github-context
7
+ - ref-name
8
+ - pull-request
9
+ - docker
10
+ - branch-name
11
+ - deployment
12
+ patterns:
13
+ - regex: '\d+/merge'
14
+ flags: 'i'
15
+ error_messages:
16
+ - "invalid reference format"
17
+ - "invalid tag format"
18
+ root_cause: |
19
+ When a workflow is triggered by a `pull_request` event, GitHub creates an ephemeral
20
+ merge commit that merges the PR head into the base branch. The context variables for
21
+ this run reflect the merge ref, not the source branch:
22
+
23
+ - `github.ref` = `refs/pull/123/merge`
24
+ - `github.ref_name` = `123/merge`
25
+ - `github.sha` = SHA of the ephemeral merge commit
26
+ - `github.head_ref` = `feature-branch-name` (the actual PR branch)
27
+ - `github.base_ref` = `main` (the target branch)
28
+
29
+ Using `github.ref_name` in contexts that expect a branch name silently produces
30
+ the merge ref string `123/merge` instead:
31
+
32
+ - **Docker image tags**: `docker.io/myapp:123/merge` — Docker rejects the forward slash
33
+ as an invalid tag character (`invalid reference format` error), OR worse, interprets
34
+ `123` as a registry name.
35
+ - **Deployment environment names**: The environment is created as `123/merge` rather
36
+ than the branch name, causing routing rules to miss the deployment.
37
+ - **Branch-based conditional logic**: `if: github.ref_name == 'feature-foo'` always
38
+ evaluates to false on pull_request events.
39
+ - **Artifact naming**: Artifacts uploaded with the ref_name contain forward slashes,
40
+ causing path traversal issues on some download handlers.
41
+
42
+ `github.head_ref` is only populated for `pull_request` and `pull_request_target`
43
+ events, making branch detection logic that works on push but silently fails on PR
44
+ events harder to diagnose.
45
+ fix: |
46
+ Use the correct context variable for each event type:
47
+
48
+ - For the PR's source branch name: `github.head_ref` (only set on pull_request events)
49
+ - For push events' branch name: `github.ref_name`
50
+ - For a branch name that works across both event types, use a conditional expression.
51
+ fix_code:
52
+ - language: yaml
53
+ label: "Unified branch name across push and pull_request events"
54
+ code: |
55
+ jobs:
56
+ build:
57
+ runs-on: ubuntu-latest
58
+ steps:
59
+ - name: Determine branch name
60
+ id: branch
61
+ run: |
62
+ if [ "${{ github.event_name }}" = "pull_request" ]; then
63
+ echo "name=${{ github.head_ref }}" >> "$GITHUB_OUTPUT"
64
+ else
65
+ echo "name=${{ github.ref_name }}" >> "$GITHUB_OUTPUT"
66
+ fi
67
+
68
+ - name: Build and tag Docker image
69
+ run: |
70
+ # Sanitize slashes for use in image tags
71
+ TAG=$(echo "${{ steps.branch.outputs.name }}" | tr '/' '-')
72
+ docker build -t "myapp:${TAG}" .
73
+ - language: yaml
74
+ label: "Expression-based branch name (no shell step needed)"
75
+ code: |
76
+ env:
77
+ BRANCH_NAME: ${{ github.event_name == 'pull_request' && github.head_ref || github.ref_name }}
78
+
79
+ jobs:
80
+ deploy:
81
+ runs-on: ubuntu-latest
82
+ environment: ${{ github.event_name == 'pull_request' && github.head_ref || github.ref_name }}
83
+ steps:
84
+ - run: echo "Deploying branch ${{ env.BRANCH_NAME }}"
85
+ prevention:
86
+ - "Never use `github.ref_name` directly in Docker image tags — always sanitize forward slashes with `tr '/' '-'` or similar"
87
+ - "Test branch-detection expressions with both `push` and `pull_request` triggers in a dry-run workflow"
88
+ - "Use `github.head_ref` for PR branch name and `github.ref_name` for push branch name — they are NOT interchangeable"
89
+ - "Add an explicit check: if `github.ref_name` contains a `/`, the workflow is running on a pull_request or merge ref, not a regular branch"
90
+ docs:
91
+ - url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/accessing-contextual-information-about-workflow-runs#github-context"
92
+ label: "GitHub Docs — github context reference"
93
+ - url: "https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request"
94
+ label: "GitHub Docs — pull_request event"
@@ -0,0 +1,134 @@
1
+ id: triggers-067
2
+ title: 'workflow_run types:[completed] fires prematurely with conclusion:null before referenced workflow finishes'
3
+ category: triggers
4
+ severity: error
5
+ tags:
6
+ - workflow_run
7
+ - conclusion
8
+ - null
9
+ - premature-trigger
10
+ - race-condition
11
+ - completed
12
+ patterns:
13
+ - regex: 'workflow_run\.conclusion.*null'
14
+ flags: 'i'
15
+ - regex: 'github\.event\.workflow_run\.conclusion'
16
+ flags: 'i'
17
+ - regex: 'conclusion.*randomly.*fail'
18
+ flags: 'i'
19
+ error_messages:
20
+ - "github.event.workflow_run.conclusion returned null — job skipped unexpectedly"
21
+ - "Unable to extend GITHUB_TOKEN expiration time due to: GITHUB_TOKEN has expired."
22
+ root_cause: |
23
+ The `workflow_run` event with `types: [completed]` is documented to fire only after the
24
+ referenced workflow finishes running. However, a known race condition in GitHub Actions'
25
+ event delivery (tracked in actions/runner#4035) causes the event to fire a second time
26
+ BEFORE the workflow has fully completed — specifically before GitHub has written the final
27
+ `conclusion` value to the workflow run record.
28
+
29
+ When this premature trigger fires, `github.event.workflow_run.conclusion` evaluates to
30
+ `null` (or an empty string `""`). Any job guarded with:
31
+
32
+ if: github.event.workflow_run.conclusion == 'success'
33
+
34
+ will evaluate to `false` and be skipped, producing a confusing pattern where the
35
+ downstream workflow runs twice — once skipped, once (correctly) executed.
36
+
37
+ GitHub Support confirmed this as a platform-side delay: the `conclusion` field remains
38
+ `null` while GitHub's backend is still updating the workflow run record. The event
39
+ is dispatched before the record is fully consistent.
40
+
41
+ This affects all workflows that use `on.workflow_run` with `types: [completed]` and
42
+ check `github.event.workflow_run.conclusion` to gate job execution.
43
+ fix: |
44
+ Two mitigations are available:
45
+
46
+ 1. **Guard with `conclusion != ''`** — Add a condition that explicitly rejects null/empty
47
+ `conclusion` values before checking for `'success'`:
48
+
49
+ if: >-
50
+ github.event.workflow_run.conclusion != '' &&
51
+ github.event.workflow_run.conclusion == 'success'
52
+
53
+ 2. **Re-query via REST API** — Instead of trusting `github.event.workflow_run.conclusion`,
54
+ use the Actions REST API to fetch the current workflow run conclusion at step runtime:
55
+
56
+ gh api /repos/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }} \
57
+ --jq '.conclusion'
58
+
59
+ This always returns the up-to-date value, bypassing the event payload race condition.
60
+
61
+ Note: adding a `sleep` between trigger and conclusion check is NOT a reliable fix, as
62
+ the delay between trigger and backend consistency is variable and can exceed seconds.
63
+ fix_code:
64
+ - language: yaml
65
+ label: 'Problem: conclusion check fails on premature null trigger'
66
+ code: |
67
+ on:
68
+ workflow_run:
69
+ workflows: ['CI Build']
70
+ types: [completed]
71
+
72
+ jobs:
73
+ deploy:
74
+ # This randomly evaluates to false when conclusion is null
75
+ if: github.event.workflow_run.conclusion == 'success'
76
+ runs-on: ubuntu-latest
77
+ steps:
78
+ - run: echo "Deploying..."
79
+ - language: yaml
80
+ label: 'Fix: guard against null conclusion before equality check'
81
+ code: |
82
+ on:
83
+ workflow_run:
84
+ workflows: ['CI Build']
85
+ types: [completed]
86
+
87
+ jobs:
88
+ deploy:
89
+ # Explicitly reject null/empty conclusion to avoid premature-trigger skips
90
+ if: >-
91
+ github.event.workflow_run.conclusion != '' &&
92
+ github.event.workflow_run.conclusion == 'success'
93
+ runs-on: ubuntu-latest
94
+ steps:
95
+ - run: echo "Deploying..."
96
+ - language: yaml
97
+ label: 'Fix: re-query conclusion via REST API for reliable value'
98
+ code: |
99
+ on:
100
+ workflow_run:
101
+ workflows: ['CI Build']
102
+ types: [completed]
103
+
104
+ jobs:
105
+ deploy:
106
+ runs-on: ubuntu-latest
107
+ steps:
108
+ - name: Check conclusion via API
109
+ id: check
110
+ env:
111
+ GH_TOKEN: ${{ github.token }}
112
+ run: |
113
+ conclusion=$(gh api \
114
+ /repos/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }} \
115
+ --jq '.conclusion')
116
+ echo "conclusion=$conclusion" >> "$GITHUB_OUTPUT"
117
+
118
+ - name: Deploy
119
+ if: steps.check.outputs.conclusion == 'success'
120
+ run: echo "Deploying..."
121
+ prevention:
122
+ - "Never rely solely on `github.event.workflow_run.conclusion == 'success'` without a null guard."
123
+ - "Add `github.event.workflow_run.conclusion != ''` as an explicit first condition to reject premature triggers."
124
+ - "If downstream jobs must be fully reliable, re-query conclusion via the REST API rather than reading from the event payload."
125
+ - "Monitor the Actions tab for unexpectedly skipped `workflow_run` triggered runs — they indicate premature triggers."
126
+ docs:
127
+ - url: 'https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#workflow_run'
128
+ label: 'GitHub Docs: workflow_run event'
129
+ - url: 'https://github.com/actions/runner/issues/4035'
130
+ label: 'actions/runner#4035: workflow_run triggers before referenced workflow completes'
131
+ - url: 'https://stackoverflow.com/questions/73107307/any-workaround-for-github-actions-workflow-run-conclusion-randomly-failing'
132
+ label: 'Stack Overflow: workflow_run.conclusion randomly failing'
133
+ - url: 'https://github.com/orgs/community/discussions/58929'
134
+ label: 'GitHub Community #58929: github.event.workflow_run.conclusion is always null'
@@ -0,0 +1,119 @@
1
+ id: yaml-syntax-064
2
+ title: 'strategy.matrix.include/exclude entry value specified as array causes "A sequence was not expected"'
3
+ category: yaml-syntax
4
+ severity: error
5
+ tags:
6
+ - matrix
7
+ - include
8
+ - exclude
9
+ - array-value
10
+ - sequence
11
+ - validation-error
12
+ - strategy
13
+ patterns:
14
+ - regex: 'A sequence was not expected'
15
+ flags: 'i'
16
+ - regex: 'matrix\.(include|exclude).*\[.*\]'
17
+ flags: 'i'
18
+ - regex: 'strategy.*matrix.*include.*sequence'
19
+ flags: 'i'
20
+ error_messages:
21
+ - "Error: The template is not valid. .github/workflows/workflow.yml (Line: 12, Col: 18): A sequence was not expected"
22
+ - "A sequence was not expected"
23
+ root_cause: |
24
+ In a `strategy.matrix`, the top-level matrix dimensions accept arrays of scalars:
25
+
26
+ php: ['8.2', '8.3', '8.4'] # valid — array of scalars
27
+
28
+ However, inside `include:` and `exclude:` entries, ALL values must be scalars
29
+ (string, number, boolean). Arrays are not allowed:
30
+
31
+ include:
32
+ - os: ubuntu-latest
33
+ php: ['8.2'] # INVALID — array not allowed in include/exclude entries
34
+
35
+ This is a common mistake when a developer copies the variable name from the main
36
+ matrix definition (where it IS an array) and pastes it into an `include:` or
37
+ `exclude:` entry without unwrapping it.
38
+
39
+ GitHub Actions' expression evaluator validates the template before execution and
40
+ throws an immediate hard failure:
41
+
42
+ Error: The template is not valid. .github/workflows/X.yml (Line: N, Col: M):
43
+ A sequence was not expected
44
+
45
+ The error points to the line where the array value starts (the `[` character),
46
+ which can be confusing because arrays are valid YAML and valid in other matrix
47
+ contexts. The fix is simply to remove the brackets and use a scalar value.
48
+
49
+ Tracked in rhysd/actionlint#630 (actionlint static analysis issue requesting
50
+ detection of this pattern).
51
+ fix: |
52
+ Replace any array-valued entries inside `include:` or `exclude:` with scalar values.
53
+ Each `include:`/`exclude:` entry is a single-combination filter — it selects or adds
54
+ one specific combination, so the value must be a scalar that matches exactly one item.
55
+
56
+ If you need to include multiple values for a key, write separate `include:` entries,
57
+ one per value.
58
+ fix_code:
59
+ - language: yaml
60
+ label: 'Problem: array value inside include entry — triggers "A sequence was not expected"'
61
+ code: |
62
+ strategy:
63
+ matrix:
64
+ os: [ubuntu-latest, macos-latest]
65
+ php: ['8.3', '8.4', '8.5']
66
+
67
+ include:
68
+ # ERROR: php value is an array — not allowed inside include entries
69
+ - os: ubuntu-latest
70
+ php: ['8.2'] # ← "A sequence was not expected" on this line
71
+
72
+ exclude:
73
+ # ERROR: os value is an array — not allowed inside exclude entries
74
+ - os: [macos-latest]
75
+ php: '8.3' # ← "A sequence was not expected"
76
+ - language: yaml
77
+ label: 'Fix: use scalar values inside include/exclude entries'
78
+ code: |
79
+ strategy:
80
+ matrix:
81
+ os: [ubuntu-latest, macos-latest]
82
+ php: ['8.3', '8.4', '8.5']
83
+
84
+ include:
85
+ # CORRECT: scalar value — adds ubuntu-latest × 8.2 as an extra job
86
+ - os: ubuntu-latest
87
+ php: '8.2' # ← scalar, not array
88
+
89
+ exclude:
90
+ # CORRECT: scalar value — excludes macos-latest × 8.3 combination
91
+ - os: macos-latest
92
+ php: '8.3' # ← scalar, not array
93
+ - language: yaml
94
+ label: 'Multiple include entries for multiple specific combinations'
95
+ code: |
96
+ strategy:
97
+ matrix:
98
+ os: [ubuntu-latest, macos-latest]
99
+ node: [18, 20]
100
+
101
+ include:
102
+ # To include multiple specific combinations, write separate entries:
103
+ - os: ubuntu-latest
104
+ node: 22 # one entry per extra combination
105
+ - os: ubuntu-latest
106
+ node: 23 # another entry for a different combination
107
+ # NOT: node: [22, 23] ← this would fail with "A sequence was not expected"
108
+ prevention:
109
+ - "Values inside `include:` and `exclude:` entries must be scalars — never use array syntax `[...]` there."
110
+ - "When copying matrix variable names from the top-level dimensions to include/exclude entries, remove the brackets."
111
+ - "Use actionlint (github.com/rhysd/actionlint) to statically validate your workflow files before pushing."
112
+ - "If you need multiple combinations, write multiple separate `include:` entries instead of one entry with an array value."
113
+ docs:
114
+ - url: 'https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/running-variations-of-jobs-in-a-workflow#expanding-or-adding-matrix-configurations'
115
+ label: 'GitHub Docs: Expanding or adding matrix configurations'
116
+ - url: 'https://github.com/rhysd/actionlint/issues/630'
117
+ label: 'rhysd/actionlint#630: Detect array values in matrix include/exclude entries'
118
+ - url: 'https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#jobsjob_idstrategymatrixinclude'
119
+ label: 'GitHub Docs: jobs.<job_id>.strategy.matrix.include syntax reference'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@htekdev/actions-debugger",
3
- "version": "1.0.100",
3
+ "version": "1.0.101",
4
4
  "description": "65+ real GitHub Actions errors, queryable by agents. CLI + MCP server + Copilot skills + error database.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",