@htekdev/actions-debugger 1.0.14 → 1.0.16

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.
Files changed (58) hide show
  1. package/dist/db/search.js +3 -1
  2. package/dist/db/search.js.map +1 -1
  3. package/dist/tools/suggest-fix.d.ts.map +1 -1
  4. package/dist/tools/suggest-fix.js +5 -1
  5. package/dist/tools/suggest-fix.js.map +1 -1
  6. package/errors/caching-artifacts/cache-key-too-long.yml +93 -0
  7. package/errors/caching-artifacts/cache-path-not-exist-skipped.yml +152 -0
  8. package/errors/caching-artifacts/cache-save-same-key-html-conflict.yml +109 -0
  9. package/errors/caching-artifacts/docker-buildx-gha-cache-capacity.yml +107 -0
  10. package/errors/caching-artifacts/setup-ruby-bundler-ephemeral-workdir-cache-miss.yml +147 -0
  11. package/errors/caching-artifacts/upload-artifact-v3-retirement-blocked.yml +123 -0
  12. package/errors/caching-artifacts/upload-artifact-v4-large-file-macos-hang.yml +111 -0
  13. package/errors/concurrency-timing/always-cleanup-5min-forced-kill.yml +140 -0
  14. package/errors/concurrency-timing/concurrency-group-env-context-undefined.yml +99 -0
  15. package/errors/concurrency-timing/required-check-pending-path-filter-skip.yml +160 -0
  16. package/errors/concurrency-timing/wait-timer-cancel-in-progress-starvation.yml +125 -0
  17. package/errors/known-unsolved/composite-action-step-timeout-minutes-ignored.yml +146 -0
  18. package/errors/known-unsolved/reusable-workflow-no-composite-action-call.yml +116 -0
  19. package/errors/known-unsolved/schedule-trigger-default-branch-only.yml +113 -0
  20. package/errors/known-unsolved/secrets-not-allowed-in-if-conditions.yml +149 -0
  21. package/errors/known-unsolved/workflow-50-rerun-limit.yml +110 -0
  22. package/errors/permissions-auth/check-run-status-modification-blocked.yml +134 -0
  23. package/errors/permissions-auth/dependabot-pr-secrets-unavailable.yml +133 -0
  24. package/errors/permissions-auth/fine-grained-pat-deployment-write-required.yml +146 -0
  25. package/errors/permissions-auth/github-app-installation-token-new-format.yml +124 -0
  26. package/errors/permissions-auth/github-packages-read-requires-packages-permission.yml +128 -0
  27. package/errors/permissions-auth/oidc-id-token-write-permission-missing.yml +169 -0
  28. package/errors/permissions-auth/permissions-empty-block-removes-contents-read.yml +97 -0
  29. package/errors/permissions-auth/reusable-workflow-permissions-not-inherited.yml +114 -0
  30. package/errors/runner-environment/checkout-windows-ebusy-lock.yml +124 -0
  31. package/errors/runner-environment/deprecated-action-version-auto-rejected.yml +89 -0
  32. package/errors/runner-environment/github-hosted-runner-disk-space-full.yml +85 -0
  33. package/errors/runner-environment/github-path-same-step-not-found.yml +114 -0
  34. package/errors/runner-environment/github-script-v6-octokit-rest-actions-not-function.yml +87 -0
  35. package/errors/runner-environment/macos-13-deprecation-brownout.yml +93 -0
  36. package/errors/runner-environment/macos-15-mono-nuget-removed.yml +151 -0
  37. package/errors/runner-environment/macos-15-xcode-simulator-sdk-policy.yml +141 -0
  38. package/errors/runner-environment/multi-runtime-nov2025-removal.yml +120 -0
  39. package/errors/runner-environment/runner-oom-exit-code-137.yml +117 -0
  40. package/errors/runner-environment/setup-go-go123-telemetry-cache-failure.yml +92 -0
  41. package/errors/runner-environment/setup-java-distribution-required.yml +108 -0
  42. package/errors/runner-environment/ubuntu-2004-retirement-brownout.yml +107 -0
  43. package/errors/runner-environment/windows-latest-d-drive-removed.yml +104 -0
  44. package/errors/runner-environment/windows-vs2026-cuda-host-compiler-unsupported.yml +145 -0
  45. package/errors/silent-failures/event-commits-empty-on-workflow-dispatch.yml +110 -0
  46. package/errors/silent-failures/fetch-tags-depth-one-silent-no-op.yml +77 -0
  47. package/errors/silent-failures/github-env-multiline-value-truncated.yml +127 -0
  48. package/errors/silent-failures/github-sha-pr-merge-commit-not-head.yml +150 -0
  49. package/errors/silent-failures/job-output-masked-as-secret-empty.yml +147 -0
  50. package/errors/silent-failures/upload-artifact-permissions-stripped.yml +98 -0
  51. package/errors/triggers/pull-request-branches-filter-matches-base-not-head.yml +140 -0
  52. package/errors/triggers/push-event-fires-on-branch-delete.yml +129 -0
  53. package/errors/triggers/push-first-commit-before-sha-zeros.yml +160 -0
  54. package/errors/yaml-syntax/continue-on-error-env-context-rejected.yml +130 -0
  55. package/errors/yaml-syntax/fromjson-empty-string-crash.yml +99 -0
  56. package/errors/yaml-syntax/if-bang-negation-yaml-tag.yml +145 -0
  57. package/errors/yaml-syntax/local-action-path-always-top-level.yml +142 -0
  58. package/package.json +1 -1
