@htekdev/actions-debugger 1.0.1 → 1.0.3

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,120 @@
1
+ id: silent-failures-008
2
+ title: "Sparse Checkout Persists to Subsequent Checkout Steps (Sticky Cone Mode)"
3
+ category: silent-failures
4
+ severity: silent-failure
5
+ tags:
6
+ - checkout
7
+ - sparse-checkout
8
+ - cone-mode
9
+ - composite-actions
10
+ - file-missing
11
+ patterns:
12
+ - regex: "sparse.*checkout.*persist"
13
+ flags: "i"
14
+ - regex: "core\\.sparseCheckout.*true"
15
+ flags: "i"
16
+ - regex: "sparse-checkout.*not disabled"
17
+ flags: "i"
18
+ error_messages:
19
+ - "Run actions/checkout@v4"
20
+ - "Expected full checkout but only sparse tree present"
21
+ root_cause: |
22
+ When `actions/checkout` is called with `sparse-checkout:` options, it sets the git
23
+ repository's `core.sparseCheckout = true` config. A subsequent call to `actions/checkout`
24
+ in the same job — even WITHOUT specifying sparse-checkout — re-uses the existing git
25
+ repository and inherits the sticky `core.sparseCheckout = true` setting.
26
+
27
+ Result: the second checkout appears to succeed (no error), but the working directory
28
+ still contains only the sparse subset from the first checkout. Files outside the
29
+ original sparse pattern are silently absent.
30
+
31
+ This most commonly occurs in two scenarios:
32
+ 1. A workflow calls `actions/checkout` with sparse-checkout for a fast initial clone,
33
+ then calls `actions/checkout` again (different ref, different path spec) expecting
34
+ a full checkout.
35
+ 2. A workflow uses sparse-checkout, then calls a composite action that internally runs
36
+ its own `actions/checkout`. The composite action's checkout inherits the sparse
37
+ setting from the parent workflow's checkout.
38
+
39
+ Root cause: a bug in `actions/checkout` — the `disableSparseCheckout()` method does not
40
+ explicitly set `core.sparseCheckout false` when `sparse-checkout` input is absent. A
41
+ fix PR (#2034) exists in the repo but has not been merged as of 2026.
42
+ fix: |
43
+ **Option 1 (recommended): Explicitly reset sparse-checkout between checkouts**
44
+ Add a `git sparse-checkout disable` step between the sparse and full checkouts. This
45
+ clears the sticky `core.sparseCheckout` flag and ensures subsequent checkouts are full.
46
+
47
+ **Option 2: Use separate `path:` directories**
48
+ Checkout into a unique subdirectory with the `path:` input to prevent git config
49
+ sharing. Each `path:` gets its own `.git` config.
50
+
51
+ **Option 3: Use `sparse-checkout-cone-mode: false` carefully**
52
+ When in non-cone mode, review that patterns don't accidentally match more or fewer
53
+ files than expected. Non-cone mode with incorrect patterns is its own source of
54
+ silent failures.
55
+ fix_code:
56
+ - language: yaml
57
+ label: "Reset sparse-checkout before a subsequent full checkout"
58
+ code: |
59
+ steps:
60
+ # First checkout: sparse (fast clone for config files only)
61
+ - uses: actions/checkout@v4
62
+ with:
63
+ sparse-checkout: |
64
+ .github
65
+ config/
66
+
67
+ - name: Reset sparse-checkout so next checkout is full
68
+ shell: bash
69
+ run: git sparse-checkout disable
70
+
71
+ # Second checkout (in composite action or next step): now gets full tree
72
+ - uses: actions/checkout@v4
73
+ with:
74
+ ref: ${{ github.sha }}
75
+ - language: yaml
76
+ label: "Use separate path: directories to avoid shared git config"
77
+ code: |
78
+ steps:
79
+ # Sparse checkout into 'config-only/' subdirectory
80
+ - uses: actions/checkout@v4
81
+ with:
82
+ path: config-only
83
+ sparse-checkout: |
84
+ config/
85
+
86
+ # Full checkout into 'full-repo/' — completely separate git repo config
87
+ - uses: actions/checkout@v4
88
+ with:
89
+ path: full-repo
90
+ - language: yaml
91
+ label: "Composite action defensive reset (add to composite action's beginning)"
92
+ code: |
93
+ # In your composite action's action.yml — reset sparse before own checkout
94
+ runs:
95
+ using: composite
96
+ steps:
97
+ - name: Reset any inherited sparse-checkout
98
+ shell: bash
99
+ run: |
100
+ if git rev-parse --git-dir > /dev/null 2>&1; then
101
+ git sparse-checkout disable 2>/dev/null || true
102
+ fi
103
+
104
+ - uses: actions/checkout@v4
105
+ with:
106
+ ref: ${{ inputs.ref }}
107
+ prevention:
108
+ - "Never assume a subsequent `actions/checkout` step gets a full tree if any earlier step used sparse-checkout."
109
+ - "Add `git sparse-checkout disable` as an explicit step between sparse and full checkouts in the same job."
110
+ - "When writing composite actions that call `actions/checkout`, add a defensive `git sparse-checkout disable` before your checkout step."
111
+ - "Use the `path:` input to isolate checkouts that need different content into separate directories."
112
+ docs:
113
+ - url: "https://github.com/actions/checkout/issues/1498"
114
+ label: "actions/checkout#1498: Sparse checkout persists in composite action"
115
+ - url: "https://github.com/actions/checkout/pull/2034"
116
+ label: "actions/checkout#2034: Fix — disable sparse-checkout on subsequent checkout (open PR)"
117
+ - url: "https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsuses"
118
+ label: "Workflow syntax: steps.uses"
119
+ - url: "https://github.com/actions/checkout#usage"
120
+ label: "actions/checkout: Usage and sparse-checkout options"
@@ -0,0 +1,105 @@
1
+ id: triggers-006
2
+ title: "Job Blocked Silently by Environment Protection Rules — No Clear Log Message"
3
+ category: triggers
4
+ severity: warning
5
+ tags:
6
+ - environment
7
+ - protection-rules
8
+ - deployment
9
+ - approval
10
+ - branch-restriction
11
+ - silent-wait
12
+ patterns:
13
+ - regex: "Waiting for.*environment.*approval"
14
+ flags: "i"
15
+ - regex: "Branch '.*' is not allowed to deploy to .* due to environment protection rules"
16
+ flags: "i"
17
+ - regex: "Expected.*Waiting for status to be reported"
18
+ flags: "i"
19
+ error_messages:
20
+ - "Branch 'feature/my-branch' is not allowed to deploy to production due to environment protection rules."
21
+ - "Waiting for approval — This workflow run requires approval from the environment's configured reviewers."
22
+ - "Expected — Waiting for status to be reported"
23
+ root_cause: |
24
+ GitHub Environments can have protection rules that gate job execution:
25
+ - **Required reviewers**: A human must approve the deployment before the job runs.
26
+ - **Branch/tag restrictions**: Only specific branches or tags are allowed to
27
+ deploy to the environment (e.g., only `main` can deploy to `production`).
28
+ - **Required status checks**: External status checks must pass first.
29
+ - **Wait timers**: A mandatory delay before the job can proceed.
30
+
31
+ When a job targets an environment with unsatisfied protection rules, it enters
32
+ a waiting state in the GitHub UI. The **workflow log may not show a clear
33
+ failure message** — the job simply appears as pending or "Expected — Waiting
34
+ for status to be reported." This is a common source of confusion for teams
35
+ that enable environment protection rules for the first time, especially in
36
+ forks or feature-branch workflows where the branch is not in the allowed list.
37
+
38
+ Documented in GitHub Community discussions #39054 and #26698.
39
+ fix: |
40
+ 1. **Check environment settings**: Repository Settings → Environments → select
41
+ the environment → review protection rules (required reviewers, deployment
42
+ branches, required checks, wait timers).
43
+
44
+ 2. **For branch restriction failures**: Add the branch that the workflow runs
45
+ on to the environment's "Deployment branches and tags" list, or change the
46
+ policy to "No restriction" for non-production environments.
47
+
48
+ 3. **For pending approval**: A configured reviewer must approve the deployment
49
+ in the GitHub UI (Actions tab → select the run → click "Review deployments").
50
+
51
+ 4. **For automated CI**: Use a separate environment with no protection rules
52
+ for automated test deployments, and reserve protected environments for
53
+ production deployments that require human approval.
54
+
55
+ 5. **For fork PRs**: Environments with protection rules can silently block
56
+ fork PRs since the fork branch is not in the allowed branch list — use a
57
+ separate no-protection environment for fork PR validation jobs.
58
+ fix_code:
59
+ - language: yaml
60
+ label: "Use separate environments for CI vs production"
61
+ code: |
62
+ jobs:
63
+ deploy-staging:
64
+ runs-on: ubuntu-latest
65
+ environment: staging # ✅ no protection rules — runs immediately
66
+ steps:
67
+ - run: ./deploy.sh staging
68
+
69
+ deploy-production:
70
+ needs: deploy-staging
71
+ runs-on: ubuntu-latest
72
+ environment: production # 🔒 has required reviewers — waits for approval
73
+ if: github.ref == 'refs/heads/main' # ✅ only main is in allowed branch list
74
+ steps:
75
+ - run: ./deploy.sh production
76
+ - language: yaml
77
+ label: "Check branch restriction: ensure workflow branch is in allowed list"
78
+ code: |
79
+ # In GitHub UI: Settings → Environments → production → Deployment branches
80
+ # Add "main" or change policy to match your workflow's ref.
81
+ #
82
+ # In workflow: use github.ref_name to verify before targeting environment
83
+ jobs:
84
+ deploy:
85
+ runs-on: ubuntu-latest
86
+ # Only run on main — matches production environment's branch restriction
87
+ if: github.ref == 'refs/heads/main'
88
+ environment: production
89
+ steps:
90
+ - run: ./deploy.sh
91
+ prevention:
92
+ - "Document environment protection rules in your repository's CONTRIBUTING.md so all developers know which branches can deploy where."
93
+ - "Test protection rules in a staging environment before applying them to production — the silent-wait behavior is surprising on first encounter."
94
+ - "For automated CI workflows that run on feature branches, use environments without branch restrictions or required reviewers."
95
+ - "After enabling environment protection rules, verify the workflow can actually trigger by running a test deployment from an allowed branch."
96
+ - "Monitor for stuck jobs in the Actions tab — a job sitting in 'waiting' or 'Expected' state usually means an environment protection rule is blocking it."
97
+ docs:
98
+ - url: "https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment"
99
+ label: "Using environments for deployment — protection rules"
100
+ - url: "https://github.com/orgs/community/discussions/39054"
101
+ label: "GitHub Community #39054 — Branch not allowed to deploy due to environment protection rules"
102
+ - url: "https://github.com/orgs/community/discussions/26698"
103
+ label: "GitHub Community #26698 — Job stuck in Expected / Waiting for status to be reported"
104
+ - url: "https://stackoverflow.com/questions/72109150/github-action-avoid-approval-on-same-environment-rule-within-same-workflow"
105
+ label: "Stack Overflow — Avoiding approval in same environment within same workflow"
@@ -0,0 +1,109 @@
1
+ id: yaml-syntax-014
2
+ title: "env Context Not Available at Job-Level if or Reusable Workflow Positions"
3
+ category: yaml-syntax
4
+ severity: error
5
+ tags:
6
+ - env
7
+ - context
8
+ - job-if
9
+ - reusable-workflow
10
+ - expression
11
+ - context-availability
12
+ patterns:
13
+ - regex: "Unrecognized named-value: 'env'"
14
+ flags: "i"
15
+ - regex: "The workflow is not valid.*Unrecognized named-value: 'env'"
16
+ flags: "i"
17
+ - regex: "Located at position \\d+ within expression.*env\\."
18
+ flags: "i"
19
+ error_messages:
20
+ - "The workflow is not valid. .github/workflows/<workflow>.yml (Line: X, Col: Y): Unrecognized named-value: 'env'. Located at position Z within expression: <expression>"
21
+ - "Unrecognized named-value: 'env'. Located at position 1 within expression"
22
+ root_cause: |
23
+ GitHub Actions evaluates job-level expressions (jobs.<job_id>.if, certain
24
+ jobs.<job_id>.with: inputs for reusable workflows) before any steps run and
25
+ before step-level env values are available. Because the `env` context is
26
+ only populated at step execution time, using `env.MY_VAR` inside a job-level
27
+ `if:` condition or inside a reusable workflow's `jobs:` block triggers a
28
+ validation error at parse time rather than a runtime failure.
29
+
30
+ This affects:
31
+ - `jobs.<job_id>.if: ${{ env.MY_VAR == 'foo' }}`
32
+ - `jobs.<job_id>.with:` fields referencing `env.*` in a reusable workflow call
33
+ - Any top-level workflow expression that attempts to read `env` context
34
+
35
+ Documented in actions/runner issues #1189, #1661, and #2372.
36
+ fix: |
37
+ Replace env context references in job-level positions with contexts that are
38
+ available at job evaluation time:
39
+ - Use `vars.*` (repository/environment variables) for static configuration values
40
+ - Use `github.*` context for event-driven values
41
+ - Use `inputs.*` for values passed into reusable workflows
42
+ - Use job outputs (`needs.<job_id>.outputs.<name>`) to pass dynamic values
43
+ computed in earlier steps to downstream job `if:` conditions
44
+
45
+ If the value is truly dynamic and set in a previous step, emit it as a step
46
+ output → job output → needs output chain so downstream jobs can reference it.
47
+ fix_code:
48
+ - language: yaml
49
+ label: "WRONG — env context in job-level if (fails validation)"
50
+ code: |
51
+ jobs:
52
+ deploy:
53
+ if: ${{ env.DEPLOY_ENV == 'production' }} # ❌ env not available here
54
+ runs-on: ubuntu-latest
55
+ steps:
56
+ - run: echo "Deploying"
57
+ - language: yaml
58
+ label: "RIGHT — use vars context or job outputs instead"
59
+ code: |
60
+ # Option 1: use vars (repository/environment variables) for static config
61
+ jobs:
62
+ deploy:
63
+ if: ${{ vars.DEPLOY_ENV == 'production' }} # ✅ vars available at job level
64
+ runs-on: ubuntu-latest
65
+ steps:
66
+ - run: echo "Deploying"
67
+
68
+ # Option 2: compute in a preceding job, emit as output
69
+ jobs:
70
+ compute-env:
71
+ runs-on: ubuntu-latest
72
+ outputs:
73
+ deploy_env: ${{ steps.set-env.outputs.deploy_env }}
74
+ steps:
75
+ - id: set-env
76
+ run: echo "deploy_env=production" >> $GITHUB_OUTPUT
77
+
78
+ deploy:
79
+ needs: compute-env
80
+ if: ${{ needs.compute-env.outputs.deploy_env == 'production' }}
81
+ runs-on: ubuntu-latest
82
+ steps:
83
+ - run: echo "Deploying"
84
+ - language: yaml
85
+ label: "RIGHT — reusable workflow: pass value via inputs not env"
86
+ code: |
87
+ # Caller workflow
88
+ jobs:
89
+ call-deploy:
90
+ uses: ./.github/workflows/deploy.yml
91
+ with:
92
+ environment: production # ✅ pass via inputs, not env
93
+ secrets: inherit
94
+ prevention:
95
+ - "Consult the GitHub docs context availability table before writing expressions — not all contexts are available at every YAML key position."
96
+ - "For job-level if conditions, use `vars.*`, `github.*`, or `needs.<job>.outputs.*` — never `env.*`."
97
+ - "For reusable workflow inputs, pass values explicitly through `with:` inputs rather than relying on caller env context."
98
+ - "Use `vars` (repository/environment variables) as a replacement for env-based feature flags that need to be available at job evaluation time."
99
+ docs:
100
+ - url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/accessing-contextual-information-about-workflow-runs#context-availability"
101
+ label: "Context availability — which contexts are available at each YAML key"
102
+ - url: "https://github.com/actions/runner/issues/1189"
103
+ label: "actions/runner #1189 — Unrecognized named-value: 'env' for job conditional"
104
+ - url: "https://github.com/actions/runner/issues/1661"
105
+ label: "actions/runner #1661 — env unrecognised in job-level if when calling reusable workflow"
106
+ - url: "https://github.com/actions/runner/issues/2372"
107
+ label: "actions/runner #2372 — Unrecognized named-value: 'env' in reusable workflow jobs"
108
+ - url: "https://stackoverflow.com/questions/76471787/why-is-env-context-not-available-in-github-action-job-level-if-statement"
109
+ label: "Stack Overflow — Why is env context not available in job level if statement?"
@@ -0,0 +1,140 @@
1
+ id: yaml-syntax-013
2
+ title: "Reusable Workflow Output Missing on.workflow_call.outputs Declaration"
3
+ category: yaml-syntax
4
+ severity: silent-failure
5
+ tags:
6
+ - reusable-workflow
7
+ - workflow-call
8
+ - outputs
9
+ - silent-failure
10
+ - job-outputs
11
+ patterns:
12
+ - regex: "needs\\.[a-zA-Z0-9_-]+\\.outputs\\.[a-zA-Z0-9_-]+"
13
+ flags: "i"
14
+ - regex: "on\\.workflow_call\\.outputs.*not defined"
15
+ flags: "i"
16
+ - regex: "output.*reusable.*workflow.*empty"
17
+ flags: "i"
18
+ error_messages:
19
+ - "The output variable was not found in the called workflow's on.workflow_call.outputs map."
20
+ - "Output 'version' not found in called workflow."
21
+ root_cause: |
22
+ A called (reusable) workflow exposes job-level outputs but forgets to declare them at
23
+ the `workflow_call` trigger level. As a result the caller workflow's
24
+ `needs.<called-job>.outputs.<name>` expression evaluates to an empty string with NO
25
+ error message — a silent failure.
26
+
27
+ GitHub Actions requires a two-layer output declaration for reusable workflows:
28
+ 1. The job inside the called workflow declares step outputs via `outputs:` on the job.
29
+ 2. The called workflow's `on.workflow_call.outputs:` section explicitly maps workflow-
30
+ level output names to job-level output expressions.
31
+
32
+ If layer 2 is missing, the caller never receives the value even though layer 1 exists.
33
+ Because the expression resolves to an empty string (not an error), downstream steps may
34
+ silently receive wrong values — version tags become empty strings, Docker image names
35
+ become malformed, deploy environment names become blank.
36
+
37
+ A second variant occurs when accessing outputs from a called workflow that uses a matrix:
38
+ matrix job outputs cannot be aggregated automatically at the workflow level, so outputs
39
+ from individual matrix legs are inaccessible to the caller.
40
+ fix: |
41
+ Add the `on.workflow_call.outputs:` section to the called workflow, mapping each
42
+ desired output name to the corresponding job output expression.
43
+
44
+ For matrix jobs: aggregate outputs into a single job (e.g. using `toJSON`) or use a
45
+ final non-matrix aggregator job inside the called workflow that reads matrix outputs
46
+ and re-exposes them as a single value.
47
+ fix_code:
48
+ - language: yaml
49
+ label: "Called workflow — correct two-layer output declaration"
50
+ code: |
51
+ # .github/workflows/build-and-version.yml (CALLED workflow)
52
+ on:
53
+ workflow_call:
54
+ # Layer 2: workflow-level outputs (REQUIRED for caller to receive values)
55
+ outputs:
56
+ version:
57
+ description: "The computed version string"
58
+ value: ${{ jobs.build.outputs.version }}
59
+ artifact-name:
60
+ description: "Name of the uploaded artifact"
61
+ value: ${{ jobs.build.outputs.artifact-name }}
62
+
63
+ jobs:
64
+ build:
65
+ runs-on: ubuntu-latest
66
+ # Layer 1: job-level outputs
67
+ outputs:
68
+ version: ${{ steps.compute-version.outputs.version }}
69
+ artifact-name: ${{ steps.upload.outputs.artifact-name }}
70
+ steps:
71
+ - id: compute-version
72
+ run: echo "version=1.2.3-${{ github.sha }}" >> $GITHUB_OUTPUT
73
+
74
+ - id: upload
75
+ uses: actions/upload-artifact@v4
76
+ with:
77
+ name: build-output
78
+ path: dist/
79
+ - language: yaml
80
+ label: "Caller workflow — consuming outputs from called workflow"
81
+ code: |
82
+ # .github/workflows/deploy.yml (CALLER workflow)
83
+ jobs:
84
+ build:
85
+ uses: ./.github/workflows/build-and-version.yml
86
+ secrets: inherit
87
+
88
+ deploy:
89
+ needs: build
90
+ runs-on: ubuntu-latest
91
+ steps:
92
+ - name: Deploy version
93
+ # This only works if the called workflow has on.workflow_call.outputs declared
94
+ run: |
95
+ echo "Deploying version: ${{ needs.build.outputs.version }}"
96
+ echo "Using artifact: ${{ needs.build.outputs.artifact-name }}"
97
+ - language: yaml
98
+ label: "Aggregate matrix outputs in a final job for caller consumption"
99
+ code: |
100
+ # Called workflow with matrix — aggregate results before exposing as outputs
101
+ on:
102
+ workflow_call:
103
+ outputs:
104
+ all-results:
105
+ value: ${{ jobs.aggregate.outputs.results }}
106
+
107
+ jobs:
108
+ test:
109
+ runs-on: ubuntu-latest
110
+ strategy:
111
+ matrix:
112
+ suite: [unit, integration, e2e]
113
+ outputs:
114
+ result-${{ matrix.suite }}: ${{ steps.run.outputs.result }}
115
+ steps:
116
+ - id: run
117
+ run: echo "result=passed" >> $GITHUB_OUTPUT
118
+
119
+ # Aggregator job: collects matrix outputs and re-exposes as single value
120
+ aggregate:
121
+ needs: test
122
+ runs-on: ubuntu-latest
123
+ outputs:
124
+ results: ${{ steps.collect.outputs.results }}
125
+ steps:
126
+ - id: collect
127
+ run: |
128
+ echo "results=${{ toJSON(needs.test.outputs) }}" >> $GITHUB_OUTPUT
129
+ prevention:
130
+ - "Always declare `on.workflow_call.outputs:` in a reusable workflow if any caller needs its outputs."
131
+ - "Test output propagation by printing `${{ needs.<job>.outputs.<name> }}` in a debug step on the caller side."
132
+ - "Treat empty string outputs from called workflows as a sign of missing `on.workflow_call.outputs:` mapping."
133
+ - "Matrix jobs inside called workflows require an aggregator job — matrix outputs cannot be directly mapped."
134
+ docs:
135
+ - url: "https://docs.github.com/en/actions/sharing-automations/reusing-workflows#using-outputs-from-a-reusable-workflow"
136
+ label: "Reusable workflows: using outputs"
137
+ - url: "https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#onworkflow_calloutputs"
138
+ label: "Workflow syntax: on.workflow_call.outputs"
139
+ - url: "https://stackoverflow.com/questions/73702333/github-actions-reuse-outputs-from-other-reusable-workflows"
140
+ label: "Stack Overflow: Reuse outputs from reusable workflows (82 upvotes)"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@htekdev/actions-debugger",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "65+ real GitHub Actions errors, queryable by agents. MCP server + Copilot skills + error database.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",