@htekdev/actions-debugger 1.0.83 → 1.0.84

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,90 @@
1
+ id: concurrency-timing-042
2
+ title: "github.event.number empty on push events collapses concurrency group across all branches"
3
+ category: concurrency-timing
4
+ severity: silent-failure
5
+ tags:
6
+ - concurrency
7
+ - github-event-number
8
+ - push-event
9
+ - cancel-in-progress
10
+ - cross-branch
11
+ - pull-request
12
+ patterns:
13
+ - regex: 'github\.event\.number\b'
14
+ flags: 'i'
15
+ error_messages:
16
+ - "Run was cancelled due to concurrency group collision between push events on different branches"
17
+ - "Unexpected cancellation of push workflow by unrelated branch push"
18
+ root_cause: |
19
+ `github.event.number` contains the pull request or issue number for events that have one
20
+ (e.g., `pull_request`, `pull_request_review`, `issue_comment`). On `push` events,
21
+ `github.event.number` is undefined and evaluates to an empty string in expressions.
22
+
23
+ When a workflow is triggered by both `push` and `pull_request` events, and the
24
+ concurrency group key uses `github.event.number`, all push-triggered runs share a
25
+ single concurrency group key (the suffix becomes empty):
26
+
27
+ group: "${{ github.workflow }}-${{ github.event.number }}"
28
+ # PR run: "CI-123" (unique per PR number)
29
+ # Push run: "CI-" (ALL branch pushes share this single group!)
30
+
31
+ With `cancel-in-progress: true`, pushing to any branch cancels all other in-progress
32
+ push runs — even if they are on completely different branches. Developers intend to
33
+ serialize CI per PR but instead unintentionally cancel unrelated branch pushes.
34
+ fix: |
35
+ Use the `||` operator to fall back to `github.ref` when `github.event.number` is empty.
36
+ `github.ref` is always populated (e.g., `refs/heads/main`, `refs/pull/123/merge`) and
37
+ produces a unique key per branch or PR.
38
+
39
+ Alternatively, use `github.event.number || github.sha` if you want push runs to each
40
+ be independent (no cancellation between pushes) while still serializing per PR.
41
+ fix_code:
42
+ - language: yaml
43
+ label: "Wrong — all push runs share the same concurrency group key"
44
+ code: |
45
+ on:
46
+ push:
47
+ branches: [main, 'feature/**']
48
+ pull_request:
49
+
50
+ concurrency:
51
+ group: ${{ github.workflow }}-${{ github.event.number }}
52
+ # On push: group = "CI-" (empty number → all pushes share one group)
53
+ # On PR: group = "CI-123" (unique per PR)
54
+ cancel-in-progress: true
55
+ - language: yaml
56
+ label: "Correct — fall back to github.ref so push runs are keyed per branch"
57
+ code: |
58
+ on:
59
+ push:
60
+ branches: [main, 'feature/**']
61
+ pull_request:
62
+
63
+ concurrency:
64
+ group: ${{ github.workflow }}-${{ github.event.number || github.ref }}
65
+ # On push: group = "CI-refs/heads/main" (unique per branch)
66
+ # On PR: group = "CI-123" (unique per PR number)
67
+ cancel-in-progress: true
68
+ - language: yaml
69
+ label: "Alternative — use github.ref for both triggers (no per-PR serialization)"
70
+ code: |
71
+ on:
72
+ push:
73
+ branches: [main, 'feature/**']
74
+ pull_request:
75
+
76
+ concurrency:
77
+ group: ${{ github.workflow }}-${{ github.ref }}
78
+ # On push: group = "CI-refs/heads/main"
79
+ # On PR: group = "CI-refs/pull/123/merge"
80
+ cancel-in-progress: true
81
+ prevention:
82
+ - "Always test concurrency group keys against all event types in the on: block"
83
+ - "Use github.event.number || github.ref as a safe pattern for mixed push/PR workflows"
84
+ - "Check that github.event.number is not undefined by printing it in a debug step when first setting up concurrency"
85
+ - "Prefer github.ref or github.ref_name as the base concurrency discriminator for branch-level serialization"
86
+ docs:
87
+ - url: "https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#jobsjob_idconcurrency"
88
+ label: "Workflow syntax: concurrency"
89
+ - url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/accessing-contextual-information-about-workflow-runs#github-context"
90
+ label: "GitHub context — github.event.number availability by event type"
@@ -0,0 +1,101 @@
1
+ id: known-unsolved-050
2
+ title: "workflow_dispatch REST API dispatch returns 204 No Content — triggered run_id unavailable"
3
+ category: known-unsolved
4
+ severity: limitation
5
+ tags:
6
+ - workflow_dispatch
7
+ - rest-api
8
+ - run-id
9
+ - polling
10
+ - automation
11
+ - cd-pipeline
12
+ patterns:
13
+ - regex: 'POST.*dispatches.*204|dispatches.*No Content'
14
+ flags: 'i'
15
+ error_messages:
16
+ - "204 No Content"
17
+ - "Unable to correlate triggered workflow run"
18
+ - "no run_id in dispatch response"
19
+ root_cause: |
20
+ The GitHub Actions REST API endpoint
21
+ `POST /repos/{owner}/{repo}/actions/workflows/{workflow_id}/dispatches`
22
+ always returns HTTP 204 No Content on success — there is no run_id or any identifier
23
+ in the response body. GitHub creates the workflow run asynchronously after the API call
24
+ returns, so the run may not exist in the system for several seconds. There is no built-in
25
+ way to correlate a `workflow_dispatch` API call to the resulting run_id.
26
+
27
+ This is a persistent limitation reported since 2020 on the GitHub feedback forum with
28
+ thousands of upvotes. Developers building CD pipelines that need to trigger a workflow
29
+ and then monitor or gate on its result are forced to use fragile polling heuristics.
30
+ fix: |
31
+ No direct fix — this is a GitHub platform limitation. Use one of these workarounds:
32
+
33
+ 1. **Inject a correlation ID via inputs**: Pass a unique value (e.g., UUID) as a
34
+ `workflow_dispatch` input. After dispatch, poll `GET /repos/.../actions/runs?event=workflow_dispatch&branch=<branch>`
35
+ and match runs whose `inputs` contain the correlation ID.
36
+
37
+ 2. **Use workflow_run event callback**: Design the triggered workflow to complete and
38
+ then fire a `workflow_run` event that your orchestrating workflow listens for.
39
+
40
+ 3. **Switch to repository_dispatch**: `repository_dispatch` with a unique `client_payload`
41
+ field lets you include a correlation ID. The triggered workflow can write it to an artifact
42
+ or output for later retrieval.
43
+
44
+ 4. **Third-party action**: Use `peter-evans/workflow-dispatch@v3` which implements polling
45
+ heuristics to approximate the run_id after dispatch.
46
+ fix_code:
47
+ - language: yaml
48
+ label: "Inject correlation ID via workflow_dispatch input — then poll to find run"
49
+ code: |
50
+ # Triggering workflow or script passes a unique correlation ID:
51
+ # POST /repos/{owner}/{repo}/actions/workflows/deploy.yml/dispatches
52
+ # { "ref": "main", "inputs": { "correlation_id": "abc-123-uuid" } }
53
+
54
+ # Triggered workflow (deploy.yml) writes ID to output artifact:
55
+ on:
56
+ workflow_dispatch:
57
+ inputs:
58
+ correlation_id:
59
+ description: 'Unique ID for run correlation'
60
+ required: false
61
+ default: ''
62
+
63
+ jobs:
64
+ deploy:
65
+ runs-on: ubuntu-latest
66
+ steps:
67
+ - run: echo "run_id=${{ github.run_id }}" >> correlation.txt
68
+ - uses: actions/upload-artifact@v4
69
+ with:
70
+ name: correlation-${{ inputs.correlation_id }}
71
+ path: correlation.txt
72
+ - language: yaml
73
+ label: "Use repository_dispatch with client_payload for reliable correlation"
74
+ code: |
75
+ # Trigger with unique client_payload via API:
76
+ # POST /repos/{owner}/{repo}/dispatches
77
+ # { "event_type": "deploy", "client_payload": { "job_id": "build-789" } }
78
+
79
+ on:
80
+ repository_dispatch:
81
+ types: [deploy]
82
+
83
+ jobs:
84
+ deploy:
85
+ runs-on: ubuntu-latest
86
+ steps:
87
+ - run: |
88
+ echo "Triggered by job: ${{ github.event.client_payload.job_id }}"
89
+ echo "This run ID: ${{ github.run_id }}"
90
+ prevention:
91
+ - "Design CD pipelines using workflow_run event callbacks instead of polling after dispatch"
92
+ - "Include a unique correlation_id input in all workflow_dispatch-triggered workflows"
93
+ - "Track the GitHub public roadmap — run_id in dispatch response is a long-requested feature"
94
+ - "Consider repository_dispatch for machine-to-machine triggers needing reliable correlation"
95
+ docs:
96
+ - url: "https://docs.github.com/en/rest/actions/workflows?apiVersion=2022-11-28#create-a-workflow-dispatch-event"
97
+ label: "REST API: Create a workflow dispatch event (returns 204 No Content)"
98
+ - url: "https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#workflow_run"
99
+ label: "workflow_run event — callback pattern for monitoring triggered workflows"
100
+ - url: "https://github.com/peter-evans/workflow-dispatch"
101
+ label: "peter-evans/workflow-dispatch — community action with polling heuristics"
@@ -0,0 +1,119 @@
1
+ id: silent-failures-078
2
+ title: "Skipped step leaves job-level outputs: silently empty — downstream jobs receive empty string"
3
+ category: silent-failures
4
+ severity: silent-failure
5
+ tags:
6
+ - job-outputs
7
+ - skipped-step
8
+ - outputs
9
+ - if-condition
10
+ - conditional
11
+ - downstream-jobs
12
+ patterns:
13
+ - regex: 'steps\.[a-z_][a-z0-9_-]*\.outputs\.[a-z_]'
14
+ flags: 'i'
15
+ error_messages:
16
+ - "needs.<job>.outputs.<key> is empty string when producing step was skipped"
17
+ - "Job output silently empty — step that writes output was conditionally skipped"
18
+ root_cause: |
19
+ A job's `outputs:` block maps keys to values using `${{ steps.<id>.outputs.<key> }}`
20
+ expressions. These expressions are evaluated at the end of the job, after all steps have
21
+ run. If the step referenced in the output mapping is skipped (due to an `if:` condition
22
+ evaluating to false), the step never runs and never writes to `$GITHUB_OUTPUT`. The
23
+ output expression evaluates to an empty string with no warning.
24
+
25
+ Downstream jobs that depend on this output via `needs.<job>.outputs.<key>` receive an
26
+ empty string and continue running without error. This silent empty propagation causes
27
+ incorrect behavior: deploy jobs receiving an empty version string, notification jobs
28
+ receiving an empty status, or matrix jobs receiving an empty configuration list.
29
+
30
+ This is distinct from the `skipped-job-outputs-empty-string` limitation (where the
31
+ entire job is skipped) — here the job itself runs successfully, but one or more of its
32
+ steps are conditionally skipped.
33
+ fix: |
34
+ Ensure the step that writes the output always runs, or provide a fallback value.
35
+ Use `if: always()` on the step if it should run regardless of prior step results.
36
+ Use a separate step to set a default/fallback output for the skipped case.
37
+ Alternatively, restructure the workflow so that the output-producing step is never
38
+ guarded by a condition that might prevent it from running.
39
+ fix_code:
40
+ - language: yaml
41
+ label: "Wrong — output step conditionally skipped, downstream sees empty string"
42
+ code: |
43
+ jobs:
44
+ build:
45
+ runs-on: ubuntu-latest
46
+ outputs:
47
+ version: ${{ steps.get-version.outputs.version }}
48
+ steps:
49
+ - uses: actions/checkout@v4
50
+
51
+ - name: Get version (only on tags)
52
+ id: get-version
53
+ if: startsWith(github.ref, 'refs/tags/') # skipped on branch pushes!
54
+ run: echo "version=${GITHUB_REF_NAME}" >> $GITHUB_OUTPUT
55
+
56
+ deploy:
57
+ needs: build
58
+ runs-on: ubuntu-latest
59
+ steps:
60
+ - run: |
61
+ echo "Deploying version: ${{ needs.build.outputs.version }}"
62
+ # On branch push: prints "Deploying version: " (empty — step was skipped)
63
+ - language: yaml
64
+ label: "Correct — provide a fallback step to always set the output"
65
+ code: |
66
+ jobs:
67
+ build:
68
+ runs-on: ubuntu-latest
69
+ outputs:
70
+ version: ${{ steps.get-version.outputs.version }}
71
+ steps:
72
+ - uses: actions/checkout@v4
73
+
74
+ - name: Get version from tag
75
+ id: get-version
76
+ run: |
77
+ if [[ "${GITHUB_REF}" == refs/tags/* ]]; then
78
+ echo "version=${GITHUB_REF_NAME}" >> $GITHUB_OUTPUT
79
+ else
80
+ echo "version=dev-${GITHUB_SHA::8}" >> $GITHUB_OUTPUT
81
+ fi
82
+ # Always runs — handles both tag and branch pushes
83
+
84
+ deploy:
85
+ needs: build
86
+ runs-on: ubuntu-latest
87
+ steps:
88
+ - run: echo "Deploying version ${{ needs.build.outputs.version }}"
89
+ - language: yaml
90
+ label: "Alternative — gate deploy job to only run when version is set"
91
+ code: |
92
+ jobs:
93
+ build:
94
+ runs-on: ubuntu-latest
95
+ outputs:
96
+ version: ${{ steps.get-version.outputs.version }}
97
+ steps:
98
+ - uses: actions/checkout@v4
99
+ - name: Get version (only on tags)
100
+ id: get-version
101
+ if: startsWith(github.ref, 'refs/tags/')
102
+ run: echo "version=${GITHUB_REF_NAME}" >> $GITHUB_OUTPUT
103
+
104
+ deploy:
105
+ needs: build
106
+ if: needs.build.outputs.version != '' # only run when version was set
107
+ runs-on: ubuntu-latest
108
+ steps:
109
+ - run: echo "Deploying ${{ needs.build.outputs.version }}"
110
+ prevention:
111
+ - "Audit all job outputs: blocks — for each step reference, verify it always runs"
112
+ - "Avoid conditional if: guards on steps that produce job-level outputs unless a fallback step provides the same output key"
113
+ - "Add an explicit check step at the end of each job that validates required outputs are non-empty"
114
+ - "Use actionlint — it warns when output-producing steps have if: conditions that may skip them"
115
+ docs:
116
+ - url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/passing-information-between-jobs"
117
+ label: "Passing information between jobs — job outputs"
118
+ - url: "https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows"
119
+ label: "Events that trigger workflows — job outputs with conditional steps"
@@ -0,0 +1,111 @@
1
+ id: triggers-058
2
+ title: "on.schedule ignores paths: filter — scheduled workflows always run"
3
+ category: triggers
4
+ severity: silent-failure
5
+ tags:
6
+ - schedule
7
+ - paths
8
+ - cron
9
+ - trigger
10
+ - filter
11
+ - paths-ignore
12
+ patterns:
13
+ - regex: 'schedule.*paths:|paths:.*cron:'
14
+ flags: 'si'
15
+ error_messages:
16
+ - "Scheduled workflow runs even when no matching files changed"
17
+ - "paths: filter has no effect on scheduled events"
18
+ root_cause: |
19
+ The `paths:` and `paths-ignore:` filters are only evaluated for `push` and `pull_request`
20
+ events, where GitHub can compare the changed files in the triggering commit against the
21
+ filter patterns. `on.schedule` events are time-based and have no associated commit or
22
+ changeset — there are no paths to compare. GitHub silently ignores any `paths:` or
23
+ `paths-ignore:` configuration placed under a `schedule:` trigger.
24
+
25
+ This commonly happens when a developer copies a `push:` trigger block that includes
26
+ `paths:` filtering and applies it to a `schedule:` block expecting the same filtering
27
+ behavior. The workflow runs on every scheduled interval regardless of what files have
28
+ changed. The `paths:` keys are not flagged as invalid — they are simply ignored without
29
+ any warning in the workflow or run logs.
30
+ fix: |
31
+ Remove `paths:` and `paths-ignore:` from `on.schedule:` blocks — they have no effect.
32
+
33
+ If you need the scheduled workflow to skip execution when certain conditions are not
34
+ met, implement gate logic inside the workflow:
35
+
36
+ - Use an early job that checks file modification times or an external flag and sets
37
+ an output. Downstream jobs use `if: needs.check.outputs.should_run == 'true'`.
38
+ - Use the `dorny/paths-filter` action to detect file changes since a known reference
39
+ (e.g., the last successful run's commit SHA stored in a cache or artifact).
40
+ - If the schedule purpose is unrelated to file changes (e.g., dependency audits,
41
+ health checks), no conditional gate is needed — let it run on schedule.
42
+ fix_code:
43
+ - language: yaml
44
+ label: "Wrong — paths: under schedule: is silently ignored"
45
+ code: |
46
+ on:
47
+ schedule:
48
+ - cron: '0 2 * * *'
49
+ paths: # silently ignored — schedule always runs
50
+ - 'src/**'
51
+ - 'package.json'
52
+ push:
53
+ branches: [main]
54
+ paths: # this paths: applies only to the push: trigger
55
+ - 'src/**'
56
+ - 'package.json'
57
+ - language: yaml
58
+ label: "Correct — paths: filter on push only; schedule unconditional or gated in-workflow"
59
+ code: |
60
+ on:
61
+ schedule:
62
+ - cron: '0 2 * * *' # no paths: here — schedule always runs
63
+ push:
64
+ branches: [main]
65
+ paths: # paths: filter applies to push trigger only
66
+ - 'src/**'
67
+ - 'package.json'
68
+
69
+ jobs:
70
+ build:
71
+ runs-on: ubuntu-latest
72
+ steps:
73
+ - uses: actions/checkout@v4
74
+ - run: npm run build
75
+
76
+ # To conditionally skip a scheduled run, use an in-workflow gate:
77
+ # jobs:
78
+ # check-changes:
79
+ # runs-on: ubuntu-latest
80
+ # outputs:
81
+ # changed: ${{ steps.filter.outputs.src }}
82
+ # steps:
83
+ # - uses: actions/checkout@v4
84
+ # with:
85
+ # fetch-depth: 2
86
+ # - uses: dorny/paths-filter@v3
87
+ # id: filter
88
+ # with:
89
+ # filters: |
90
+ # src:
91
+ # - 'src/**'
92
+ #
93
+ # build:
94
+ # needs: check-changes
95
+ # if: needs.check-changes.outputs.changed == 'true' || github.event_name == 'push'
96
+ # runs-on: ubuntu-latest
97
+ # steps:
98
+ # - uses: actions/checkout@v4
99
+ # - run: npm run build
100
+ prevention:
101
+ - "Only use paths: and paths-ignore: under push: and pull_request: trigger blocks"
102
+ - "Verify which filters apply to which events using the GitHub Actions syntax reference"
103
+ - "actionlint reports a warning when paths: is used under schedule: — run it in CI"
104
+ - "For scheduled conditional logic, gate using job if: conditions on in-workflow checks"
105
+ docs:
106
+ - url: "https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#onpushpull_requestpull_request_targetpaths"
107
+ label: "Workflow syntax: paths filter (applies to push and pull_request only)"
108
+ - url: "https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#schedule"
109
+ label: "Events that trigger workflows: schedule"
110
+ - url: "https://github.com/dorny/paths-filter"
111
+ label: "dorny/paths-filter — detect file changes inside a scheduled workflow"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@htekdev/actions-debugger",
3
- "version": "1.0.83",
3
+ "version": "1.0.84",
4
4
  "description": "65+ real GitHub Actions errors, queryable by agents. CLI + MCP server + Copilot skills + error database.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",