@htekdev/actions-debugger 1.0.94 → 1.0.95

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,107 @@
1
+ id: caching-artifacts-052
2
+ title: '`download-artifact@v4` `name:` Does Not Support Glob Patterns — Use `pattern:` Instead'
3
+ category: caching-artifacts
4
+ severity: silent-failure
5
+ tags:
6
+ - download-artifact
7
+ - v4-breaking-change
8
+ - glob
9
+ - pattern
10
+ - migration
11
+ - artifact-download
12
+ patterns:
13
+ - regex: 'download-artifact@v4|download-artifact@v3.*name.*\*'
14
+ flags: 'i'
15
+ - regex: 'name\s*:\s*[''"][^''"]*\*[^''"]*[''"]'
16
+ flags: 'i'
17
+ error_messages:
18
+ - "No artifacts found with the provided name"
19
+ - "Error: Unable to find any artifacts for the associated workflow"
20
+ - "Unable to find artifact 'my-*-artifact'"
21
+ root_cause: |
22
+ In `actions/download-artifact@v3`, the `name:` input accepted glob patterns
23
+ (e.g., `name: 'build-*'`) and would download all matching artifacts.
24
+ In `actions/download-artifact@v4` this behavior changed: `name:` now requires
25
+ an EXACT artifact name match. Glob characters in `name:` are treated as
26
+ literal characters, so `name: 'build-*'` looks for an artifact literally
27
+ named `build-*`, finds none, and either errors or silently downloads nothing
28
+ depending on the `error-no-files-found` setting.
29
+
30
+ The `pattern:` input was introduced in v4 as the replacement for glob-based
31
+ artifact selection. Migrating from v3 to v4 requires moving glob expressions
32
+ from `name:` to `pattern:`.
33
+
34
+ This silently impacts workflows that:
35
+ - Download multiple build artifacts from matrix jobs using a shared prefix
36
+ - Use wildcards to grab all artifacts from a set of parallel jobs
37
+ - Were migrated to v4 without reading the full migration guide
38
+ fix: |
39
+ Replace glob patterns in `name:` with the `pattern:` input in
40
+ `actions/download-artifact@v4`. The `name:` input should only be used
41
+ when downloading a single artifact by its exact name.
42
+
43
+ When using `pattern:`, the action also has a `merge-multiple` option
44
+ that controls whether matched artifacts are merged into one directory
45
+ or placed in separate subdirectories.
46
+ fix_code:
47
+ - language: yaml
48
+ label: "WRONG — glob in name: silently matches nothing in v4"
49
+ code: |
50
+ steps:
51
+ - uses: actions/download-artifact@v4
52
+ with:
53
+ name: 'build-*' # ❌ globs not supported in name: for v4
54
+ path: ./artifacts
55
+ - language: yaml
56
+ label: "RIGHT — use pattern: for glob matching in v4"
57
+ code: |
58
+ steps:
59
+ - uses: actions/download-artifact@v4
60
+ with:
61
+ pattern: 'build-*' # ✅ use pattern: for glob matching
62
+ path: ./artifacts
63
+ merge-multiple: true # flatten into single directory
64
+ - language: yaml
65
+ label: "RIGHT — download exact artifact by name in v4"
66
+ code: |
67
+ steps:
68
+ - uses: actions/download-artifact@v4
69
+ with:
70
+ name: build-linux-amd64 # ✅ exact name, no glob needed
71
+ path: ./dist/linux
72
+ - language: yaml
73
+ label: "Matrix upload + glob download pattern"
74
+ code: |
75
+ jobs:
76
+ build:
77
+ strategy:
78
+ matrix:
79
+ os: [linux, windows, macos]
80
+ runs-on: ubuntu-latest
81
+ steps:
82
+ - uses: actions/upload-artifact@v4
83
+ with:
84
+ name: build-${{ matrix.os }} # distinct name per job
85
+ path: ./dist/
86
+
87
+ package:
88
+ needs: build
89
+ runs-on: ubuntu-latest
90
+ steps:
91
+ - uses: actions/download-artifact@v4
92
+ with:
93
+ pattern: 'build-*' # ✅ downloads all build-* artifacts
94
+ path: ./all-builds
95
+ merge-multiple: false # keep per-artifact subdirectories
96
+ prevention:
97
+ - "When migrating from download-artifact@v3 to @v4, audit all `name:` inputs for glob characters and move them to `pattern:`."
98
+ - "Use `name:` only for exact single-artifact downloads; use `pattern:` for any glob or multi-artifact download."
99
+ - "Set `error-no-files-found: error` to fail fast when no artifacts match, exposing glob issues early."
100
+ - "Review the download-artifact v4 migration guide before updating the action version."
101
+ docs:
102
+ - url: "https://github.com/actions/download-artifact/blob/main/docs/MIGRATION.md"
103
+ label: "download-artifact v4 migration guide"
104
+ - url: "https://github.com/actions/download-artifact#inputs"
105
+ label: "download-artifact — inputs reference (pattern vs name)"
106
+ - url: "https://github.com/actions/toolkit/releases/tag/%40actions%2Fartifact%402.0.0"
107
+ label: "actions/toolkit v2 — artifact v2 API underlying v4 action"
@@ -0,0 +1,114 @@
1
+ id: known-unsolved-053
2
+ title: '`workflow_dispatch` Has No Native Array or List Input Type — Must Serialize as JSON String'
3
+ category: known-unsolved
4
+ severity: limitation
5
+ tags:
6
+ - workflow_dispatch
7
+ - inputs
8
+ - array
9
+ - list
10
+ - json
11
+ - limitation
12
+ patterns:
13
+ - regex: 'workflow_dispatch.*inputs|inputs.*type\s*:\s*string.*array'
14
+ flags: 'im'
15
+ - regex: "fromJSON\\(.*inputs\\."
16
+ flags: 'i'
17
+ error_messages:
18
+ - "Input type 'array' is not supported for workflow_dispatch"
19
+ - "Unexpected value 'array'"
20
+ root_cause: |
21
+ GitHub Actions `workflow_dispatch` supports only five input types:
22
+ `string`, `boolean`, `choice`, `number`, and `environment`. There is no
23
+ native `array` or `list` type. Users who need to pass multiple values
24
+ (e.g., a list of services to deploy, a set of environments to target)
25
+ must serialize the array as a JSON string and parse it in the workflow.
26
+
27
+ This limitation affects:
28
+ - Manual dispatch with dynamic target lists
29
+ - CI/CD automation via the REST API (`POST /repos/.../actions/workflows/.../dispatches`)
30
+ - Reuse of workflow_dispatch workflows that naturally accept variable-length input
31
+ - Validation — no schema can prevent malformed JSON from being passed
32
+
33
+ A `type: array` schema was proposed in actions/runner#1844 (800+ reactions)
34
+ and remains one of the highest-voted open feature requests for GitHub Actions.
35
+ fix: |
36
+ Serialize the array as a JSON string in the dispatch call and use
37
+ `fromJSON()` in the workflow to parse it into a matrix or loop variable.
38
+
39
+ Workarounds by use case:
40
+ 1. **API dispatch**: Serialize to `'["a","b","c"]'` and use `fromJSON(inputs.targets)`
41
+ 2. **UI dispatch**: Document the expected JSON format in the input description
42
+ 3. **Choice type**: If the list is finite and known ahead of time, use
43
+ `type: choice` with predefined options instead
44
+ 4. **Multiple boolean inputs**: For small fixed sets, use separate boolean
45
+ inputs per option (verbose but typed)
46
+ fix_code:
47
+ - language: yaml
48
+ label: "Workaround — serialize array as JSON string, parse with fromJSON"
49
+ code: |
50
+ on:
51
+ workflow_dispatch:
52
+ inputs:
53
+ services:
54
+ description: 'JSON array of services to deploy e.g. ["api","worker","ui"]'
55
+ required: true
56
+ type: string
57
+ default: '["api","worker"]'
58
+
59
+ jobs:
60
+ deploy:
61
+ runs-on: ubuntu-latest
62
+ strategy:
63
+ matrix:
64
+ service: ${{ fromJSON(inputs.services) }}
65
+ steps:
66
+ - run: echo "Deploying ${{ matrix.service }}"
67
+ - language: yaml
68
+ label: "Workaround — comma-separated string split in shell"
69
+ code: |
70
+ on:
71
+ workflow_dispatch:
72
+ inputs:
73
+ environments:
74
+ description: 'Comma-separated environments e.g. staging,production'
75
+ required: true
76
+ type: string
77
+ default: 'staging'
78
+
79
+ jobs:
80
+ deploy:
81
+ runs-on: ubuntu-latest
82
+ steps:
83
+ - name: Deploy to each environment
84
+ run: |
85
+ IFS=',' read -ra ENVS <<< "${{ inputs.environments }}"
86
+ for env in "${ENVS[@]}"; do
87
+ echo "Deploying to: $env"
88
+ done
89
+ - language: yaml
90
+ label: "Alternative — use type: choice for known finite sets"
91
+ code: |
92
+ on:
93
+ workflow_dispatch:
94
+ inputs:
95
+ target_env:
96
+ description: 'Target environment'
97
+ required: true
98
+ type: choice
99
+ options:
100
+ - staging
101
+ - production
102
+ - both
103
+ prevention:
104
+ - "Document the expected JSON format in the input `description` field so UI dispatchers know the required syntax."
105
+ - "Add a validation step that runs `echo '${{ inputs.targets }}' | jq .` to fail fast on malformed JSON before processing."
106
+ - "Consider using `type: choice` with predefined options if the list is small and known at workflow-definition time."
107
+ - "For API-driven workflows, generate the JSON array programmatically and pass it as a string in the dispatch payload."
108
+ docs:
109
+ - url: "https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#onworkflow_dispatchinputsinput_idtype"
110
+ label: "workflow_dispatch input types — supported values"
111
+ - url: "https://github.com/actions/runner/issues/1844"
112
+ label: "actions/runner #1844 — Support array inputs for workflow_dispatch (800+ reactions)"
113
+ - url: "https://docs.github.com/en/rest/actions/workflows#create-a-workflow-dispatch-event"
114
+ label: "REST API — Create a workflow dispatch event"
@@ -0,0 +1,103 @@
1
+ id: permissions-auth-053
2
+ title: 'GITHUB_TOKEN `packages: write` Cannot Delete Package Versions — Requires PAT with `delete:packages`'
3
+ category: permissions-auth
4
+ severity: error
5
+ tags:
6
+ - packages
7
+ - github-token
8
+ - delete-packages
9
+ - container-registry
10
+ - package-cleanup
11
+ - permissions
12
+ patterns:
13
+ - regex: 'Resource not accessible by integration'
14
+ flags: 'i'
15
+ - regex: 'DELETE.*packages.*versions|packages.*DELETE.*versions'
16
+ flags: 'i'
17
+ - regex: '403.*package|package.*403'
18
+ flags: 'i'
19
+ error_messages:
20
+ - "Resource not accessible by integration"
21
+ - "403 Forbidden — DELETE https://api.github.com/user/packages/{type}/{name}/versions/{id}"
22
+ - "Error: Resource not accessible by integration (HTTP 403)"
23
+ root_cause: |
24
+ The `packages: write` permission in `GITHUB_TOKEN` grants the ability to
25
+ publish and overwrite package versions but does NOT include the ability to
26
+ delete them. Package version deletion requires account-level permission
27
+ (`delete:packages` OAuth scope) that cannot be granted to an installation
28
+ token. The GitHub Packages REST API delete endpoint
29
+ (`DELETE /user/packages/{type}/{name}/versions/{id}` or the org equivalent)
30
+ validates the caller's account-level scope, which GITHUB_TOKEN—being a
31
+ repository-scoped installation token—can never satisfy regardless of the
32
+ `permissions: packages: write` declaration in the workflow.
33
+
34
+ This commonly surfaces in:
35
+ - Container image cleanup jobs that try to prune old tags/digests
36
+ - npm, Maven, or RubyGems package version retention workflows
37
+ - Automated housekeeping that uses `ghcr.io` image management actions
38
+ fix: |
39
+ Store a fine-grained or classic PAT with `delete:packages` scope as a
40
+ repository secret (e.g., `PACKAGES_DELETE_TOKEN`) and use that token when
41
+ calling the Packages delete API or actions that delete package versions.
42
+
43
+ For GitHub Container Registry (ghcr.io) image pruning, use a PAT or a
44
+ GitHub App installation token with Packages write + admin scope. Pass it
45
+ as the `token:` input to the relevant cleanup action.
46
+ fix_code:
47
+ - language: yaml
48
+ label: "WRONG — GITHUB_TOKEN cannot delete package versions (403)"
49
+ code: |
50
+ jobs:
51
+ cleanup:
52
+ runs-on: ubuntu-latest
53
+ permissions:
54
+ packages: write # ❌ write permission does not grant delete
55
+ steps:
56
+ - name: Delete old package version
57
+ run: |
58
+ # This call will return 403 "Resource not accessible by integration"
59
+ VERSION_ID=12345
60
+ curl -X DELETE \
61
+ -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \
62
+ https://api.github.com/user/packages/container/my-image/versions/$VERSION_ID
63
+ - language: yaml
64
+ label: "RIGHT — use a PAT with delete:packages scope"
65
+ code: |
66
+ jobs:
67
+ cleanup:
68
+ runs-on: ubuntu-latest
69
+ steps:
70
+ - name: Delete old package version
71
+ env:
72
+ GH_TOKEN: ${{ secrets.PACKAGES_DELETE_TOKEN }} # PAT with delete:packages
73
+ run: |
74
+ VERSION_ID=12345
75
+ curl -X DELETE \
76
+ -H "Authorization: Bearer $GH_TOKEN" \
77
+ https://api.github.com/user/packages/container/my-image/versions/$VERSION_ID
78
+ - language: yaml
79
+ label: "RIGHT — ghcr.io cleanup action with PAT"
80
+ code: |
81
+ jobs:
82
+ cleanup-images:
83
+ runs-on: ubuntu-latest
84
+ steps:
85
+ - uses: snok/container-retention-policy@v3
86
+ with:
87
+ account: user
88
+ token: ${{ secrets.PACKAGES_DELETE_TOKEN }} # PAT with delete:packages
89
+ image-names: my-image
90
+ cut-off: 7 days ago UTC
91
+ keep-n-most-recent: 5
92
+ prevention:
93
+ - "Never assume `packages: write` is sufficient for full package lifecycle management — deletion is always PAT-only."
94
+ - "Create a dedicated PAT or GitHub App with `delete:packages` scope and store it as a secret for cleanup workflows."
95
+ - "Scope cleanup jobs separately from build jobs so the PAT is only used where deletion is needed."
96
+ - "Document in your workflow that PACKAGES_DELETE_TOKEN requires `delete:packages` scope so it is renewed with the right scopes."
97
+ docs:
98
+ - url: "https://docs.github.com/en/rest/packages/packages#delete-a-package-version-for-a-user"
99
+ label: "REST API — Delete a package version for a user"
100
+ - url: "https://docs.github.com/en/packages/learn-github-packages/about-permissions-for-github-packages#about-scopes-and-permissions-for-package-registries"
101
+ label: "About permissions for GitHub Packages"
102
+ - url: "https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-fine-grained-personal-access-token"
103
+ label: "Creating a fine-grained PAT with delete:packages"
@@ -0,0 +1,120 @@
1
+ id: silent-failures-087
2
+ title: '`fail-fast: false` Does Not Prevent Downstream `needs:` Jobs From Being Skipped When Matrix Jobs Fail'
3
+ category: silent-failures
4
+ severity: silent-failure
5
+ tags:
6
+ - matrix
7
+ - fail-fast
8
+ - needs
9
+ - downstream-job
10
+ - skipped
11
+ - strategy
12
+ patterns:
13
+ - regex: 'fail-fast\s*:\s*false'
14
+ flags: 'i'
15
+ - regex: 'needs\s*:.*matrix|matrix.*needs\s*:'
16
+ flags: 'im'
17
+ error_messages:
18
+ - "This job was skipped"
19
+ - "Job 'X' is skipped because all dependencies failed or were skipped"
20
+ root_cause: |
21
+ `strategy.fail-fast: false` only prevents other MATRIX jobs from being
22
+ cancelled when one matrix job fails. It does NOT affect how downstream
23
+ jobs that `needs:` the matrix job handle the overall result.
24
+
25
+ When at least one matrix job fails (even with `fail-fast: false` allowing
26
+ all others to complete), the `needs.<matrix-job>.result` for the downstream
27
+ job evaluates to `'failure'`. A downstream job with a standard `needs:`
28
+ dependency is then SKIPPED — not because of `fail-fast`, but because its
29
+ dependency is in a failed state.
30
+
31
+ This surprises developers who add `fail-fast: false` expecting the entire
32
+ pipeline to continue running end-to-end. The final summary/report job
33
+ that needs the matrix job is silently skipped, producing no output.
34
+ fix: |
35
+ Add `if: always()` to downstream jobs that should run regardless of matrix
36
+ outcome. Then explicitly check `needs.<job>.result` values to determine
37
+ pass/fail:
38
+
39
+ - `if: always()` ensures the job is never skipped due to upstream failure
40
+ - Check `contains(needs.*.result, 'failure')` to detect any matrix failure
41
+ - Use `needs.<job>.result == 'success'` for strict pass gates
42
+ fix_code:
43
+ - language: yaml
44
+ label: "WRONG — summary job silently skipped when matrix job fails"
45
+ code: |
46
+ jobs:
47
+ test:
48
+ strategy:
49
+ fail-fast: false # ❌ allows all matrix jobs to run, but...
50
+ matrix:
51
+ node: [18, 20, 22]
52
+ runs-on: ubuntu-latest
53
+ steps:
54
+ - run: npm test
55
+
56
+ summary:
57
+ needs: test # ❌ still skipped if any matrix job failed
58
+ runs-on: ubuntu-latest
59
+ steps:
60
+ - run: echo "All tests done"
61
+ - language: yaml
62
+ label: "RIGHT — use if: always() and check result explicitly"
63
+ code: |
64
+ jobs:
65
+ test:
66
+ strategy:
67
+ fail-fast: false
68
+ matrix:
69
+ node: [18, 20, 22]
70
+ runs-on: ubuntu-latest
71
+ steps:
72
+ - run: npm test
73
+
74
+ summary:
75
+ needs: test
76
+ if: always() # ✅ runs even when test jobs failed
77
+ runs-on: ubuntu-latest
78
+ steps:
79
+ - name: Check matrix results
80
+ if: contains(needs.test.result, 'failure')
81
+ run: |
82
+ echo "One or more matrix jobs failed"
83
+ exit 1
84
+ - name: Success
85
+ run: echo "All matrix jobs passed"
86
+ - language: yaml
87
+ label: "RIGHT — gate final deploy only when all matrix jobs pass"
88
+ code: |
89
+ jobs:
90
+ test:
91
+ strategy:
92
+ fail-fast: false
93
+ matrix:
94
+ node: [18, 20, 22]
95
+ runs-on: ubuntu-latest
96
+ outputs:
97
+ result: ${{ job.status }}
98
+ steps:
99
+ - run: npm test
100
+
101
+ deploy:
102
+ needs: test
103
+ if: always() && needs.test.result == 'success' # ✅ explicit success check
104
+ runs-on: ubuntu-latest
105
+ steps:
106
+ - run: echo "Deploying"
107
+ prevention:
108
+ - "Always add `if: always()` to aggregation/summary/deploy jobs that need to run after a matrix job."
109
+ - "Explicitly check `needs.<job>.result` or `contains(needs.*.result, 'failure')` rather than relying on implicit pass-through."
110
+ - "Understand that `fail-fast: false` is matrix-scoped — it does not change how the `needs:` graph handles failures."
111
+ - "Use job outputs combined with `if: always()` to build robust reporting jobs that capture all matrix outcomes."
112
+ docs:
113
+ - url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/using-jobs-in-a-workflow#defining-prerequisite-jobs"
114
+ label: "Defining prerequisite jobs — needs context and result values"
115
+ - url: "https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#jobsjob_idstrategyfail-fast"
116
+ label: "workflow syntax — jobs.<job_id>.strategy.fail-fast"
117
+ - url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/evaluate-expressions-in-workflows-and-actions#status-check-functions"
118
+ label: "Status check functions — always(), success(), failure()"
119
+ - url: "https://github.com/orgs/community/discussions/26822"
120
+ label: "GitHub Community — fail-fast: false but summary job still skipped"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@htekdev/actions-debugger",
3
- "version": "1.0.94",
3
+ "version": "1.0.95",
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",