@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.
- package/errors/caching-artifacts/artifact-download-no-artifacts-found.yml +118 -0
- package/errors/known-unsolved/workflow-rerun-limit.yml +101 -0
- package/errors/permissions-auth/gcp-oidc-workload-identity-misconfigured.yml +130 -0
- package/errors/runner-environment/macos-14-sonoma-eol.yml +89 -0
- package/errors/runner-environment/macos-latest-to-macos-26.yml +127 -0
- package/errors/runner-environment/node20-to-node24-migration.yml +118 -0
- package/errors/runner-environment/powershell-74-to-76-upgrade.yml +112 -0
- package/errors/runner-environment/service-container-unhealthy.yml +126 -0
- package/errors/runner-environment/windows-latest-vs2026-migration.yml +131 -0
- package/errors/silent-failures/hashfiles-empty-string-cache-collision.yml +96 -0
- package/errors/silent-failures/sparse-checkout-sticky-cone-mode.yml +120 -0
- package/errors/triggers/environment-protection-rules-silent-block.yml +105 -0
- package/errors/yaml-syntax/env-context-unavailable-job-level.yml +109 -0
- package/errors/yaml-syntax/reusable-workflow-missing-output-declaration.yml +140 -0
- package/package.json +1 -1
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
id: runner-environment-016
|
|
2
|
+
title: "Node 20 → Node 24 Forced Migration Breaks Actions and macOS 13 Runners"
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- node
|
|
7
|
+
- node24
|
|
8
|
+
- deprecation
|
|
9
|
+
- macos
|
|
10
|
+
- arm32
|
|
11
|
+
- runtime-migration
|
|
12
|
+
patterns:
|
|
13
|
+
- regex: "Node\\.?20 actions are deprecated"
|
|
14
|
+
flags: "i"
|
|
15
|
+
- regex: "Please update the following actions to use Node\\.?24"
|
|
16
|
+
flags: "i"
|
|
17
|
+
- regex: "node20 is deprecated"
|
|
18
|
+
flags: "i"
|
|
19
|
+
- regex: "macOS 13.*not supported.*Node 24"
|
|
20
|
+
flags: "i"
|
|
21
|
+
- regex: "ARM32.*no longer supported"
|
|
22
|
+
flags: "i"
|
|
23
|
+
error_messages:
|
|
24
|
+
- "Node.js 20 actions are deprecated. Please update the following actions to use Node.js 24."
|
|
25
|
+
- "node20 is deprecated and will be disabled in a future runner release."
|
|
26
|
+
- "Error: This action requires Node.js 24 or higher. Current version: 20."
|
|
27
|
+
root_cause: |
|
|
28
|
+
GitHub announced deprecation of Node 20 on Actions runners on September 19, 2025
|
|
29
|
+
(editor updated May 19, 2026: migration date confirmed June 16, 2026). Starting
|
|
30
|
+
June 16, 2026, all GitHub-hosted runners default to Node 24.
|
|
31
|
+
|
|
32
|
+
Three distinct breakage scenarios exist:
|
|
33
|
+
|
|
34
|
+
1. **Marketplace actions using `runs.using: 'node20'`** — any third-party or custom
|
|
35
|
+
action that declares `runs.using: node20` in its `action.yml` will emit deprecation
|
|
36
|
+
warnings and eventually fail when GitHub removes Node 20 from runners later in 2026.
|
|
37
|
+
|
|
38
|
+
2. **macOS 13 (and older) runners are incompatible with Node 24** — Node 24 dropped
|
|
39
|
+
support for macOS 13.4 and lower. Workflows specifying `runs-on: macos-13` (or older
|
|
40
|
+
images) fail at the runner startup phase or produce unexpected errors from the
|
|
41
|
+
Node-based runner bootstrapper.
|
|
42
|
+
|
|
43
|
+
3. **ARM32 self-hosted runners** — Node 24 has no official ARM32 support. Self-hosted
|
|
44
|
+
runners on ARM32 hardware silently lose the ability to execute Node-based actions
|
|
45
|
+
after the Node 20 removal milestone.
|
|
46
|
+
fix: |
|
|
47
|
+
**For action authors:** Update `action.yml` to declare `runs.using: 'node24'` and
|
|
48
|
+
test locally with Node 24. Publish a new release so downstream consumers pick it up.
|
|
49
|
+
|
|
50
|
+
**For workflow authors:**
|
|
51
|
+
- Upgrade all `uses:` pins to the latest major version that ships with Node 24 support
|
|
52
|
+
(e.g. `actions/checkout@v4 → @v4` already Node-24-ready; `actions/setup-node@v4`
|
|
53
|
+
already Node-24-ready).
|
|
54
|
+
- Replace `runs-on: macos-13` with `runs-on: macos-latest` or `macos-14+`.
|
|
55
|
+
- For ARM32 self-hosted runners: migrate to ARM64 hardware or use container-based
|
|
56
|
+
execution that bundles its own Node runtime.
|
|
57
|
+
|
|
58
|
+
**Temporary escape hatch (not for production long-term):**
|
|
59
|
+
Set `ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION=true` in the workflow `env` block to
|
|
60
|
+
continue using Node 20 until GitHub removes it from runners later in 2026.
|
|
61
|
+
fix_code:
|
|
62
|
+
- language: yaml
|
|
63
|
+
label: "Upgrade pinned action versions to Node 24-compatible releases"
|
|
64
|
+
code: |
|
|
65
|
+
steps:
|
|
66
|
+
# Pin to latest major — all official actions already ship Node 24 builds
|
|
67
|
+
- uses: actions/checkout@v4
|
|
68
|
+
- uses: actions/setup-node@v4
|
|
69
|
+
with:
|
|
70
|
+
node-version: '20'
|
|
71
|
+
- uses: actions/upload-artifact@v4
|
|
72
|
+
with:
|
|
73
|
+
name: dist
|
|
74
|
+
path: dist/
|
|
75
|
+
- language: yaml
|
|
76
|
+
label: "Migrate macOS runner from macos-13 to macos-latest"
|
|
77
|
+
code: |
|
|
78
|
+
jobs:
|
|
79
|
+
build:
|
|
80
|
+
# macos-13 is incompatible with Node 24 — use macos-latest (14+)
|
|
81
|
+
runs-on: macos-latest
|
|
82
|
+
steps:
|
|
83
|
+
- uses: actions/checkout@v4
|
|
84
|
+
- language: yaml
|
|
85
|
+
label: "Temporary escape hatch — keep Node 20 until explicit removal"
|
|
86
|
+
code: |
|
|
87
|
+
jobs:
|
|
88
|
+
build:
|
|
89
|
+
runs-on: ubuntu-latest
|
|
90
|
+
env:
|
|
91
|
+
# WARNING: temporary only — Node 20 will be fully removed later in 2026
|
|
92
|
+
ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: 'true'
|
|
93
|
+
steps:
|
|
94
|
+
- uses: actions/checkout@v4
|
|
95
|
+
- language: yaml
|
|
96
|
+
label: "Test Node 24 compatibility before the mandatory cutover"
|
|
97
|
+
code: |
|
|
98
|
+
jobs:
|
|
99
|
+
build:
|
|
100
|
+
runs-on: ubuntu-latest
|
|
101
|
+
env:
|
|
102
|
+
# Force Node 24 to test compatibility ahead of the June 16 cutover
|
|
103
|
+
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: 'true'
|
|
104
|
+
steps:
|
|
105
|
+
- uses: actions/checkout@v4
|
|
106
|
+
prevention:
|
|
107
|
+
- "Subscribe to GitHub changelog https://github.blog/changelog/label/actions/ for deprecation notices."
|
|
108
|
+
- "Run `FORCE_JAVASCRIPT_ACTIONS_TO_NODE24=true` in CI to catch Node 24 incompatibilities early."
|
|
109
|
+
- "Avoid pinning to old major versions of `actions/*` — use floating major tags (e.g. @v4)."
|
|
110
|
+
- "Audit custom/internal actions for `runs.using: node20` declarations before the June 16, 2026 migration date."
|
|
111
|
+
- "Migrate macOS CI to macos-14 or macos-latest to ensure Node 24 compatibility."
|
|
112
|
+
docs:
|
|
113
|
+
- url: "https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/"
|
|
114
|
+
label: "GitHub Changelog: Deprecation of Node 20 on GitHub Actions runners"
|
|
115
|
+
- url: "https://docs.github.com/en/actions/creating-actions/metadata-syntax-for-github-actions#runs-for-javascript-actions"
|
|
116
|
+
label: "Metadata syntax: runs.using for JavaScript actions"
|
|
117
|
+
- url: "https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources"
|
|
118
|
+
label: "Supported runners and hardware resources"
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
id: runner-environment-019
|
|
2
|
+
title: "PowerShell 7.4 → 7.6 LTS Upgrade Breaks pwsh Scripts"
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: warning
|
|
5
|
+
tags:
|
|
6
|
+
- powershell
|
|
7
|
+
- pwsh
|
|
8
|
+
- runner-image
|
|
9
|
+
- breaking-change
|
|
10
|
+
- windows
|
|
11
|
+
- linux
|
|
12
|
+
patterns:
|
|
13
|
+
- regex: "The term 'ThreadJob\\\\\\\\Start-ThreadJob' is not recognized"
|
|
14
|
+
flags: "i"
|
|
15
|
+
- regex: "Cannot bind parameter.*ChildPath.*expected.*String.*got.*Array"
|
|
16
|
+
flags: "i"
|
|
17
|
+
- regex: "WildcardPattern.*backtick|escape.*pattern.*unexpected"
|
|
18
|
+
flags: "i"
|
|
19
|
+
- regex: "New-EventLog.*source.*trailing|event source.*not found"
|
|
20
|
+
flags: "i"
|
|
21
|
+
error_messages:
|
|
22
|
+
- "The term 'ThreadJob\\Start-ThreadJob' is not recognized as a name of a cmdlet, function, script file, or executable program."
|
|
23
|
+
- "Cannot bind parameter 'ChildPath'. Cannot convert the 'System.Object[]' value of type 'System.Object[]' to type 'System.String'."
|
|
24
|
+
- "Start-ThreadJob : The term 'ThreadJob\\Start-ThreadJob' is not recognized"
|
|
25
|
+
root_cause: |
|
|
26
|
+
GitHub Actions upgraded PowerShell from 7.4.x to 7.6 LTS on all runner images beginning
|
|
27
|
+
June 8, 2026 (completing June 15, 2026). This affects every runner OS: ubuntu-22.04,
|
|
28
|
+
ubuntu-24.04, ubuntu-slim, macos-14/15/26, windows-2022/2025/2025-vs2026.
|
|
29
|
+
|
|
30
|
+
PowerShell 7.6 is built on .NET 10 (7.4 was on .NET 8). The documented breaking changes are:
|
|
31
|
+
|
|
32
|
+
1. **ThreadJob module renamed**: `ThreadJob` module is now `Microsoft.PowerShell.ThreadJob`.
|
|
33
|
+
Scripts calling `ThreadJob\Start-ThreadJob` with the old module-qualified name will throw
|
|
34
|
+
a "not recognized" error. The cmdlet itself (`Start-ThreadJob`) still works without prefix.
|
|
35
|
+
|
|
36
|
+
2. **`Join-Path -ChildPath` now accepts `string[]`**: Parameter binding changed from `string`
|
|
37
|
+
to `string[]`. Existing code that passes multiple -ChildPath args may see binding errors
|
|
38
|
+
depending on how arguments were constructed.
|
|
39
|
+
|
|
40
|
+
3. **`WildcardPattern.Escape` now correctly escapes lone backticks**: Scripts that relied on
|
|
41
|
+
the previous (incorrect) behavior of backtick handling in wildcard patterns may produce
|
|
42
|
+
different results.
|
|
43
|
+
|
|
44
|
+
4. **Event source name trailing space removed**: New-EventLog / Write-EventLog source names
|
|
45
|
+
no longer have a trailing space. Scripts that matched exact event source names including
|
|
46
|
+
the trailing space (e.g., `"MySource "`) will fail to match.
|
|
47
|
+
|
|
48
|
+
5. **.NET 10 runtime**: Any `pwsh` script using .NET types or reflection that was tested
|
|
49
|
+
against .NET 8 behavior may see subtle differences.
|
|
50
|
+
fix: |
|
|
51
|
+
**ThreadJob module name** — the most common breaking change:
|
|
52
|
+
Replace `ThreadJob\Start-ThreadJob` with `Microsoft.PowerShell.ThreadJob\Start-ThreadJob`,
|
|
53
|
+
or just call `Start-ThreadJob` without the module qualifier.
|
|
54
|
+
|
|
55
|
+
**Event source name** — if you match exact source names:
|
|
56
|
+
Trim any trailing spaces from source name comparisons.
|
|
57
|
+
|
|
58
|
+
**Pin PowerShell version** if you need time to migrate (not recommended long-term):
|
|
59
|
+
Install a specific pwsh version in your workflow before running scripts.
|
|
60
|
+
|
|
61
|
+
**Test locally**: Install PowerShell 7.6 (`winget install Microsoft.PowerShell`) and run
|
|
62
|
+
your scripts to catch any remaining issues before they surface in CI.
|
|
63
|
+
fix_code:
|
|
64
|
+
- language: yaml
|
|
65
|
+
label: "Fix ThreadJob module-qualified name"
|
|
66
|
+
code: |
|
|
67
|
+
# In your PowerShell script — change this:
|
|
68
|
+
# ThreadJob\Start-ThreadJob -ScriptBlock { ... }
|
|
69
|
+
# To either:
|
|
70
|
+
# Start-ThreadJob -ScriptBlock { ... } # simplest fix
|
|
71
|
+
# Microsoft.PowerShell.ThreadJob\Start-ThreadJob -ScriptBlock { ... } # fully qualified
|
|
72
|
+
- language: yaml
|
|
73
|
+
label: "Pin PowerShell version as a temporary workaround"
|
|
74
|
+
code: |
|
|
75
|
+
jobs:
|
|
76
|
+
build:
|
|
77
|
+
runs-on: ubuntu-latest
|
|
78
|
+
steps:
|
|
79
|
+
- uses: actions/checkout@v4
|
|
80
|
+
|
|
81
|
+
# Pin pwsh to 7.4.x temporarily while migrating
|
|
82
|
+
- name: Install PowerShell 7.4
|
|
83
|
+
run: |
|
|
84
|
+
wget -q "https://github.com/PowerShell/PowerShell/releases/download/v7.4.10/powershell_7.4.10-1.deb_amd64.deb"
|
|
85
|
+
sudo dpkg -i powershell_7.4.10-1.deb_amd64.deb
|
|
86
|
+
|
|
87
|
+
- name: Run PowerShell script
|
|
88
|
+
shell: pwsh
|
|
89
|
+
run: ./scripts/build.ps1
|
|
90
|
+
- language: yaml
|
|
91
|
+
label: "Fix event source name trailing-space match"
|
|
92
|
+
code: |
|
|
93
|
+
# Before (broken on 7.6):
|
|
94
|
+
# if ($event.Source -eq "MyApp ") { ... }
|
|
95
|
+
#
|
|
96
|
+
# After (works on 7.4 and 7.6):
|
|
97
|
+
# if ($event.Source.Trim() -eq "MyApp") { ... }
|
|
98
|
+
prevention:
|
|
99
|
+
- "Subscribe to actions/runner-images announcements for PowerShell upgrade notices well before they ship."
|
|
100
|
+
- "Always use unqualified cmdlet names (`Start-ThreadJob`) rather than module-qualified names (`ThreadJob\\Start-ThreadJob`) to avoid module-rename breakage."
|
|
101
|
+
- "Run your PowerShell scripts through PSScriptAnalyzer with the latest rule set after any PS version upgrade."
|
|
102
|
+
- "Test pwsh workflows in a matrix with the previous and new PS version during runner image transition periods."
|
|
103
|
+
docs:
|
|
104
|
+
- url: "https://github.com/actions/runner-images/issues/14150"
|
|
105
|
+
label: "GitHub Announcement: PowerShell 7.4 → 7.6 upgrade on all runner images"
|
|
106
|
+
- url: "https://learn.microsoft.com/en-us/powershell/scripting/whats-new/what-s-new-in-powershell-76"
|
|
107
|
+
label: "PowerShell 7.6 release notes and breaking changes"
|
|
108
|
+
- url: "https://learn.microsoft.com/en-us/powershell/scripting/install/powershell-support-lifecycle"
|
|
109
|
+
label: "PowerShell support lifecycle"
|
|
110
|
+
source:
|
|
111
|
+
article: "https://htek.dev/articles/github-actions-debugging-guide"
|
|
112
|
+
section: "Runner image tool version changes"
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
id: runner-environment-021
|
|
2
|
+
title: "Service Container Marked Unhealthy — Health Check Timeout"
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- service-container
|
|
7
|
+
- healthcheck
|
|
8
|
+
- docker
|
|
9
|
+
- timeout
|
|
10
|
+
- postgres
|
|
11
|
+
- redis
|
|
12
|
+
- rabbitmq
|
|
13
|
+
patterns:
|
|
14
|
+
- regex: "service is unhealthy"
|
|
15
|
+
flags: "i"
|
|
16
|
+
- regex: "Failed to initialize.*service is unhealthy"
|
|
17
|
+
flags: "i"
|
|
18
|
+
- regex: "##\\[error\\]Failed to initialize.*service"
|
|
19
|
+
flags: "i"
|
|
20
|
+
- regex: "container_id.*unhealthy"
|
|
21
|
+
flags: "i"
|
|
22
|
+
error_messages:
|
|
23
|
+
- "##[error]Failed to initialize, rabbitmq service is unhealthy."
|
|
24
|
+
- "##[error]Failed to initialize, postgres service is unhealthy."
|
|
25
|
+
- "##[error]Failed to initialize, redis service is unhealthy."
|
|
26
|
+
- "unhealthy"
|
|
27
|
+
- "service is starting, waiting 29 seconds before checking again."
|
|
28
|
+
root_cause: |
|
|
29
|
+
GitHub Actions checks the Docker HEALTHCHECK status of service containers
|
|
30
|
+
before allowing dependent job steps to run. If the container does not
|
|
31
|
+
transition to `healthy` within the runner's fixed retry window, the job
|
|
32
|
+
fails with "service is unhealthy".
|
|
33
|
+
|
|
34
|
+
This commonly occurs because:
|
|
35
|
+
1. **No options specified** — Docker uses the image's built-in HEALTHCHECK,
|
|
36
|
+
which may be missing, too aggressive, or unsuitable for the CI environment.
|
|
37
|
+
2. **Startup time** — services like PostgreSQL, RabbitMQ, or Elasticsearch
|
|
38
|
+
take longer to initialize on GitHub-hosted runners than on local machines,
|
|
39
|
+
and the default health-check interval/retries expire before they're ready.
|
|
40
|
+
3. **Wrong health-check command** — a network ping health check may fail if
|
|
41
|
+
the service port isn't yet bound even though the process is running.
|
|
42
|
+
4. **Missing `--health-start-period`** — without a start period, Docker counts
|
|
43
|
+
health-check failures from container start, before the service has had time
|
|
44
|
+
to initialize.
|
|
45
|
+
|
|
46
|
+
Documented in actions/example-services issue #3.
|
|
47
|
+
fix: |
|
|
48
|
+
Add `options:` to the service container definition with explicit health-check
|
|
49
|
+
parameters suited to the service and GitHub-hosted runner environment:
|
|
50
|
+
|
|
51
|
+
- `--health-cmd`: Use a service-native health check command, not a TCP probe.
|
|
52
|
+
Examples:
|
|
53
|
+
PostgreSQL: `pg_isready -U postgres`
|
|
54
|
+
Redis: `redis-cli ping`
|
|
55
|
+
MySQL: `mysqladmin ping -h localhost`
|
|
56
|
+
RabbitMQ: `rabbitmqctl node_health_check`
|
|
57
|
+
|
|
58
|
+
- `--health-interval 10s`: Check every 10 seconds
|
|
59
|
+
- `--health-timeout 5s`: Allow up to 5 seconds per check
|
|
60
|
+
- `--health-retries 5`: Retry up to 5 times before marking unhealthy
|
|
61
|
+
- `--health-start-period 30s`: Give 30 seconds before counting failures
|
|
62
|
+
|
|
63
|
+
If the image lacks a health check and the options approach is insufficient,
|
|
64
|
+
add an explicit wait step after job start using the service label name to
|
|
65
|
+
poll readiness with a loop.
|
|
66
|
+
fix_code:
|
|
67
|
+
- language: yaml
|
|
68
|
+
label: "PostgreSQL service container with proper health check"
|
|
69
|
+
code: |
|
|
70
|
+
jobs:
|
|
71
|
+
test:
|
|
72
|
+
runs-on: ubuntu-latest
|
|
73
|
+
services:
|
|
74
|
+
postgres:
|
|
75
|
+
image: postgres:16
|
|
76
|
+
env:
|
|
77
|
+
POSTGRES_PASSWORD: postgres
|
|
78
|
+
POSTGRES_DB: testdb
|
|
79
|
+
ports:
|
|
80
|
+
- 5432:5432
|
|
81
|
+
options: >-
|
|
82
|
+
--health-cmd "pg_isready -U postgres"
|
|
83
|
+
--health-interval 10s
|
|
84
|
+
--health-timeout 5s
|
|
85
|
+
--health-retries 5
|
|
86
|
+
--health-start-period 30s
|
|
87
|
+
steps:
|
|
88
|
+
- run: psql postgresql://postgres:postgres@localhost:5432/testdb -c "SELECT 1"
|
|
89
|
+
- language: yaml
|
|
90
|
+
label: "Redis service container with proper health check"
|
|
91
|
+
code: |
|
|
92
|
+
services:
|
|
93
|
+
redis:
|
|
94
|
+
image: redis:7
|
|
95
|
+
ports:
|
|
96
|
+
- 6379:6379
|
|
97
|
+
options: >-
|
|
98
|
+
--health-cmd "redis-cli ping"
|
|
99
|
+
--health-interval 10s
|
|
100
|
+
--health-timeout 5s
|
|
101
|
+
--health-retries 5
|
|
102
|
+
- language: yaml
|
|
103
|
+
label: "Fallback — explicit wait step if health check unreliable"
|
|
104
|
+
code: |
|
|
105
|
+
steps:
|
|
106
|
+
- name: Wait for PostgreSQL to be ready
|
|
107
|
+
run: |
|
|
108
|
+
until pg_isready -h localhost -p 5432 -U postgres; do
|
|
109
|
+
echo "Waiting for postgres..."
|
|
110
|
+
sleep 2
|
|
111
|
+
done
|
|
112
|
+
timeout-minutes: 2
|
|
113
|
+
prevention:
|
|
114
|
+
- "Always specify `options:` with `--health-cmd`, `--health-interval`, `--health-retries`, and `--health-start-period` for every service container."
|
|
115
|
+
- "Use service-native health check commands (pg_isready, redis-cli ping) rather than generic TCP probes."
|
|
116
|
+
- "Add `--health-start-period` of 20-30 seconds for services with slow initialization (PostgreSQL, Elasticsearch, RabbitMQ)."
|
|
117
|
+
- "Test health check timing locally in Docker before relying on it in CI: `docker run --health-cmd '...' --health-interval 5s <image>`."
|
|
118
|
+
docs:
|
|
119
|
+
- url: "https://docs.github.com/en/actions/using-containerized-services/about-service-containers"
|
|
120
|
+
label: "About service containers"
|
|
121
|
+
- url: "https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idservicesservice_idoptions"
|
|
122
|
+
label: "Workflow syntax — services options"
|
|
123
|
+
- url: "https://github.com/actions/example-services/issues/3"
|
|
124
|
+
label: "actions/example-services #3 — Service container health check questions and fixes"
|
|
125
|
+
- url: "https://stackoverflow.com/questions/66763353/how-to-health-check-a-service-in-github"
|
|
126
|
+
label: "Stack Overflow — How to health check a service in GitHub Actions"
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
id: runner-environment-020
|
|
2
|
+
title: "windows-latest Now Uses Visual Studio 2026 — VS 2022 Components Removed"
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- windows
|
|
7
|
+
- visual-studio
|
|
8
|
+
- runner-image
|
|
9
|
+
- breaking-change
|
|
10
|
+
- msbuild
|
|
11
|
+
- dotnet
|
|
12
|
+
patterns:
|
|
13
|
+
- regex: "MSB[0-9]+.*Visual Studio 2022|The tools version.*15\\.0.*is not available"
|
|
14
|
+
flags: "i"
|
|
15
|
+
- regex: "Dotfuscator.*not found|dotfuscator.*missing"
|
|
16
|
+
flags: "i"
|
|
17
|
+
- regex: "Component.*Azure.ServiceFabric.Tools.*not installed"
|
|
18
|
+
flags: "i"
|
|
19
|
+
- regex: "VC\\.Tools\\.ARM.*not found|Microsoft\\.VisualStudio\\.Component\\.VC\\.Tools\\.ARM"
|
|
20
|
+
flags: "i"
|
|
21
|
+
- regex: "error.*NETSDK1045.*The current .NET SDK does not support targeting .NET (5|6|7)"
|
|
22
|
+
flags: "i"
|
|
23
|
+
- regex: "Visual Studio.*version 17\\.[0-9]+.*not found|MSBuild.*17\\.[0-9]+.*not available"
|
|
24
|
+
flags: "i"
|
|
25
|
+
error_messages:
|
|
26
|
+
- "MSB4019: The imported project 'Microsoft.CppBuild.targets' was not found."
|
|
27
|
+
- "Error: Dotfuscator is not installed. Please install Dotfuscator Community."
|
|
28
|
+
- "The component 'Microsoft.VisualStudio.Component.Azure.ServiceFabric.Tools' is not installed."
|
|
29
|
+
- "MSBUILD : error MSB1009: Project file does not exist. Switch: /version:17"
|
|
30
|
+
- "The current .NET SDK does not support targeting .NET 7.0."
|
|
31
|
+
root_cause: |
|
|
32
|
+
The `windows-latest` and `windows-2025` labels in GitHub Actions were migrated to use
|
|
33
|
+
**Windows Server 2025 with Visual Studio 2026** beginning June 8, 2026 (completing
|
|
34
|
+
June 15, 2026). Previously these labels ran Visual Studio 2022 (version 17.x).
|
|
35
|
+
|
|
36
|
+
Visual Studio 2026 (version 18.x) ships with MSBuild 18 and removes several VS 2022
|
|
37
|
+
components that workflows may depend on:
|
|
38
|
+
|
|
39
|
+
**Removed VS components:**
|
|
40
|
+
- `Component.Dotfuscator` — .NET obfuscation tool
|
|
41
|
+
- `Microsoft.VisualStudio.Component.Azure.ServiceFabric.Tools`
|
|
42
|
+
- `Microsoft.VisualStudio.Component.TestTools.CodedUITest`
|
|
43
|
+
- `Microsoft.VisualStudio.Component.TestTools.WebLoadTest`
|
|
44
|
+
- `Microsoft.VisualStudio.Component.VC.Tools.ARM` — ARM cross-compilation toolchain
|
|
45
|
+
- `Microsoft.VisualStudio.Component.VC.Modules.x86.x64`
|
|
46
|
+
- `Microsoft.VisualStudio.Component.VC.Runtimes.ARM.Spectre`
|
|
47
|
+
- `Microsoft.VisualStudio.Component.VC.MFC.ARM` and `.ARM.Spectre`
|
|
48
|
+
- `Microsoft.VisualStudio.Component.VC.ATL.ARM` and `.ARM.Spectre`
|
|
49
|
+
- `Microsoft.VisualStudio.ComponentGroup.Azure.CloudServices`
|
|
50
|
+
- `Microsoft.VisualStudio.ComponentGroup.Azure.ResourceManager.Tools`
|
|
51
|
+
|
|
52
|
+
**Other changes:**
|
|
53
|
+
- CMake updated from 3.31.6 → 4.3.2 (adds VS 18 2026 generator, deprecates some older generators)
|
|
54
|
+
- Android Command Line Tools updated from 16.0 → 19.0
|
|
55
|
+
- MSVC v143 toolset is added as a compatibility shim for projects requiring it
|
|
56
|
+
fix: |
|
|
57
|
+
**Immediate rollback:** Pin to `windows-2022` to keep Visual Studio 2022:
|
|
58
|
+
```yaml
|
|
59
|
+
runs-on: windows-2022
|
|
60
|
+
```
|
|
61
|
+
Note: `windows-2022` continues to run VS 2022 (version 17.x) and will remain supported.
|
|
62
|
+
|
|
63
|
+
**For removed components:**
|
|
64
|
+
- **Dotfuscator**: Remove from build pipeline, or install manually via the Dotfuscator
|
|
65
|
+
Community installer in a workflow step. Consider alternatives like ConfuserEx.
|
|
66
|
+
- **ARM VC toolchain** (`VC.Tools.ARM`): Use the separate `windows-11-arm64` runner label
|
|
67
|
+
for native ARM64 builds, or cross-compile via MSVC v143 shim that ships with VS 2026.
|
|
68
|
+
- **Azure Service Fabric Tools**: Install the Service Fabric SDK directly via PowerShell
|
|
69
|
+
if your workflow requires it.
|
|
70
|
+
- **CMake generator**: Update your CMake invocation from `-G "Visual Studio 17 2022"` to
|
|
71
|
+
`-G "Visual Studio 18 2026"`.
|
|
72
|
+
fix_code:
|
|
73
|
+
- language: yaml
|
|
74
|
+
label: "Pin to windows-2022 for immediate rollback (VS 2022)"
|
|
75
|
+
code: |
|
|
76
|
+
jobs:
|
|
77
|
+
build:
|
|
78
|
+
# Temporarily pin to VS 2022 while migrating
|
|
79
|
+
runs-on: windows-2022
|
|
80
|
+
steps:
|
|
81
|
+
- uses: actions/checkout@v4
|
|
82
|
+
- name: Build
|
|
83
|
+
run: msbuild MyProject.sln /p:Configuration=Release
|
|
84
|
+
- language: yaml
|
|
85
|
+
label: "Migrate to VS 2026 — update CMake generator and toolset"
|
|
86
|
+
code: |
|
|
87
|
+
jobs:
|
|
88
|
+
build:
|
|
89
|
+
runs-on: windows-latest # now VS 2026
|
|
90
|
+
steps:
|
|
91
|
+
- uses: actions/checkout@v4
|
|
92
|
+
|
|
93
|
+
- name: Configure CMake (VS 2026 generator)
|
|
94
|
+
run: |
|
|
95
|
+
cmake -B build -G "Visual Studio 18 2026" -A x64 `
|
|
96
|
+
-DCMAKE_BUILD_TYPE=Release
|
|
97
|
+
|
|
98
|
+
- name: Build
|
|
99
|
+
run: cmake --build build --config Release
|
|
100
|
+
|
|
101
|
+
# If you need MSVC v143 (VS 2022 toolset) compatibility:
|
|
102
|
+
# cmake -B build -G "Visual Studio 18 2026" -A x64 -T v143
|
|
103
|
+
- language: yaml
|
|
104
|
+
label: "Test against both VS 2022 and VS 2026 during migration"
|
|
105
|
+
code: |
|
|
106
|
+
jobs:
|
|
107
|
+
build:
|
|
108
|
+
strategy:
|
|
109
|
+
matrix:
|
|
110
|
+
os: [windows-2022, windows-latest]
|
|
111
|
+
runs-on: ${{ matrix.os }}
|
|
112
|
+
steps:
|
|
113
|
+
- uses: actions/checkout@v4
|
|
114
|
+
- name: Build and test
|
|
115
|
+
run: msbuild MyProject.sln /p:Configuration=Release /t:Build,Test
|
|
116
|
+
prevention:
|
|
117
|
+
- "Avoid depending on specific Visual Studio components that are not part of the core VS 2022/2026 workloads — install them explicitly in your workflow if needed."
|
|
118
|
+
- "Subscribe to actions/runner-images announcements to receive advance notice of `windows-latest` migrations."
|
|
119
|
+
- "Test your Windows workflows against `windows-2025-vs2026` before the `windows-latest` migration completes."
|
|
120
|
+
- "Use MSBuild's `-T v143` toolset flag to target the VS 2022 compiler toolchain from within VS 2026 if full migration is not yet feasible."
|
|
121
|
+
- "Search your workflows for CMake generator strings like 'Visual Studio 17 2022' and update them proactively."
|
|
122
|
+
docs:
|
|
123
|
+
- url: "https://github.com/actions/runner-images/issues/14017"
|
|
124
|
+
label: "GitHub Announcement: windows-latest migrates to Visual Studio 2026"
|
|
125
|
+
- url: "https://github.com/actions/runner-images/issues/14016"
|
|
126
|
+
label: "GitHub Announcement: Windows Server 2025 with VS 2026 now GA"
|
|
127
|
+
- url: "https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners"
|
|
128
|
+
label: "About GitHub-hosted runners"
|
|
129
|
+
source:
|
|
130
|
+
article: "https://htek.dev/articles/github-actions-debugging-guide"
|
|
131
|
+
section: "Windows runner Visual Studio migrations"
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
id: silent-failures-009
|
|
2
|
+
title: "hashFiles() Returns Empty String When No Files Match — Silent Cache Key Collision"
|
|
3
|
+
category: silent-failures
|
|
4
|
+
severity: silent-failure
|
|
5
|
+
tags:
|
|
6
|
+
- cache
|
|
7
|
+
- hashFiles
|
|
8
|
+
- cache-key
|
|
9
|
+
- collision
|
|
10
|
+
- glob
|
|
11
|
+
- silent-failure
|
|
12
|
+
patterns:
|
|
13
|
+
- regex: "key: [A-Za-z0-9_-]+-$"
|
|
14
|
+
flags: "m"
|
|
15
|
+
- regex: "Cache restored from key: [A-Za-z0-9_-]+(?!-[0-9a-f]{64})"
|
|
16
|
+
flags: "i"
|
|
17
|
+
error_messages:
|
|
18
|
+
- "Cache restored from key: Linux-node-"
|
|
19
|
+
- "Cache restored from key: Linux-pip-"
|
|
20
|
+
- "No error shown — workflow succeeds but wrong cache is restored"
|
|
21
|
+
root_cause: |
|
|
22
|
+
The `hashFiles()` expression function returns an empty string (not an error)
|
|
23
|
+
when the supplied glob pattern matches no files in the workspace. This silently
|
|
24
|
+
truncates the cache key, turning a key like:
|
|
25
|
+
|
|
26
|
+
${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
|
27
|
+
|
|
28
|
+
into:
|
|
29
|
+
|
|
30
|
+
Linux-node-
|
|
31
|
+
|
|
32
|
+
when no package-lock.json exists. This short, predictable key collides across
|
|
33
|
+
branches and runs, causing stale or wrong cache content to be restored without
|
|
34
|
+
any warning. The workflow log shows the cache as restored successfully.
|
|
35
|
+
|
|
36
|
+
Documented in actions/runner issue #894. Commonly triggered by:
|
|
37
|
+
- Lockfile not yet committed (new project setup)
|
|
38
|
+
- Wrong glob path (e.g., `**/package-lock.json` but lockfile is at root)
|
|
39
|
+
- Wrong working directory at cache step execution time
|
|
40
|
+
- Matrix jobs where not all matrix values have a matching lockfile
|
|
41
|
+
fix: |
|
|
42
|
+
Add a fallback value to the hashFiles() expression using the `||` operator so
|
|
43
|
+
the key is always deterministic even when no files match:
|
|
44
|
+
|
|
45
|
+
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') || 'no-lockfile' }}
|
|
46
|
+
|
|
47
|
+
Also verify that the glob actually matches the file by running
|
|
48
|
+
`find . -name "package-lock.json"` in a debug step before the cache step.
|
|
49
|
+
|
|
50
|
+
For matrix workflows, include the matrix value in the key to prevent
|
|
51
|
+
cross-matrix collisions even when hash is empty:
|
|
52
|
+
|
|
53
|
+
key: ${{ runner.os }}-node-${{ matrix.node-version }}-${{ hashFiles('**/package-lock.json') || 'no-lockfile' }}
|
|
54
|
+
fix_code:
|
|
55
|
+
- language: yaml
|
|
56
|
+
label: "WRONG — hashFiles with no fallback (silently short key on miss)"
|
|
57
|
+
code: |
|
|
58
|
+
- uses: actions/cache@v4
|
|
59
|
+
with:
|
|
60
|
+
path: ~/.npm
|
|
61
|
+
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
|
|
62
|
+
# ❌ If no package-lock.json found, key becomes "Linux-node-"
|
|
63
|
+
# All runs share the same truncated key → wrong cache restored silently
|
|
64
|
+
- language: yaml
|
|
65
|
+
label: "RIGHT — hashFiles with explicit fallback"
|
|
66
|
+
code: |
|
|
67
|
+
- uses: actions/cache@v4
|
|
68
|
+
with:
|
|
69
|
+
path: ~/.npm
|
|
70
|
+
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') || 'no-lockfile' }}
|
|
71
|
+
# ✅ If no lockfile, key becomes "Linux-node-no-lockfile" — deterministic and unique
|
|
72
|
+
restore-keys: |
|
|
73
|
+
${{ runner.os }}-node-
|
|
74
|
+
- language: yaml
|
|
75
|
+
label: "DEBUG — verify glob matches before caching"
|
|
76
|
+
code: |
|
|
77
|
+
- name: Debug — check lockfile exists
|
|
78
|
+
run: find . -name "package-lock.json" | head -5
|
|
79
|
+
# If empty output: fix the glob or ensure lockfile is committed
|
|
80
|
+
|
|
81
|
+
- uses: actions/cache@v4
|
|
82
|
+
with:
|
|
83
|
+
path: ~/.npm
|
|
84
|
+
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') || 'no-lockfile' }}
|
|
85
|
+
prevention:
|
|
86
|
+
- "Always provide a `|| 'fallback-value'` after any hashFiles() call to prevent empty-string cache key truncation."
|
|
87
|
+
- "Test your hashFiles() glob locally: run `find . -name 'your-lockfile'` from the repo root to confirm it matches."
|
|
88
|
+
- "Include stable discriminators (runner.os, matrix values, Node version) in cache keys to reduce collision risk."
|
|
89
|
+
- "Review restored cache key in workflow logs — a key ending in just a short prefix without a 64-char hash is a sign of an empty hashFiles()."
|
|
90
|
+
docs:
|
|
91
|
+
- url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/evaluate-expressions-in-workflows-and-actions#hashfiles"
|
|
92
|
+
label: "hashFiles() function documentation"
|
|
93
|
+
- url: "https://github.com/actions/runner/issues/894"
|
|
94
|
+
label: "actions/runner #894 — hashFiles returns empty string instead of hash"
|
|
95
|
+
- url: "https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows"
|
|
96
|
+
label: "Caching dependencies to speed up workflows"
|