@htekdev/actions-debugger 1.0.99 → 1.0.101
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/errors/caching-artifacts/caching-artifacts-055.yml +104 -0
- package/errors/caching-artifacts/caching-artifacts-056.yml +113 -0
- package/errors/caching-artifacts/caching-artifacts-057.yml +98 -0
- package/errors/known-unsolved/known-unsolved-055.yml +124 -0
- package/errors/permissions-auth/permissions-auth-058.yml +101 -0
- package/errors/permissions-auth/permissions-auth-059.yml +136 -0
- package/errors/permissions-auth/permissions-auth-060.yml +115 -0
- package/errors/runner-environment/runner-environment-169.yml +88 -0
- package/errors/runner-environment/runner-environment-170.yml +93 -0
- package/errors/silent-failures/github-event-pull-request-null-on-non-pr-events.yml +96 -0
- package/errors/silent-failures/silent-failures-091.yml +94 -0
- package/errors/triggers/pull-request-edited-type-not-in-defaults.yml +82 -0
- package/errors/triggers/skip-ci-commit-message-silently-skips-workflows.yml +80 -0
- package/errors/triggers/triggers-067.yml +134 -0
- package/errors/yaml-syntax/yaml-syntax-064.yml +119 -0
- package/errors/yaml-syntax/yaml-syntax-error-hides-workflow-from-actions-ui.yml +94 -0
- package/package.json +1 -1
|
@@ -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,134 @@
|
|
|
1
|
+
id: triggers-067
|
|
2
|
+
title: 'workflow_run types:[completed] fires prematurely with conclusion:null before referenced workflow finishes'
|
|
3
|
+
category: triggers
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- workflow_run
|
|
7
|
+
- conclusion
|
|
8
|
+
- null
|
|
9
|
+
- premature-trigger
|
|
10
|
+
- race-condition
|
|
11
|
+
- completed
|
|
12
|
+
patterns:
|
|
13
|
+
- regex: 'workflow_run\.conclusion.*null'
|
|
14
|
+
flags: 'i'
|
|
15
|
+
- regex: 'github\.event\.workflow_run\.conclusion'
|
|
16
|
+
flags: 'i'
|
|
17
|
+
- regex: 'conclusion.*randomly.*fail'
|
|
18
|
+
flags: 'i'
|
|
19
|
+
error_messages:
|
|
20
|
+
- "github.event.workflow_run.conclusion returned null — job skipped unexpectedly"
|
|
21
|
+
- "Unable to extend GITHUB_TOKEN expiration time due to: GITHUB_TOKEN has expired."
|
|
22
|
+
root_cause: |
|
|
23
|
+
The `workflow_run` event with `types: [completed]` is documented to fire only after the
|
|
24
|
+
referenced workflow finishes running. However, a known race condition in GitHub Actions'
|
|
25
|
+
event delivery (tracked in actions/runner#4035) causes the event to fire a second time
|
|
26
|
+
BEFORE the workflow has fully completed — specifically before GitHub has written the final
|
|
27
|
+
`conclusion` value to the workflow run record.
|
|
28
|
+
|
|
29
|
+
When this premature trigger fires, `github.event.workflow_run.conclusion` evaluates to
|
|
30
|
+
`null` (or an empty string `""`). Any job guarded with:
|
|
31
|
+
|
|
32
|
+
if: github.event.workflow_run.conclusion == 'success'
|
|
33
|
+
|
|
34
|
+
will evaluate to `false` and be skipped, producing a confusing pattern where the
|
|
35
|
+
downstream workflow runs twice — once skipped, once (correctly) executed.
|
|
36
|
+
|
|
37
|
+
GitHub Support confirmed this as a platform-side delay: the `conclusion` field remains
|
|
38
|
+
`null` while GitHub's backend is still updating the workflow run record. The event
|
|
39
|
+
is dispatched before the record is fully consistent.
|
|
40
|
+
|
|
41
|
+
This affects all workflows that use `on.workflow_run` with `types: [completed]` and
|
|
42
|
+
check `github.event.workflow_run.conclusion` to gate job execution.
|
|
43
|
+
fix: |
|
|
44
|
+
Two mitigations are available:
|
|
45
|
+
|
|
46
|
+
1. **Guard with `conclusion != ''`** — Add a condition that explicitly rejects null/empty
|
|
47
|
+
`conclusion` values before checking for `'success'`:
|
|
48
|
+
|
|
49
|
+
if: >-
|
|
50
|
+
github.event.workflow_run.conclusion != '' &&
|
|
51
|
+
github.event.workflow_run.conclusion == 'success'
|
|
52
|
+
|
|
53
|
+
2. **Re-query via REST API** — Instead of trusting `github.event.workflow_run.conclusion`,
|
|
54
|
+
use the Actions REST API to fetch the current workflow run conclusion at step runtime:
|
|
55
|
+
|
|
56
|
+
gh api /repos/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }} \
|
|
57
|
+
--jq '.conclusion'
|
|
58
|
+
|
|
59
|
+
This always returns the up-to-date value, bypassing the event payload race condition.
|
|
60
|
+
|
|
61
|
+
Note: adding a `sleep` between trigger and conclusion check is NOT a reliable fix, as
|
|
62
|
+
the delay between trigger and backend consistency is variable and can exceed seconds.
|
|
63
|
+
fix_code:
|
|
64
|
+
- language: yaml
|
|
65
|
+
label: 'Problem: conclusion check fails on premature null trigger'
|
|
66
|
+
code: |
|
|
67
|
+
on:
|
|
68
|
+
workflow_run:
|
|
69
|
+
workflows: ['CI Build']
|
|
70
|
+
types: [completed]
|
|
71
|
+
|
|
72
|
+
jobs:
|
|
73
|
+
deploy:
|
|
74
|
+
# This randomly evaluates to false when conclusion is null
|
|
75
|
+
if: github.event.workflow_run.conclusion == 'success'
|
|
76
|
+
runs-on: ubuntu-latest
|
|
77
|
+
steps:
|
|
78
|
+
- run: echo "Deploying..."
|
|
79
|
+
- language: yaml
|
|
80
|
+
label: 'Fix: guard against null conclusion before equality check'
|
|
81
|
+
code: |
|
|
82
|
+
on:
|
|
83
|
+
workflow_run:
|
|
84
|
+
workflows: ['CI Build']
|
|
85
|
+
types: [completed]
|
|
86
|
+
|
|
87
|
+
jobs:
|
|
88
|
+
deploy:
|
|
89
|
+
# Explicitly reject null/empty conclusion to avoid premature-trigger skips
|
|
90
|
+
if: >-
|
|
91
|
+
github.event.workflow_run.conclusion != '' &&
|
|
92
|
+
github.event.workflow_run.conclusion == 'success'
|
|
93
|
+
runs-on: ubuntu-latest
|
|
94
|
+
steps:
|
|
95
|
+
- run: echo "Deploying..."
|
|
96
|
+
- language: yaml
|
|
97
|
+
label: 'Fix: re-query conclusion via REST API for reliable value'
|
|
98
|
+
code: |
|
|
99
|
+
on:
|
|
100
|
+
workflow_run:
|
|
101
|
+
workflows: ['CI Build']
|
|
102
|
+
types: [completed]
|
|
103
|
+
|
|
104
|
+
jobs:
|
|
105
|
+
deploy:
|
|
106
|
+
runs-on: ubuntu-latest
|
|
107
|
+
steps:
|
|
108
|
+
- name: Check conclusion via API
|
|
109
|
+
id: check
|
|
110
|
+
env:
|
|
111
|
+
GH_TOKEN: ${{ github.token }}
|
|
112
|
+
run: |
|
|
113
|
+
conclusion=$(gh api \
|
|
114
|
+
/repos/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }} \
|
|
115
|
+
--jq '.conclusion')
|
|
116
|
+
echo "conclusion=$conclusion" >> "$GITHUB_OUTPUT"
|
|
117
|
+
|
|
118
|
+
- name: Deploy
|
|
119
|
+
if: steps.check.outputs.conclusion == 'success'
|
|
120
|
+
run: echo "Deploying..."
|
|
121
|
+
prevention:
|
|
122
|
+
- "Never rely solely on `github.event.workflow_run.conclusion == 'success'` without a null guard."
|
|
123
|
+
- "Add `github.event.workflow_run.conclusion != ''` as an explicit first condition to reject premature triggers."
|
|
124
|
+
- "If downstream jobs must be fully reliable, re-query conclusion via the REST API rather than reading from the event payload."
|
|
125
|
+
- "Monitor the Actions tab for unexpectedly skipped `workflow_run` triggered runs — they indicate premature triggers."
|
|
126
|
+
docs:
|
|
127
|
+
- url: 'https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#workflow_run'
|
|
128
|
+
label: 'GitHub Docs: workflow_run event'
|
|
129
|
+
- url: 'https://github.com/actions/runner/issues/4035'
|
|
130
|
+
label: 'actions/runner#4035: workflow_run triggers before referenced workflow completes'
|
|
131
|
+
- url: 'https://stackoverflow.com/questions/73107307/any-workaround-for-github-actions-workflow-run-conclusion-randomly-failing'
|
|
132
|
+
label: 'Stack Overflow: workflow_run.conclusion randomly failing'
|
|
133
|
+
- url: 'https://github.com/orgs/community/discussions/58929'
|
|
134
|
+
label: 'GitHub Community #58929: github.event.workflow_run.conclusion is always null'
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
id: yaml-syntax-064
|
|
2
|
+
title: 'strategy.matrix.include/exclude entry value specified as array causes "A sequence was not expected"'
|
|
3
|
+
category: yaml-syntax
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- matrix
|
|
7
|
+
- include
|
|
8
|
+
- exclude
|
|
9
|
+
- array-value
|
|
10
|
+
- sequence
|
|
11
|
+
- validation-error
|
|
12
|
+
- strategy
|
|
13
|
+
patterns:
|
|
14
|
+
- regex: 'A sequence was not expected'
|
|
15
|
+
flags: 'i'
|
|
16
|
+
- regex: 'matrix\.(include|exclude).*\[.*\]'
|
|
17
|
+
flags: 'i'
|
|
18
|
+
- regex: 'strategy.*matrix.*include.*sequence'
|
|
19
|
+
flags: 'i'
|
|
20
|
+
error_messages:
|
|
21
|
+
- "Error: The template is not valid. .github/workflows/workflow.yml (Line: 12, Col: 18): A sequence was not expected"
|
|
22
|
+
- "A sequence was not expected"
|
|
23
|
+
root_cause: |
|
|
24
|
+
In a `strategy.matrix`, the top-level matrix dimensions accept arrays of scalars:
|
|
25
|
+
|
|
26
|
+
php: ['8.2', '8.3', '8.4'] # valid — array of scalars
|
|
27
|
+
|
|
28
|
+
However, inside `include:` and `exclude:` entries, ALL values must be scalars
|
|
29
|
+
(string, number, boolean). Arrays are not allowed:
|
|
30
|
+
|
|
31
|
+
include:
|
|
32
|
+
- os: ubuntu-latest
|
|
33
|
+
php: ['8.2'] # INVALID — array not allowed in include/exclude entries
|
|
34
|
+
|
|
35
|
+
This is a common mistake when a developer copies the variable name from the main
|
|
36
|
+
matrix definition (where it IS an array) and pastes it into an `include:` or
|
|
37
|
+
`exclude:` entry without unwrapping it.
|
|
38
|
+
|
|
39
|
+
GitHub Actions' expression evaluator validates the template before execution and
|
|
40
|
+
throws an immediate hard failure:
|
|
41
|
+
|
|
42
|
+
Error: The template is not valid. .github/workflows/X.yml (Line: N, Col: M):
|
|
43
|
+
A sequence was not expected
|
|
44
|
+
|
|
45
|
+
The error points to the line where the array value starts (the `[` character),
|
|
46
|
+
which can be confusing because arrays are valid YAML and valid in other matrix
|
|
47
|
+
contexts. The fix is simply to remove the brackets and use a scalar value.
|
|
48
|
+
|
|
49
|
+
Tracked in rhysd/actionlint#630 (actionlint static analysis issue requesting
|
|
50
|
+
detection of this pattern).
|
|
51
|
+
fix: |
|
|
52
|
+
Replace any array-valued entries inside `include:` or `exclude:` with scalar values.
|
|
53
|
+
Each `include:`/`exclude:` entry is a single-combination filter — it selects or adds
|
|
54
|
+
one specific combination, so the value must be a scalar that matches exactly one item.
|
|
55
|
+
|
|
56
|
+
If you need to include multiple values for a key, write separate `include:` entries,
|
|
57
|
+
one per value.
|
|
58
|
+
fix_code:
|
|
59
|
+
- language: yaml
|
|
60
|
+
label: 'Problem: array value inside include entry — triggers "A sequence was not expected"'
|
|
61
|
+
code: |
|
|
62
|
+
strategy:
|
|
63
|
+
matrix:
|
|
64
|
+
os: [ubuntu-latest, macos-latest]
|
|
65
|
+
php: ['8.3', '8.4', '8.5']
|
|
66
|
+
|
|
67
|
+
include:
|
|
68
|
+
# ERROR: php value is an array — not allowed inside include entries
|
|
69
|
+
- os: ubuntu-latest
|
|
70
|
+
php: ['8.2'] # ← "A sequence was not expected" on this line
|
|
71
|
+
|
|
72
|
+
exclude:
|
|
73
|
+
# ERROR: os value is an array — not allowed inside exclude entries
|
|
74
|
+
- os: [macos-latest]
|
|
75
|
+
php: '8.3' # ← "A sequence was not expected"
|
|
76
|
+
- language: yaml
|
|
77
|
+
label: 'Fix: use scalar values inside include/exclude entries'
|
|
78
|
+
code: |
|
|
79
|
+
strategy:
|
|
80
|
+
matrix:
|
|
81
|
+
os: [ubuntu-latest, macos-latest]
|
|
82
|
+
php: ['8.3', '8.4', '8.5']
|
|
83
|
+
|
|
84
|
+
include:
|
|
85
|
+
# CORRECT: scalar value — adds ubuntu-latest × 8.2 as an extra job
|
|
86
|
+
- os: ubuntu-latest
|
|
87
|
+
php: '8.2' # ← scalar, not array
|
|
88
|
+
|
|
89
|
+
exclude:
|
|
90
|
+
# CORRECT: scalar value — excludes macos-latest × 8.3 combination
|
|
91
|
+
- os: macos-latest
|
|
92
|
+
php: '8.3' # ← scalar, not array
|
|
93
|
+
- language: yaml
|
|
94
|
+
label: 'Multiple include entries for multiple specific combinations'
|
|
95
|
+
code: |
|
|
96
|
+
strategy:
|
|
97
|
+
matrix:
|
|
98
|
+
os: [ubuntu-latest, macos-latest]
|
|
99
|
+
node: [18, 20]
|
|
100
|
+
|
|
101
|
+
include:
|
|
102
|
+
# To include multiple specific combinations, write separate entries:
|
|
103
|
+
- os: ubuntu-latest
|
|
104
|
+
node: 22 # one entry per extra combination
|
|
105
|
+
- os: ubuntu-latest
|
|
106
|
+
node: 23 # another entry for a different combination
|
|
107
|
+
# NOT: node: [22, 23] ← this would fail with "A sequence was not expected"
|
|
108
|
+
prevention:
|
|
109
|
+
- "Values inside `include:` and `exclude:` entries must be scalars — never use array syntax `[...]` there."
|
|
110
|
+
- "When copying matrix variable names from the top-level dimensions to include/exclude entries, remove the brackets."
|
|
111
|
+
- "Use actionlint (github.com/rhysd/actionlint) to statically validate your workflow files before pushing."
|
|
112
|
+
- "If you need multiple combinations, write multiple separate `include:` entries instead of one entry with an array value."
|
|
113
|
+
docs:
|
|
114
|
+
- url: 'https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/running-variations-of-jobs-in-a-workflow#expanding-or-adding-matrix-configurations'
|
|
115
|
+
label: 'GitHub Docs: Expanding or adding matrix configurations'
|
|
116
|
+
- url: 'https://github.com/rhysd/actionlint/issues/630'
|
|
117
|
+
label: 'rhysd/actionlint#630: Detect array values in matrix include/exclude entries'
|
|
118
|
+
- url: 'https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#jobsjob_idstrategymatrixinclude'
|
|
119
|
+
label: 'GitHub Docs: jobs.<job_id>.strategy.matrix.include syntax reference'
|
|
@@ -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