@htekdev/actions-debugger 1.0.97 → 1.0.99
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/errors/known-unsolved/reusable-workflow-github-event-is-workflow-call-event.yml +112 -0
- package/errors/permissions-auth/oidc-token-rate-limited-large-parallel-matrix.yml +114 -0
- package/errors/runner-environment/macos-15-ios-simulator-runtimes-not-preinstalled.yml +75 -0
- package/errors/runner-environment/pip-install-externally-managed-environment-pep668.yml +69 -0
- package/errors/runner-environment/setup-dotnet-eol-net6-net7-version-not-found.yml +72 -0
- package/errors/silent-failures/macos-latest-upgraded-to-macos-15-xcode-16-swift-6.yml +71 -0
- package/errors/silent-failures/vars-context-environment-shadows-repo-org.yml +97 -0
- package/errors/yaml-syntax/timeout-minutes-env-context-unavailable.yml +93 -0
- package/package.json +1 -1
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
id: known-unsolved-054
|
|
2
|
+
title: 'github.event in a reusable workflow is the workflow_call event, not the caller event'
|
|
3
|
+
category: known-unsolved
|
|
4
|
+
severity: silent-failure
|
|
5
|
+
tags:
|
|
6
|
+
- reusable-workflow
|
|
7
|
+
- workflow-call
|
|
8
|
+
- github-event
|
|
9
|
+
- context
|
|
10
|
+
- inputs
|
|
11
|
+
- github-context
|
|
12
|
+
patterns:
|
|
13
|
+
- regex: 'github\.event\.(pull_request|commits|release|head_commit)\b'
|
|
14
|
+
flags: 'i'
|
|
15
|
+
error_messages: []
|
|
16
|
+
root_cause: |
|
|
17
|
+
When a caller workflow invokes a reusable workflow via jobs.<id>.uses, the
|
|
18
|
+
github.event context inside the callee is the workflow_call event object,
|
|
19
|
+
NOT the triggering event (push, pull_request, schedule, etc.) of the caller.
|
|
20
|
+
|
|
21
|
+
All event-specific payload fields are undefined inside the reusable workflow
|
|
22
|
+
and evaluate to empty string or null without any error:
|
|
23
|
+
- github.event.pull_request (undefined — returns null)
|
|
24
|
+
- github.event.commits (undefined — returns null)
|
|
25
|
+
- github.event.release (undefined — returns null)
|
|
26
|
+
- github.event.head_commit (undefined — returns null)
|
|
27
|
+
- github.event.inputs (undefined — use inputs context instead)
|
|
28
|
+
|
|
29
|
+
Additionally, github.event_name inside the callee always returns 'workflow_call',
|
|
30
|
+
regardless of what event triggered the caller.
|
|
31
|
+
|
|
32
|
+
Importantly, github.ref, github.sha, and github.actor DO retain the caller's
|
|
33
|
+
values inside the callee — it is specifically github.event and github.event_name
|
|
34
|
+
that reflect the workflow_call context, not the caller's triggering event.
|
|
35
|
+
|
|
36
|
+
This catches developers by surprise when refactoring inline jobs into reusable
|
|
37
|
+
workflows: the refactored callee silently loses access to the event payload it
|
|
38
|
+
previously used, with no validation error or warning at parse time or runtime.
|
|
39
|
+
|
|
40
|
+
This is by design — reusable workflows execute as independent workflow_call
|
|
41
|
+
events and there is no mechanism to inherit the caller's event context. GitHub
|
|
42
|
+
has confirmed this will not change.
|
|
43
|
+
fix: |
|
|
44
|
+
There is no workaround that exposes the caller's github.event inside the callee.
|
|
45
|
+
The required approach is to declare all needed event data as explicit inputs:
|
|
46
|
+
in the reusable workflow and forward them via with: in the caller.
|
|
47
|
+
|
|
48
|
+
github.ref, github.sha, and github.actor are available in the callee without
|
|
49
|
+
any explicit forwarding — they are inherited automatically from the caller context.
|
|
50
|
+
fix_code:
|
|
51
|
+
- language: yaml
|
|
52
|
+
label: 'Wrong — accessing caller event payload inside reusable workflow (silently empty)'
|
|
53
|
+
code: |
|
|
54
|
+
# .github/workflows/reusable.yml — these are all EMPTY inside the callee
|
|
55
|
+
on:
|
|
56
|
+
workflow_call:
|
|
57
|
+
|
|
58
|
+
jobs:
|
|
59
|
+
process:
|
|
60
|
+
runs-on: ubuntu-latest
|
|
61
|
+
steps:
|
|
62
|
+
- run: echo "PR = ${{ github.event.pull_request.number }}" # null
|
|
63
|
+
- run: echo "Event = ${{ github.event_name }}" # 'workflow_call'
|
|
64
|
+
- run: echo "Commit = ${{ github.event.head_commit.message }}" # null
|
|
65
|
+
- language: yaml
|
|
66
|
+
label: 'Correct — declare inputs in callee and forward event data from caller'
|
|
67
|
+
code: |
|
|
68
|
+
# .github/workflows/reusable.yml — declare needed event data as inputs
|
|
69
|
+
on:
|
|
70
|
+
workflow_call:
|
|
71
|
+
inputs:
|
|
72
|
+
pr_number:
|
|
73
|
+
type: number
|
|
74
|
+
default: 0
|
|
75
|
+
description: 'Pull request number from github.event.pull_request.number'
|
|
76
|
+
triggering_event:
|
|
77
|
+
type: string
|
|
78
|
+
required: true
|
|
79
|
+
description: 'The caller event name (github.event_name)'
|
|
80
|
+
|
|
81
|
+
jobs:
|
|
82
|
+
process:
|
|
83
|
+
runs-on: ubuntu-latest
|
|
84
|
+
steps:
|
|
85
|
+
- run: echo "PR = ${{ inputs.pr_number }}"
|
|
86
|
+
- run: echo "Triggered by = ${{ inputs.triggering_event }}"
|
|
87
|
+
# github.ref and github.sha are safe to use directly — they are inherited
|
|
88
|
+
- run: echo "SHA = ${{ github.sha }}"
|
|
89
|
+
|
|
90
|
+
# ---- CALLER WORKFLOW ----
|
|
91
|
+
# .github/workflows/caller.yml — forward event data via with:
|
|
92
|
+
on: [push, pull_request]
|
|
93
|
+
|
|
94
|
+
jobs:
|
|
95
|
+
call-reusable:
|
|
96
|
+
uses: ./.github/workflows/reusable.yml
|
|
97
|
+
with:
|
|
98
|
+
pr_number: ${{ github.event.pull_request.number || 0 }}
|
|
99
|
+
triggering_event: ${{ github.event_name }}
|
|
100
|
+
prevention:
|
|
101
|
+
- 'Never access github.event.* fields directly inside a reusable workflow — they will always be empty'
|
|
102
|
+
- 'github.event_name inside a reusable workflow always returns workflow_call, not the caller event'
|
|
103
|
+
- 'Declare all required event data as explicit workflow_call inputs and forward with with: in the caller'
|
|
104
|
+
- 'github.ref, github.sha, and github.actor are inherited from the caller and are safe to use'
|
|
105
|
+
- 'Add a comment in the reusable workflow reminding contributors not to use github.event directly'
|
|
106
|
+
docs:
|
|
107
|
+
- url: 'https://docs.github.com/en/actions/sharing-automations/reusing-workflows#limitations'
|
|
108
|
+
label: 'GitHub Docs — Reusing workflows: Limitations'
|
|
109
|
+
- url: 'https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/contexts#github-context'
|
|
110
|
+
label: 'GitHub Docs — github context'
|
|
111
|
+
- url: 'https://docs.github.com/en/actions/sharing-automations/reusing-workflows#passing-inputs-and-secrets-to-a-called-workflow'
|
|
112
|
+
label: 'GitHub Docs — Passing inputs and secrets to a called workflow'
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
id: permissions-auth-056
|
|
2
|
+
title: 'OIDC token requests rate-limited in large parallel matrix — random 429 job failures'
|
|
3
|
+
category: permissions-auth
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- oidc
|
|
7
|
+
- id-token
|
|
8
|
+
- rate-limit
|
|
9
|
+
- matrix
|
|
10
|
+
- parallel
|
|
11
|
+
- aws
|
|
12
|
+
- gcp
|
|
13
|
+
- azure
|
|
14
|
+
patterns:
|
|
15
|
+
- regex: 'Failed to get ID token.*429'
|
|
16
|
+
flags: 'i'
|
|
17
|
+
- regex: 'ACTIONS_ID_TOKEN_REQUEST_URL.*429'
|
|
18
|
+
flags: 'i'
|
|
19
|
+
- regex: 'No ID token is available.*rate.limit'
|
|
20
|
+
flags: 'i'
|
|
21
|
+
error_messages:
|
|
22
|
+
- "Error: Failed to get ID token: Request failed with status code 429"
|
|
23
|
+
- "Error: Failed to get ID token: Error code: 429"
|
|
24
|
+
root_cause: |
|
|
25
|
+
GitHub's OIDC token endpoint (ACTIONS_ID_TOKEN_REQUEST_URL) has per-workflow-run
|
|
26
|
+
rate limits on simultaneous token requests. When a large matrix workflow spawns
|
|
27
|
+
many parallel jobs (typically 20+) that all request OIDC tokens at the start of
|
|
28
|
+
their runs, the burst of simultaneous requests can exceed the endpoint's rate
|
|
29
|
+
limit, and some jobs receive HTTP 429 responses.
|
|
30
|
+
|
|
31
|
+
Cloud provider actions that call the OIDC endpoint internally during setup
|
|
32
|
+
are affected:
|
|
33
|
+
- aws-actions/configure-aws-credentials
|
|
34
|
+
- google-github-actions/auth
|
|
35
|
+
- azure/login (with OIDC federated credentials)
|
|
36
|
+
|
|
37
|
+
In a large matrix, all legs start within seconds of each other, creating a
|
|
38
|
+
simultaneous burst that exceeds the endpoint limit. The failure is
|
|
39
|
+
non-deterministic: some jobs succeed and some fail on any given run. Manually
|
|
40
|
+
re-running the failed jobs typically succeeds because the burst window has
|
|
41
|
+
passed. This intermittent behavior makes the 429 root cause difficult to
|
|
42
|
+
diagnose without inspecting verbose action output for the HTTP status code.
|
|
43
|
+
|
|
44
|
+
The rate limit is enforced per workflow run, not per repository or per user.
|
|
45
|
+
Actions that include built-in retry logic may mask the error by successfully
|
|
46
|
+
retrying, but add latency to affected jobs.
|
|
47
|
+
fix: |
|
|
48
|
+
Reduce parallel OIDC token requests by setting max-parallel on the matrix
|
|
49
|
+
strategy. A value between 5 and 15 typically prevents rate limit breaches
|
|
50
|
+
while still providing meaningful parallelism.
|
|
51
|
+
|
|
52
|
+
Alternatively, restructure the workflow to acquire a single OIDC-derived
|
|
53
|
+
credential in a setup job and pass it as a job output to downstream matrix
|
|
54
|
+
jobs — but this must be done carefully to avoid exposing short-lived tokens
|
|
55
|
+
in workflow logs. Check the cloud provider's documentation for recommended
|
|
56
|
+
token-sharing patterns.
|
|
57
|
+
|
|
58
|
+
Enable step debug logging (ACTIONS_STEP_DEBUG secret set to 'true') to
|
|
59
|
+
confirm the 429 root cause when diagnosing intermittent OIDC failures.
|
|
60
|
+
fix_code:
|
|
61
|
+
- language: yaml
|
|
62
|
+
label: 'Set max-parallel to prevent simultaneous OIDC token request burst'
|
|
63
|
+
code: |
|
|
64
|
+
jobs:
|
|
65
|
+
deploy:
|
|
66
|
+
strategy:
|
|
67
|
+
matrix:
|
|
68
|
+
region: [us-east-1, us-west-2, eu-west-1, ap-southeast-1, ap-northeast-1,
|
|
69
|
+
sa-east-1, ca-central-1, ap-south-1, ap-east-1, eu-central-1]
|
|
70
|
+
max-parallel: 5 # Prevents simultaneous OIDC token burst
|
|
71
|
+
runs-on: ubuntu-latest
|
|
72
|
+
permissions:
|
|
73
|
+
id-token: write
|
|
74
|
+
contents: read
|
|
75
|
+
steps:
|
|
76
|
+
- name: Configure AWS credentials
|
|
77
|
+
uses: aws-actions/configure-aws-credentials@v4
|
|
78
|
+
with:
|
|
79
|
+
role-to-assume: arn:aws:iam::123456789:role/deploy-${{ matrix.region }}
|
|
80
|
+
aws-region: ${{ matrix.region }}
|
|
81
|
+
- name: Deploy
|
|
82
|
+
run: ./scripts/deploy.sh ${{ matrix.region }}
|
|
83
|
+
- language: yaml
|
|
84
|
+
label: 'Enable OIDC debug logging to confirm 429 rate limit as root cause'
|
|
85
|
+
code: |
|
|
86
|
+
# Add this secret to the repository: ACTIONS_STEP_DEBUG = true
|
|
87
|
+
# Then re-run the failing workflow and check step logs for:
|
|
88
|
+
# "Request failed with status code 429"
|
|
89
|
+
# in the cloud auth action's output to confirm rate limiting.
|
|
90
|
+
|
|
91
|
+
jobs:
|
|
92
|
+
deploy:
|
|
93
|
+
runs-on: ubuntu-latest
|
|
94
|
+
permissions:
|
|
95
|
+
id-token: write
|
|
96
|
+
steps:
|
|
97
|
+
- name: Configure credentials (verbose for debugging)
|
|
98
|
+
uses: aws-actions/configure-aws-credentials@v4
|
|
99
|
+
with:
|
|
100
|
+
role-to-assume: arn:aws:iam::123456789:role/ci-role
|
|
101
|
+
aws-region: us-east-1
|
|
102
|
+
prevention:
|
|
103
|
+
- 'Use max-parallel on matrix strategies that use OIDC authentication to limit burst requests'
|
|
104
|
+
- 'Enable ACTIONS_STEP_DEBUG secret to see HTTP status codes in cloud auth action logs'
|
|
105
|
+
- 'Treat intermittent OIDC failures in large matrix workflows as a 429 rate limit until proven otherwise'
|
|
106
|
+
- 'Check whether the cloud auth action has built-in retry logic — some versions retry automatically'
|
|
107
|
+
- 'Consider staggering matrix jobs with a sleep step if max-parallel alone does not resolve the issue'
|
|
108
|
+
docs:
|
|
109
|
+
- url: 'https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/about-security-hardening-with-openid-connect'
|
|
110
|
+
label: 'GitHub Docs — About security hardening with OpenID Connect'
|
|
111
|
+
- url: 'https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#jobsjob_idstrategymax-parallel'
|
|
112
|
+
label: 'GitHub Docs — jobs.<job_id>.strategy.max-parallel'
|
|
113
|
+
- url: 'https://docs.github.com/en/actions/monitoring-and-troubleshooting-workflows/enabling-debug-logging'
|
|
114
|
+
label: 'GitHub Docs — Enabling debug logging'
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
id: runner-environment-167
|
|
2
|
+
title: "macOS 15 / Xcode 16: iOS Simulator Runtimes Not Pre-Installed — xcodebuild test Fails with No Matching Destination"
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- macos
|
|
7
|
+
- xcode
|
|
8
|
+
- ios
|
|
9
|
+
- simulator
|
|
10
|
+
- xcodebuild
|
|
11
|
+
- runner-image
|
|
12
|
+
patterns:
|
|
13
|
+
- regex: 'Unable to find a destination matching the provided destination specifier'
|
|
14
|
+
flags: i
|
|
15
|
+
- regex: 'No simulator runtime matching .* was found'
|
|
16
|
+
flags: i
|
|
17
|
+
- regex: 'Could not find a simulator destination'
|
|
18
|
+
flags: i
|
|
19
|
+
error_messages:
|
|
20
|
+
- "error: Unable to find a destination matching the provided destination specifier: { platform:iOS Simulator, name:iPhone 15 }"
|
|
21
|
+
- "error: No simulator runtime matching 'iOS 18.0' was found."
|
|
22
|
+
- "Testing failed: Could not find a destination that satisfied the requested destination specifier."
|
|
23
|
+
- "xcodebuild: error: 'xcodebuild test' requires a simulator, but no runtimes are installed."
|
|
24
|
+
root_cause: |
|
|
25
|
+
Starting with Xcode 16 on macOS 15 GitHub-hosted runners, Apple decoupled iOS/iPadOS simulator
|
|
26
|
+
runtimes from the Xcode installation to reduce download sizes. Unlike Xcode 15 where simulator
|
|
27
|
+
runtimes for iOS 17 were bundled, Xcode 16 ships without any pre-installed simulator runtimes.
|
|
28
|
+
Running `xcrun simctl list runtimes` on macos-15 returns an empty list. When `xcodebuild test`
|
|
29
|
+
is called with an iOS Simulator destination, it fails immediately because there are no runtimes
|
|
30
|
+
to match against. This affects all iOS, tvOS, and watchOS simulator-based tests.
|
|
31
|
+
fix: |
|
|
32
|
+
Option 1 — Download the required simulator runtime before testing (adds ~5-10 min):
|
|
33
|
+
Use `xcrun simctl runtime add <identifier>` to download the runtime.
|
|
34
|
+
|
|
35
|
+
Option 2 — Pin to macos-14 which ships with simulator runtimes pre-installed.
|
|
36
|
+
|
|
37
|
+
Option 3 — Use `xcode-install` or `xcodes` to select an older Xcode with bundled runtimes.
|
|
38
|
+
fix_code:
|
|
39
|
+
- language: yaml
|
|
40
|
+
label: "Install iOS simulator runtime before running xcodebuild test"
|
|
41
|
+
code: |
|
|
42
|
+
- name: Install iOS 18 Simulator Runtime
|
|
43
|
+
run: |
|
|
44
|
+
xcrun simctl runtime add "com.apple.CoreSimulator.SimRuntime.iOS-18-0"
|
|
45
|
+
timeout-minutes: 15
|
|
46
|
+
- name: Run iOS Tests
|
|
47
|
+
run: |
|
|
48
|
+
xcodebuild test \
|
|
49
|
+
-scheme MyApp \
|
|
50
|
+
-destination 'platform=iOS Simulator,name=iPhone 16,OS=18.0'
|
|
51
|
+
- language: yaml
|
|
52
|
+
label: "Pin to macos-14 to use pre-installed simulator runtimes"
|
|
53
|
+
code: |
|
|
54
|
+
jobs:
|
|
55
|
+
test:
|
|
56
|
+
runs-on: macos-14 # Simulator runtimes bundled with Xcode 15
|
|
57
|
+
steps:
|
|
58
|
+
- uses: actions/checkout@v4
|
|
59
|
+
- name: Run iOS Tests
|
|
60
|
+
run: |
|
|
61
|
+
xcodebuild test \
|
|
62
|
+
-scheme MyApp \
|
|
63
|
+
-destination 'platform=iOS Simulator,name=iPhone 15'
|
|
64
|
+
prevention:
|
|
65
|
+
- "Always pin to a specific macOS version rather than macos-latest for iOS CI workflows"
|
|
66
|
+
- "Add a `xcrun simctl list runtimes` step early in your workflow to detect missing runtimes fast"
|
|
67
|
+
- "Check GitHub Actions runner-images release notes when bumping macOS version"
|
|
68
|
+
- "Budget extra CI time (10-15 min) for simulator runtime download when using Xcode 16+"
|
|
69
|
+
docs:
|
|
70
|
+
- url: "https://github.com/actions/runner-images/issues/10337"
|
|
71
|
+
label: "runner-images: Simulator runtimes not pre-installed with Xcode 16"
|
|
72
|
+
- url: "https://developer.apple.com/documentation/xcode/installing-additional-simulator-runtimes"
|
|
73
|
+
label: "Apple: Installing Additional Simulator Runtimes"
|
|
74
|
+
- url: "https://github.com/actions/runner-images/blob/main/images/macos/macos-15-Readme.md"
|
|
75
|
+
label: "macOS 15 Runner Image — Installed Software"
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
id: runner-environment-168
|
|
2
|
+
title: "pip install Fails with 'externally-managed-environment' on Ubuntu 22.04/24.04 (PEP 668)"
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- python
|
|
7
|
+
- pip
|
|
8
|
+
- pep668
|
|
9
|
+
- ubuntu-22
|
|
10
|
+
- ubuntu-24
|
|
11
|
+
- externally-managed
|
|
12
|
+
patterns:
|
|
13
|
+
- regex: 'error: externally-managed-environment'
|
|
14
|
+
flags: i
|
|
15
|
+
- regex: 'This environment is externally managed'
|
|
16
|
+
flags: i
|
|
17
|
+
- regex: 'If you wish to install a non-Debian.*package.*--break-system-packages'
|
|
18
|
+
flags: i
|
|
19
|
+
error_messages:
|
|
20
|
+
- "error: externally-managed-environment"
|
|
21
|
+
- "× This environment is externally managed"
|
|
22
|
+
- "To install Python packages system-wide, try apt install python3-xyz"
|
|
23
|
+
- "If you wish to install a non-Debian-packaged Python package, create a virtual environment using python3 -m venv path/to/venv"
|
|
24
|
+
root_cause: |
|
|
25
|
+
PEP 668 (implemented in Python 3.11+) marks system Python installations as "externally managed"
|
|
26
|
+
to prevent pip from overwriting system packages managed by the OS package manager (apt, brew, etc.).
|
|
27
|
+
Ubuntu 22.04 adopted this restriction for its bundled Python 3.10+, and Ubuntu 24.04 enforces it
|
|
28
|
+
strictly. When a workflow uses the system Python (python3 without actions/setup-python) and runs
|
|
29
|
+
`pip install`, the installation fails immediately with the "externally-managed-environment" error.
|
|
30
|
+
This breaks workflows that previously ran pip install directly without a virtual environment.
|
|
31
|
+
fix: |
|
|
32
|
+
Option 1 (Recommended) — Use actions/setup-python to install an isolated Python:
|
|
33
|
+
The action installs Python in the tool cache, outside the system-managed environment.
|
|
34
|
+
|
|
35
|
+
Option 2 — Create a virtual environment before running pip:
|
|
36
|
+
python3 -m venv .venv && source .venv/bin/activate && pip install ...
|
|
37
|
+
|
|
38
|
+
Option 3 (Quick fix, not recommended for CI) — Pass --break-system-packages:
|
|
39
|
+
pip install --break-system-packages <package>
|
|
40
|
+
fix_code:
|
|
41
|
+
- language: yaml
|
|
42
|
+
label: "Use actions/setup-python to avoid externally-managed-environment error"
|
|
43
|
+
code: |
|
|
44
|
+
- uses: actions/setup-python@v5
|
|
45
|
+
with:
|
|
46
|
+
python-version: '3.12'
|
|
47
|
+
- name: Install dependencies
|
|
48
|
+
run: pip install -r requirements.txt # Uses tool-cache Python, not system Python
|
|
49
|
+
- language: yaml
|
|
50
|
+
label: "Use a virtual environment with system Python"
|
|
51
|
+
code: |
|
|
52
|
+
- name: Create venv and install
|
|
53
|
+
run: |
|
|
54
|
+
python3 -m venv .venv
|
|
55
|
+
.venv/bin/pip install -r requirements.txt
|
|
56
|
+
- name: Run tests
|
|
57
|
+
run: .venv/bin/pytest
|
|
58
|
+
prevention:
|
|
59
|
+
- "Always use actions/setup-python rather than relying on the runner's system Python"
|
|
60
|
+
- "If system Python must be used, wrap all pip calls in a virtual environment (python3 -m venv)"
|
|
61
|
+
- "Avoid pip install --break-system-packages in CI — it risks corrupting the runner environment"
|
|
62
|
+
- "Pin python-version in setup-python to avoid unexpected upgrades between runner image updates"
|
|
63
|
+
docs:
|
|
64
|
+
- url: "https://peps.python.org/pep-0668/"
|
|
65
|
+
label: "PEP 668 — Marking Python base environments as externally managed"
|
|
66
|
+
- url: "https://github.com/actions/setup-python"
|
|
67
|
+
label: "actions/setup-python — GitHub"
|
|
68
|
+
- url: "https://github.com/actions/runner-images/issues/6943"
|
|
69
|
+
label: "runner-images: PEP 668 externally-managed-environment on Ubuntu 22.04"
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
id: runner-environment-166
|
|
2
|
+
title: "actions/setup-dotnet Fails Installing EOL .NET 6 and .NET 7 — Version Not Found in Cache or CDN"
|
|
3
|
+
category: runner-environment
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- dotnet
|
|
7
|
+
- setup-dotnet
|
|
8
|
+
- eol
|
|
9
|
+
- version-not-found
|
|
10
|
+
- net6
|
|
11
|
+
- net7
|
|
12
|
+
patterns:
|
|
13
|
+
- regex: 'Error: Version \d+\.\d+\.[\dx]+ was not found in the local cache or download source'
|
|
14
|
+
flags: i
|
|
15
|
+
- regex: 'Error: Unable to find dotnet version.*satisf'
|
|
16
|
+
flags: i
|
|
17
|
+
- regex: 'Error: Could not find dotnet version matching'
|
|
18
|
+
flags: i
|
|
19
|
+
error_messages:
|
|
20
|
+
- "Error: Version 6.0.x was not found in the local cache or download source."
|
|
21
|
+
- "Error: Unable to find dotnet version that satisfies: 7.0"
|
|
22
|
+
- "Error: Could not find dotnet version matching '6.x'."
|
|
23
|
+
- "Failed to install dotnet from official website."
|
|
24
|
+
root_cause: |
|
|
25
|
+
.NET 6 reached end-of-life on November 12, 2024, and .NET 7 reached end-of-life on May 14, 2024.
|
|
26
|
+
After EOL, Microsoft removes these SDK builds from the official download CDN
|
|
27
|
+
(dotnetcli.azureedge.net). actions/setup-dotnet@v4+ will fail with "Version not found" when the
|
|
28
|
+
requested version is unavailable from Microsoft's servers and is absent from the GitHub-hosted
|
|
29
|
+
runner tool cache. Workflows pinned to dotnet-version: '6.x', '6.0.x', or '7.x' break silently
|
|
30
|
+
until CI runs after the removal date — no prior warning is given by the action.
|
|
31
|
+
fix: |
|
|
32
|
+
Upgrade to a supported .NET LTS version:
|
|
33
|
+
- .NET 8 (LTS, supported until November 10, 2026)
|
|
34
|
+
- .NET 9 (STS, supported until May 2026)
|
|
35
|
+
- .NET 10 (LTS, current preview)
|
|
36
|
+
|
|
37
|
+
Also update <TargetFramework> in .csproj files to match.
|
|
38
|
+
fix_code:
|
|
39
|
+
- language: yaml
|
|
40
|
+
label: "Upgrade from EOL .NET 6/7 to .NET 8 LTS"
|
|
41
|
+
code: |
|
|
42
|
+
- name: Setup .NET
|
|
43
|
+
uses: actions/setup-dotnet@v4
|
|
44
|
+
with:
|
|
45
|
+
dotnet-version: '8.x' # LTS — supported until November 2026
|
|
46
|
+
# dotnet-version: '6.x' # EOL November 12, 2024 — will fail
|
|
47
|
+
# dotnet-version: '7.x' # EOL May 14, 2024 — will fail
|
|
48
|
+
- name: Build
|
|
49
|
+
run: dotnet build
|
|
50
|
+
- language: yaml
|
|
51
|
+
label: "Matrix build across multiple supported .NET versions"
|
|
52
|
+
code: |
|
|
53
|
+
strategy:
|
|
54
|
+
matrix:
|
|
55
|
+
dotnet: ['8.x', '9.x']
|
|
56
|
+
steps:
|
|
57
|
+
- uses: actions/setup-dotnet@v4
|
|
58
|
+
with:
|
|
59
|
+
dotnet-version: ${{ matrix.dotnet }}
|
|
60
|
+
- run: dotnet test
|
|
61
|
+
prevention:
|
|
62
|
+
- "Use only LTS .NET versions in production CI (8.x, 10.x) for maximum support lifetime"
|
|
63
|
+
- "Track EOL dates at https://dotnet.microsoft.com/en-us/platform/support/policy/dotnet-core"
|
|
64
|
+
- "Set a calendar reminder for EOL dates to migrate at least 3 months before end-of-life"
|
|
65
|
+
- "Enable Dependabot for dotnet-version in workflow files to surface upgrade recommendations"
|
|
66
|
+
docs:
|
|
67
|
+
- url: "https://dotnet.microsoft.com/en-us/platform/support/policy/dotnet-core"
|
|
68
|
+
label: ".NET Support Lifecycle — Microsoft"
|
|
69
|
+
- url: "https://github.com/actions/setup-dotnet"
|
|
70
|
+
label: "actions/setup-dotnet — GitHub"
|
|
71
|
+
- url: "https://github.com/actions/setup-dotnet/issues/475"
|
|
72
|
+
label: "actions/setup-dotnet: EOL version download failures"
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
id: silent-failures-089
|
|
2
|
+
title: "macos-latest Silently Upgraded to macOS 15 (Sequoia) — Xcode 16 and Swift 6 Strictness"
|
|
3
|
+
category: silent-failures
|
|
4
|
+
severity: silent-failure
|
|
5
|
+
tags:
|
|
6
|
+
- macos
|
|
7
|
+
- xcode
|
|
8
|
+
- swift
|
|
9
|
+
- runner-version
|
|
10
|
+
- label-change
|
|
11
|
+
patterns:
|
|
12
|
+
- regex: 'Sending .* risks causing data races'
|
|
13
|
+
flags: i
|
|
14
|
+
- regex: 'does not conform to protocol .Sendable.'
|
|
15
|
+
flags: i
|
|
16
|
+
- regex: 'error: Expression is not assignable'
|
|
17
|
+
flags: i
|
|
18
|
+
error_messages:
|
|
19
|
+
- "error: Sending 'self' risks causing data races"
|
|
20
|
+
- "error: Type 'X' does not conform to protocol 'Sendable'"
|
|
21
|
+
- "note: annotate with '@MainActor' if property should only be accessed from the main actor"
|
|
22
|
+
root_cause: |
|
|
23
|
+
GitHub changed macos-latest to point to macOS 15 (Sequoia) with Xcode 16 in December 2024.
|
|
24
|
+
Xcode 16 enables Swift strict concurrency checking (Swift 6 language mode prerequisites) by
|
|
25
|
+
default. Workflows written and tested on macOS 14 (Sonoma) with Xcode 15 silently receive
|
|
26
|
+
macOS 15 with Xcode 16, which promotes Swift concurrency warnings to errors and enforces
|
|
27
|
+
Sendable conformance. Unlike a build failure with a clear version mismatch message, workflows
|
|
28
|
+
appear to run normally until the Swift compiler raises concurrency errors on previously clean code.
|
|
29
|
+
This mirrors the ubuntu-latest → ubuntu-24.04 silent label change (see silent-failures-059).
|
|
30
|
+
fix: |
|
|
31
|
+
Option 1 — Pin to macos-14 until your codebase is Swift 6 ready:
|
|
32
|
+
runs-on: macos-14
|
|
33
|
+
|
|
34
|
+
Option 2 — Disable strict concurrency checking temporarily:
|
|
35
|
+
Add SWIFT_STRICT_CONCURRENCY=minimal to xcodebuild arguments.
|
|
36
|
+
|
|
37
|
+
Option 3 — Migrate to Swift 6 concurrency (recommended long term):
|
|
38
|
+
Annotate types with @MainActor, Sendable, or nonisolated as appropriate.
|
|
39
|
+
Use async/await and actors for shared mutable state.
|
|
40
|
+
fix_code:
|
|
41
|
+
- language: yaml
|
|
42
|
+
label: "Pin to macos-14 until Swift 6 migration is complete"
|
|
43
|
+
code: |
|
|
44
|
+
jobs:
|
|
45
|
+
build:
|
|
46
|
+
runs-on: macos-14 # Pinned — avoids Xcode 16 Swift 6 strictness
|
|
47
|
+
# Use macos-15 once concurrency issues are resolved
|
|
48
|
+
steps:
|
|
49
|
+
- uses: actions/checkout@v4
|
|
50
|
+
- name: Build and test
|
|
51
|
+
run: xcodebuild test -scheme MyApp -destination 'platform=iOS Simulator,name=iPhone 15'
|
|
52
|
+
- language: yaml
|
|
53
|
+
label: "Disable Swift strict concurrency temporarily with SWIFT_STRICT_CONCURRENCY=minimal"
|
|
54
|
+
code: |
|
|
55
|
+
- name: Build with relaxed concurrency checking
|
|
56
|
+
run: |
|
|
57
|
+
xcodebuild build \
|
|
58
|
+
-scheme MyApp \
|
|
59
|
+
SWIFT_STRICT_CONCURRENCY=minimal
|
|
60
|
+
prevention:
|
|
61
|
+
- "Pin to a specific macOS version (macos-14, macos-15) instead of macos-latest for stability"
|
|
62
|
+
- "Follow GitHub Changelog for macos-latest label change announcements before they happen"
|
|
63
|
+
- "Run Xcode 16 locally with Swift strict concurrency enabled before CI failures surface"
|
|
64
|
+
- "Add a step printing runner OS version (sw_vers) to detect unexpected runner upgrades"
|
|
65
|
+
docs:
|
|
66
|
+
- url: "https://github.blog/changelog/2024-12-02-github-actions-macos-15-is-now-generally-available/"
|
|
67
|
+
label: "GitHub Changelog: macOS 15 Generally Available (Dec 2024)"
|
|
68
|
+
- url: "https://developer.apple.com/documentation/swift/updating-an-app-to-use-strict-concurrency"
|
|
69
|
+
label: "Apple: Updating an App to Use Strict Concurrency"
|
|
70
|
+
- url: "https://github.com/actions/runner-images/blob/main/images/macos/macos-15-Readme.md"
|
|
71
|
+
label: "macOS 15 Runner Image — Installed Software"
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
id: silent-failures-088
|
|
2
|
+
title: 'vars.* context: environment-scoped variable silently shadows repository and org variable'
|
|
3
|
+
category: silent-failures
|
|
4
|
+
severity: silent-failure
|
|
5
|
+
tags:
|
|
6
|
+
- vars
|
|
7
|
+
- variables
|
|
8
|
+
- environment
|
|
9
|
+
- precedence
|
|
10
|
+
- shadow
|
|
11
|
+
- configuration
|
|
12
|
+
patterns:
|
|
13
|
+
- regex: 'vars\.[A-Z_]+'
|
|
14
|
+
flags: 'i'
|
|
15
|
+
error_messages: []
|
|
16
|
+
root_cause: |
|
|
17
|
+
The vars.* context resolves configuration variables in strict precedence order:
|
|
18
|
+
environment-scoped > repository-level > organization-level. When a job specifies
|
|
19
|
+
an environment: key, any variable defined at that deployment environment's scope
|
|
20
|
+
with the same name as a repository or organization variable silently overrides
|
|
21
|
+
the higher-scope value.
|
|
22
|
+
|
|
23
|
+
No warning or error is emitted when shadowing occurs. The workflow runs
|
|
24
|
+
successfully but uses the environment-scoped value rather than the expected
|
|
25
|
+
org or repository value.
|
|
26
|
+
|
|
27
|
+
Common scenario: an organization defines vars.REGION='us-east-1' for all repos.
|
|
28
|
+
A production deployment environment defines vars.REGION='eu-west-1' to override
|
|
29
|
+
it for EU deploys. All jobs that reference the production environment now receive
|
|
30
|
+
'eu-west-1' — including notification jobs, post-deploy validation jobs, or any
|
|
31
|
+
other job that happens to run in the production environment but was not intended
|
|
32
|
+
to use the EU override.
|
|
33
|
+
|
|
34
|
+
Unlike secrets, where absence raises a validation error, variable shadowing is
|
|
35
|
+
entirely transparent to the workflow author. Debugging requires manually
|
|
36
|
+
inspecting variable scopes in GitHub Settings across three levels (org, repo,
|
|
37
|
+
environment) to find the effective value.
|
|
38
|
+
fix: |
|
|
39
|
+
Use scope-specific prefixes for variables that intentionally override
|
|
40
|
+
parent-scope defaults (e.g., PROD_REGION instead of REGION). Audit effective
|
|
41
|
+
variable values at runtime by echoing vars.* at the start of critical jobs.
|
|
42
|
+
|
|
43
|
+
To inspect what is currently configured:
|
|
44
|
+
- GitHub > Organization Settings > Variables (org-level)
|
|
45
|
+
- Repo Settings > Secrets and variables > Variables (repo-level)
|
|
46
|
+
- Repo Settings > Environments > <name> > Variables (environment-level)
|
|
47
|
+
fix_code:
|
|
48
|
+
- language: yaml
|
|
49
|
+
label: 'Debug effective vars.* resolution in a job with environment scope'
|
|
50
|
+
code: |
|
|
51
|
+
jobs:
|
|
52
|
+
deploy:
|
|
53
|
+
environment: production
|
|
54
|
+
runs-on: ubuntu-latest
|
|
55
|
+
steps:
|
|
56
|
+
- name: Audit effective variable values
|
|
57
|
+
run: |
|
|
58
|
+
echo "REGION (effective): ${{ vars.REGION }}"
|
|
59
|
+
# If this shows 'eu-west-1' when you expected 'us-east-1',
|
|
60
|
+
# the 'production' environment has a REGION variable that
|
|
61
|
+
# silently shadows the org or repository-level value.
|
|
62
|
+
- language: yaml
|
|
63
|
+
label: 'Use environment-scoped prefixes to make overrides explicit'
|
|
64
|
+
code: |
|
|
65
|
+
# Organization variable: REGION=us-east-1
|
|
66
|
+
# Environment 'production' variable: PROD_REGION=eu-west-1 (distinct name)
|
|
67
|
+
|
|
68
|
+
jobs:
|
|
69
|
+
deploy:
|
|
70
|
+
environment: production
|
|
71
|
+
runs-on: ubuntu-latest
|
|
72
|
+
steps:
|
|
73
|
+
- name: Deploy to production
|
|
74
|
+
run: |
|
|
75
|
+
# Explicit — no ambiguity about which scope is used
|
|
76
|
+
deploy --region ${{ vars.PROD_REGION }}
|
|
77
|
+
|
|
78
|
+
notify:
|
|
79
|
+
environment: production
|
|
80
|
+
runs-on: ubuntu-latest
|
|
81
|
+
steps:
|
|
82
|
+
- name: Notify
|
|
83
|
+
run: |
|
|
84
|
+
# Without prefix, this would silently get 'eu-west-1' instead
|
|
85
|
+
# of 'us-east-1' if REGION is defined at environment scope
|
|
86
|
+
notify --datacenter ${{ vars.NOTIFICATION_REGION }}
|
|
87
|
+
prevention:
|
|
88
|
+
- 'Prefix environment-scoped variable names to make overrides explicit — PROD_REGION not REGION'
|
|
89
|
+
- 'Audit all three variable scopes before deployments: org, repo, and environment'
|
|
90
|
+
- 'Add a comment in the workflow file documenting which variables each environment is expected to override'
|
|
91
|
+
- 'For critical deployment config, avoid relying on implicit variable inheritance — reference scope-prefixed names'
|
|
92
|
+
- 'Run a variable audit step at the start of critical jobs to log effective vars.* values'
|
|
93
|
+
docs:
|
|
94
|
+
- url: 'https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/store-information-in-variables#precedence-for-variable-values'
|
|
95
|
+
label: 'GitHub Docs — Variable precedence for the vars.* context'
|
|
96
|
+
- url: 'https://docs.github.com/en/actions/managing-workflow-runs-and-deployments/managing-deployments/managing-environments-for-deployment'
|
|
97
|
+
label: 'GitHub Docs — Managing environments for deployment'
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
id: yaml-syntax-061
|
|
2
|
+
title: 'env context unavailable in job-level timeout-minutes field'
|
|
3
|
+
category: yaml-syntax
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- env
|
|
7
|
+
- timeout-minutes
|
|
8
|
+
- context
|
|
9
|
+
- context-availability
|
|
10
|
+
- job-level
|
|
11
|
+
patterns:
|
|
12
|
+
- regex: 'Unrecognized named-value: .env.'
|
|
13
|
+
flags: 'i'
|
|
14
|
+
- regex: 'timeout-minutes.*\$\{\{.*env\.'
|
|
15
|
+
flags: 'i'
|
|
16
|
+
error_messages:
|
|
17
|
+
- "The workflow is not valid. .github/workflows/<workflow>.yml (Line: X, Col: Y): Unrecognized named-value: 'env'. Located at position Z within expression: env.MY_TIMEOUT"
|
|
18
|
+
root_cause: |
|
|
19
|
+
The env context is not available in job-level timeout-minutes expressions.
|
|
20
|
+
GitHub Actions evaluates jobs.<job_id>.timeout-minutes before steps run and
|
|
21
|
+
before step-level env values are populated. The available contexts at this
|
|
22
|
+
position are: github, inputs, vars, needs, strategy, and matrix only.
|
|
23
|
+
|
|
24
|
+
Developers commonly try to make timeouts configurable by setting a workflow-level
|
|
25
|
+
env: block (e.g., env: { JOB_TIMEOUT: 60 }) and referencing it as
|
|
26
|
+
${{ env.JOB_TIMEOUT }} in timeout-minutes, expecting it to work like env
|
|
27
|
+
references inside steps. This fails with a parse-time validation error because
|
|
28
|
+
the env context is not evaluated at job metadata positions.
|
|
29
|
+
|
|
30
|
+
Note: env IS available in step-level timeout-minutes
|
|
31
|
+
(jobs.<job_id>.steps[*].timeout-minutes) — this restriction only applies at
|
|
32
|
+
the job level. This asymmetry trips up developers who test in steps first
|
|
33
|
+
and then try to lift the same expression to job level.
|
|
34
|
+
fix: |
|
|
35
|
+
Use the vars context (repository or environment variables) instead of env for
|
|
36
|
+
job-level timeout-minutes. Repository variables can be set under
|
|
37
|
+
Settings > Secrets and variables > Variables and are available at job-evaluation
|
|
38
|
+
time.
|
|
39
|
+
|
|
40
|
+
If the timeout value needs to vary per workflow run, pass it as a workflow
|
|
41
|
+
input (inputs.*) for workflow_dispatch or workflow_call, or use matrix values
|
|
42
|
+
to parameterize timeouts per leg.
|
|
43
|
+
fix_code:
|
|
44
|
+
- language: yaml
|
|
45
|
+
label: 'Wrong — env context in job-level timeout-minutes (validation error)'
|
|
46
|
+
code: |
|
|
47
|
+
env:
|
|
48
|
+
JOB_TIMEOUT: 60
|
|
49
|
+
|
|
50
|
+
jobs:
|
|
51
|
+
build:
|
|
52
|
+
runs-on: ubuntu-latest
|
|
53
|
+
timeout-minutes: ${{ env.JOB_TIMEOUT }} # ERROR: env not available here
|
|
54
|
+
steps:
|
|
55
|
+
- run: make build
|
|
56
|
+
- language: yaml
|
|
57
|
+
label: 'Correct — use vars context for a configurable job timeout'
|
|
58
|
+
code: |
|
|
59
|
+
# Set JOB_TIMEOUT_MINUTES in repository Settings > Variables (e.g., "60")
|
|
60
|
+
jobs:
|
|
61
|
+
build:
|
|
62
|
+
runs-on: ubuntu-latest
|
|
63
|
+
timeout-minutes: ${{ fromJSON(vars.JOB_TIMEOUT_MINUTES || '60') }}
|
|
64
|
+
steps:
|
|
65
|
+
- run: make build
|
|
66
|
+
- language: yaml
|
|
67
|
+
label: 'Correct — pass timeout as workflow_dispatch input'
|
|
68
|
+
code: |
|
|
69
|
+
on:
|
|
70
|
+
workflow_dispatch:
|
|
71
|
+
inputs:
|
|
72
|
+
timeout:
|
|
73
|
+
type: number
|
|
74
|
+
default: 60
|
|
75
|
+
description: 'Job timeout in minutes'
|
|
76
|
+
|
|
77
|
+
jobs:
|
|
78
|
+
build:
|
|
79
|
+
runs-on: ubuntu-latest
|
|
80
|
+
timeout-minutes: ${{ inputs.timeout }}
|
|
81
|
+
steps:
|
|
82
|
+
- run: make build
|
|
83
|
+
prevention:
|
|
84
|
+
- 'Use vars.* (repository or environment variables) for static configurable timeouts at job level'
|
|
85
|
+
- 'Use inputs.* for runtime-configurable timeouts passed via workflow_dispatch or workflow_call'
|
|
86
|
+
- 'env context is only available at step level and below — not at the job metadata level'
|
|
87
|
+
- 'step-level timeout-minutes does support env context; only job-level timeout-minutes does not'
|
|
88
|
+
- 'Available contexts in job-level fields: github, inputs, vars, needs, strategy, matrix'
|
|
89
|
+
docs:
|
|
90
|
+
- url: 'https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/contexts#context-availability'
|
|
91
|
+
label: 'GitHub Docs — Context availability per workflow position'
|
|
92
|
+
- url: 'https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#jobsjob_idtimeout-minutes'
|
|
93
|
+
label: 'GitHub Docs — jobs.<job_id>.timeout-minutes'
|
package/package.json
CHANGED