@htekdev/actions-debugger 1.0.42 → 1.0.43

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,114 @@
1
+ id: caching-artifacts-033
2
+ title: 'upload-artifact@v4 requires unique artifact names per run — duplicate name is a hard error'
3
+ category: caching-artifacts
4
+ severity: error
5
+ tags:
6
+ - upload-artifact
7
+ - v4
8
+ - duplicate-name
9
+ - breaking-change
10
+ - matrix
11
+ patterns:
12
+ - regex: 'An artifact with this name already exists on the workflow run'
13
+ flags: 'i'
14
+ - regex: 'Failed to CreateArtifact.*already exists'
15
+ flags: 'i'
16
+ error_messages:
17
+ - 'An artifact with this name already exists on the workflow run'
18
+ - 'Failed to CreateArtifact: Artifact already exists'
19
+ root_cause: |
20
+ actions/upload-artifact@v4 changed artifact name uniqueness enforcement from v3:
21
+
22
+ v3 behavior: uploading with a duplicate name silently merged the new files
23
+ into the existing artifact, potentially overwriting same-named files.
24
+
25
+ v4 behavior: uploading with a name that already exists in the same workflow
26
+ run is a hard error. The step fails immediately with:
27
+ "An artifact with this name already exists on the workflow run"
28
+
29
+ Common triggers:
30
+ 1. Matrix jobs all writing to a fixed artifact name (e.g., name: build-output)
31
+ without including a matrix dimension in the name.
32
+ 2. Multiple upload-artifact steps in the same job with the same name: value.
33
+ 3. Reusable workflows invoked multiple times in one run using identical names.
34
+ 4. Two upload steps with no name: parameter — both default to "artifact".
35
+
36
+ Workflows that relied on v3's merge behavior and were silently uploading
37
+ duplicate names will fail immediately after upgrading to v4.
38
+ fix: |
39
+ Include a unique identifier in the artifact name for each upload step.
40
+ For matrix jobs, include a matrix dimension value. For independent parallel
41
+ jobs, include the job name or a specific run-scoped identifier.
42
+
43
+ If you need to consolidate artifacts from multiple sources, have each job
44
+ upload with a unique name, then use a final consolidation job that downloads
45
+ all artifacts and re-uploads a merged set.
46
+ fix_code:
47
+ - language: yaml
48
+ label: 'Matrix jobs — include matrix dimension in artifact name'
49
+ code: |
50
+ strategy:
51
+ matrix:
52
+ os: [ubuntu-latest, windows-latest, macos-latest]
53
+
54
+ steps:
55
+ - name: Build
56
+ run: make build
57
+
58
+ - uses: actions/upload-artifact@v4
59
+ with:
60
+ name: build-output-${{ matrix.os }} # Unique per matrix cell
61
+ path: dist/
62
+ - language: yaml
63
+ label: 'Multiple upload steps — use distinct explicit names'
64
+ code: |
65
+ steps:
66
+ - uses: actions/upload-artifact@v4
67
+ with:
68
+ name: test-results # Distinct name
69
+ path: test-output/
70
+
71
+ - uses: actions/upload-artifact@v4
72
+ with:
73
+ name: coverage-report # Different name — no conflict
74
+ path: coverage/
75
+ - language: yaml
76
+ label: 'Merge artifacts across matrix jobs in a downstream job'
77
+ code: |
78
+ jobs:
79
+ build:
80
+ strategy:
81
+ matrix:
82
+ os: [ubuntu-latest, windows-latest]
83
+ steps:
84
+ - uses: actions/upload-artifact@v4
85
+ with:
86
+ name: dist-${{ matrix.os }}
87
+ path: dist/
88
+
89
+ package:
90
+ needs: build
91
+ runs-on: ubuntu-latest
92
+ steps:
93
+ - uses: actions/download-artifact@v4
94
+ with:
95
+ pattern: dist-*
96
+ merge-multiple: true
97
+ path: all-dist/
98
+
99
+ - uses: actions/upload-artifact@v4
100
+ with:
101
+ name: final-package
102
+ path: all-dist/
103
+ prevention:
104
+ - 'Always specify an explicit name: for each upload-artifact step rather than relying on the default "artifact"'
105
+ - 'For matrix jobs, include at least one matrix variable in the artifact name'
106
+ - 'Audit workflows being migrated from v3 to v4 for any step that omits name: or uses the same name twice'
107
+ - 'Two steps with no name: both default to "artifact" and will always conflict in v4'
108
+ docs:
109
+ - url: 'https://github.com/actions/upload-artifact/blob/main/docs/MIGRATION.md'
110
+ label: 'upload-artifact v3 to v4 migration guide'
111
+ - url: 'https://github.com/actions/upload-artifact'
112
+ label: 'actions/upload-artifact repository'
113
+ - url: 'https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/storing-workflow-data-as-artifacts'
114
+ label: 'GitHub Docs — Storing workflow data as artifacts'
@@ -0,0 +1,123 @@
1
+ id: permissions-auth-034
2
+ title: 'Job-level permissions: block replaces workflow-level permissions — undeclared scopes are silently removed'
3
+ category: permissions-auth
4
+ severity: silent-failure
5
+ tags:
6
+ - permissions
7
+ - GITHUB_TOKEN
8
+ - job-level
9
+ - workflow-level
10
+ - 403
11
+ patterns:
12
+ - regex: 'Resource not accessible by integration'
13
+ flags: 'i'
14
+ - regex: 'HttpError.*403'
15
+ flags: 'i'
16
+ error_messages:
17
+ - 'Resource not accessible by integration'
18
+ - 'HttpError: Resource not accessible by integration'
19
+ - '403 Forbidden'
20
+ root_cause: |
21
+ The permissions: block in GitHub Actions is a REPLACEMENT at the scope where
22
+ it is applied — it does NOT inherit or merge with permissions defined at a
23
+ parent scope.
24
+
25
+ Example: if a workflow defines top-level permissions:
26
+ permissions:
27
+ contents: write
28
+ issues: write
29
+ pull-requests: write
30
+
31
+ And a job within that workflow also defines permissions:
32
+ permissions:
33
+ deployments: write
34
+
35
+ Then that job's GITHUB_TOKEN has ONLY deployments: write. The
36
+ contents: write, issues: write, and pull-requests: write scopes are
37
+ completely dropped for that job.
38
+
39
+ Developers expect job-level permissions to be ADDITIVE (adding new
40
+ permissions on top of the workflow-level set). The actual behavior is the
41
+ opposite: job-level permissions creates an entirely new permission set for
42
+ that job, discarding all workflow-level grants not re-declared.
43
+
44
+ The failure is silent — no warning is emitted about the permission reduction.
45
+ Steps produce 403 or "Resource not accessible by integration" only when
46
+ they actually attempt to use the silently-removed permission.
47
+ fix: |
48
+ When using a job-level permissions: block, re-declare ALL permissions
49
+ that the job needs — not just the new ones you want to add.
50
+
51
+ Alternatively, if all jobs in the workflow need the same permission set,
52
+ set permissions only at the workflow level and omit job-level overrides.
53
+
54
+ Best practice: prefer job-level permissions over workflow-level for the
55
+ principle of least privilege — each job explicitly declares only what it
56
+ needs, with no inheritance confusion.
57
+ fix_code:
58
+ - language: yaml
59
+ label: 'Wrong: job-level block silently drops workflow-level grants'
60
+ code: |
61
+ # Workflow level
62
+ permissions:
63
+ contents: write
64
+ issues: write
65
+
66
+ jobs:
67
+ deploy:
68
+ permissions:
69
+ deployments: write # This REPLACES the above — contents and issues are now GONE
70
+ steps:
71
+ - name: Comment on issue
72
+ uses: actions/github-script@v7
73
+ with:
74
+ script: |
75
+ # This will 403 — issues: write was silently removed
76
+ await github.rest.issues.createComment({ issue_number: 1, body: 'deployed' })
77
+ - language: yaml
78
+ label: 'Correct: re-declare all needed permissions at job level'
79
+ code: |
80
+ # No workflow-level permissions block needed when using job-level
81
+
82
+ jobs:
83
+ deploy:
84
+ permissions:
85
+ contents: write # Re-declared (was at workflow level)
86
+ issues: write # Re-declared (was at workflow level)
87
+ deployments: write # New permission added
88
+ steps:
89
+ - name: Comment on issue
90
+ uses: actions/github-script@v7
91
+ with:
92
+ script: |
93
+ await github.rest.issues.createComment({ issue_number: 1, body: 'deployed' })
94
+ - language: yaml
95
+ label: 'Minimal job permissions — each job declares only what it needs'
96
+ code: |
97
+ # No workflow-level permissions block — all scoped to jobs
98
+
99
+ jobs:
100
+ test:
101
+ permissions:
102
+ checks: write
103
+ contents: read
104
+ steps:
105
+ - uses: actions/checkout@v4
106
+
107
+ deploy:
108
+ permissions:
109
+ contents: read
110
+ deployments: write
111
+ id-token: write
112
+ steps:
113
+ - run: echo "deploying"
114
+ prevention:
115
+ - 'When adding a job-level permissions block, start by listing every permission the job needs from scratch'
116
+ - 'Do not assume any permissions flow down from the workflow level when a job block is present'
117
+ - 'Prefer defining all permissions at the job level (not workflow level) to make the permission set explicit'
118
+ - 'The GitHub Docs explicitly state: permissions at the job level override the workflow-level setting'
119
+ docs:
120
+ - url: 'https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token'
121
+ label: 'GitHub Docs — Controlling permissions for GITHUB_TOKEN'
122
+ - url: 'https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#jobsjob_idpermissions'
123
+ label: 'GitHub Docs — jobs.<job_id>.permissions syntax'
@@ -0,0 +1,99 @@
1
+ id: silent-failures-048
2
+ title: 'Composite action outputs not propagated — outputs: declaration required in action.yml'
3
+ category: silent-failures
4
+ severity: silent-failure
5
+ tags:
6
+ - composite
7
+ - outputs
8
+ - action.yml
9
+ - step-outputs
10
+ - empty-string
11
+ patterns:
12
+ - regex: 'steps\.\w+\.outputs\.'
13
+ flags: 'i'
14
+ error_messages: []
15
+ root_cause: |
16
+ In composite actions, step outputs from internal steps are NOT automatically
17
+ visible to the action's callers. The composite action's action.yml must
18
+ declare an outputs: block that explicitly maps each output name to a value
19
+ expression referencing an internal step's output:
20
+
21
+ outputs:
22
+ my-result:
23
+ description: "The result"
24
+ value: ${{ steps.build.outputs.result }}
25
+
26
+ Without this declaration, ${{ steps.my-action.outputs.my-result }} in the
27
+ calling workflow evaluates to empty string with no error or warning.
28
+
29
+ This is different from regular workflow jobs, where step outputs are
30
+ accessible within the same job via steps.<id>.outputs.<name> without any
31
+ explicit mapping. Composite actions require explicit wiring because the
32
+ action boundary creates an isolation layer — internal step IDs are not
33
+ exposed to callers.
34
+
35
+ Common mistake pattern: developer tests the composite action, sees that
36
+ internal steps set outputs correctly, but the caller always receives "".
37
+ The action.yml outputs: block is missing or references a wrong step id.
38
+ fix: |
39
+ 1. Open the composite action's action.yml file.
40
+ 2. Add an outputs: block (after the inputs: block if present).
41
+ 3. For each output you need to expose, add an entry with:
42
+ value: ${{ steps.<internal-step-id>.outputs.<output-name> }}
43
+ 4. Ensure the referenced internal step has a matching id: field.
44
+ 5. Ensure the internal step writes outputs via GITHUB_OUTPUT:
45
+ echo "result=value" >> $GITHUB_OUTPUT
46
+ fix_code:
47
+ - language: yaml
48
+ label: 'action.yml — declare outputs with value expressions'
49
+ code: |
50
+ # .github/actions/my-build/action.yml
51
+ name: 'My Build Action'
52
+ description: 'Builds the project and returns the version'
53
+
54
+ outputs:
55
+ build-version:
56
+ description: 'The version that was built'
57
+ value: ${{ steps.get-version.outputs.version }}
58
+ artifact-path:
59
+ description: 'Path to the built artifact'
60
+ value: ${{ steps.build.outputs.artifact }}
61
+
62
+ runs:
63
+ using: composite
64
+ steps:
65
+ - id: get-version
66
+ shell: bash
67
+ run: echo "version=$(cat version.txt)" >> $GITHUB_OUTPUT
68
+
69
+ - id: build
70
+ shell: bash
71
+ run: |
72
+ make build
73
+ echo "artifact=dist/app.tar.gz" >> $GITHUB_OUTPUT
74
+ - language: yaml
75
+ label: 'Calling workflow — accessing composite action outputs'
76
+ code: |
77
+ jobs:
78
+ release:
79
+ runs-on: ubuntu-latest
80
+ steps:
81
+ - uses: actions/checkout@v4
82
+
83
+ - id: build
84
+ uses: ./.github/actions/my-build
85
+
86
+ - name: Use outputs
87
+ run: |
88
+ echo "Version: ${{ steps.build.outputs.build-version }}"
89
+ echo "Artifact: ${{ steps.build.outputs.artifact-path }}"
90
+ prevention:
91
+ - 'Every composite action output must have a corresponding entry in the outputs: block of action.yml'
92
+ - 'Internal steps must have an id: field for the outputs value: expression to reference'
93
+ - 'The step id in the value: expression must exactly match the internal step id: value'
94
+ - 'Add a debug step in the action to print $GITHUB_OUTPUT contents when troubleshooting'
95
+ docs:
96
+ - url: 'https://docs.github.com/en/actions/sharing-automations/creating-actions/metadata-syntax-for-github-actions#outputs-for-composite-actions'
97
+ label: 'GitHub Docs — Outputs for composite actions'
98
+ - url: 'https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/passing-information-between-jobs'
99
+ label: 'GitHub Docs — Passing information between jobs'
@@ -0,0 +1,96 @@
1
+ id: triggers-032
2
+ title: 'on.workflow_run.workflows matches name: field not filename — mismatch silently never triggers'
3
+ category: triggers
4
+ severity: warning
5
+ tags:
6
+ - workflow_run
7
+ - trigger
8
+ - name-mismatch
9
+ - silent
10
+ - filename
11
+ patterns:
12
+ - regex: 'workflow_run'
13
+ flags: ''
14
+ error_messages: []
15
+ root_cause: |
16
+ The on.workflow_run.workflows: array matches against the target workflow's
17
+ top-level name: field — NOT the workflow's filename.
18
+
19
+ If the target workflow contains:
20
+ name: CI Pipeline
21
+
22
+ then the triggering workflow must specify:
23
+ on:
24
+ workflow_run:
25
+ workflows: ["CI Pipeline"]
26
+
27
+ Using the filename ("build.yml", "ci.yml", or ".github/workflows/ci.yml")
28
+ never matches when a name: field is present. The comparison is case-sensitive:
29
+ "CI" != "ci" != "Ci".
30
+
31
+ Secondary rule: if the target workflow has no name: field, GitHub uses the
32
+ workflow file path relative to the repo root as the match string (e.g.,
33
+ ".github/workflows/build.yml").
34
+
35
+ No error or warning is produced on mismatch — the triggering workflow
36
+ silently never fires. This is one of the most common workflow_run
37
+ misconfiguration patterns on Stack Overflow.
38
+ fix: |
39
+ 1. Open the target workflow file.
40
+ 2. Find the top-level name: field. If absent, note the repo-relative path.
41
+ 3. Use that exact string (case-sensitive) in the workflows: array.
42
+ 4. Merge/deploy the triggering workflow to the default branch — workflow_run
43
+ only fires when the trigger configuration itself is on the default branch.
44
+ fix_code:
45
+ - language: yaml
46
+ label: 'Correct: match the target workflow name: field exactly'
47
+ code: |
48
+ # Target workflow file: .github/workflows/ci.yml
49
+ name: CI Pipeline # <-- this is what workflow_run matches on
50
+
51
+ on: [push]
52
+ jobs:
53
+ build:
54
+ runs-on: ubuntu-latest
55
+ steps:
56
+ - run: echo "building"
57
+
58
+ ---
59
+ # Triggering workflow file: .github/workflows/deploy.yml
60
+ on:
61
+ workflow_run:
62
+ workflows: ["CI Pipeline"] # Must match name: exactly (not "ci.yml")
63
+ types: [completed]
64
+ jobs:
65
+ deploy:
66
+ if: ${{ github.event.workflow_run.conclusion == 'success' }}
67
+ runs-on: ubuntu-latest
68
+ steps:
69
+ - run: echo "deploying"
70
+ - language: yaml
71
+ label: 'When target workflow has no name: field, use the file path'
72
+ code: |
73
+ # Target workflow has no name: field at .github/workflows/build.yml
74
+ on: [push]
75
+ jobs:
76
+ build:
77
+ runs-on: ubuntu-latest
78
+ steps:
79
+ - run: echo "building"
80
+
81
+ ---
82
+ # Triggering workflow must use the repo-relative path
83
+ on:
84
+ workflow_run:
85
+ workflows: [".github/workflows/build.yml"]
86
+ types: [completed]
87
+ prevention:
88
+ - 'Always add a name: field to every workflow you intend to reference in workflow_run'
89
+ - 'Copy the name: value exactly (including capitalization and spaces) into workflows:'
90
+ - 'Add a comment in the triggering workflow citing which file the name came from'
91
+ - 'workflow_run silently never fires on name mismatches — no diagnostic is emitted'
92
+ docs:
93
+ - url: 'https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#workflow_run'
94
+ label: 'GitHub Docs — workflow_run trigger'
95
+ - url: 'https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#name'
96
+ label: 'GitHub Docs — Workflow name: field'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@htekdev/actions-debugger",
3
- "version": "1.0.42",
3
+ "version": "1.0.43",
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",