@htekdev/actions-debugger 1.0.56 → 1.0.58

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 (25) hide show
  1. package/errors/caching-artifacts/caching-artifacts-038.yml +95 -0
  2. package/errors/caching-artifacts/caching-artifacts-039.yml +110 -0
  3. package/errors/caching-artifacts/caching-artifacts-040.yml +112 -0
  4. package/errors/concurrency-timing/concurrency-timing-033.yml +104 -0
  5. package/errors/concurrency-timing/concurrency-timing-034.yml +123 -0
  6. package/errors/known-unsolved/known-unsolved-038.yml +124 -0
  7. package/errors/known-unsolved/known-unsolved-039.yml +102 -0
  8. package/errors/permissions-auth/permissions-auth-041.yml +110 -0
  9. package/errors/permissions-auth/permissions-auth-042.yml +125 -0
  10. package/errors/runner-environment/runner-environment-112.yml +98 -0
  11. package/errors/runner-environment/runner-environment-113.yml +118 -0
  12. package/errors/runner-environment/runner-environment-114.yml +130 -0
  13. package/errors/runner-environment/runner-environment-115.yml +120 -0
  14. package/errors/runner-environment/runner-environment-116.yml +106 -0
  15. package/errors/runner-environment/runner-environment-117.yml +109 -0
  16. package/errors/runner-environment/runner-environment-118.yml +102 -0
  17. package/errors/silent-failures/silent-failures-057.yml +120 -0
  18. package/errors/silent-failures/silent-failures-058.yml +126 -0
  19. package/errors/silent-failures/silent-failures-059.yml +104 -0
  20. package/errors/triggers/triggers-041.yml +105 -0
  21. package/errors/triggers/triggers-042.yml +110 -0
  22. package/errors/triggers/triggers-043.yml +125 -0
  23. package/errors/yaml-syntax/yaml-syntax-040.yml +135 -0
  24. package/errors/yaml-syntax/yaml-syntax-041.yml +147 -0
  25. package/package.json +1 -1
