@htekdev/actions-debugger 1.0.23 → 1.0.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/errors/caching-artifacts/artifact-minimum-retention-one-day.yml +153 -0
- package/errors/caching-artifacts/cache-api-propagation-delay-post-save.yml +128 -0
- package/errors/caching-artifacts/cache-backend-internal-error-skipped.yml +75 -0
- package/errors/caching-artifacts/cache-hit-step-id-case-sensitive-mismatch.yml +95 -0
- package/errors/caching-artifacts/cache-save-post-step-skipped-on-failure.yml +114 -0
- package/errors/concurrency-timing/deploy-pages-in-progress-deployment-wedged.yml +70 -0
- package/errors/concurrency-timing/deployment-review-timeout-expired.yml +88 -0
- package/errors/concurrency-timing/job-concurrency-scope-per-run-not-global.yml +81 -0
- package/errors/concurrency-timing/merge-queue-concurrency-cancel-blocks-all.yml +86 -0
- package/errors/concurrency-timing/reusable-workflow-github-workflow-context-cancel.yml +124 -0
- package/errors/concurrency-timing/runner-scale-set-jobs-never-start.yml +123 -0
- package/errors/concurrency-timing/runner-temp-dir-race-concurrent-workers.yml +90 -0
- package/errors/known-unsolved/artifact-download-url-unauthenticated-404.yml +98 -0
- package/errors/known-unsolved/checkout-v6-credentials-docker-run-manual.yml +105 -0
- package/errors/known-unsolved/concurrency-groups-repo-scoped-only.yml +138 -0
- package/errors/known-unsolved/matrix-256-job-limit.yml +142 -0
- package/errors/known-unsolved/merge-group-paths-filter-not-supported.yml +137 -0
- package/errors/known-unsolved/no-job-allow-failure.yml +73 -0
- package/errors/known-unsolved/schedule-cron-hours-long-queue-drift.yml +101 -0
- package/errors/permissions-auth/checkout-persist-credentials-token-write.yml +90 -0
- package/errors/permissions-auth/create-github-app-token-cross-job-token-revoked.yml +95 -0
- package/errors/permissions-auth/github-token-contents-write-missing-git-push.yml +117 -0
- package/errors/permissions-auth/org-actions-policy-blocks-unapproved-action.yml +106 -0
- package/errors/runner-environment/codeql-action-v2-deprecated.yml +110 -0
- package/errors/runner-environment/macos-26-openssl-3-system-library-breaking.yml +114 -0
- package/errors/runner-environment/macos-26-ruby-34-default-upgrade.yml +114 -0
- package/errors/runner-environment/macos-26-xcode-default-265-pin-required.yml +99 -0
- package/errors/runner-environment/macos-latest-label-switches-to-macos26.yml +127 -0
- package/errors/runner-environment/node20-removed-toolcache-default-node22.yml +104 -0
- package/errors/runner-environment/powershell-74-76-threadjob-module-rename.yml +124 -0
- package/errors/runner-environment/self-hosted-runner-not-found.yml +134 -0
- package/errors/runner-environment/self-hosted-runner-selinux-service-exec-failure.yml +116 -0
- package/errors/runner-environment/service-container-no-healthcheck.yml +158 -0
- package/errors/runner-environment/setup-node-v5-corepack-pnpm-not-found.yml +101 -0
- package/errors/runner-environment/setup-node-yarn-not-installed-self-hosted.yml +76 -0
- package/errors/runner-environment/setup-python-externally-managed-env-error.yml +95 -0
- package/errors/runner-environment/windows-2019-runner-retired-june2025.yml +118 -0
- package/errors/runner-environment/windows-2022-docker-daemon-not-started.yml +108 -0
- package/errors/silent-failures/cache-hit-output-string-not-boolean.yml +96 -0
- package/errors/silent-failures/checkout-lfs-pointer-not-content.yml +105 -0
- package/errors/silent-failures/reusable-workflow-output-skipped-contains-secret.yml +115 -0
- package/errors/silent-failures/setup-node-silent-download-exit-zero.yml +105 -0
- package/errors/silent-failures/setup-python-truncated-manifest-silent-exit.yml +111 -0
- package/errors/silent-failures/undefined-env-expression-empty-string-silent.yml +115 -0
- package/errors/silent-failures/windows-powershell-github-output-bash-syntax.yml +118 -0
- package/errors/triggers/fork-pr-first-time-contributor-approval-required.yml +142 -0
- package/errors/triggers/on-push-branches-glob-star-no-slash-match.yml +78 -0
- package/errors/triggers/pull-request-target-env-protection-default-branch-eval.yml +117 -0
- package/errors/triggers/required-status-check-renamed-never-passes.yml +87 -0
- package/errors/triggers/schedule-cron-self-hosted-runner-not-triggered.yml +107 -0
- package/errors/yaml-syntax/composite-action-run-shell-missing.yml +90 -0
- package/errors/yaml-syntax/composite-action-secrets-context-unavailable.yml +99 -0
- package/errors/yaml-syntax/github-script-octokit-renamed-to-github.yml +130 -0
- package/errors/yaml-syntax/labeler-v5-config-format-breaking.yml +67 -0
- package/errors/yaml-syntax/runs-on-expression-array-syntax-error.yml +121 -0
- package/errors/yaml-syntax/setup-go-matrix-version-float-coercion.yml +69 -0
- package/package.json +1 -1
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
id: triggers-022
|
|
2
|
+
title: "Fork PR Workflows Paused — First-Time Contributor Requires Approval"
|
|
3
|
+
category: triggers
|
|
4
|
+
severity: warning
|
|
5
|
+
tags:
|
|
6
|
+
- fork
|
|
7
|
+
- pull_request
|
|
8
|
+
- first-time-contributor
|
|
9
|
+
- approval
|
|
10
|
+
- secrets
|
|
11
|
+
- outside-collaborator
|
|
12
|
+
patterns:
|
|
13
|
+
- regex: "This run (?:was triggered by a (?:first-time contributor|new GitHub user)|requires approval)"
|
|
14
|
+
flags: "i"
|
|
15
|
+
- regex: "Workflow run requires approval"
|
|
16
|
+
flags: "i"
|
|
17
|
+
- regex: "requires approval from a maintainer"
|
|
18
|
+
flags: "i"
|
|
19
|
+
- regex: "waiting for approval"
|
|
20
|
+
flags: "i"
|
|
21
|
+
error_messages:
|
|
22
|
+
- "This run was triggered by a first-time contributor and requires approval from a maintainer with write access."
|
|
23
|
+
- "Workflow run requires approval"
|
|
24
|
+
- "This run requires approval from a maintainer with write access."
|
|
25
|
+
root_cause: |
|
|
26
|
+
GitHub requires manual approval before running workflows triggered by pull
|
|
27
|
+
requests from forked repositories when the contributor meets certain criteria.
|
|
28
|
+
This is a security measure to prevent untrusted code from accessing repository
|
|
29
|
+
secrets or running CI at the organization's expense.
|
|
30
|
+
|
|
31
|
+
GitHub's fork PR approval policy (configurable per repo, org, or enterprise)
|
|
32
|
+
determines when approval is required. The default for public repos is:
|
|
33
|
+
"Require approval for first-time contributors who are new to GitHub" — meaning
|
|
34
|
+
contributors who have never contributed to any public GitHub repo need approval
|
|
35
|
+
on their first PR. For private repos, the default is to require approval from
|
|
36
|
+
all outside collaborators.
|
|
37
|
+
|
|
38
|
+
When approval is required, the workflow run is shown in the Actions tab with
|
|
39
|
+
a yellow banner reading "This run was triggered by a first-time contributor
|
|
40
|
+
and requires approval from a maintainer with write access." The workflow does
|
|
41
|
+
not start until a maintainer with write access clicks "Approve and run."
|
|
42
|
+
|
|
43
|
+
Workflows awaiting approval for more than 30 days are automatically deleted.
|
|
44
|
+
Importantly, if no maintainer approves the run, CI results will never appear
|
|
45
|
+
on the pull request — blocking any required status checks from passing and
|
|
46
|
+
preventing the PR from being merged.
|
|
47
|
+
|
|
48
|
+
Three root causes are commonly conflated:
|
|
49
|
+
1. First-time contributor to GitHub (no prior public repo contributions).
|
|
50
|
+
2. First-time contributor to this specific repository (even if experienced on GitHub).
|
|
51
|
+
3. Outside collaborator (not a member of the org that owns the repo).
|
|
52
|
+
|
|
53
|
+
The approval gate is per-workflow-run, not per-PR. If a contributor pushes
|
|
54
|
+
additional commits to an already-approved PR, each new push triggers a new
|
|
55
|
+
run that must be re-approved.
|
|
56
|
+
fix: |
|
|
57
|
+
Option 1 — Approve manually (per-run action):
|
|
58
|
+
Go to the repository's Actions tab → find the pending workflow run with the
|
|
59
|
+
yellow approval banner → click "Approve and run". Repeat for each new commit
|
|
60
|
+
push by the same contributor.
|
|
61
|
+
|
|
62
|
+
Option 2 — Change the approval policy (repo setting):
|
|
63
|
+
Go to Settings → Actions → General → Fork pull request workflows.
|
|
64
|
+
Change from "Require approval for first-time contributors who are new to GitHub"
|
|
65
|
+
to "Require approval for first-time contributors" (blocks all new contributors
|
|
66
|
+
to THIS repo, not all of GitHub) or "Not required" (disables the gate entirely).
|
|
67
|
+
Note: "Not required" means secrets are accessible to fork PR workflows —
|
|
68
|
+
only use this for private repos or repos with no sensitive secrets.
|
|
69
|
+
|
|
70
|
+
Option 3 — Use pull_request_target for secret-free PR workflows:
|
|
71
|
+
If you only need access to repository secrets in a separate, controlled job,
|
|
72
|
+
use pull_request_target instead of pull_request. The pull_request_target
|
|
73
|
+
event runs in the context of the base repo and has access to secrets, but
|
|
74
|
+
you should NEVER check out the PR's code and run it — only read PR metadata.
|
|
75
|
+
|
|
76
|
+
Option 4 — Approve all runs for a contributor via REST API:
|
|
77
|
+
POST /repos/{owner}/{repo}/actions/runs/{run_id}/approve
|
|
78
|
+
Use this to batch-approve pending runs from a trusted contributor programmatically.
|
|
79
|
+
fix_code:
|
|
80
|
+
- language: yaml
|
|
81
|
+
label: "Change approval policy — require approval for first-time contributors to THIS repo only"
|
|
82
|
+
code: |
|
|
83
|
+
# In GitHub UI: Settings → Actions → General → Fork pull request workflows
|
|
84
|
+
# Select: "Require approval for first-time contributors"
|
|
85
|
+
# This is the balanced option — trusts repeat contributors, gates new ones.
|
|
86
|
+
|
|
87
|
+
# For automation workflows that need to run on all fork PRs without approval,
|
|
88
|
+
# use pull_request_target (read-only PR metadata only — NEVER run PR code):
|
|
89
|
+
on:
|
|
90
|
+
pull_request_target:
|
|
91
|
+
types: [opened, synchronize]
|
|
92
|
+
|
|
93
|
+
jobs:
|
|
94
|
+
label:
|
|
95
|
+
runs-on: ubuntu-latest
|
|
96
|
+
permissions:
|
|
97
|
+
pull-requests: write
|
|
98
|
+
steps:
|
|
99
|
+
- name: Label first-time contributor
|
|
100
|
+
uses: actions/github-script@v7
|
|
101
|
+
with:
|
|
102
|
+
script: |
|
|
103
|
+
const pr = context.payload.pull_request;
|
|
104
|
+
if (pr.author_association === 'FIRST_TIME_CONTRIBUTOR') {
|
|
105
|
+
await github.rest.issues.addLabels({
|
|
106
|
+
owner: context.repo.owner,
|
|
107
|
+
repo: context.repo.repo,
|
|
108
|
+
issue_number: pr.number,
|
|
109
|
+
labels: ['first-time-contributor']
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
- language: yaml
|
|
113
|
+
label: "Separate workflow — gate secrets behind explicit approval check"
|
|
114
|
+
code: |
|
|
115
|
+
# Use pull_request for the CI job (no secrets, runs on fork code safely)
|
|
116
|
+
# Use pull_request_target with environment protection for secret-requiring jobs
|
|
117
|
+
on:
|
|
118
|
+
pull_request:
|
|
119
|
+
branches: [main]
|
|
120
|
+
|
|
121
|
+
jobs:
|
|
122
|
+
test:
|
|
123
|
+
runs-on: ubuntu-latest
|
|
124
|
+
steps:
|
|
125
|
+
- uses: actions/checkout@v4
|
|
126
|
+
- run: npm test
|
|
127
|
+
# No secrets needed — runs without approval gate
|
|
128
|
+
prevention:
|
|
129
|
+
- "Document in CONTRIBUTING.md that first-time contributors' CI runs require maintainer approval before they start — set expectations early."
|
|
130
|
+
- "Set the approval policy to 'Require approval for first-time contributors' (not 'new to GitHub') to minimize repeated approvals for experienced contributors who are new to your repo."
|
|
131
|
+
- "Use separate workflow files for CI (no secrets, runs on pull_request) and deployment/release (needs secrets, runs on merge to main) — this reduces how often the approval gate is hit."
|
|
132
|
+
- "For open-source projects with many external PRs, consider a bot that auto-approves workflow runs from contributors who have already passed a one-time review (e.g., using the approve-run REST API after manually approving the first PR)."
|
|
133
|
+
- "Never use pull_request_target to run code from the fork — only use it for read-only operations on PR metadata. Mixing it with code execution from the fork is a security vulnerability."
|
|
134
|
+
docs:
|
|
135
|
+
- url: "https://docs.github.com/en/actions/how-tos/manage-workflow-runs/approve-runs-from-forks"
|
|
136
|
+
label: "GitHub Docs: Approving workflow runs from forks"
|
|
137
|
+
- url: "https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/enabling-features-for-your-repository/managing-github-actions-settings-for-a-repository#configuring-required-approval-for-workflows-from-public-forks"
|
|
138
|
+
label: "GitHub Docs: Configuring required approval for workflows from public forks"
|
|
139
|
+
- url: "https://github.blog/changelog/2022-11-14-github-actions-require-approval-for-running-workflows-from-private-forks/"
|
|
140
|
+
label: "GitHub Changelog: Require approval for workflows from private forks (Nov 2022)"
|
|
141
|
+
- url: "https://github.com/orgs/community/discussions/14334"
|
|
142
|
+
label: "GitHub Community Discussion #14334: Fork PR approval pain points"
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
id: "triggers-023"
|
|
2
|
+
title: "Single-star branch filter does not match branch names containing slashes"
|
|
3
|
+
category: "triggers"
|
|
4
|
+
severity: "silent-failure"
|
|
5
|
+
tags:
|
|
6
|
+
- "branches-filter"
|
|
7
|
+
- "glob"
|
|
8
|
+
- "on-push"
|
|
9
|
+
- "slash"
|
|
10
|
+
- "feature-branch"
|
|
11
|
+
- "workflow-not-triggering"
|
|
12
|
+
patterns:
|
|
13
|
+
- regex: "branches:\\s*\\n\\s+-\\s+'\\*'\\s*$"
|
|
14
|
+
flags: "im"
|
|
15
|
+
- regex: "branches:\\s*\\[\\s*['\"]\\*['\"]\\s*\\]"
|
|
16
|
+
flags: "i"
|
|
17
|
+
error_messages:
|
|
18
|
+
- "Workflow does not trigger on feature/my-branch despite branches: ['*']"
|
|
19
|
+
root_cause: |
|
|
20
|
+
GitHub Actions uses Unix glob patterns for branch and tag filters. The single `*`
|
|
21
|
+
wildcard matches any character EXCEPT the forward slash `/`. This means:
|
|
22
|
+
|
|
23
|
+
branches: ['*'] matches: main, develop, hotfix-123
|
|
24
|
+
branches: ['*'] does NOT match: feature/my-feature, release/v1.2.0
|
|
25
|
+
|
|
26
|
+
To match any branch name including those with slashes, you must use `**` (double
|
|
27
|
+
star), which matches any character including `/`.
|
|
28
|
+
|
|
29
|
+
No error is thrown when the filter excludes a branch — the workflow simply does not
|
|
30
|
+
appear in the Actions tab for pushes to `feature/*`-style branches. Developers who
|
|
31
|
+
expect `*` to mean "all branches" (as in many other CI systems) are silently surprised
|
|
32
|
+
when feature branch pushes produce no workflow runs.
|
|
33
|
+
|
|
34
|
+
This follows the same glob semantics documented in GitHub's filter pattern cheat sheet
|
|
35
|
+
but is one of the most common "workflow not triggering" reports in GitHub Community.
|
|
36
|
+
fix: |
|
|
37
|
+
Replace single `*` with `**` in your branches filter to match all branch names
|
|
38
|
+
including those containing slashes. For selective matching, use prefix patterns
|
|
39
|
+
like 'feature/**' or 'release/**'.
|
|
40
|
+
fix_code:
|
|
41
|
+
- language: yaml
|
|
42
|
+
label: "Before: single star silently excludes feature/* branches"
|
|
43
|
+
code: |
|
|
44
|
+
on:
|
|
45
|
+
push:
|
|
46
|
+
branches:
|
|
47
|
+
- '*' # ❌ does NOT match feature/my-feature or release/v1.0.0
|
|
48
|
+
|
|
49
|
+
- language: yaml
|
|
50
|
+
label: "After: double star matches all branches including those with slashes"
|
|
51
|
+
code: |
|
|
52
|
+
on:
|
|
53
|
+
push:
|
|
54
|
+
branches:
|
|
55
|
+
- '**' # ✅ matches any branch name including feature/my-feature
|
|
56
|
+
|
|
57
|
+
- language: yaml
|
|
58
|
+
label: "Practical example: main plus all feature and release branches"
|
|
59
|
+
code: |
|
|
60
|
+
on:
|
|
61
|
+
push:
|
|
62
|
+
branches:
|
|
63
|
+
- main
|
|
64
|
+
- 'feature/**' # ✅ feature/foo, feature/bar/baz, etc.
|
|
65
|
+
- 'release/**' # ✅ release/v1.0, release/v1.0.1, etc.
|
|
66
|
+
- 'hotfix/**' # ✅ hotfix/critical-fix, etc.
|
|
67
|
+
prevention:
|
|
68
|
+
- "Use '**' when you mean 'any branch' and reserve '*' for single-segment names only."
|
|
69
|
+
- "Test your branch filter by pushing to a feature/test branch in a non-production context and verifying a workflow run appears."
|
|
70
|
+
- "Consult the GitHub filter pattern cheat sheet before using glob characters in branches, tags, or paths filters."
|
|
71
|
+
- "Use 'branches-ignore' with an empty list and 'branches: [**]' to explicitly document intent to run on all branches."
|
|
72
|
+
docs:
|
|
73
|
+
- url: "https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet"
|
|
74
|
+
label: "GitHub Docs — Filter pattern cheat sheet"
|
|
75
|
+
- url: "https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#onpushbranchesbranchesignore"
|
|
76
|
+
label: "GitHub Docs — on.push.branches filter"
|
|
77
|
+
- url: "https://github.com/orgs/community/discussions/147369"
|
|
78
|
+
label: "GitHub Community #147369 — Workflow not triggering on expected branches"
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
id: triggers-021
|
|
2
|
+
title: "pull_request_target Environment Branch Protection Now Evaluates Against Default Branch (Nov 2025 Breaking Change)"
|
|
3
|
+
category: triggers
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- pull_request_target
|
|
7
|
+
- environment
|
|
8
|
+
- branch-protection
|
|
9
|
+
- deployment
|
|
10
|
+
- breaking-change
|
|
11
|
+
- default-branch
|
|
12
|
+
- evaluation-ref
|
|
13
|
+
patterns:
|
|
14
|
+
- regex: "Branch 'refs/pull/\\d+/merge' is not allowed to deploy to .+ due to environment protection rules"
|
|
15
|
+
flags: "i"
|
|
16
|
+
- regex: "pull_request_target.*environment.*protection"
|
|
17
|
+
flags: "im"
|
|
18
|
+
- regex: "is not allowed to deploy to .+ due to environment protection rules"
|
|
19
|
+
flags: "i"
|
|
20
|
+
error_messages:
|
|
21
|
+
- "Branch 'refs/pull/904/merge' is not allowed to deploy to prod due to environment protection rules."
|
|
22
|
+
- "Branch 'refs/pull/123/merge' is not allowed to deploy to staging due to environment protection rules."
|
|
23
|
+
root_cause: |
|
|
24
|
+
In November 2025, GitHub changed how environment branch protection rules are evaluated
|
|
25
|
+
for `pull_request_target` workflows. Before the change:
|
|
26
|
+
- The evaluation ref could be the PR head SHA or the merge ref, depending on
|
|
27
|
+
how the workflow was written.
|
|
28
|
+
After the change (effective ~December 2025):
|
|
29
|
+
- `pull_request_target` workflows ALWAYS run from the **default branch** as the
|
|
30
|
+
workflow source reference (`GITHUB_REF`/`GITHUB_SHA`).
|
|
31
|
+
- Environment branch protection rules are now evaluated against the **execution
|
|
32
|
+
reference** (the default branch) rather than the PR head.
|
|
33
|
+
|
|
34
|
+
**Who is affected:**
|
|
35
|
+
Workflows using `pull_request_target` with environment deployments that have
|
|
36
|
+
branch protection rules configured to allow only specific branch patterns.
|
|
37
|
+
|
|
38
|
+
For example, if an environment's branch restriction allows `main` only, a
|
|
39
|
+
`pull_request_target` workflow that previously passed (because it matched some
|
|
40
|
+
derived ref) may now fail if GitHub evaluates a different ref. Conversely,
|
|
41
|
+
workflows that previously respected PR-branch restrictions may now bypass them
|
|
42
|
+
because the default branch is used instead.
|
|
43
|
+
|
|
44
|
+
This change was made for security: it ensures `pull_request_target` cannot be
|
|
45
|
+
used to circumvent branch-based deployment restrictions via crafted PR refs.
|
|
46
|
+
|
|
47
|
+
The `environment-protection-rules-silent-block` entry (triggers-006) covers the
|
|
48
|
+
general case of environment rules blocking deployment. This entry specifically
|
|
49
|
+
documents the November 2025 behavioral change and its migration path.
|
|
50
|
+
fix: |
|
|
51
|
+
Update your environment branch protection rules to match the execution reference
|
|
52
|
+
used after the behavioral change:
|
|
53
|
+
|
|
54
|
+
1. **If deployments are now incorrectly blocked:** Add the default branch (e.g.,
|
|
55
|
+
`main`) to the environment's allowed branch patterns, since `pull_request_target`
|
|
56
|
+
now executes in the default branch context.
|
|
57
|
+
|
|
58
|
+
2. **If PR-based branch restrictions are no longer enforced:** Switch from
|
|
59
|
+
`pull_request_target` to `pull_request` (if the elevated-permissions use case
|
|
60
|
+
can be removed), which uses the PR head ref and respects branch-filter rules
|
|
61
|
+
as expected.
|
|
62
|
+
|
|
63
|
+
3. **For cross-repo PR deployments that legitimately need `pull_request_target`:**
|
|
64
|
+
Use required reviewers on the environment to gate deployments instead of
|
|
65
|
+
(or in addition to) branch restrictions — required reviewers are not affected
|
|
66
|
+
by this ref-evaluation change.
|
|
67
|
+
fix_code:
|
|
68
|
+
- language: yaml
|
|
69
|
+
label: "Use pull_request instead of pull_request_target when elevated secrets not needed"
|
|
70
|
+
code: |
|
|
71
|
+
# Before (uses pull_request_target — broad access, affected by Nov 2025 change):
|
|
72
|
+
# on:
|
|
73
|
+
# pull_request_target:
|
|
74
|
+
# types: [opened, synchronize]
|
|
75
|
+
|
|
76
|
+
# After (use pull_request — runs in PR head context, branch filters work as expected):
|
|
77
|
+
on:
|
|
78
|
+
pull_request:
|
|
79
|
+
types: [opened, synchronize]
|
|
80
|
+
branches:
|
|
81
|
+
- main
|
|
82
|
+
|
|
83
|
+
jobs:
|
|
84
|
+
deploy-preview:
|
|
85
|
+
runs-on: ubuntu-latest
|
|
86
|
+
environment: staging
|
|
87
|
+
steps:
|
|
88
|
+
- uses: actions/checkout@v4
|
|
89
|
+
- run: echo "Deploy preview for ${{ github.head_ref }}"
|
|
90
|
+
- language: yaml
|
|
91
|
+
label: "Add required reviewers to the environment instead of relying on branch filters alone"
|
|
92
|
+
code: |
|
|
93
|
+
# In GitHub repo Settings → Environments → staging → Protection rules:
|
|
94
|
+
# ✅ Required reviewers: add team "platform-team"
|
|
95
|
+
# (branch restrictions can be kept or relaxed — human approval is the gate)
|
|
96
|
+
|
|
97
|
+
jobs:
|
|
98
|
+
deploy:
|
|
99
|
+
runs-on: ubuntu-latest
|
|
100
|
+
environment: staging # requires approval from platform-team
|
|
101
|
+
steps:
|
|
102
|
+
- uses: actions/checkout@v4
|
|
103
|
+
- run: ./deploy.sh
|
|
104
|
+
prevention:
|
|
105
|
+
- "Prefer `pull_request` over `pull_request_target` unless your workflow specifically needs write permissions or secrets from the base repo for fork PR handling."
|
|
106
|
+
- "Use required reviewers in environments rather than relying solely on branch name patterns for deployment gating."
|
|
107
|
+
- "After enabling `pull_request_target`, validate that environment protection rules still behave as expected by reviewing which ref GitHub uses as the evaluation context."
|
|
108
|
+
- "Monitor the GitHub Actions changelog for behavioral changes to security-sensitive event types like `pull_request_target`."
|
|
109
|
+
docs:
|
|
110
|
+
- url: "https://github.blog/changelog/2025-11-07-actions-pull_request_target-and-environment-branch-protections-changes/"
|
|
111
|
+
label: "GitHub Changelog: pull_request_target and environment branch protections changes (Nov 2025)"
|
|
112
|
+
- url: "https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#pull_request_target"
|
|
113
|
+
label: "GitHub Docs: pull_request_target event"
|
|
114
|
+
- url: "https://docs.github.com/en/actions/managing-workflow-runs-and-deployments/managing-deployments/managing-environments-for-deployment"
|
|
115
|
+
label: "GitHub Docs: Managing environments for deployment"
|
|
116
|
+
- url: "https://github.com/orgs/community/discussions/181616"
|
|
117
|
+
label: "Community Discussion: pull_request_target environment branch protection evaluation"
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
id: triggers-020
|
|
2
|
+
title: "Renamed Workflow or Job Leaves Stale Required Status Check Permanently Blocking Merges"
|
|
3
|
+
category: triggers
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- branch-protection
|
|
7
|
+
- required-status-checks
|
|
8
|
+
- workflow-rename
|
|
9
|
+
- merge-blocked
|
|
10
|
+
- repository-settings
|
|
11
|
+
patterns:
|
|
12
|
+
- regex: "Expected.*Waiting for status to be reported"
|
|
13
|
+
flags: "i"
|
|
14
|
+
- regex: "Required status check.*has not passed"
|
|
15
|
+
flags: "i"
|
|
16
|
+
error_messages:
|
|
17
|
+
- "Required status checks have not passed for this pull request"
|
|
18
|
+
- "Expected — Waiting for status to be reported"
|
|
19
|
+
- "Required status check has not passed"
|
|
20
|
+
root_cause: |
|
|
21
|
+
GitHub branch protection rules reference required status checks by their EXACT string
|
|
22
|
+
name: `<Workflow Name> / <job-id>` (e.g., `CI / build`). When a workflow file's
|
|
23
|
+
`name:` field is changed, a job ID is renamed, or a third-party check context string
|
|
24
|
+
changes, the new check runs and passes — but the branch protection rule still
|
|
25
|
+
references the old string.
|
|
26
|
+
|
|
27
|
+
The old check name is stuck at "Expected — Waiting for status to be reported"
|
|
28
|
+
permanently because no workflow run ever reports that exact string again. Every PR
|
|
29
|
+
targeting the protected branch is blocked from merging regardless of CI status.
|
|
30
|
+
|
|
31
|
+
Common triggers:
|
|
32
|
+
- Renaming the top-level `name:` of a workflow file
|
|
33
|
+
- Renaming a job ID (`jobs.<id>`)
|
|
34
|
+
- Migrating from one CI system to another
|
|
35
|
+
- Using a third-party action that changed its check context string
|
|
36
|
+
- Refactoring a monorepo with multiple workflow files that share a check name
|
|
37
|
+
|
|
38
|
+
This affects all open PRs immediately when the workflow is renamed — there is no
|
|
39
|
+
grace period or deprecation.
|
|
40
|
+
fix: |
|
|
41
|
+
1. Go to Settings → Branches → Branch protection rules → Edit for the affected branch.
|
|
42
|
+
2. Under "Require status checks to pass before merging", remove the stale check name.
|
|
43
|
+
3. Start typing the NEW check name and select it from the autocomplete dropdown.
|
|
44
|
+
The format is: "Workflow Name / job-id" (exactly as shown in the PR checks UI).
|
|
45
|
+
4. Save the branch protection rule.
|
|
46
|
+
|
|
47
|
+
To find the exact new check name without guessing:
|
|
48
|
+
gh api repos/{owner}/{repo}/commits/{ref}/check-runs --jq '.check_runs[].name'
|
|
49
|
+
|
|
50
|
+
If multiple branches are protected with the same stale rule, repeat for each.
|
|
51
|
+
fix_code:
|
|
52
|
+
- language: yaml
|
|
53
|
+
label: "Find current check names via GitHub CLI"
|
|
54
|
+
code: |
|
|
55
|
+
# List all check names currently reported for the default branch
|
|
56
|
+
gh api "repos/{owner}/{repo}/commits/main/check-runs" \
|
|
57
|
+
--jq '.check_runs[] | "\(.name) — \(.status)/\(.conclusion)"'
|
|
58
|
+
|
|
59
|
+
# Or for a specific open PR's head SHA:
|
|
60
|
+
gh api "repos/{owner}/{repo}/commits/{sha}/check-runs" \
|
|
61
|
+
--jq '.check_runs[].name'
|
|
62
|
+
- language: yaml
|
|
63
|
+
label: "Prevention: document required check names in workflow comments"
|
|
64
|
+
code: |
|
|
65
|
+
# Branch protection references this check as: "CI / build"
|
|
66
|
+
# If you rename this workflow or job, update Settings > Branches > Protection rules
|
|
67
|
+
name: CI # <-- changing this breaks the required check "CI / build"
|
|
68
|
+
on: [push, pull_request]
|
|
69
|
+
|
|
70
|
+
jobs:
|
|
71
|
+
build: # <-- changing this ID also breaks "CI / build"
|
|
72
|
+
runs-on: ubuntu-latest
|
|
73
|
+
steps:
|
|
74
|
+
- run: make build
|
|
75
|
+
prevention:
|
|
76
|
+
- "Before renaming a workflow or job, check Settings → Branches to see if any protection rules reference the current check name."
|
|
77
|
+
- "Add a comment in the workflow file listing the exact required status check string so renames are noticed."
|
|
78
|
+
- "After any workflow rename, immediately update branch protection rules and verify with an open PR."
|
|
79
|
+
- "Use the GitHub CLI command above to audit current check names after any CI refactor."
|
|
80
|
+
- "In monorepos, standardize workflow names and job IDs to minimize rename frequency."
|
|
81
|
+
docs:
|
|
82
|
+
- url: "https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches#require-status-checks-before-merging"
|
|
83
|
+
label: "GitHub Docs: Required status checks"
|
|
84
|
+
- url: "https://docs.github.com/en/rest/checks/runs#list-check-runs-for-a-git-reference"
|
|
85
|
+
label: "REST API: List check runs for a git reference"
|
|
86
|
+
- url: "https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#name"
|
|
87
|
+
label: "Workflow syntax: name field"
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
id: triggers-024
|
|
2
|
+
title: "Scheduled Cron Workflow Does Not Trigger on Self-Hosted Runner"
|
|
3
|
+
category: triggers
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- cron
|
|
7
|
+
- schedule
|
|
8
|
+
- self-hosted-runner
|
|
9
|
+
- trigger
|
|
10
|
+
- offline
|
|
11
|
+
patterns:
|
|
12
|
+
- regex: "cron.*self.hosted"
|
|
13
|
+
flags: "i"
|
|
14
|
+
- regex: "schedule.*self.hosted"
|
|
15
|
+
flags: "i"
|
|
16
|
+
error_messages:
|
|
17
|
+
- "No trigger for scheduled cron task in Github actions on a self-hosted runner"
|
|
18
|
+
root_cause: |
|
|
19
|
+
Scheduled (on: schedule) workflows are queued by GitHub hosted-runner dispatch
|
|
20
|
+
infrastructure. When the job targets a self-hosted runner (runs-on: [self-hosted, ...]),
|
|
21
|
+
the schedule dispatcher attempts to assign the job to a registered self-hosted runner.
|
|
22
|
+
|
|
23
|
+
The workflow silently never runs when:
|
|
24
|
+
1. The self-hosted runner is offline or disconnected at the moment the schedule fires.
|
|
25
|
+
2. The runner is busy with another job and no other runner with the required label is idle.
|
|
26
|
+
3. The runner binary is outdated or the registration token has expired, causing the runner
|
|
27
|
+
to appear registered but fail to accept new jobs.
|
|
28
|
+
4. The repository has been inactive for 60+ days (GitHub disables scheduled workflows
|
|
29
|
+
on inactive repositories automatically).
|
|
30
|
+
|
|
31
|
+
Unlike GitHub-hosted runners, where a fresh VM is provisioned on demand for every job,
|
|
32
|
+
self-hosted runners must be online and idle at exactly the moment the schedule fires.
|
|
33
|
+
If no eligible runner is available, the queued job is eventually abandoned with no retry
|
|
34
|
+
and no error visible in the Actions UI. The run simply does not appear.
|
|
35
|
+
Reported in actions/runner#4210 (21 reactions, open since Jan 2026).
|
|
36
|
+
fix: |
|
|
37
|
+
Option 1 (recommended): Run the scheduled trigger on a GitHub-hosted runner.
|
|
38
|
+
Use ubuntu-latest for the schedule job and dispatch the real work to self-hosted
|
|
39
|
+
via workflow_dispatch or a separate triggered workflow.
|
|
40
|
+
|
|
41
|
+
Option 2: Use an external scheduler with workflow_dispatch.
|
|
42
|
+
Remove the on: schedule trigger. Use an external cron (cron job, cloud function, GitHub App)
|
|
43
|
+
to call the GitHub REST API dispatches endpoint on a schedule. The workflow is triggered
|
|
44
|
+
by workflow_dispatch instead, which does not require the runner to be available at a
|
|
45
|
+
fixed clock time.
|
|
46
|
+
|
|
47
|
+
Option 3: Ensure runner availability with a persistent service.
|
|
48
|
+
Run the self-hosted runner as a systemd service with Restart=always so it is online
|
|
49
|
+
when schedules fire. This reduces but does not eliminate the risk.
|
|
50
|
+
fix_code:
|
|
51
|
+
- language: yaml
|
|
52
|
+
label: "Option 1: Schedule on GitHub-hosted, dispatch to self-hosted"
|
|
53
|
+
code: |
|
|
54
|
+
on:
|
|
55
|
+
schedule:
|
|
56
|
+
- cron: '0 2 * * *'
|
|
57
|
+
workflow_dispatch: {}
|
|
58
|
+
|
|
59
|
+
jobs:
|
|
60
|
+
# Lightweight orchestrator runs on GitHub-hosted (always available at schedule time)
|
|
61
|
+
trigger:
|
|
62
|
+
runs-on: ubuntu-latest
|
|
63
|
+
steps:
|
|
64
|
+
- name: Trigger self-hosted workflow
|
|
65
|
+
uses: actions/github-script@v7
|
|
66
|
+
with:
|
|
67
|
+
script: |
|
|
68
|
+
await github.rest.actions.createWorkflowDispatch({
|
|
69
|
+
owner: context.repo.owner,
|
|
70
|
+
repo: context.repo.repo,
|
|
71
|
+
workflow_id: 'heavy-work.yml',
|
|
72
|
+
ref: 'main'
|
|
73
|
+
});
|
|
74
|
+
- language: yaml
|
|
75
|
+
label: "Option 2: Receive dispatch from external cron scheduler"
|
|
76
|
+
code: |
|
|
77
|
+
# External scheduler calls:
|
|
78
|
+
# curl -X POST \
|
|
79
|
+
# -H "Authorization: Bearer $GH_TOKEN" \
|
|
80
|
+
# https://api.github.com/repos/OWNER/REPO/actions/workflows/nightly.yml/dispatches \
|
|
81
|
+
# -d '{"ref":"main"}'
|
|
82
|
+
#
|
|
83
|
+
# Your workflow:
|
|
84
|
+
on:
|
|
85
|
+
workflow_dispatch: {} # Triggered externally; no GitHub-side scheduling dependency
|
|
86
|
+
|
|
87
|
+
jobs:
|
|
88
|
+
nightly:
|
|
89
|
+
runs-on: [self-hosted, linux, x64]
|
|
90
|
+
steps:
|
|
91
|
+
- uses: actions/checkout@v4
|
|
92
|
+
- run: ./scripts/nightly.sh
|
|
93
|
+
prevention:
|
|
94
|
+
- "Run self-hosted runners as a persistent systemd service (Restart=always, RestartSec=10) to minimize offline windows."
|
|
95
|
+
- "Add workflow_dispatch: alongside schedule: so missed runs can be manually re-triggered from the Actions UI."
|
|
96
|
+
- "Monitor runner registration status via GET /repos/{owner}/{repo}/actions/runners and alert on offline runners."
|
|
97
|
+
- "Keep repositories active with at least one push or workflow run to prevent scheduled workflow disablement after 60 days of inactivity."
|
|
98
|
+
- "Consider using ephemeral runners with autoscaling (ARC) so runners are always provisioned on demand."
|
|
99
|
+
docs:
|
|
100
|
+
- url: "https://github.com/actions/runner/issues/4210"
|
|
101
|
+
label: "actions/runner#4210 — Cron not triggering on self-hosted runner (Jan 2026)"
|
|
102
|
+
- url: "https://github.com/orgs/community/discussions/185024"
|
|
103
|
+
label: "Community discussion: self-hosted runner not triggering scheduled cron"
|
|
104
|
+
- url: "https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#schedule"
|
|
105
|
+
label: "schedule event documentation"
|
|
106
|
+
- url: "https://docs.github.com/en/actions/managing-workflow-runs-and-deployments/managing-workflow-runs/disabling-and-enabling-a-workflow"
|
|
107
|
+
label: "Workflow disabled after 60 days of repo inactivity"
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
id: yaml-syntax-030
|
|
2
|
+
title: "Composite Action run: Step Missing Required shell: Property"
|
|
3
|
+
category: yaml-syntax
|
|
4
|
+
severity: error
|
|
5
|
+
tags:
|
|
6
|
+
- composite-action
|
|
7
|
+
- shell
|
|
8
|
+
- required-property
|
|
9
|
+
- action-yml
|
|
10
|
+
- schema-validation
|
|
11
|
+
patterns:
|
|
12
|
+
- regex: "Required property is missing: shell"
|
|
13
|
+
flags: "i"
|
|
14
|
+
- regex: "action\\.yml.*Required property is missing: shell"
|
|
15
|
+
flags: "i"
|
|
16
|
+
error_messages:
|
|
17
|
+
- "Required property is missing: shell"
|
|
18
|
+
- "(Line: 29, Col: 5): Required property is missing: shell"
|
|
19
|
+
- "Error: GitHub.DistributedTask.ObjectTemplating.TemplateValidationException: The template is not valid."
|
|
20
|
+
- "Error: Fail to load action.yml"
|
|
21
|
+
root_cause: |
|
|
22
|
+
Every run: step inside a composite action's action.yml MUST declare an explicit
|
|
23
|
+
shell: property. This is mandatory for composite actions — unlike regular workflow
|
|
24
|
+
run: steps where the runner infers the shell from the operating system, composite
|
|
25
|
+
action steps require an explicit declaration because the action may run on any OS.
|
|
26
|
+
|
|
27
|
+
The validation error fires at workflow preparation time (before any steps execute),
|
|
28
|
+
causing the entire workflow to fail with "Fail to load <action>.yml".
|
|
29
|
+
|
|
30
|
+
This is a common mistake when:
|
|
31
|
+
- Converting a workflow step into a reusable composite action
|
|
32
|
+
- Copying run: steps from a workflow into action.yml without adding shell:
|
|
33
|
+
- Using a third-party composite action whose author omitted the shell: property
|
|
34
|
+
fix: |
|
|
35
|
+
Add shell: to every run: step in the composite action's action.yml.
|
|
36
|
+
|
|
37
|
+
Supported shell values: bash, sh, python, pwsh, powershell, cmd
|
|
38
|
+
|
|
39
|
+
For cross-platform composite actions, use shell: bash (available on all
|
|
40
|
+
GitHub-hosted runners including Windows via Git Bash). If platform-specific
|
|
41
|
+
behavior is needed, use if: runner.os == 'Windows' conditionals with
|
|
42
|
+
separate steps.
|
|
43
|
+
fix_code:
|
|
44
|
+
- language: yaml
|
|
45
|
+
label: "Broken action.yml — run steps missing shell:"
|
|
46
|
+
code: |
|
|
47
|
+
runs:
|
|
48
|
+
using: "composite"
|
|
49
|
+
steps:
|
|
50
|
+
- name: Install dependencies
|
|
51
|
+
run: npm ci
|
|
52
|
+
- name: Run build
|
|
53
|
+
run: npm run build
|
|
54
|
+
- language: yaml
|
|
55
|
+
label: "Fixed action.yml — shell: added to every run step"
|
|
56
|
+
code: |
|
|
57
|
+
runs:
|
|
58
|
+
using: "composite"
|
|
59
|
+
steps:
|
|
60
|
+
- name: Install dependencies
|
|
61
|
+
run: npm ci
|
|
62
|
+
shell: bash
|
|
63
|
+
- name: Run build
|
|
64
|
+
run: npm run build
|
|
65
|
+
shell: bash
|
|
66
|
+
- language: yaml
|
|
67
|
+
label: "Cross-platform composite action with OS-conditional steps"
|
|
68
|
+
code: |
|
|
69
|
+
runs:
|
|
70
|
+
using: "composite"
|
|
71
|
+
steps:
|
|
72
|
+
- name: Run script (cross-platform)
|
|
73
|
+
run: echo "Running on ${{ runner.os }}"
|
|
74
|
+
shell: bash
|
|
75
|
+
- name: Windows-only step
|
|
76
|
+
if: runner.os == 'Windows'
|
|
77
|
+
run: Write-Host "Windows step"
|
|
78
|
+
shell: pwsh
|
|
79
|
+
prevention:
|
|
80
|
+
- "Add actionlint to your CI — it catches missing shell: properties in composite actions."
|
|
81
|
+
- "When creating a new composite action, start from the GitHub documentation template which includes shell: on all run steps."
|
|
82
|
+
- "Every run: step in action.yml requires shell: — add this to code review checklists."
|
|
83
|
+
- "Use rhysd/actionlint locally or as a pre-commit hook to validate composite action syntax before pushing."
|
|
84
|
+
docs:
|
|
85
|
+
- url: "https://docs.github.com/en/actions/sharing-automations/creating-actions/creating-a-composite-action"
|
|
86
|
+
label: "GitHub Docs: Creating a composite action"
|
|
87
|
+
- url: "https://stackoverflow.com/questions/71041836/github-actions-required-property-is-missing-shell"
|
|
88
|
+
label: "Stack Overflow: Required property is missing: shell (Score: 51, 31K views)"
|
|
89
|
+
- url: "https://docs.github.com/en/actions/sharing-automations/creating-actions/metadata-syntax-for-github-actions#runs-for-composite-actions"
|
|
90
|
+
label: "GitHub Docs: Metadata syntax for composite actions (runs.steps[*].shell)"
|