@htekdev/actions-debugger 1.0.98 → 1.0.100

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,104 @@
1
+ id: caching-artifacts-055
2
+ title: 'setup-python cache: poetry broken when poetry is installed before setup-python — virtualenv 20.33.0+ Python version mismatch'
3
+ category: caching-artifacts
4
+ severity: error
5
+ tags:
6
+ - setup-python
7
+ - poetry
8
+ - cache
9
+ - virtualenv
10
+ - python-version
11
+ - pipx
12
+ - ordering
13
+ patterns:
14
+ - regex: 'Current Python version \([\d.]+\) is not allowed by the project'
15
+ flags: 'i'
16
+ - regex: 'poetry.*install.*exit code 1'
17
+ flags: 'i'
18
+ - regex: 'Please change python executable via the "env use" command'
19
+ flags: 'i'
20
+ - regex: 'installed package poetry.*using Python \d+\.\d+'
21
+ flags: 'i'
22
+ error_messages:
23
+ - "Current Python version (3.12.3) is not allowed by the project (>= 3.13, < 4). Please change python executable via the \"env use\" command."
24
+ - "Current Python version (3.11.9) is not allowed by the project (>=3.12,<3.13). Please change python executable via the \"env use\" command."
25
+ - "Error: Process completed with exit code 1."
26
+ root_cause: |
27
+ When using actions/setup-python with cache: 'poetry', the action requires
28
+ poetry to be installed BEFORE it runs (to resolve the cache path). Developers
29
+ commonly install poetry via pipx before calling setup-python, which causes
30
+ pipx to anchor poetry to the runner's pre-installed system Python (e.g., 3.12.3).
31
+
32
+ After setup-python runs and installs the project's target Python version
33
+ (e.g., 3.13), poetry's internal virtualenv logic still references the Python
34
+ version it was originally installed with. Consequently, when poetry creates
35
+ or activates a virtual environment, it resolves to the old Python version —
36
+ which violates the project's python requirement and produces the
37
+ "Current Python version is not allowed" error.
38
+
39
+ This became a consistent failure in August 2025 when virtualenv 20.33.0
40
+ changed how it resolves the Python interpreter for new virtual environments,
41
+ making the version mismatch explicit and fatal rather than silently using
42
+ the wrong interpreter.
43
+
44
+ The fundamental issue is a circular dependency in the documented workflow:
45
+ setup-python needs poetry installed to set up caching, but poetry must be
46
+ installed after setup-python to use the correct Python version.
47
+ fix: |
48
+ Use actions/cache manually instead of setup-python's built-in poetry cache.
49
+ Install poetry AFTER setup-python so it is anchored to the correct Python.
50
+ This avoids the circular ordering problem entirely.
51
+ fix_code:
52
+ - language: yaml
53
+ label: 'Workaround — Manual cache + install poetry after setup-python'
54
+ code: |
55
+ steps:
56
+ - uses: actions/setup-python@v5
57
+ id: setup-python
58
+ with:
59
+ python-version: '3.13'
60
+ # Do NOT use cache: 'poetry' here
61
+
62
+ - name: Install poetry
63
+ run: pipx install poetry
64
+
65
+ - name: Cache poetry virtualenv
66
+ uses: actions/cache@v4
67
+ with:
68
+ path: ~/.cache/pypoetry/virtualenvs
69
+ key: ${{ runner.os }}-poetry-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/poetry.lock') }}
70
+ restore-keys: |
71
+ ${{ runner.os }}-poetry-${{ steps.setup-python.outputs.python-version }}-
72
+
73
+ - name: Install dependencies
74
+ run: poetry install
75
+ - language: yaml
76
+ label: 'Alternative — pin virtualenv version as a short-term patch'
77
+ code: |
78
+ steps:
79
+ - name: Install poetry (with pinned virtualenv)
80
+ run: |
81
+ pipx install poetry
82
+ pipx inject poetry virtualenv==20.26.6
83
+
84
+ - uses: actions/setup-python@v5
85
+ with:
86
+ python-version: '3.13'
87
+ cache: 'poetry'
88
+
89
+ - name: Install dependencies
90
+ run: poetry install
91
+ prevention:
92
+ - "Never use setup-python cache: poetry in combination with a poetry install step that runs before setup-python."
93
+ - "Use actions/cache manually to avoid the circular dependency between poetry installation and Python version resolution."
94
+ - "Keep poetry updated — poetry 2.1.4+ partially mitigates the virtualenv version mismatch for some project configurations."
95
+ - "Use uv as an alternative to poetry; uv is installed on GitHub-hosted runners and handles Python version resolution differently."
96
+ docs:
97
+ - url: 'https://github.com/actions/setup-python/issues/1167'
98
+ label: 'actions/setup-python #1167 — Issues with poetry caching (Aug 2025)'
99
+ - url: 'https://github.com/python-poetry/poetry/issues/10490'
100
+ label: 'python-poetry/poetry #10490 — virtualenv 20.33.0 compatibility issue'
101
+ - url: 'https://github.com/pypa/virtualenv/issues/2931'
102
+ label: 'pypa/virtualenv #2931 — Python interpreter resolution change'
103
+ - url: 'https://github.com/actions/setup-python/blob/main/docs/advanced-usage.md#caching-packages'
104
+ label: 'actions/setup-python — Caching packages documentation'
@@ -0,0 +1,124 @@
1
+ id: known-unsolved-055
2
+ title: 'github.event.workflow_run.pull_requests is empty for fork PRs — PR context unavailable in triggered workflow'
3
+ category: known-unsolved
4
+ severity: silent-failure
5
+ tags:
6
+ - workflow_run
7
+ - fork
8
+ - pull-requests
9
+ - event-context
10
+ - security
11
+ - limitation
12
+ - pull_request
13
+ patterns:
14
+ - regex: 'github\.event\.workflow_run\.pull_requests'
15
+ flags: 'i'
16
+ - regex: 'pull_requests.*\[\]|workflow_run.*pull_requests.*empty'
17
+ flags: 'i'
18
+ error_messages:
19
+ - "# No error thrown — github.event.workflow_run.pull_requests evaluates to [] for fork PRs"
20
+ - "Error: PR number is empty or undefined"
21
+ - "Cannot read properties of undefined (reading 'number')"
22
+ root_cause: |
23
+ When a workflow is triggered by on: workflow_run: and the upstream workflow
24
+ was triggered by a pull_request event from a fork, the
25
+ github.event.workflow_run.pull_requests array is deliberately empty ([]).
26
+
27
+ For same-repository PRs, the pull_requests array is populated with PR
28
+ metadata (number, head.sha, head.ref, base.ref, etc.). For fork PRs, it
29
+ is always an empty array for security reasons: GitHub does not expose PR
30
+ metadata from fork branches through this event payload to prevent
31
+ untrusted code from accessing repository information via the privileged
32
+ workflow_run context.
33
+
34
+ This is a known, by-design limitation (GitHub closed the tracker issue as
35
+ "not planned"). The result is that workflows designed to comment on PRs,
36
+ post status checks, or download artifacts using the PR number silently
37
+ fail or crash when run against fork-originated pull requests because
38
+ github.event.workflow_run.pull_requests[0].number evaluates to undefined.
39
+
40
+ The limitation is easy to miss during development because the workflow
41
+ works correctly for PRs from within the same organization — the failure
42
+ only appears when an external contributor opens a fork PR.
43
+ fix: |
44
+ Pass the required PR information as an artifact from the upstream
45
+ (untrusted) workflow to the downstream (privileged) workflow_run workflow.
46
+ The upstream workflow writes the PR number to a file and uploads it as
47
+ an artifact; the downstream workflow downloads the artifact and reads
48
+ the PR number from it.
49
+
50
+ This is the officially documented pattern for safe fork PR workflows.
51
+ fix_code:
52
+ - language: yaml
53
+ label: 'Upstream (untrusted) workflow — upload PR number as artifact'
54
+ code: |
55
+ # .github/workflows/pr-checks.yml (runs on pull_request, limited privileges)
56
+ name: PR Checks
57
+ on:
58
+ pull_request:
59
+
60
+ jobs:
61
+ test:
62
+ runs-on: ubuntu-latest
63
+ steps:
64
+ - uses: actions/checkout@v4
65
+ - run: echo "${{ github.event.number }}" > pr_number.txt
66
+ - uses: actions/upload-artifact@v4
67
+ with:
68
+ name: pr-number
69
+ path: pr_number.txt
70
+ - language: yaml
71
+ label: 'Downstream (privileged) workflow — download artifact to get PR number'
72
+ code: |
73
+ # .github/workflows/pr-comment.yml (runs on workflow_run, full privileges)
74
+ name: PR Comment
75
+ on:
76
+ workflow_run:
77
+ workflows: ["PR Checks"]
78
+ types: [completed]
79
+
80
+ jobs:
81
+ comment:
82
+ runs-on: ubuntu-latest
83
+ steps:
84
+ - name: Download PR number artifact
85
+ uses: actions/github-script@v7
86
+ with:
87
+ script: |
88
+ const artifacts = await github.rest.actions.listWorkflowRunArtifacts({
89
+ owner: context.repo.owner,
90
+ repo: context.repo.repo,
91
+ run_id: context.payload.workflow_run.id,
92
+ });
93
+ const prArtifact = artifacts.data.artifacts.find(a => a.name === 'pr-number');
94
+ if (!prArtifact) { core.setFailed('No pr-number artifact'); return; }
95
+ const download = await github.rest.actions.downloadArtifact({
96
+ owner: context.repo.owner,
97
+ repo: context.repo.repo,
98
+ artifact_id: prArtifact.id,
99
+ archive_format: 'zip',
100
+ });
101
+ require('fs').writeFileSync('pr_number.zip', Buffer.from(download.data));
102
+ - run: unzip pr_number.zip && echo "PR=$(cat pr_number.txt)" >> $GITHUB_ENV
103
+ - name: Post comment
104
+ uses: actions/github-script@v7
105
+ with:
106
+ script: |
107
+ await github.rest.issues.createComment({
108
+ owner: context.repo.owner,
109
+ repo: context.repo.repo,
110
+ issue_number: Number(process.env.PR),
111
+ body: 'Checks passed!'
112
+ });
113
+ prevention:
114
+ - "Always use the artifact-passing pattern for workflow_run workflows that need PR context — never assume github.event.workflow_run.pull_requests is populated."
115
+ - "Check the triggering event type: if github.event.workflow_run.event == 'pull_request' and the array is empty, the PR came from a fork."
116
+ - "Use github.event.workflow_run.head_branch and head_sha for correlating runs, but not for PR numbers (which are unavailable for forks)."
117
+ - "Consider using the gh-action-pr-number community action which handles the artifact-based lookup pattern automatically."
118
+ docs:
119
+ - url: 'https://github.com/actions/runner/issues/3444'
120
+ label: 'actions/runner #3444 — workflow_run from fork pull_request lacks pull_requests payload'
121
+ - url: 'https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#using-data-from-the-triggering-workflow'
122
+ label: 'GitHub Docs — Using data from the triggering workflow (artifact pattern)'
123
+ - url: 'https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_run'
124
+ label: 'GitHub Docs — workflow_run event reference'
@@ -0,0 +1,101 @@
1
+ id: permissions-auth-058
2
+ title: 'actions/checkout does not rewrite ssh:// submodule URLs — only git@github.com: format is rewritten'
3
+ category: permissions-auth
4
+ severity: error
5
+ tags:
6
+ - checkout
7
+ - submodules
8
+ - ssh
9
+ - gitmodules
10
+ - URL-rewriting
11
+ - host-key-verification
12
+ - ssh-key
13
+ patterns:
14
+ - regex: 'Host key verification failed'
15
+ flags: 'i'
16
+ - regex: 'ssh://.*Permission denied|ssh://.*Could not read from remote'
17
+ flags: 'i'
18
+ - regex: 'fatal: clone of .ssh://. into submodule path .* failed'
19
+ flags: 'i'
20
+ - regex: 'git@github\.com.*vs.*ssh://github\.com'
21
+ flags: 'i'
22
+ error_messages:
23
+ - "Host key verification failed."
24
+ - "fatal: Could not read from remote repository."
25
+ - "Please make sure you have the correct access rights and the repository exists."
26
+ - "fatal: clone of 'ssh://git@github.com/Org/SubRepo.git' into submodule path '<path>' failed"
27
+ root_cause: |
28
+ actions/checkout rewrites submodule URLs in .gitmodules to inject the
29
+ provided ssh-key or GITHUB_TOKEN credentials, but the rewriting logic only
30
+ handles the git@github.com: URL format. URLs using the alternative
31
+ ssh://git@github.com/ scheme are NOT rewritten and are passed to git
32
+ as-is.
33
+
34
+ When git attempts to clone an ssh:// URL without an SSH agent providing
35
+ the key, and without the runner having github.com in ~/.ssh/known_hosts,
36
+ the clone fails with "Host key verification failed." or permission errors.
37
+
38
+ The affected code path is actions/checkout/src/git-auth-helper.ts which
39
+ contains an explicit regex that only matches the git@ style:
40
+ /^git@github\.com:/
41
+ The ssh:// variant does not match, so the credential injection and
42
+ known_hosts population steps are skipped for those URLs.
43
+
44
+ This is a confirmed open bug with a pending fix (PR #2367), but as of
45
+ early 2026 it remains unmerged and unreleased.
46
+ fix: |
47
+ Convert all submodule URLs in .gitmodules from ssh:// to git@github.com:
48
+ format. This ensures actions/checkout's URL rewriting logic applies the
49
+ SSH key and adds the host key to known_hosts.
50
+
51
+ If you cannot change .gitmodules (e.g., the submodule is a third-party
52
+ repo), use a manual git config insteadOf URL rewrite in a pre-checkout
53
+ step to normalize the URL before the checkout action runs.
54
+ fix_code:
55
+ - language: bash
56
+ label: 'Option A — Change .gitmodules to use git@ format instead of ssh://'
57
+ code: |
58
+ # .gitmodules — BEFORE (broken)
59
+ [submodule "MySubrepo"]
60
+ path = MySubrepo
61
+ url = ssh://git@github.com/Org/MySubrepo.git
62
+
63
+ # .gitmodules — AFTER (working)
64
+ [submodule "MySubrepo"]
65
+ path = MySubrepo
66
+ url = git@github.com:Org/MySubrepo.git
67
+ - language: yaml
68
+ label: 'Option B — Add git config URL rewrite step before checkout'
69
+ code: |
70
+ steps:
71
+ - name: Rewrite ssh:// submodule URLs to git@ format
72
+ run: |
73
+ git config --global url."git@github.com:".insteadOf "ssh://git@github.com/"
74
+
75
+ - uses: actions/checkout@v4
76
+ with:
77
+ submodules: recursive
78
+ ssh-key: ${{ secrets.SSH_DEPLOY_KEY }}
79
+ - language: yaml
80
+ label: 'Option C — Use HTTPS with token for submodule auth (avoids SSH entirely)'
81
+ code: |
82
+ steps:
83
+ - uses: actions/checkout@v4
84
+ with:
85
+ submodules: recursive
86
+ token: ${{ secrets.PAT_WITH_SUBMODULE_ACCESS }}
87
+ # Requires .gitmodules to use https:// URLs
88
+ prevention:
89
+ - "Standardize on git@github.com: format for all .gitmodules URLs in repositories using actions/checkout with SSH keys."
90
+ - "Use HTTPS URLs with a PAT for submodule access when possible — this is simpler and avoids SSH host key issues entirely."
91
+ - "Add a linting step (e.g., grep .gitmodules for ssh://) to your repo's pre-commit hooks to catch the wrong URL format early."
92
+ - "Track actions/checkout PR #2367 for the fix; upgrade once it is merged and released."
93
+ docs:
94
+ - url: 'https://github.com/actions/checkout/issues/2178'
95
+ label: 'actions/checkout #2178 — ssh:// URLs in .gitmodules do not work'
96
+ - url: 'https://github.com/actions/checkout/pull/2367'
97
+ label: 'actions/checkout PR #2367 — Fix: also rewrite ssh:// URLs'
98
+ - url: 'https://github.com/actions/checkout/blob/main/src/git-auth-helper.ts'
99
+ label: 'actions/checkout git-auth-helper.ts — URL rewriting source code'
100
+ - url: 'https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/using-conditions-to-control-job-execution'
101
+ label: 'GitHub Docs — Checking out submodules'
@@ -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,88 @@
1
+ id: runner-environment-169
2
+ title: 'actions/runner 2.320.0+ container image removes SSH — "error: cannot run ssh: No such file or directory"'
3
+ category: runner-environment
4
+ severity: error
5
+ tags:
6
+ - runner
7
+ - ssh
8
+ - openssh-client
9
+ - git-submodules
10
+ - self-hosted
11
+ - container-runner
12
+ - 2.320
13
+ patterns:
14
+ - regex: 'error: cannot run ssh: No such file or directory'
15
+ flags: 'i'
16
+ - regex: 'fatal: unable to fork'
17
+ flags: 'i'
18
+ - regex: 'Unable to locate executable file: ssh'
19
+ flags: 'i'
20
+ - regex: 'error downloading.*ssh://.*No such file or directory'
21
+ flags: 'i'
22
+ error_messages:
23
+ - "error: cannot run ssh: No such file or directory"
24
+ - "fatal: unable to fork"
25
+ - "Unable to locate executable file: ssh. Please verify either the file path exists or the file can be found within a directory specified by the PATH environment variable."
26
+ - "error downloading 'ssh://git@github.com/...': /usr/bin/git exited with 128: error: cannot run ssh: No such file or directory"
27
+ root_cause: |
28
+ Starting with actions/runner 2.320.0, the base container image
29
+ (ghcr.io/actions/actions-runner) no longer ships openssh-client by default.
30
+ Workflows that rely on git operations over SSH — including submodule cloning
31
+ via SSH URLs, Terragrunt module downloads over ssh://, or any step that
32
+ calls ssh-keyscan — fail at runtime because the ssh binary is absent from
33
+ the runner's PATH.
34
+
35
+ This affected both self-hosted runners built from the official container
36
+ image and any ephemeral runners (Actions Runner Controller / ARC) that
37
+ derive from ghcr.io/actions/actions-runner:2.320.0+. Hosted runners
38
+ (ubuntu-latest, etc.) were not affected because they use a separate,
39
+ pre-loaded VM image that still includes openssh-client.
40
+
41
+ The regression was introduced when the container image was slimmed down
42
+ between 2.319.1 and 2.320.0 without a corresponding changelog callout,
43
+ leaving self-hosted container runners silently broken on upgrade.
44
+ fix: |
45
+ Install openssh-client in the runner container image before the runner
46
+ process starts. For Dockerfiles extending the official image, add an
47
+ explicit RUN instruction. For ARC runner deployments, add an
48
+ initContainers step or a containerStartupCommand to install the package.
49
+
50
+ If you do not control the image, add an installation step at the top of
51
+ the failing workflow job before any SSH-dependent steps.
52
+ fix_code:
53
+ - language: yaml
54
+ label: 'Option A — Add install step in the workflow before any SSH steps'
55
+ code: |
56
+ jobs:
57
+ build:
58
+ runs-on: self-hosted
59
+ steps:
60
+ - name: Install SSH client
61
+ run: |
62
+ apt-get update -qq && apt-get install -y --no-install-recommends openssh-client
63
+ - name: Checkout with submodules
64
+ uses: actions/checkout@v4
65
+ with:
66
+ submodules: recursive
67
+ ssh-key: ${{ secrets.SSH_KEY }}
68
+ - language: dockerfile
69
+ label: 'Option B — Bake openssh-client into a custom runner image'
70
+ code: |
71
+ FROM ghcr.io/actions/actions-runner:latest
72
+ USER root
73
+ RUN apt-get update && apt-get install -y --no-install-recommends openssh-client && rm -rf /var/lib/apt/lists/*
74
+ USER runner
75
+ prevention:
76
+ - "Pin your ARC / self-hosted runner image to a tested version (e.g., ghcr.io/actions/actions-runner:2.319.1) and test upgrades in a staging environment before rolling out."
77
+ - "Add a pre-flight check step that runs 'which ssh || (apt-get install -y openssh-client)' if your workflow requires SSH."
78
+ - "Prefer HTTPS-based submodule URLs and GITHUB_TOKEN for submodule auth in GitHub Actions — this avoids SSH entirely."
79
+ - "Subscribe to the actions/runner GitHub Releases feed to catch breaking changes in container image composition."
80
+ docs:
81
+ - url: 'https://github.com/actions/runner/issues/3490'
82
+ label: 'actions/runner #3490 — Runner 2.320.0 no longer has SSH installed'
83
+ - url: 'https://github.com/actions/runner/issues/3488'
84
+ label: 'actions/runner #3488 — Runner version 2.320.0 breaks custom image'
85
+ - url: 'https://github.com/actions/checkout/issues/1942'
86
+ label: 'actions/checkout #1942 — Unable to locate executable file: ssh'
87
+ - url: 'https://github.com/actions/runner/releases'
88
+ label: 'actions/runner releases'
@@ -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,96 @@
1
+ id: silent-failures-090
2
+ title: '`github.event.pull_request.*` Fields Are Null on Non-PR Events — Comparisons Silently Evaluate Incorrectly'
3
+ category: silent-failures
4
+ severity: silent-failure
5
+ tags:
6
+ - github-context
7
+ - pull_request
8
+ - null-context
9
+ - push-event
10
+ - multi-event
11
+ - expression
12
+ patterns:
13
+ - regex: 'github\.event\.pull_request\.\w+'
14
+ flags: 'i'
15
+ error_messages:
16
+ - "Unexpected value '' in expression"
17
+ root_cause: |
18
+ When a workflow is triggered by a non-pull_request event — such as `push`, `schedule`,
19
+ `workflow_dispatch`, `workflow_call`, or `release` — the `github.event.pull_request`
20
+ object is null. Every child field evaluates to empty string `""` in expressions.
21
+
22
+ This silently breaks conditions in multi-event workflows:
23
+
24
+ - `if: github.event.pull_request.draft == false`
25
+ On a push event, `draft` resolves to `""`. The comparison `"" == false` evaluates to
26
+ FALSE (empty string is not boolean false), so the step silently skips.
27
+
28
+ - `if: github.event.pull_request.merged == true`
29
+ Always false on push events, causing steps intended for merged-PR context to silently
30
+ never execute.
31
+
32
+ - `env: PR_NUMBER: ${{ github.event.pull_request.number }}`
33
+ Sets `PR_NUMBER` to empty string on push events. Downstream scripts that require a
34
+ PR number fail with "invalid argument" or use `0` as the number.
35
+
36
+ - `if: github.event.pull_request.head.repo.fork != true`
37
+ Always evaluates to true on push events (empty string != true), bypassing fork guards.
38
+
39
+ The root issue is that workflows triggered by multiple events (e.g., `on: [push,
40
+ pull_request]`) share the same `if:` conditions and `env:` references, but the
41
+ `github.event` object structure differs per event type. Note that `yaml-syntax-060`
42
+ covers the object filter `.*` operator on null — this entry covers field-level null
43
+ comparisons in `if:` and `env:` contexts.
44
+ fix: |
45
+ Guard all `github.event.pull_request.*` access with an event type check:
46
+
47
+ if: github.event_name == 'pull_request' && github.event.pull_request.draft == false
48
+
49
+ For env variables that should only apply on PR events, set them conditionally:
50
+ use a step to export the variable only when running under a pull_request trigger,
51
+ or use separate jobs per event type.
52
+
53
+ For the fork guard pattern, use `github.event_name == 'pull_request' &&
54
+ github.event.pull_request.head.repo.fork` as a combined check rather than relying
55
+ on the fork field being non-null.
56
+ fix_code:
57
+ - language: yaml
58
+ label: "Guard PR context access with event type check in if: condition"
59
+ code: |
60
+ jobs:
61
+ check-draft:
62
+ runs-on: ubuntu-latest
63
+ steps:
64
+ - name: Skip if draft PR (only meaningful on PR events)
65
+ # Without the event_name guard, draft is "" on push — comparison silently fails
66
+ if: github.event_name != 'pull_request' || github.event.pull_request.draft == false
67
+ run: echo "Proceeding — not a draft PR"
68
+ - language: yaml
69
+ label: "Export PR-specific context safely in multi-event workflows"
70
+ code: |
71
+ on: [push, pull_request]
72
+
73
+ jobs:
74
+ deploy:
75
+ runs-on: ubuntu-latest
76
+ steps:
77
+ - name: Export PR metadata (PR events only)
78
+ if: github.event_name == 'pull_request'
79
+ run: |
80
+ echo "PR_NUMBER=${{ github.event.pull_request.number }}" >> $GITHUB_ENV
81
+ echo "IS_DRAFT=${{ github.event.pull_request.draft }}" >> $GITHUB_ENV
82
+
83
+ - name: Deploy
84
+ run: |
85
+ echo "Branch: ${{ github.ref_name }}"
86
+ # Use PR_NUMBER only after confirming event_name == pull_request above
87
+ prevention:
88
+ - "In multi-event workflows, always guard `github.event.pull_request.*` access with `github.event_name == 'pull_request'`"
89
+ - "Run actionlint on workflow files — it detects context availability mismatches per event type"
90
+ - "Test workflows manually for both push and pull_request trigger types to verify that conditional logic works as expected"
91
+ - "Prefer separate jobs or separate workflow files per event type rather than a single workflow handling multiple events with shared conditions"
92
+ docs:
93
+ - url: "https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows"
94
+ label: "GitHub Docs: Events that trigger workflows — context availability per event"
95
+ - url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/contexts#github-context"
96
+ label: "GitHub Docs: Contexts — github.event object structure"
@@ -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,82 @@
1
+ id: triggers-066
2
+ title: '`pull_request` Default Event Types Exclude `edited` — PR Title, Body, and Base Branch Changes Do Not Trigger CI'
3
+ category: triggers
4
+ severity: silent-failure
5
+ tags:
6
+ - pull_request
7
+ - event-types
8
+ - edited
9
+ - silent
10
+ - title-body
11
+ - default-types
12
+ patterns:
13
+ - regex: 'types:\s*\[.*edited.*\]'
14
+ flags: 'i'
15
+ error_messages:
16
+ - "Workflow not triggered on pull_request edited event"
17
+ root_cause: |
18
+ The `pull_request` event defaults to `types: [opened, synchronize, reopened]`.
19
+ The `edited` type — which fires when the PR title, body (description), base branch,
20
+ or milestone is modified — is NOT included in the defaults.
21
+
22
+ Workflows configured as `on: pull_request:` without an explicit `types:` key do NOT
23
+ run when a developer:
24
+ - Corrects a typo in the PR title
25
+ - Adds required information to the PR description (e.g., issue reference, testing notes)
26
+ - Changes the PR target base branch to a different branch
27
+
28
+ This creates a common silent failure: PR validation workflows that enforce title
29
+ conventions (Conventional Commits, Jira ticket format), required description sections,
30
+ or base branch policies run correctly on initial PR open and on new commits — but they
31
+ silently skip when the developer edits the PR title or description to fix a violation.
32
+ The developer believes CI re-ran and passed, but the workflow never executed.
33
+
34
+ This follows the same pattern as `labeled` and `ready_for_review` not being in
35
+ pull_request defaults — both are documented but frequently overlooked.
36
+ fix: |
37
+ Explicitly declare the types your workflow responds to. Add `edited` to the types list
38
+ for any workflow that validates or reacts to PR metadata:
39
+
40
+ on:
41
+ pull_request:
42
+ types: [opened, synchronize, reopened, edited]
43
+
44
+ Only include the types you actually need. Adding `edited` to workflows that don't use
45
+ PR metadata (title, body, base) causes unnecessary runs.
46
+ fix_code:
47
+ - language: yaml
48
+ label: "Include 'edited' in types to trigger on PR title and body changes"
49
+ code: |
50
+ on:
51
+ pull_request:
52
+ types: [opened, synchronize, reopened, edited]
53
+ - language: yaml
54
+ label: "Workflow that validates PR title only on open and edit events"
55
+ code: |
56
+ on:
57
+ pull_request:
58
+ types: [opened, edited] # Only metadata-relevant events — no need for synchronize
59
+
60
+ jobs:
61
+ validate-title:
62
+ runs-on: ubuntu-latest
63
+ steps:
64
+ - name: Check PR title format
65
+ env:
66
+ PR_TITLE: ${{ github.event.pull_request.title }}
67
+ run: |
68
+ echo "Validating title: $PR_TITLE"
69
+ if [[ ! "$PR_TITLE" =~ ^(feat|fix|chore|docs|refactor|test|ci)\: ]]; then
70
+ echo "ERROR: PR title must follow Conventional Commits format"
71
+ exit 1
72
+ fi
73
+ prevention:
74
+ - "Always explicitly list all required `types` in pull_request triggers — never rely on defaults for validation workflows"
75
+ - "Test PR validation workflows end-to-end by editing the PR title and verifying the workflow re-runs"
76
+ - "Add a comment above the `on:` block documenting which event types the workflow responds to and why"
77
+ - "Refer to the full list of pull_request event types in GitHub docs when creating new PR workflows"
78
+ docs:
79
+ - url: "https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#pull_request"
80
+ label: "GitHub Docs: Events that trigger workflows — pull_request"
81
+ - url: "https://docs.github.com/en/webhooks/webhook-events-and-payloads#pull_request"
82
+ label: "GitHub Docs: Webhook events — pull_request event payload and types"
@@ -0,0 +1,80 @@
1
+ id: triggers-065
2
+ title: '`[skip ci]` and `[skip actions]` Commit Message Flags Silently Skip All Triggered Workflows'
3
+ category: triggers
4
+ severity: silent-failure
5
+ tags:
6
+ - skip-ci
7
+ - commit-message
8
+ - workflow-skip
9
+ - silent
10
+ - push
11
+ - pull_request
12
+ patterns:
13
+ - regex: '\[skip[ -]ci\]'
14
+ flags: 'i'
15
+ - regex: '\[ci[ -]skip\]'
16
+ flags: 'i'
17
+ - regex: '\[skip actions\]'
18
+ flags: 'i'
19
+ error_messages:
20
+ - "[skip ci]"
21
+ - "[ci skip]"
22
+ - "[no ci]"
23
+ - "[skip actions]"
24
+ - "[actions skip]"
25
+ root_cause: |
26
+ GitHub Actions inspects the HEAD commit message (and all commits in a push batch) for
27
+ skip directives: [skip ci], [ci skip], [no ci], [skip actions], and [actions skip].
28
+ When any directive is found, GitHub skips ALL workflows triggered by that push or its
29
+ associated pull_request events — completely silently.
30
+
31
+ No workflow run is created, no status check is posted to the commit, no email or
32
+ notification is sent, and the PR shows "No checks" or prior checks disappear without
33
+ explanation. There is no indicator in the UI that workflows were intentionally skipped.
34
+
35
+ Common causes of unintended skips:
36
+ - Automated commits from bots (changelog updates, version bumps) that include [skip ci]
37
+ are squash-merged and the directive ends up in the merge commit message
38
+ - Dependabot or Renovate PRs that carry skip flags from upstream commit messages
39
+ - Developers testing locally add [skip ci] to a commit and forget to remove it before
40
+ the final push to a shared branch
41
+ - CI automation that auto-amends commit messages and inadvertently includes the pattern
42
+ fix: |
43
+ Remove the skip directive from the commit message. To re-trigger CI without rewriting
44
+ history, create an empty commit (a commit with no file changes) and upload it — this
45
+ creates a new push event without any skip directive.
46
+
47
+ If an automated process is adding skip flags unintentionally, update the automation's
48
+ commit template to exclude them. If the skip is intentional for one workflow but not
49
+ others, note that there is no per-workflow opt-out — the skip is global across all
50
+ workflows triggered by that push.
51
+
52
+ To control workflow execution without commit message flags, prefer path filters
53
+ (on.push.paths) or branch filters (on.push.branches) for selective CI execution.
54
+ fix_code:
55
+ - language: yaml
56
+ label: "Use path filters instead of commit-message skip flags to reduce unnecessary runs"
57
+ code: |
58
+ on:
59
+ push:
60
+ branches: [main]
61
+ paths:
62
+ - 'src/**'
63
+ - 'tests/**'
64
+ - '!docs/**' # Ignore documentation-only changes without needing [skip ci]
65
+ - language: yaml
66
+ label: "Add workflow_dispatch as a manual fallback trigger if push was silently skipped"
67
+ code: |
68
+ on:
69
+ push:
70
+ branches: [main]
71
+ workflow_dispatch: # Allows manual re-trigger if a skip-flagged push missed CI
72
+ prevention:
73
+ - "Audit any automation that commits to your repository and verify it does not include [skip ci] unless intentional"
74
+ - "Establish a team convention: [skip ci] skips ALL workflows — prefer path filters for selective skipping"
75
+ - "Review squash-merge commit messages before merging PRs whose titles contain skip directives"
76
+ - "Check the GitHub Actions tab for missing runs rather than assuming a test passed silently"
77
+ - "Use `on: workflow_dispatch` as a manual safety valve to re-run CI on any branch"
78
+ docs:
79
+ - url: "https://docs.github.com/en/actions/managing-workflow-runs-and-deployments/managing-workflow-runs/skipping-workflow-runs"
80
+ label: "GitHub Docs: Skipping workflow runs"
@@ -0,0 +1,94 @@
1
+ id: yaml-syntax-063
2
+ title: 'YAML Syntax Error in Workflow File Silently Hides Workflow from Actions UI and Disables `workflow_dispatch`'
3
+ category: yaml-syntax
4
+ severity: silent-failure
5
+ tags:
6
+ - yaml-syntax
7
+ - workflow-dispatch
8
+ - ui-hidden
9
+ - silent
10
+ - parse-error
11
+ - debugging
12
+ patterns:
13
+ - regex: 'invalid workflow file'
14
+ flags: 'i'
15
+ - regex: 'You have an error in your yaml syntax'
16
+ flags: 'i'
17
+ error_messages:
18
+ - "You have an error in your YAML syntax on line N"
19
+ - "No workflow file found for event"
20
+ - "invalid workflow file: .github/workflows/X.yml"
21
+ root_cause: |
22
+ When a GitHub Actions workflow file contains a YAML syntax error or schema validation
23
+ error, GitHub silently stops showing the workflow in the Actions tab and removes any
24
+ `workflow_dispatch` "Run workflow" button associated with it. No email, notification,
25
+ annotation, or repository-level banner is surfaced to warn the owner. The workflow
26
+ simply disappears from the UI.
27
+
28
+ Error categories that cause silent hiding:
29
+ - Standard YAML parse errors: incorrect indentation, unquoted colons in values,
30
+ duplicate keys, or tab characters used in place of spaces
31
+ - Missing required workflow keys: `runs-on` on a job, `steps` on a job, `on:` trigger
32
+ - Unrecognized keys that fail schema validation (e.g., typos in top-level keys)
33
+ - Invalid expression syntax inside `${{ }}` blocks
34
+ - Workflow exceeding GitHub's size limit (~500 KB)
35
+
36
+ This is distinct from the "workflow_dispatch button missing because the workflow file
37
+ is not on the default branch" issue. That error requires the file to be absent from
38
+ the default branch; this error occurs even when the file IS on the default branch but
39
+ is syntactically or structurally invalid.
40
+
41
+ Developers spend significant time investigating why CI "stopped running" or why the
42
+ dispatch button "disappeared" without realizing the workflow file has an error — because
43
+ GitHub provides no proactive notification.
44
+ fix: |
45
+ Validate workflow YAML before every change:
46
+
47
+ 1. Use actionlint locally to catch both YAML parse errors and GitHub Actions-specific
48
+ schema errors before the change reaches the default branch.
49
+ 2. Use the GitHub web editor — it highlights YAML parse errors inline as you type.
50
+ 3. Check the repository Actions tab: workflows with parse errors may show a yellow
51
+ warning triangle, or they may simply be absent from the list.
52
+ 4. Query the REST API to verify workflow state:
53
+ GET /repos/{owner}/{repo}/actions/workflows
54
+ Workflows missing from the response or with state "disabled_manually" may indicate
55
+ a parse failure on the default branch.
56
+ fix_code:
57
+ - language: yaml
58
+ label: "Add actionlint to CI to catch workflow YAML errors before they reach the default branch"
59
+ code: |
60
+ name: Lint Workflows
61
+ on:
62
+ pull_request:
63
+ paths:
64
+ - '.github/workflows/**'
65
+ jobs:
66
+ lint:
67
+ runs-on: ubuntu-latest
68
+ steps:
69
+ - uses: actions/checkout@v4
70
+ - name: Run actionlint
71
+ uses: rhysd/actionlint@latest
72
+ - language: yaml
73
+ label: "Correct structure for a minimal valid workflow file"
74
+ code: |
75
+ name: My Workflow # Optional but recommended
76
+ on: # Required: at least one trigger
77
+ push:
78
+ branches: [main]
79
+ jobs: # Required: at least one job
80
+ build: # Job ID
81
+ runs-on: ubuntu-latest # Required: runner label
82
+ steps: # Required: at least one step
83
+ - uses: actions/checkout@v4
84
+ prevention:
85
+ - "Install the actionlint VS Code extension to get inline YAML validation while editing workflow files"
86
+ - "Add a pull_request workflow that runs actionlint on all files under .github/workflows/ to catch errors before merging"
87
+ - "If workflow_dispatch button disappears, immediately check the Actions tab for parse error indicators"
88
+ - "Use GitHub's web editor for quick edits — it provides inline YAML validation"
89
+ - "Never use tab characters for indentation in YAML files — use spaces (2-space indent is standard)"
90
+ docs:
91
+ - url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/workflow-syntax-for-github-actions"
92
+ label: "GitHub Docs: Workflow syntax for GitHub Actions"
93
+ - url: "https://github.com/rhysd/actionlint"
94
+ label: "actionlint — Static checker for GitHub Actions workflow files"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@htekdev/actions-debugger",
3
- "version": "1.0.98",
3
+ "version": "1.0.100",
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",