@@ -0,0 +1,120 @@
1
+ id: silent-failures-057
2
+ title: "needs.<job>.outputs empty when upstream job failed — if: always() downstream job silently receives empty strings"
3
+ category: silent-failures
4
+ severity: silent-failure
5
+ tags:
6
+ - needs
7
+ - job-outputs
8
+ - always
9
+ - failure
10
+ - silent-failure
11
+ - job-dependencies
12
+ - error-handling
13
+ patterns:
14
+ - regex: 'needs\.\w+\.outputs\.\w+'
15
+ flags: 'i'
16
+ - regex: 'if.*always.*needs.*result.*failure'
17
+ flags: 'i'
18
+ error_messages: []
19
+ root_cause: |
20
+ GitHub Actions job outputs are only populated when the upstream job completes successfully
21
+ (exit code 0). If an upstream job fails, its outputs are never set in the workflow context
22
+ — even if the job partially executed and wrote to $GITHUB_OUTPUT before the failure.
23
+
24
+ When a downstream job uses `if: always()` or `if: needs.upstream.result == 'failure'`
25
+ to run after a failed upstream job, all `needs.<upstream>.outputs.*` values resolve to
26
+ empty strings. No warning is emitted in the logs. The downstream job runs without any
27
+ indication that it received empty output values instead of the expected data.
28
+
29
+ This silently causes:
30
+ - Notification steps sending messages with blank context (empty SHA, branch, artifact path)
31
+ - Conditional steps skipping because a non-empty string check evaluates to false
32
+ - Upload or deploy steps using empty or incorrectly-derived paths
33
+ - Downstream matrix jobs running with no dimension values
34
+
35
+ The pattern is valid YAML — `needs.upstream.outputs.my_value` passes schema validation.
36
+ The failure only manifests at runtime after the upstream job has failed, and the symptoms
37
+ look unrelated to the empty output (e.g., "artifact not found" rather than "output was empty").
38
+ fix: |
39
+ Option 1 (recommended): Set outputs as early as possible in the upstream job, before any
40
+ step that might fail. Use a dedicated first step to write context values to $GITHUB_OUTPUT
41
+ before running builds or tests that could fail.
42
+
43
+ Option 2: Add `|| 'fallback'` expressions to all `needs.*.outputs.*` references in
44
+ if:always() downstream jobs to make empty values visible:
45
+ env:
46
+ ARTIFACT_PATH: ${{ needs.build.outputs.artifact_path || 'unknown' }}
47
+
48
+ Option 3: In notification/cleanup jobs, use `github.*` context values directly rather
49
+ than relying on upstream job outputs for data that is always available:
50
+ github.sha, github.ref_name, github.actor, github.run_id
51
+
52
+ Option 4: Use a `result` check before accessing outputs and provide explicit fallbacks
53
+ when result is not 'success':
54
+ ${{ needs.build.result == 'success' && needs.build.outputs.artifact || 'build-failed' }}
55
+ fix_code:
56
+ - language: yaml
57
+ label: "Set outputs in a first step before any step that might fail"
58
+ code: |
59
+ jobs:
60
+ build:
61
+ runs-on: ubuntu-latest
62
+ outputs:
63
+ artifact_path: ${{ steps.init.outputs.artifact_path }}
64
+ commit_sha: ${{ steps.init.outputs.commit_sha }}
65
+ steps:
66
+ # Set outputs FIRST before any step that might fail
67
+ - name: Initialize outputs
68
+ id: init
69
+ run: |
70
+ echo "artifact_path=dist/" >> $GITHUB_OUTPUT
71
+ echo "commit_sha=${{ github.sha }}" >> $GITHUB_OUTPUT
72
+
73
+ - uses: actions/checkout@v4
74
+
75
+ - name: Build (may fail)
76
+ run: npm run build
77
+
78
+ notify:
79
+ needs: build
80
+ if: always()
81
+ runs-on: ubuntu-latest
82
+ steps:
83
+ - name: Send build notification
84
+ run: |
85
+ RESULT="${{ needs.build.result }}"
86
+ # Use || fallback since outputs are empty when build failed
87
+ ARTIFACT="${{ needs.build.outputs.artifact_path || 'N/A' }}"
88
+ SHA="${{ needs.build.outputs.commit_sha || github.sha }}"
89
+ echo "Build: $RESULT | Artifact: $ARTIFACT | SHA: $SHA"
90
+ - language: yaml
91
+ label: "Use github context directly in failure-handling jobs instead of upstream outputs"
92
+ code: |
93
+ jobs:
94
+ notify-on-failure:
95
+ needs: [build, test]
96
+ if: failure()
97
+ runs-on: ubuntu-latest
98
+ steps:
99
+ - name: Notify failure
100
+ run: |
101
+ # Use github context — always available regardless of upstream failure
102
+ echo "Repository: ${{ github.repository }}"
103
+ echo "Branch: ${{ github.ref_name }}"
104
+ echo "Commit: ${{ github.sha }}"
105
+ echo "Actor: ${{ github.actor }}"
106
+ echo "Run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
107
+ prevention:
108
+ - "Write all critical values to GITHUB_OUTPUT in the very first step of a job, before any step that might fail"
109
+ - "Add || 'fallback' to every needs.*.outputs.* expression in if:always() or if:failure() downstream jobs"
110
+ - "Use github.* context values for data always available (sha, ref_name, actor, run_id) rather than upstream outputs"
111
+ - "Test failure paths by adding a workflow_dispatch that intentionally fails the upstream job and verify downstream output"
112
+ docs:
113
+ - url: "https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idoutputs"
114
+ label: "GitHub Docs — Job outputs"
115
+ - url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/accessing-contextual-information-about-workflow-runs#needs-context"
116
+ label: "GitHub Docs — needs context"
117
+ - url: "https://github.com/orgs/community/discussions/18163"
118
+ label: "GitHub Community — needs outputs empty when job failed"
119
+ - url: "https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idif"
120
+ label: "GitHub Docs — if conditions with always()"
@@ -0,0 +1,126 @@
1
+ id: silent-failures-058
2
+ title: "workflow_dispatch type:choice inputs bypass validation via REST API — arbitrary strings accepted silently"
3
+ category: silent-failures
4
+ severity: silent-failure
5
+ tags:
6
+ - workflow_dispatch
7
+ - inputs
8
+ - choice
9
+ - rest-api
10
+ - validation
11
+ - type-checking
12
+ patterns:
13
+ - regex: 'type:\s*choice'
14
+ flags: 'i'
15
+ - regex: 'workflow.*dispatch.*inputs.*choice'
16
+ flags: 'i'
17
+ error_messages:
18
+ - "type: choice"
19
+ root_cause: |
20
+ The workflow_dispatch event supports an input type of 'choice' which presents
21
+ a dropdown menu in the GitHub UI, restricting the user to a predefined list of
22
+ valid values. However, this validation is enforced only in the GitHub web UI —
23
+ it is NOT enforced by the GitHub Actions API.
24
+
25
+ When a workflow is triggered via the REST API (POST /repos/{owner}/{repo}/actions/
26
+ workflows/{workflow_id}/dispatches), any string value can be supplied for a
27
+ choice-type input, including values not in the defined options list. The workflow
28
+ accepts and runs with the unsanitized value without error or warning.
29
+
30
+ This means:
31
+ - CI/CD scripts calling workflow_dispatch via REST API can accidentally pass
32
+ the wrong environment name (typos, case differences, wrong string)
33
+ - Automation systems that construct the dispatch payload dynamically may pass
34
+ a value that was valid at construction time but is no longer a valid choice
35
+ - Malicious actors with repository write access can trigger unexpected code paths
36
+ by dispatching with unexpected values
37
+
38
+ Steps using 'if: inputs.environment == "production"' may silently skip or
39
+ silently run depending on whether the API-supplied string matches exactly.
40
+ No error is raised — the workflow just behaves unexpectedly.
41
+
42
+ Example: inputs.environment options are ['dev', 'staging', 'production'] but
43
+ API call passes 'prod' — all condition checks against 'production' silently
44
+ fail, causing the deployment step to be skipped with no indication of why.
45
+ fix: |
46
+ Explicitly validate choice-type inputs at the start of the workflow using a
47
+ validation step that fails fast with a clear error message when an invalid
48
+ value is supplied.
49
+
50
+ For critical path decisions (environment selection, deployment targets), use
51
+ a validation step before any consequential operations:
52
+
53
+ - name: Validate environment input
54
+ run: |
55
+ case "${{ inputs.environment }}" in
56
+ dev|staging|production) ;;
57
+ *) echo "Invalid environment: ${{ inputs.environment }}" && exit 1 ;;
58
+ esac
59
+
60
+ This approach works regardless of how the workflow was triggered (UI or API)
61
+ and produces a clear failure message instead of a silent wrong-path execution.
62
+ fix_code:
63
+ - language: yaml
64
+ label: "Validate choice input before using it — fails fast with clear error"
65
+ code: |
66
+ on:
67
+ workflow_dispatch:
68
+ inputs:
69
+ environment:
70
+ description: 'Target environment'
71
+ type: choice
72
+ required: true
73
+ options:
74
+ - dev
75
+ - staging
76
+ - production
77
+
78
+ jobs:
79
+ deploy:
80
+ runs-on: ubuntu-latest
81
+ steps:
82
+ - name: Validate environment input
83
+ run: |
84
+ valid_envs="dev staging production"
85
+ if ! echo "$valid_envs" | grep -qw "${{ inputs.environment }}"; then
86
+ echo "ERROR: Invalid environment '${{ inputs.environment }}'"
87
+ echo "Valid options: $valid_envs"
88
+ exit 1
89
+ fi
90
+
91
+ - name: Deploy to ${{ inputs.environment }}
92
+ run: echo "Deploying to ${{ inputs.environment }}"
93
+ - language: yaml
94
+ label: "Use environment-scoped deployment for automatic protection"
95
+ code: |
96
+ on:
97
+ workflow_dispatch:
98
+ inputs:
99
+ environment:
100
+ description: 'Target environment'
101
+ type: choice
102
+ required: true
103
+ options:
104
+ - dev
105
+ - staging
106
+ - production
107
+
108
+ jobs:
109
+ deploy:
110
+ runs-on: ubuntu-latest
111
+ environment: ${{ inputs.environment }} # Invalid names cause job failure
112
+ steps:
113
+ - name: Deploy
114
+ run: echo "Deploying to ${{ inputs.environment }}"
115
+ prevention:
116
+ - "Never rely solely on type:choice validation — always add an explicit validation step for inputs that affect deployment targets or security-sensitive code paths"
117
+ - "Use environment: ${{ inputs.environment }} on jobs to leverage GitHub's environment protection rules as a secondary validation layer"
118
+ - "Document that API dispatch bypasses choice validation in your workflow's comments so future maintainers know validation is needed"
119
+ - "In automation scripts that call workflow_dispatch via API, validate the environment string against the allowed list before making the API call"
120
+ docs:
121
+ - url: "https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#workflow_dispatch"
122
+ label: "GitHub Docs — workflow_dispatch inputs"
123
+ - url: "https://docs.github.com/en/rest/actions/workflows#create-a-workflow-dispatch-event"
124
+ label: "GitHub REST API — Create a workflow dispatch event"
125
+ - url: "https://stackoverflow.com/questions/69578241/github-actions-workflow-dispatch-with-choices"
126
+ label: "Stack Overflow — workflow_dispatch with choice inputs (highly voted)"
@@ -0,0 +1,104 @@
1
+ id: silent-failures-059
2
+ title: "ubuntu-latest label changed to ubuntu-24.04 — workflows silently regress without any code change"
3
+ category: silent-failures
4
+ severity: silent-failure
5
+ tags:
6
+ - ubuntu-latest
7
+ - ubuntu-24.04
8
+ - runner-label
9
+ - breaking-change
10
+ - silent-regression
11
+ - changelog
12
+ patterns:
13
+ - regex: 'runs-on:\s*ubuntu-latest'
14
+ flags: 'i'
15
+ - regex: 'GITHUB_ENV.*ubuntu-24\.04'
16
+ flags: 'i'
17
+ - regex: 'ImageVersion.*24\.04'
18
+ flags: 'i'
19
+ error_messages:
20
+ - "ubuntu-latest now points to ubuntu-24.04"
21
+ - "ImageVersion: 24.04"
22
+ - "DISTRIB_CODENAME=noble"
23
+ root_cause: |
24
+ GitHub periodically updates the `ubuntu-latest` runner label to point to a newer
25
+ Ubuntu LTS release. When GitHub updated `ubuntu-latest` from ubuntu-22.04 to
26
+ ubuntu-24.04, workflows using `runs-on: ubuntu-latest` silently started running on
27
+ a different operating system with no error, no annotation, and no workflow file change.
28
+
29
+ This is a silent failure because:
30
+ - The workflow YAML file is unchanged
31
+ - GitHub Actions does not emit any warning when the label target changes
32
+ - Workflow run logs show "ubuntu-24.04" only in the runner image annotation, which
33
+ many developers don't actively monitor
34
+ - All jobs complete with exit code 0 even though the software environment changed
35
+
36
+ Ubuntu 24.04 (Noble) introduced multiple breaking changes relative to 22.04 (Jammy):
37
+ - Python 3.12 as default (removes distutils, changes pip behavior)
38
+ - OpenSSL 3.3 with stricter TLS renegotiation defaults
39
+ - nftables replaces iptables (breaks Docker networking setups using iptables rules)
40
+ - python3-distutils apt package removed
41
+ - python alias may not resolve to python3 in all contexts
42
+ - libssl1.1 removed (only libssl3 available)
43
+ - Various default package versions changed (gcc, make, cmake)
44
+
45
+ Any workflow that relied on implicit ubuntu-22.04 behavior while pinning only
46
+ `ubuntu-latest` is at risk of silent behavioral changes, test flakiness, or
47
+ hard build failures that appear unrelated to any code change.
48
+ fix: |
49
+ Pin the runner to an explicit Ubuntu version to opt out of automatic label
50
+ updates. Use `runs-on: ubuntu-22.04` if you need the previous behavior, or
51
+ explicitly migrate to `runs-on: ubuntu-24.04` and verify all workflow steps
52
+ work correctly.
53
+
54
+ To identify which runner version you are actually running, add a diagnostic step:
55
+
56
+ ```bash
57
+ echo "Runner: $RUNNER_OS $ImageVersion"
58
+ lsb_release -a
59
+ ```
60
+
61
+ Review each ubuntu-24.04 breaking change that applies to your workflow and
62
+ address them before pinning to ubuntu-24.04. See the related runner-environment
63
+ entries for specific package and API breakages.
64
+ fix_code:
65
+ - language: yaml
66
+ label: "Pin to explicit Ubuntu version instead of ubuntu-latest"
67
+ code: |
68
+ jobs:
69
+ build:
70
+ # Pin explicitly instead of ubuntu-latest to avoid silent label updates
71
+ runs-on: ubuntu-22.04 # or ubuntu-24.04 after testing
72
+
73
+ # To migrate to 24.04, test explicitly first:
74
+ # runs-on: ubuntu-24.04
75
+ steps:
76
+ - uses: actions/checkout@v4
77
+ - name: Show runner info
78
+ run: lsb_release -a && python3 --version
79
+ - language: yaml
80
+ label: "Matrix strategy to test across Ubuntu versions before committing"
81
+ code: |
82
+ jobs:
83
+ test:
84
+ strategy:
85
+ matrix:
86
+ os: [ubuntu-22.04, ubuntu-24.04]
87
+ runs-on: ${{ matrix.os }}
88
+ steps:
89
+ - uses: actions/checkout@v4
90
+ - name: Run tests
91
+ run: npm test
92
+ prevention:
93
+ - "Never use `ubuntu-latest` in production workflows — pin to an explicit version (ubuntu-22.04, ubuntu-24.04)"
94
+ - "Subscribe to GitHub Changelog announcements for runner label change notices before they go live"
95
+ - "Add a matrix build that tests both current and next Ubuntu LTS versions as part of ongoing CI"
96
+ - "Include a step that prints `lsb_release -a` to make runner version visible in logs without digging into annotations"
97
+ - "When migrating to a new Ubuntu version, run `apt-cache policy <package>` to verify package availability before deploying"
98
+ docs:
99
+ - url: "https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources"
100
+ label: "GitHub Docs — Supported runners (ubuntu-latest current target)"
101
+ - url: "https://github.blog/changelog/2025-01-16-github-actions-all-actions-on-ubuntu-latest-will-now-be-run-on-ubuntu-24-04/"
102
+ label: "GitHub Changelog — ubuntu-latest updated to ubuntu-24.04"
103
+ - url: "https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2404-Readme.md"
104
+ label: "runner-images — Ubuntu 24.04 pre-installed software list"
@@ -0,0 +1,105 @@
1
+ id: triggers-041
2
+ title: "on.schedule workflow only runs from default branch — schedule changes in feature branches never fire"
3
+ category: triggers
4
+ severity: limitation
5
+ tags:
6
+ - schedule
7
+ - cron
8
+ - default-branch
9
+ - triggers
10
+ - known-limitation
11
+ - testing
12
+ patterns:
13
+ - regex: 'schedule.*not.*trigger'
14
+ flags: 'i'
15
+ - regex: 'cron.*not.*running.*branch'
16
+ flags: 'i'
17
+ - regex: 'workflow.*not.*present.*default.*branch'
18
+ flags: 'i'
19
+ error_messages:
20
+ - "This workflow has a workflow_dispatch event trigger, however a workflow_dispatch event workflow run cannot be created as this workflow is not present in the default branch."
21
+ root_cause: |
22
+ GitHub Actions `on.schedule` workflows only execute from the repository's default branch
23
+ (typically `main` or `master`). No matter what branch the workflow file is pushed to, the
24
+ schedule trigger always runs the version of the workflow file on the default branch.
25
+
26
+ This creates a silent testing trap: developers modify a cron-based workflow in a feature
27
+ branch, push it, and wait for the scheduled time. The schedule fires correctly — but runs
28
+ the OLD workflow definition from the default branch, not the feature branch changes. The
29
+ developer sees no behavior change and cannot validate their modifications until after merging.
30
+
31
+ There is no GitHub UI indication that a scheduled workflow is "pending for a branch". All
32
+ scheduled runs appear under the default branch in the Actions tab regardless of which branch
33
+ triggered or modified them.
34
+
35
+ This limitation applies exclusively to `on.schedule`. Other triggers (`on.push`,
36
+ `on.pull_request`, `on.workflow_dispatch`) work correctly from any branch that contains
37
+ the workflow file.
38
+ fix: |
39
+ There is no way to run `on.schedule` from a feature branch. Use these testing alternatives:
40
+
41
+ Option 1 (recommended): Add `on.workflow_dispatch` to the same workflow alongside
42
+ `on.schedule`. Use the GitHub UI or CLI to manually trigger runs from your feature branch
43
+ to validate changes before merging.
44
+
45
+ Option 2: Add `on.push` with a specific branch filter during development. Push triggers
46
+ fire from any branch and will use the feature branch's workflow definition.
47
+
48
+ Option 3: Use `act` (nektos/act) locally to simulate scheduled runs before pushing.
49
+
50
+ Option 4: Merge to a short-lived integration/staging branch that serves as a temporary
51
+ "default" for validation, then merge to main.
52
+
53
+ After validation, merge to the default branch — the schedule will automatically use the
54
+ updated workflow definition from that point forward.
55
+ fix_code:
56
+ - language: yaml
57
+ label: "Add workflow_dispatch alongside schedule to enable branch-based testing"
58
+ code: |
59
+ on:
60
+ # Production: runs on schedule from default branch only
61
+ schedule:
62
+ - cron: '0 6 * * 1' # Every Monday at 6 AM UTC
63
+
64
+ # Development: add this to test changes from any branch manually
65
+ workflow_dispatch:
66
+
67
+ jobs:
68
+ scheduled-job:
69
+ runs-on: ubuntu-latest
70
+ steps:
71
+ - uses: actions/checkout@v4
72
+ - name: Run scheduled task
73
+ run: ./scripts/weekly-task.sh
74
+ - language: yaml
75
+ label: "Add on.push temporarily during development to fire from feature branch"
76
+ code: |
77
+ on:
78
+ schedule:
79
+ - cron: '0 6 * * 1'
80
+
81
+ # TEMPORARY: Remove before merging — used to test schedule logic from branch
82
+ push:
83
+ branches: ['feature/update-schedule-workflow']
84
+
85
+ jobs:
86
+ scheduled-job:
87
+ runs-on: ubuntu-latest
88
+ steps:
89
+ - uses: actions/checkout@v4
90
+ - name: Run scheduled task
91
+ run: ./scripts/weekly-task.sh
92
+ prevention:
93
+ - "Always add workflow_dispatch to workflows that primarily use on.schedule — it enables branch-level testing at any time"
94
+ - "Use act (nektos/act) locally to simulate scheduled workflow runs during development"
95
+ - "Add a comment in the workflow file noting that schedule: only fires from the default branch"
96
+ - "Treat schedule-only workflows as default-branch-only code — validate in staging branches before merging"
97
+ docs:
98
+ - url: "https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#schedule"
99
+ label: "GitHub Docs — schedule event"
100
+ - url: "https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_dispatch"
101
+ label: "GitHub Docs — workflow_dispatch event (for manual testing)"
102
+ - url: "https://github.com/nektos/act"
103
+ label: "nektos/act — Run Actions locally"
104
+ - url: "https://github.com/orgs/community/discussions/21536"
105
+ label: "GitHub Community — Scheduled workflow only runs on default branch"
@@ -0,0 +1,110 @@
1
+ id: triggers-042
2
+ title: "workflow_run trigger only activates when the listener workflow file exists on the default branch"
3
+ category: triggers
4
+ severity: silent-failure
5
+ tags:
6
+ - workflow_run
7
+ - default-branch
8
+ - trigger
9
+ - silent-failure
10
+ - feature-branch
11
+ - testing
12
+ patterns:
13
+ - regex: 'on:\s*[\r\n]+\s*workflow_run'
14
+ flags: 'is'
15
+ - regex: 'workflow_run.*workflows.*completed'
16
+ flags: 'is'
17
+ error_messages: []
18
+ root_cause: |
19
+ GitHub only reads the `on: workflow_run:` trigger definition from workflow files
20
+ that exist on the **default branch** of the repository. If a workflow file
21
+ containing `on: workflow_run:` exists only on a feature branch, pull request branch,
22
+ or any non-default branch, the trigger is silently ignored — no error is reported,
23
+ the workflow file is valid, and GitHub simply never fires the workflow.
24
+
25
+ This means that changes to a `workflow_run` listener workflow cannot be exercised
26
+ on a branch before merging to the default branch. A brand-new `workflow_run` listener
27
+ added on a feature branch will not activate even when the triggering workflow
28
+ (listed under `workflows:`) completes successfully.
29
+
30
+ This behavior is consistent with other event-driven triggers that GitHub reads only
31
+ from the default branch:
32
+ - `on: schedule` — cron schedule (documented, see entry triggers-041)
33
+ - `on: workflow_dispatch` — manual trigger (known-unsolved entry covers UI visibility)
34
+ - `on: workflow_run` — this entry
35
+
36
+ The distinction matters most for `workflow_run` because developers often add a
37
+ `workflow_run` listener to automate post-CI steps (deploy, notifications, releases)
38
+ and naturally develop and test the listener on a branch before merging it.
39
+
40
+ Note: The `branches:` filter inside `on: workflow_run:` controls WHICH branches the
41
+ triggering workflow must run on — this is separate from where the listener workflow
42
+ itself must reside (always the default branch).
43
+ fix: |
44
+ Merge the workflow file containing `on: workflow_run:` to the default branch before
45
+ expecting it to activate. To test the workflow logic before merging:
46
+
47
+ 1. Add a temporary `on: workflow_dispatch:` trigger alongside `on: workflow_run:`.
48
+ This allows manual test runs on any branch after the file lands on the default branch.
49
+ 2. Use `act` locally to simulate `workflow_run` events before pushing.
50
+ 3. Test using a throw-away default branch in a fork during development.
51
+
52
+ Once the file is on the default branch, the `workflow_run` trigger activates
53
+ immediately for all future triggering workflow completions.
54
+ fix_code:
55
+ - language: yaml
56
+ label: "Add workflow_dispatch alongside workflow_run for pre-merge testing"
57
+ code: |
58
+ name: Post-CI Deploy
59
+
60
+ on:
61
+ # Temporary: enables manual test runs after this file merges to default branch
62
+ workflow_dispatch:
63
+
64
+ # Primary trigger: only active after this file is on the default branch
65
+ workflow_run:
66
+ workflows: ["CI"] # Must match the exact workflow name: field value
67
+ types: [completed]
68
+ branches: [main] # Only triggers when CI ran on these branches
69
+
70
+ jobs:
71
+ deploy:
72
+ # Only deploy when CI actually passed
73
+ if: ${{ github.event.workflow_run.conclusion == 'success' || github.event_name == 'workflow_dispatch' }}
74
+ runs-on: ubuntu-latest
75
+ steps:
76
+ - uses: actions/checkout@v4
77
+ - run: echo "Deploying..."
78
+
79
+ - language: yaml
80
+ label: "Minimal workflow_run listener (file must be on default branch)"
81
+ code: |
82
+ name: Notify on CI Complete
83
+
84
+ on:
85
+ workflow_run:
86
+ workflows: ["Build and Test"] # Exact name from the other workflow's 'name:' field
87
+ types: [completed]
88
+
89
+ jobs:
90
+ notify:
91
+ runs-on: ubuntu-latest
92
+ steps:
93
+ - name: Report conclusion
94
+ run: |
95
+ echo "Triggered by: ${{ github.event.workflow_run.name }}"
96
+ echo "Conclusion: ${{ github.event.workflow_run.conclusion }}"
97
+ echo "Head branch: ${{ github.event.workflow_run.head_branch }}"
98
+ prevention:
99
+ - "Merge workflow files with on: workflow_run: to the default branch before expecting them to fire — there is no way to test this trigger on a feature branch"
100
+ - "Add on: workflow_dispatch: temporarily for manual testing after the file lands on the default branch"
101
+ - "Use act (https://github.com/nektos/act) locally to simulate workflow_run events during development"
102
+ - "Document in team runbooks that workflow_run, schedule, and workflow_dispatch triggers require the workflow file on the default branch"
103
+ - "Verify the workflows: list uses the exact value of the triggering workflow's name: field — a mismatch causes the same silent non-firing behavior"
104
+ docs:
105
+ - url: "https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#workflow_run"
106
+ label: "GitHub Docs — workflow_run trigger"
107
+ - url: "https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#triggering-a-workflow-from-a-workflow"
108
+ label: "GitHub Docs — Triggering a workflow from a workflow"
109
+ - url: "https://github.com/nektos/act"
110
+ label: "act — Run GitHub Actions locally for testing"