@@ -0,0 +1,160 @@
1
+ id: concurrency-timing-013
2
+ title: "Required Status Check Stuck in Pending When Workflow Skipped by Path or Branch Filter"
3
+ category: concurrency-timing
4
+ severity: warning
5
+ tags:
6
+ - required-status-check
7
+ - path-filter
8
+ - branch-filter
9
+ - pending
10
+ - pull-request
11
+ - branch-protection
12
+ - paths
13
+ - blocked-pr
14
+ patterns:
15
+ - regex: "Some checks haven't completed yet|Required status check.*pending"
16
+ flags: "i"
17
+ - regex: "Waiting for status:.*pending"
18
+ flags: "i"
19
+ error_messages:
20
+ - "Some checks haven't completed yet"
21
+ - "Required status check is pending"
22
+ - "Waiting for status: CI / test (pending)"
23
+ root_cause: |
24
+ GitHub Actions workflows that use `paths:`, `paths-ignore:`, `branches:`, or
25
+ `branches-ignore:` filters will NOT run — and will NOT report ANY status — for
26
+ commits that don't match the filter criteria.
27
+
28
+ When a required status check is configured in a branch protection rule and the
29
+ workflow providing that check is skipped by a filter:
30
+ - The check is NEVER created for that commit — it remains in "Pending" state indefinitely
31
+ - The PR is blocked from merging with "Some checks haven't completed yet"
32
+ - The check CANNOT be manually re-triggered without pushing a commit that matches the filter
33
+
34
+ Common scenario:
35
+ A repository has a `ci.yml` workflow with `paths: ['src/**', '*.ts']` and
36
+ `CI / test` configured as a required status check. A developer opens a PR that only
37
+ changes `README.md` or `.github/docs/`. The `CI / test` check never runs, shows as
38
+ "Pending" forever, and the PR is permanently blocked from merging without an admin
39
+ override or a dummy code commit to trigger the workflow.
40
+
41
+ This is explicitly documented behavior but frequently misunderstood:
42
+ - The workflow appears to work correctly for code-change PRs (the common case)
43
+ - The bug only surfaces on documentation-only, config-only, or administrative PRs
44
+ - Developers and reviewers see a pending check with no way to trigger it
45
+
46
+ Note: This is distinct from skipped-needs-cascade (job dependency skipping) — this
47
+ is specifically about the WORKFLOW TRIGGER filter preventing the run from ever starting,
48
+ so no job status is reported at all.
49
+
50
+ Source: GitHub Docs — Troubleshooting required status checks: "If a workflow is skipped
51
+ due to path filtering, branch filtering or a commit message, then checks associated
52
+ with that workflow will remain in a 'Pending' state. A pull request that requires those
53
+ checks to be successful will be blocked from merging."
54
+ fix: |
55
+ Two main approaches:
56
+
57
+ 1. **Always-succeeding bypass job** — remove path filters from the workflow trigger,
58
+ run the workflow for all PRs, use `dorny/paths-filter` or `tj-actions/changed-files`
59
+ to detect changes inside the workflow, and add a sentinel job that always produces a
60
+ status. Configure the required check to point at the sentinel job name.
61
+
62
+ 2. **Split workflow** — keep the path-filtered workflow for actual CI work, and add a
63
+ separate always-running workflow that provides the required status check name
64
+ (succeeds immediately for non-code PRs, waits for CI for code PRs).
65
+ fix_code:
66
+ - language: yaml
67
+ label: "Fix: always-running workflow with internal path detection and sentinel job"
68
+ code: |
69
+ name: CI
70
+ # No path filter — workflow always runs for all PRs
71
+ on:
72
+ pull_request:
73
+ branches: [main]
74
+
75
+ jobs:
76
+ changes:
77
+ runs-on: ubuntu-latest
78
+ outputs:
79
+ code: ${{ steps.filter.outputs.code }}
80
+ steps:
81
+ - uses: actions/checkout@v4
82
+ - uses: dorny/paths-filter@v3
83
+ id: filter
84
+ with:
85
+ filters: |
86
+ code:
87
+ - 'src/**'
88
+ - '*.ts'
89
+ - 'package*.json'
90
+
91
+ test:
92
+ needs: changes
93
+ if: needs.changes.outputs.code == 'true'
94
+ runs-on: ubuntu-latest
95
+ steps:
96
+ - uses: actions/checkout@v4
97
+ - run: npm ci && npm test
98
+
99
+ # Branch protection required check: "CI / ci-gate" (not "CI / test")
100
+ # Always produces a status — green for docs PRs, waits for test on code PRs
101
+ ci-gate:
102
+ needs: [changes, test]
103
+ if: always()
104
+ runs-on: ubuntu-latest
105
+ steps:
106
+ - name: Confirm CI passed or code was not changed
107
+ run: |
108
+ CODE_CHANGED="${{ needs.changes.outputs.code }}"
109
+ TEST_RESULT="${{ needs.test.result }}"
110
+ if [[ "$CODE_CHANGED" == "false" ]]; then
111
+ echo "✅ No code changes — CI gate passes automatically"
112
+ elif [[ "$TEST_RESULT" == "success" ]]; then
113
+ echo "✅ Tests passed"
114
+ else
115
+ echo "❌ Tests $TEST_RESULT"
116
+ exit 1
117
+ fi
118
+
119
+ - language: yaml
120
+ label: "Alternative: run all steps always but skip expensive ones via filter"
121
+ code: |
122
+ name: CI
123
+ on:
124
+ pull_request:
125
+ branches: [main]
126
+ # No workflow-level path filter — status always reported
127
+
128
+ jobs:
129
+ test:
130
+ runs-on: ubuntu-latest
131
+ steps:
132
+ - uses: actions/checkout@v4
133
+
134
+ - uses: dorny/paths-filter@v3
135
+ id: filter
136
+ with:
137
+ filters: |
138
+ code: ['src/**', '*.ts', 'package*.json']
139
+
140
+ - name: Install dependencies
141
+ if: steps.filter.outputs.code == 'true'
142
+ run: npm ci
143
+
144
+ - name: Run tests
145
+ if: steps.filter.outputs.code == 'true'
146
+ run: npm test
147
+ # Job always completes with success — check is always reported
148
+ prevention:
149
+ - "Never use workflow-level `paths:` or `branches:` filters as the sole trigger for a required status check."
150
+ - "Use `dorny/paths-filter` or `tj-actions/changed-files` INSIDE an always-running workflow instead of workflow-level path filters."
151
+ - "Name required status checks after jobs that always produce a status, even on non-code PRs."
152
+ - "Test branch protection rules by opening a documentation-only PR to verify all required checks complete."
153
+ - "Consider admin overrides as a last resort, not a workflow fix — the root cause will keep happening."
154
+ docs:
155
+ - url: "https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks"
156
+ label: "Troubleshooting required status checks (path filter skip documented)"
157
+ - url: "https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#onpushpull_requestpull_request_targetpathspaths-ignore"
158
+ label: "Workflow syntax: paths and paths-ignore filters"
159
+ - url: "https://github.com/dorny/paths-filter"
160
+ label: "dorny/paths-filter — detect changed files inside workflow"
@@ -0,0 +1,125 @@
1
+ id: concurrency-timing-012
2
+ title: "Deployment wait-timer + cancel-in-progress: true Creates Permanent Deployment Starvation Loop"
3
+ category: concurrency-timing
4
+ severity: warning
5
+ tags:
6
+ - wait-timer
7
+ - cancel-in-progress
8
+ - deployment
9
+ - environment
10
+ - starvation
11
+ - concurrency
12
+ - production
13
+ patterns:
14
+ - regex: "Run was cancelled|Canceling since a higher priority waiting request"
15
+ flags: "i"
16
+ - regex: "wait.?timer|waiting for environment.*approval"
17
+ flags: "i"
18
+ error_messages:
19
+ - "Run was cancelled"
20
+ - "Canceling since a higher priority waiting request for 'production' exists"
21
+ root_cause: |
22
+ When a deployment workflow combines `concurrency.cancel-in-progress: true` with a
23
+ deployment environment that has a `wait-timer` configured (a mandatory delay before
24
+ deployment proceeds), every new commit to the branch creates a starvation loop where
25
+ no deployment ever reaches the execution phase:
26
+
27
+ 1. Run A starts → deployment job begins waiting out the environment wait-timer (e.g., 5 min)
28
+ 2. A new commit is pushed → Run B starts in the same concurrency group
29
+ 3. `cancel-in-progress: true` fires → Run A is cancelled while still in the wait-timer
30
+ 4. Run B now begins its own wait-timer countdown
31
+ 5. Another commit arrives → Run B is cancelled during its timer
32
+ 6. This repeats indefinitely — no deployment ever executes
33
+
34
+ This loop is particularly insidious because:
35
+ - All cancellations appear expected and benign in the Actions UI (no failures shown)
36
+ - The repository looks healthy — CI passes, deployments start — but production is
37
+ silently never updated
38
+ - Active development repos where commits arrive faster than the wait-timer duration
39
+ are especially vulnerable
40
+
41
+ Note: GitHub's concurrency model allows only ONE pending run per group. With
42
+ `cancel-in-progress: true`, a new run cancels the RUNNING run (not just queues) —
43
+ so even a very short wait-timer cannot escape this if commits arrive frequently.
44
+ fix: |
45
+ Do not combine `cancel-in-progress: true` with deployment environment `wait-timer`
46
+ on the same workflow. Use `cancel-in-progress: false` (the default) for deploy
47
+ workflows — this queues runs so each commit eventually deploys in order.
48
+
49
+ If you want fast feedback for CI but reliable deployments for CD, split them into
50
+ separate workflow files with different concurrency strategies.
51
+ fix_code:
52
+ - language: yaml
53
+ label: "Fix: disable cancel-in-progress for deploy workflow with wait-timer"
54
+ code: |
55
+ name: Deploy to Production
56
+ on:
57
+ push:
58
+ branches: [main]
59
+
60
+ concurrency:
61
+ group: deploy-production
62
+ cancel-in-progress: false # Queue — never starve a deployment with wait-timer
63
+
64
+ jobs:
65
+ deploy:
66
+ runs-on: ubuntu-latest
67
+ environment: production # Has wait-timer: 5 configured
68
+ steps:
69
+ - uses: actions/checkout@v4
70
+ - run: ./deploy.sh
71
+
72
+ - language: yaml
73
+ label: "Split pipeline: CI cancels freely; deploy queues safely after CI"
74
+ code: |
75
+ # ci.yml — fast feedback, cancel stale runs is fine
76
+ name: CI
77
+ on:
78
+ push:
79
+ branches: [main]
80
+ concurrency:
81
+ group: ci-${{ github.ref }}
82
+ cancel-in-progress: true # OK: no side effects
83
+
84
+ jobs:
85
+ test:
86
+ runs-on: ubuntu-latest
87
+ steps:
88
+ - uses: actions/checkout@v4
89
+ - run: npm test
90
+
91
+ ---
92
+ # deploy.yml — triggered after CI, environment has wait-timer
93
+ name: Deploy
94
+ on:
95
+ workflow_run:
96
+ workflows: ["CI"]
97
+ types: [completed]
98
+ branches: [main]
99
+
100
+ concurrency:
101
+ group: deploy-production
102
+ cancel-in-progress: false # Queue; every successful CI run gets deployed
103
+
104
+ jobs:
105
+ deploy:
106
+ if: ${{ github.event.workflow_run.conclusion == 'success' }}
107
+ runs-on: ubuntu-latest
108
+ environment: production # wait-timer is safe — no cancel-in-progress racing it
109
+ steps:
110
+ - uses: actions/checkout@v4
111
+ with:
112
+ ref: ${{ github.event.workflow_run.head_sha }}
113
+ - run: ./deploy.sh
114
+ prevention:
115
+ - "Never combine `cancel-in-progress: true` with a deployment environment `wait-timer` in the same workflow."
116
+ - "Use `cancel-in-progress: false` for any workflow that deploys to environments with protection rules."
117
+ - "Decouple CI (cancel-ok, fast) from CD (queued, reliable) into separate workflow files."
118
+ - "Monitor the Actions tab for a pattern of all deployments showing as CANCELLED — this is a sign of starvation."
119
+ docs:
120
+ - url: "https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/using-concurrency"
121
+ label: "GitHub Docs: Using concurrency in GitHub Actions"
122
+ - url: "https://docs.github.com/en/actions/managing-workflow-runs-and-deployments/managing-deployments/managing-environments-for-deployment#wait-timer"
123
+ label: "GitHub Docs: Managing environments — wait timer"
124
+ - url: "https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#workflow_run"
125
+ label: "workflow_run event — decouple CI and CD pipelines"
@@ -0,0 +1,146 @@
1
+ id: known-unsolved-017
2
+ title: "timeout-minutes Is Silently Ignored on Steps Inside Composite Actions"
3
+ category: known-unsolved
4
+ severity: limitation
5
+ tags:
6
+ - timeout-minutes
7
+ - composite-action
8
+ - limitation
9
+ - step-timeout
10
+ - composite
11
+ - hung-step
12
+ - action-yml
13
+ patterns:
14
+ - regex: "timeout.?minutes.*composite|using.*composite.*timeout"
15
+ flags: "i"
16
+ - regex: "Unexpected value 'timeout-minutes'"
17
+ flags: "i"
18
+ error_messages:
19
+ - "Unexpected value 'timeout-minutes'"
20
+ root_cause: |
21
+ GitHub Actions supports `timeout-minutes` at the job level and at individual step level
22
+ inside regular workflow files. However, `timeout-minutes` is NOT enforced on steps
23
+ inside composite actions (action.yml files using `runs.using: composite`).
24
+
25
+ Adding `timeout-minutes` to a step within a composite action's `steps:` block is
26
+ accepted by the YAML parser without error, but the timeout is silently NOT applied
27
+ at runtime. A hung step inside a composite action will run until the parent job's
28
+ overall `timeout-minutes` is exhausted — up to 6 hours on GitHub-hosted runners by
29
+ default.
30
+
31
+ This creates a dangerous gap:
32
+ - Network-dependent steps (downloads, API calls, package installs) inside a composite
33
+ action can hang indefinitely if the network is slow or unresponsive
34
+ - `actions/cache` intermittently stalls; wrapping it in a composite action with a
35
+ step `timeout-minutes: 5` provides NO protection
36
+ - Composite action authors cannot provide defensive step timeouts — users of the
37
+ composite action must rely entirely on the calling job's `timeout-minutes`
38
+ - Since the step timeout appears to be set (the YAML is valid), developers believe
39
+ they have a guard when they actually have none
40
+
41
+ The limitation has been tracked and discussed in the community since 2021
42
+ (actions/runner#1979) and remains unresolved as of 2026.
43
+
44
+ Source: actions/runner#1979 — "We would like to see timeout-minutes supported on
45
+ steps in composite actions. Occasionally actions like actions/cache bug out and run
46
+ for the default timeout time (6 hours) which causes unnecessary costs."
47
+ fix: |
48
+ Since step-level timeouts cannot be enforced inside composite actions, use these
49
+ workarounds:
50
+
51
+ 1. **Shell-level timeout**: Wrap commands in `timeout <seconds>` (bash) or `Start-Sleep`
52
+ + `Start-Job` with timeout (PowerShell) to kill hung processes from within the script.
53
+ 2. **Job-level `timeout-minutes`**: Set a conservative timeout on the calling job as a
54
+ safety net — it limits the composite action's maximum runtime.
55
+ 3. **Step-level timeout in the calling workflow**: When calling a composite action as
56
+ a step in a workflow file, `timeout-minutes` IS supported at the step level in the
57
+ workflow (not inside the composite itself). This provides a per-call timeout.
58
+ 4. **Split into multiple reusable actions**: Replace a large composite action with
59
+ multiple smaller ones, each invoked as a separate workflow step — where step-level
60
+ `timeout-minutes` IS enforced.
61
+ fix_code:
62
+ - language: yaml
63
+ label: "WRONG — timeout-minutes inside composite action step is silently ignored"
64
+ code: |
65
+ # action.yml — composite action
66
+ name: "Setup with Timeout"
67
+ runs:
68
+ using: composite
69
+ steps:
70
+ - name: Download dependencies
71
+ timeout-minutes: 5 # ← SILENTLY IGNORED — not enforced at runtime
72
+ shell: bash
73
+ run: curl -o deps.tar.gz "${{ inputs.deps-url }}"
74
+
75
+ - language: yaml
76
+ label: "Workaround: shell-level timeout inside composite action"
77
+ code: |
78
+ # action.yml — composite action
79
+ name: "Setup with Shell Timeout"
80
+ runs:
81
+ using: composite
82
+ steps:
83
+ - name: Download dependencies with shell timeout
84
+ shell: bash
85
+ run: |
86
+ # timeout-minutes on this step would be ignored — use shell timeout instead
87
+ timeout 300 curl -o deps.tar.gz "${{ inputs.deps-url }}" || {
88
+ echo "::error::Download timed out after 5 minutes"
89
+ exit 1
90
+ }
91
+
92
+ - name: Cache restore with timeout guard
93
+ shell: bash
94
+ run: |
95
+ timeout 120 ./restore-cache.sh || {
96
+ echo "::warning::Cache restore timed out — continuing without cache"
97
+ }
98
+
99
+ - language: yaml
100
+ label: "Workaround: step-level timeout in the calling WORKFLOW (not inside composite)"
101
+ code: |
102
+ # workflow.yml — timeout-minutes at step level in workflow DOES work
103
+ jobs:
104
+ build:
105
+ runs-on: ubuntu-latest
106
+ timeout-minutes: 30 # Job-level safety net
107
+ steps:
108
+ - uses: actions/checkout@v4
109
+
110
+ # timeout-minutes here is at the WORKFLOW step level — this IS enforced
111
+ - name: Run composite action
112
+ uses: ./.github/actions/my-composite-action
113
+ timeout-minutes: 10 # Works: this is a workflow step, not inside the composite
114
+
115
+ - run: npm run build
116
+
117
+ - language: yaml
118
+ label: "Workaround: split composite into multiple actions — each gets timeout"
119
+ code: |
120
+ # workflow.yml — multiple smaller actions instead of one large composite
121
+ jobs:
122
+ build:
123
+ runs-on: ubuntu-latest
124
+ steps:
125
+ # Each step in the workflow gets enforceable timeout-minutes
126
+ - uses: ./.github/actions/setup-node
127
+ timeout-minutes: 5 # Enforced — workflow step level
128
+
129
+ - uses: ./.github/actions/restore-cache
130
+ timeout-minutes: 3 # Enforced
131
+
132
+ - uses: ./.github/actions/install-deps
133
+ timeout-minutes: 10 # Enforced
134
+ prevention:
135
+ - "Never rely on `timeout-minutes` inside composite action `steps:` — the field is accepted but silently ignored."
136
+ - "Use `timeout <seconds>` (bash) or PowerShell job timeouts as shell-level guards for long-running composite steps."
137
+ - "Apply `timeout-minutes` at the step level in the CALLING WORKFLOW (not inside the composite) for per-invocation limits."
138
+ - "Always set a job-level `timeout-minutes` on any job that calls composite actions, as a safety net against runaway steps."
139
+ - "Composite action authors should document the expected maximum runtime so callers can set appropriate job-level timeouts."
140
+ docs:
141
+ - url: "https://github.com/actions/runner/issues/1979"
142
+ label: "actions/runner#1979 — timeout-minutes not enforced in composite action steps (open since 2021)"
143
+ - url: "https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#jobsjob_idstepstimeout-minutes"
144
+ label: "GitHub Docs: steps[*].timeout-minutes (workflow-level steps — works)"
145
+ - url: "https://docs.github.com/en/actions/sharing-automations/creating-actions/metadata-syntax-for-github-actions#runs-for-composite-actions"
146
+ label: "GitHub Docs: Metadata syntax for composite actions"
@@ -0,0 +1,116 @@
1
+ id: known-unsolved-014
2
+ title: "Reusable Workflows Cannot Be Called from Composite Actions"
3
+ category: known-unsolved
4
+ severity: limitation
5
+ tags:
6
+ - composite-action
7
+ - reusable-workflow
8
+ - workflow-call
9
+ - limitation
10
+ - uses-key
11
+ - no-fix
12
+ patterns:
13
+ - regex: "Reusable workflows cannot be referenced from composite actions"
14
+ flags: "i"
15
+ - regex: "uses:.*\\.github/workflows/.*\\.yml.*composite"
16
+ flags: "i"
17
+ - regex: "A reusable workflow cannot be used as a step in a composite action"
18
+ flags: "i"
19
+ error_messages:
20
+ - "Error: Reusable workflows cannot be referenced from composite actions."
21
+ - "A reusable workflow cannot be used as a step in a composite action."
22
+ root_cause: |
23
+ GitHub Actions enforces a strict separation between two different abstraction levels:
24
+ - **Actions** (composite, JavaScript, Docker) — called from workflow steps via `uses:`
25
+ - **Reusable workflows** (called via `workflow_call` trigger) — called from workflow jobs
26
+ via `uses:` at the JOB level, not the step level
27
+
28
+ A composite action runs within a step inside a job. A reusable workflow, however, IS a
29
+ job (or set of jobs). You cannot embed a job inside a step — this is a fundamental
30
+ architectural constraint, not a configuration error.
31
+
32
+ This fails at validation time with a clear error message. The error is triggered when:
33
+ - A composite action's `runs.steps` contains a `uses:` entry that points to a
34
+ `.github/workflows/*.yml` file (a reusable workflow)
35
+ - An organization tried to nest workflow-level orchestration inside a step-level action
36
+
37
+ There is no workaround that preserves both the composite action wrapping and the reusable
38
+ workflow invocation. GitHub has confirmed this is by design and has no plans to change it.
39
+ The GitHub Actions team's rationale: reusable workflows operate at the job/runner level
40
+ and require job-level context (needs:, outputs:, secrets: inheritance) that cannot exist
41
+ inside a step.
42
+ fix: |
43
+ There is no fix — this is a platform limitation.
44
+
45
+ The recommended alternatives are:
46
+ 1. **Restructure to call the reusable workflow at the job level** (not from inside a
47
+ composite action). Move the reusable workflow call to a dedicated job in your workflow
48
+ file using `jobs.my-job.uses:`.
49
+ 2. **Convert the reusable workflow into a composite action** if the logic does not require
50
+ job-level features (matrix, needs: dependencies, explicit runner selection, secrets
51
+ inheritance via `secrets: inherit`).
52
+ 3. **Inline the reusable workflow steps** into the composite action directly. While this
53
+ loses the DRY benefit of the reusable workflow, it resolves the structural constraint.
54
+ fix_code:
55
+ - language: yaml
56
+ label: "Call reusable workflow at job level (not from composite action)"
57
+ code: |
58
+ # ❌ This FAILS — cannot call reusable workflow from composite action step
59
+ # In: .github/actions/my-composite/action.yml
60
+ # runs:
61
+ # using: "composite"
62
+ # steps:
63
+ # - uses: ./.github/workflows/shared-build.yml # ERROR: not allowed
64
+ # with:
65
+ # environment: staging
66
+
67
+ # ✅ Call reusable workflow at job level in workflow file instead
68
+ jobs:
69
+ setup:
70
+ runs-on: ubuntu-latest
71
+ steps:
72
+ # Composite action can still do pre/post steps
73
+ - uses: ./.github/actions/my-composite
74
+ with:
75
+ param: value
76
+
77
+ shared-build:
78
+ needs: setup
79
+ uses: ./.github/workflows/shared-build.yml
80
+ with:
81
+ environment: staging
82
+ secrets: inherit
83
+ - language: yaml
84
+ label: "Convert reusable workflow to composite action (when job-level features not needed)"
85
+ code: |
86
+ # .github/actions/shared-build/action.yml
87
+ name: "Shared Build"
88
+ description: "Composite action equivalent of the shared-build reusable workflow"
89
+ inputs:
90
+ environment:
91
+ required: true
92
+ description: "Target environment"
93
+ runs:
94
+ using: "composite"
95
+ steps:
96
+ - name: Setup Node
97
+ uses: actions/setup-node@v4
98
+ with:
99
+ node-version: '20'
100
+ - name: Build
101
+ shell: bash
102
+ run: npm run build:${{ inputs.environment }}
103
+ prevention:
104
+ - "Understand the GitHub Actions hierarchy: Docker/JS/composite actions run WITHIN steps; reusable workflows run AS jobs."
105
+ - "Use composite actions when you want to share steps across workflows within a single job."
106
+ - "Use reusable workflows (workflow_call) when you want to share an entire job or multi-job sequence."
107
+ - "If you need both abstraction levels, combine them: a job calls a reusable workflow, and within that workflow's jobs, steps call composite actions."
108
+ docs:
109
+ - url: "https://docs.github.com/en/actions/sharing-automations/reusing-workflows#limitations"
110
+ label: "GitHub docs — Reusing workflows: limitations (composite action restriction)"
111
+ - url: "https://docs.github.com/en/actions/sharing-automations/creating-actions/creating-a-composite-action"
112
+ label: "GitHub docs — Creating a composite action"
113
+ - url: "https://github.com/orgs/community/discussions/11834"
114
+ label: "Community discussion #11834 — reusable workflow called from composite action error"
115
+ - url: "https://stackoverflow.com/questions/70421268/how-to-reference-a-reusable-workflow-from-a-composite-action"
116
+ label: "Stack Overflow — reference reusable workflow from composite action"
@@ -0,0 +1,113 @@
1
+ id: known-unsolved-015
2
+ title: "Scheduled Workflows Only Run on the Default Branch — Cannot Target Arbitrary Branches"
3
+ category: known-unsolved
4
+ severity: limitation
5
+ tags:
6
+ - schedule
7
+ - cron
8
+ - default-branch
9
+ - trigger
10
+ - branches-filter
11
+ - platform-limitation
12
+ patterns:
13
+ - regex: "schedule.*branches|branches.*schedule"
14
+ flags: "i"
15
+ - regex: "cron.*not.*branch|branch.*cron.*ignored"
16
+ flags: "i"
17
+ - regex: "Unexpected value 'branches'"
18
+ flags: "i"
19
+ error_messages:
20
+ - "You have an error in your yaml syntax on line X"
21
+ - "Unexpected value 'branches'"
22
+ - "The 'branches' filter is not supported under 'schedule'"
23
+ root_cause: |
24
+ GitHub Actions schedule (cron) triggers **always run the workflow file from the
25
+ repository's default branch** (typically `main`). This is an intentional platform
26
+ security constraint.
27
+
28
+ There is no supported way to target a non-default branch with a `schedule:` trigger:
29
+ - Adding `branches:` under `schedule:` causes a YAML syntax error ("Unexpected value
30
+ 'branches'") — it is not a valid key in that position.
31
+ - Placing the schedule workflow on a non-default branch does not cause it to run.
32
+ - The `github.ref` and `github.head_ref` values will always reflect the default branch
33
+ when triggered by a schedule event.
34
+
35
+ **Why GitHub enforces this:**
36
+ If scheduled workflows could target arbitrary branches, an attacker who pushes
37
+ malicious code to a feature branch could have it execute on a cron schedule with the
38
+ repository's full secrets — a significant supply-chain risk. By restricting cron runs
39
+ to the default branch, GitHub ensures only reviewed/merged code runs on schedule.
40
+
41
+ **Platform impact:**
42
+ - Cannot create separate nightly build schedules for multiple branches from one repo.
43
+ - Cannot run a scheduled integration test on a long-lived release branch without
44
+ special workarounds.
45
+ - Community has requested this capability since 2021 (community discussion #16107).
46
+
47
+ Sources: Stack Overflow Q/A, GitHub Community #16107, GitHub Docs
48
+ fix: |
49
+ There is no direct fix — this is a platform constraint. Use these workarounds:
50
+
51
+ **Workaround 1 (Recommended): Check out the target branch in the scheduled workflow**
52
+ Keep the scheduled workflow on the default branch but have the job check out the
53
+ desired branch in its `actions/checkout` step:
54
+
55
+ **Workaround 2: Trigger via `workflow_dispatch` from an external scheduler**
56
+ Use the GitHub REST API or `gh workflow run` from a controlled external system
57
+ (another scheduled job, GitHub App, etc.) to trigger a `workflow_dispatch` event
58
+ targeting a specific `ref` (branch or tag).
59
+
60
+ **Workaround 3: `workflow_run` chaining**
61
+ Not a direct substitute, but a workflow triggered by `workflow_run` on a push to
62
+ the target branch can perform scheduled-like follow-up logic.
63
+
64
+ **For release branches:** Merge a scheduled workflow file into each release branch
65
+ as part of the branch maintenance process — each branch can independently schedule
66
+ its own cron.
67
+ fix_code:
68
+ - language: yaml
69
+ label: "Broken — branches filter not valid under schedule, causes YAML error"
70
+ code: |
71
+ # ❌ BROKEN: 'branches' is not a valid key under schedule — YAML syntax error
72
+ on:
73
+ schedule:
74
+ - cron: '0 1 * * *'
75
+ branches: # ← invalid key, causes: Unexpected value 'branches'
76
+ - release/v2
77
+ - language: yaml
78
+ label: "Workaround — check out target branch in the scheduled workflow step"
79
+ code: |
80
+ # ✅ WORKAROUND: workflow lives on default branch, checks out the desired ref
81
+ on:
82
+ schedule:
83
+ - cron: '0 1 * * *' # runs from default branch (main)
84
+
85
+ jobs:
86
+ nightly-test:
87
+ runs-on: ubuntu-latest
88
+ steps:
89
+ - uses: actions/checkout@v4
90
+ with:
91
+ ref: 'release/v2' # explicitly check out the target branch
92
+ # All subsequent steps operate on release/v2 code
93
+ - run: ./run-tests.sh
94
+ - language: yaml
95
+ label: "Workaround — trigger workflow_dispatch against a specific branch via gh CLI"
96
+ code: |
97
+ # ✅ WORKAROUND: External script that fires workflow_dispatch targeting a branch
98
+ # Run this from another scheduled job (e.g., a GitHub App or a cron runner)
99
+ gh workflow run nightly.yml \
100
+ --repo owner/repo \
101
+ --ref release/v2 # workflow_dispatch supports specifying a branch ref
102
+ prevention:
103
+ - "Do not add `branches:` under `schedule:` — it is not a valid key and will cause YAML syntax errors."
104
+ - "Design scheduled workflows to check out the target branch explicitly via `actions/checkout` with the `ref:` input."
105
+ - "For complex multi-branch scheduling needs, consider using a GitHub App or external scheduler that fires `workflow_dispatch` events targeting specific refs."
106
+ - "Document this platform limitation in team wikis to prevent repeated attempts at adding `branches:` to schedule triggers."
107
+ docs:
108
+ - url: "https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#schedule"
109
+ label: "GitHub Docs: Events that trigger workflows — schedule"
110
+ - url: "https://github.com/orgs/community/discussions/16107"
111
+ label: "GitHub Community #16107 — Schedule trigger target branch request"
112
+ - url: "https://stackoverflow.com/questions/63612155/how-do-i-trigger-a-scheduled-action-on-a-specific-branch"
113
+ label: "Stack Overflow: How to trigger a scheduled action on a specific branch"