@htekdev/actions-debugger 1.0.16 → 1.0.17
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.
- package/errors/known-unsolved/no-automatic-job-retry.yml +92 -0
- package/errors/silent-failures/github-env-same-step-not-available.yml +72 -0
- package/errors/triggers/push-pull-request-duplicate-runs.yml +74 -0
- package/errors/triggers/workflow-dispatch-inputs-string-coercion.yml +89 -0
- package/package.json +1 -1
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
id: known-unsolved-019
|
|
2
|
+
title: "No built-in automatic retry for individual failed jobs — only full workflow re-run or manual step"
|
|
3
|
+
category: known-unsolved
|
|
4
|
+
severity: limitation
|
|
5
|
+
tags:
|
|
6
|
+
- retry
|
|
7
|
+
- flaky
|
|
8
|
+
- job
|
|
9
|
+
- re-run
|
|
10
|
+
- known-limitation
|
|
11
|
+
- matrix
|
|
12
|
+
patterns:
|
|
13
|
+
- regex: "retry|re-run|rerun|flaky"
|
|
14
|
+
flags: "i"
|
|
15
|
+
error_messages:
|
|
16
|
+
- "There is no native retry: N option for jobs in GitHub Actions"
|
|
17
|
+
root_cause: |
|
|
18
|
+
GitHub Actions provides no built-in retry: count field at the job level. When a
|
|
19
|
+
job fails due to a flaky test, a transient network error, or an intermittent
|
|
20
|
+
service dependency, the only native options are: (1) manually re-run the failed
|
|
21
|
+
job via the UI or API, (2) re-run the entire workflow, or (3) add shell-level
|
|
22
|
+
retry loops inside run steps. There is no declarative way to say "retry this job
|
|
23
|
+
up to N times automatically before marking it as failed." This is a long-standing
|
|
24
|
+
platform limitation tracked in multiple GitHub Community discussions. The
|
|
25
|
+
workflow-level timeout-minutes and job-level timeout-minutes exist, but neither
|
|
26
|
+
provides automatic retry semantics. For matrix jobs, a single flaky matrix entry
|
|
27
|
+
failing causes the whole matrix (or the workflow, with default fail-fast:true) to
|
|
28
|
+
fail with no automatic per-matrix-slot retry.
|
|
29
|
+
fix: |
|
|
30
|
+
Workarounds depend on the scope of flakiness. For step-level flakiness, use a
|
|
31
|
+
shell retry loop or the nick-fields/retry third-party action. For job-level
|
|
32
|
+
flakiness in CI, consider using the GitHub REST API with a calling orchestrator
|
|
33
|
+
workflow that re-dispatches on failure. For matrix flakiness, capture failed
|
|
34
|
+
matrix entries and dispatch a targeted follow-up workflow run. Manual re-run via
|
|
35
|
+
gh run rerun --failed is the simplest workaround for human-in-the-loop flows.
|
|
36
|
+
fix_code:
|
|
37
|
+
- language: yaml
|
|
38
|
+
label: "Workaround — shell-level retry loop inside a run step"
|
|
39
|
+
code: |
|
|
40
|
+
steps:
|
|
41
|
+
- name: Flaky network step with retry
|
|
42
|
+
run: |
|
|
43
|
+
for i in 1 2 3; do
|
|
44
|
+
curl -sf https://api.example.com/deploy && break
|
|
45
|
+
echo "Attempt $i failed, retrying in 10s..."
|
|
46
|
+
sleep 10
|
|
47
|
+
done
|
|
48
|
+
- language: yaml
|
|
49
|
+
label: "Workaround — nick-fields/retry action for step-level retry"
|
|
50
|
+
code: |
|
|
51
|
+
steps:
|
|
52
|
+
- name: Retry flaky step
|
|
53
|
+
uses: nick-fields/retry@v3
|
|
54
|
+
with:
|
|
55
|
+
timeout_minutes: 10
|
|
56
|
+
max_attempts: 3
|
|
57
|
+
command: npm test
|
|
58
|
+
- language: yaml
|
|
59
|
+
label: "Workaround — re-run only failed jobs via gh CLI after workflow completes"
|
|
60
|
+
code: |
|
|
61
|
+
# In a post-pipeline script or calling workflow:
|
|
62
|
+
# gh run rerun <RUN_ID> --failed re-runs only the jobs that failed
|
|
63
|
+
# Automate this with an on.workflow_run trigger checking conclusion == 'failure'
|
|
64
|
+
on:
|
|
65
|
+
workflow_run:
|
|
66
|
+
workflows: ["CI"]
|
|
67
|
+
types: [completed]
|
|
68
|
+
|
|
69
|
+
jobs:
|
|
70
|
+
auto-retry:
|
|
71
|
+
if: github.event.workflow_run.conclusion == 'failure'
|
|
72
|
+
runs-on: ubuntu-latest
|
|
73
|
+
steps:
|
|
74
|
+
- name: Re-run failed jobs once
|
|
75
|
+
env:
|
|
76
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
77
|
+
run: |
|
|
78
|
+
gh run rerun ${{ github.event.workflow_run.id }} --failed --repo ${{ github.repository }}
|
|
79
|
+
prevention:
|
|
80
|
+
- "Design tests and deployment steps to be idempotent so manual re-runs are safe"
|
|
81
|
+
- "Use step-level retry wrappers (shell loops or nick-fields/retry) for known-flaky external calls"
|
|
82
|
+
- "Separate flaky integration tests into their own workflow so re-runs are scoped and cheaper"
|
|
83
|
+
- "Track flakiness metrics; persistent flakiness signals a real bug, not just a retry need"
|
|
84
|
+
docs:
|
|
85
|
+
- url: "https://github.com/orgs/community/discussions/26186"
|
|
86
|
+
label: "GitHub Community — native job retry support request"
|
|
87
|
+
- url: "https://docs.github.com/en/actions/managing-workflow-runs-and-deployments/managing-workflow-runs/re-running-workflows-and-jobs"
|
|
88
|
+
label: "Re-running workflows and jobs — GitHub Actions"
|
|
89
|
+
- url: "https://github.com/nick-fields/retry"
|
|
90
|
+
label: "nick-fields/retry — step-level retry action (third-party workaround)"
|
|
91
|
+
- url: "https://cli.github.com/manual/gh_run_rerun"
|
|
92
|
+
label: "gh run rerun — GitHub CLI reference"
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
id: silent-failures-024
|
|
2
|
+
title: "GITHUB_ENV variable written in a step is not available within the same step"
|
|
3
|
+
category: silent-failures
|
|
4
|
+
severity: silent-failure
|
|
5
|
+
tags:
|
|
6
|
+
- GITHUB_ENV
|
|
7
|
+
- environment-variables
|
|
8
|
+
- step-ordering
|
|
9
|
+
- run
|
|
10
|
+
- same-step
|
|
11
|
+
patterns:
|
|
12
|
+
- regex: "GITHUB_ENV[^\\n]*\\n[^\\n]*\\$\\{?[A-Z_][A-Z0-9_]*\\}?"
|
|
13
|
+
flags: "ms"
|
|
14
|
+
- regex: "echo\\s+[\"']?[A-Z_][A-Z0-9_]*=[^\"'\\n]+[\"']?\\s*>>\\s*\\$GITHUB_ENV"
|
|
15
|
+
flags: "i"
|
|
16
|
+
error_messages:
|
|
17
|
+
- "echo MY_VAR=value >> $GITHUB_ENV"
|
|
18
|
+
root_cause: |
|
|
19
|
+
Writes to $GITHUB_ENV (appending NAME=value lines to the runner's environment file)
|
|
20
|
+
take effect for all SUBSEQUENT steps in the same job, but NOT for the current
|
|
21
|
+
step's run block. The Actions runner reads the environment file once at the start
|
|
22
|
+
of each step, before the run block executes. Any $GITHUB_ENV writes made during
|
|
23
|
+
that run block are not re-read until the next step begins. Consequently, if a run
|
|
24
|
+
block writes `echo "BUILD_ID=abc" >> $GITHUB_ENV` and then immediately references
|
|
25
|
+
`$BUILD_ID` later in the same run block, the variable is empty. No error or warning
|
|
26
|
+
is emitted — the reference silently evaluates to an empty string. The identical
|
|
27
|
+
delayed-effect behavior applies to $GITHUB_PATH: path entries added in one step
|
|
28
|
+
are only visible in the PATH of subsequent steps.
|
|
29
|
+
fix: |
|
|
30
|
+
Split the write and the read into separate steps. If you need the value within the
|
|
31
|
+
same shell invocation, use a native shell variable assignment (VAR=value) for
|
|
32
|
+
immediate access and still write to $GITHUB_ENV if the value is needed by later
|
|
33
|
+
steps. Do not rely on $GITHUB_ENV for intra-step communication.
|
|
34
|
+
fix_code:
|
|
35
|
+
- language: yaml
|
|
36
|
+
label: "Wrong — reference GITHUB_ENV variable in the same step that writes it"
|
|
37
|
+
code: |
|
|
38
|
+
steps:
|
|
39
|
+
- name: Set and use variable (BROKEN — BUILD_ID is empty)
|
|
40
|
+
run: |
|
|
41
|
+
echo "BUILD_ID=abc123" >> $GITHUB_ENV
|
|
42
|
+
echo "Build ID is: $BUILD_ID" # Empty — GITHUB_ENV not re-read mid-step
|
|
43
|
+
- language: yaml
|
|
44
|
+
label: "Correct — read the exported variable in the following step"
|
|
45
|
+
code: |
|
|
46
|
+
steps:
|
|
47
|
+
- name: Export variable
|
|
48
|
+
run: echo "BUILD_ID=abc123" >> $GITHUB_ENV
|
|
49
|
+
|
|
50
|
+
- name: Use exported variable
|
|
51
|
+
run: echo "Build ID is: $BUILD_ID" # Available here — next step reads GITHUB_ENV
|
|
52
|
+
- language: yaml
|
|
53
|
+
label: "Correct — use a shell variable for same-step access, also export for later steps"
|
|
54
|
+
code: |
|
|
55
|
+
steps:
|
|
56
|
+
- name: Compute and export build ID
|
|
57
|
+
run: |
|
|
58
|
+
BUILD_ID=$(git rev-parse --short HEAD)
|
|
59
|
+
echo "BUILD_ID=${BUILD_ID}" >> $GITHUB_ENV # Export for later steps
|
|
60
|
+
echo "Build ID is: ${BUILD_ID}" # Shell var — available immediately
|
|
61
|
+
prevention:
|
|
62
|
+
- "Never reference a variable by its GITHUB_ENV name ($VAR_NAME) in the same run block that writes it"
|
|
63
|
+
- "Use native shell variables (VAR=value; echo $VAR) for same-step access; only use GITHUB_ENV for cross-step sharing"
|
|
64
|
+
- "The same rule applies to $GITHUB_PATH — path additions take effect in the next step, not the current one"
|
|
65
|
+
- "If a step relies on a GITHUB_ENV variable set by a prior step in the same run, ensure step ordering is correct"
|
|
66
|
+
docs:
|
|
67
|
+
- url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/store-information-in-variables#passing-a-value-between-steps"
|
|
68
|
+
label: "Passing values between steps using GITHUB_ENV — GitHub Actions"
|
|
69
|
+
- url: "https://github.com/orgs/community/discussions/26672"
|
|
70
|
+
label: "GitHub Community — GITHUB_ENV variable not available in same step it is written"
|
|
71
|
+
- url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/workflow-commands-for-github-actions#setting-an-environment-variable"
|
|
72
|
+
label: "Setting an environment variable via workflow commands — GitHub Actions"
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
id: triggers-017
|
|
2
|
+
title: "push and pull_request events both fire for same-repo PR branches causing duplicate CI runs"
|
|
3
|
+
category: triggers
|
|
4
|
+
severity: warning
|
|
5
|
+
tags:
|
|
6
|
+
- push
|
|
7
|
+
- pull_request
|
|
8
|
+
- duplicate-runs
|
|
9
|
+
- concurrency
|
|
10
|
+
- same-repo
|
|
11
|
+
- branch
|
|
12
|
+
patterns:
|
|
13
|
+
- regex: "on:\\s*\\n\\s+(push|pull_request):"
|
|
14
|
+
flags: "ms"
|
|
15
|
+
error_messages:
|
|
16
|
+
- "Duplicate workflow runs triggered for the same commit SHA"
|
|
17
|
+
- "Two simultaneous CI runs on the same branch"
|
|
18
|
+
root_cause: |
|
|
19
|
+
When a developer pushes to a branch that has an open pull request within the same
|
|
20
|
+
repository (not a fork), both the push event and the pull_request event (types:
|
|
21
|
+
[synchronize]) fire independently for the same commit SHA. This creates two
|
|
22
|
+
separate workflow runs executing identical CI checks simultaneously. For fork PRs
|
|
23
|
+
only the pull_request event fires (the fork push doesn't trigger the base repo),
|
|
24
|
+
so duplication only affects same-repository branches. The redundant run wastes
|
|
25
|
+
billed minutes, creates confusing duplicate status check entries on the PR, and
|
|
26
|
+
can cause race conditions in deployment or release workflows where two runs race
|
|
27
|
+
to update the same environment.
|
|
28
|
+
fix: |
|
|
29
|
+
For workflows intended purely as PR checks, use only on.pull_request and remove
|
|
30
|
+
the push trigger. If the same workflow needs to run both on PRs and on direct
|
|
31
|
+
pushes to main/trunk (post-merge), filter with branches: so they don't overlap.
|
|
32
|
+
Adding a concurrency group keyed on github.ref or github.head_ref automatically
|
|
33
|
+
cancels the slower duplicate run when both triggers must remain.
|
|
34
|
+
fix_code:
|
|
35
|
+
- language: yaml
|
|
36
|
+
label: "Option 1 — separate triggers so they do not overlap"
|
|
37
|
+
code: |
|
|
38
|
+
on:
|
|
39
|
+
# PR CI: only pull_request covers commits pushed to the PR branch
|
|
40
|
+
pull_request:
|
|
41
|
+
branches: [main]
|
|
42
|
+
# Post-merge CI: only the push to main after merging
|
|
43
|
+
push:
|
|
44
|
+
branches: [main]
|
|
45
|
+
# This way a push to a feature branch triggers pull_request ONLY,
|
|
46
|
+
# and a merge to main triggers push ONLY — no duplicates.
|
|
47
|
+
- language: yaml
|
|
48
|
+
label: "Option 2 — concurrency group to cancel the slower duplicate"
|
|
49
|
+
code: |
|
|
50
|
+
on:
|
|
51
|
+
push:
|
|
52
|
+
branches-ignore: [main]
|
|
53
|
+
pull_request:
|
|
54
|
+
branches: [main]
|
|
55
|
+
|
|
56
|
+
concurrency:
|
|
57
|
+
group: ci-${{ github.head_ref || github.ref }}
|
|
58
|
+
cancel-in-progress: true
|
|
59
|
+
# When both push and pull_request fire for the same branch, the second
|
|
60
|
+
# run cancels the first, leaving only one active run per branch.
|
|
61
|
+
prevention:
|
|
62
|
+
- "Audit every workflow with both on.push and on.pull_request — verify the branch filters don't overlap for same-repo contributors"
|
|
63
|
+
- "For PR validation CI, prefer on.pull_request only; add a separate on.push.branches: [main] for post-merge checks"
|
|
64
|
+
- "Always add a concurrency group when both push and pull_request triggers are needed to prevent redundant runs"
|
|
65
|
+
- "Check your Actions billing dashboard for unexpectedly doubled minute usage as a signal for duplicate trigger overlap"
|
|
66
|
+
docs:
|
|
67
|
+
- url: "https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#pull_request"
|
|
68
|
+
label: "pull_request event — GitHub Actions documentation"
|
|
69
|
+
- url: "https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#push"
|
|
70
|
+
label: "push event — GitHub Actions documentation"
|
|
71
|
+
- url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/control-the-concurrency-of-workflows-and-jobs"
|
|
72
|
+
label: "Controlling concurrency of workflows and jobs — GitHub Actions"
|
|
73
|
+
- url: "https://github.com/orgs/community/discussions/26284"
|
|
74
|
+
label: "GitHub Community — avoiding duplicate workflow runs on push and pull_request"
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
id: triggers-016
|
|
2
|
+
title: "workflow_dispatch inputs are always string type regardless of declared type"
|
|
3
|
+
category: triggers
|
|
4
|
+
severity: silent-failure
|
|
5
|
+
tags:
|
|
6
|
+
- workflow_dispatch
|
|
7
|
+
- inputs
|
|
8
|
+
- type-coercion
|
|
9
|
+
- boolean
|
|
10
|
+
- number
|
|
11
|
+
- expression
|
|
12
|
+
patterns:
|
|
13
|
+
- regex: "inputs\\.[a-zA-Z_][a-zA-Z0-9_]*\\s*==\\s*(true|false)"
|
|
14
|
+
flags: "i"
|
|
15
|
+
- regex: "inputs\\.[a-zA-Z_][a-zA-Z0-9_]*\\s*[><!]=?\\s*[0-9]"
|
|
16
|
+
flags: "i"
|
|
17
|
+
error_messages:
|
|
18
|
+
- "if: ${{ inputs.enable_debug == true }}"
|
|
19
|
+
- "if: ${{ inputs.retry_count > 3 }}"
|
|
20
|
+
- "if: ${{ inputs.deploy == false }}"
|
|
21
|
+
root_cause: |
|
|
22
|
+
All workflow_dispatch input values are delivered as strings at runtime, regardless
|
|
23
|
+
of the type: boolean or type: number declaration in the workflow YAML. The type
|
|
24
|
+
declaration controls the GitHub UI widget (checkbox vs text field) but does NOT
|
|
25
|
+
change the runtime data type. Comparing inputs.my_flag == true evaluates as
|
|
26
|
+
string('true') == boolean(true) which is always false. Similarly, arithmetic
|
|
27
|
+
comparisons like inputs.count > 3 perform lexicographic string comparison, not
|
|
28
|
+
numeric comparison. This is documented in GitHub Actions docs but commonly missed
|
|
29
|
+
by developers relying on the YAML type declaration to enforce runtime types.
|
|
30
|
+
The same caveat applies to inputs passed via the GitHub REST API and GitHub CLI.
|
|
31
|
+
fix: |
|
|
32
|
+
Compare boolean inputs against the string 'true' or 'false'. For numeric inputs,
|
|
33
|
+
wrap with fromJSON() before arithmetic comparison. The expression
|
|
34
|
+
inputs.enable_debug == 'true' correctly evaluates when the checkbox is checked
|
|
35
|
+
in the GitHub UI or when the value 'true' is passed via the API.
|
|
36
|
+
fix_code:
|
|
37
|
+
- language: yaml
|
|
38
|
+
label: "Boolean input — compare against string literal 'true'"
|
|
39
|
+
code: |
|
|
40
|
+
on:
|
|
41
|
+
workflow_dispatch:
|
|
42
|
+
inputs:
|
|
43
|
+
enable_debug:
|
|
44
|
+
type: boolean
|
|
45
|
+
description: "Enable debug mode"
|
|
46
|
+
default: false
|
|
47
|
+
|
|
48
|
+
jobs:
|
|
49
|
+
build:
|
|
50
|
+
runs-on: ubuntu-latest
|
|
51
|
+
steps:
|
|
52
|
+
- name: Debug step
|
|
53
|
+
# WRONG: inputs.enable_debug == true (string vs boolean, always false)
|
|
54
|
+
# CORRECT: compare against string
|
|
55
|
+
if: inputs.enable_debug == 'true'
|
|
56
|
+
run: echo "Debug mode enabled"
|
|
57
|
+
- language: yaml
|
|
58
|
+
label: "Number input — use fromJSON() for numeric comparison"
|
|
59
|
+
code: |
|
|
60
|
+
on:
|
|
61
|
+
workflow_dispatch:
|
|
62
|
+
inputs:
|
|
63
|
+
retry_count:
|
|
64
|
+
type: number
|
|
65
|
+
description: "Number of retries"
|
|
66
|
+
default: 3
|
|
67
|
+
|
|
68
|
+
jobs:
|
|
69
|
+
deploy:
|
|
70
|
+
runs-on: ubuntu-latest
|
|
71
|
+
steps:
|
|
72
|
+
- name: High-retry warning
|
|
73
|
+
# WRONG: inputs.retry_count > 5 (string comparison, '6' > '5' is true but '10' > '5' is false lexicographically)
|
|
74
|
+
# CORRECT: cast to number first
|
|
75
|
+
if: fromJSON(inputs.retry_count) > 5
|
|
76
|
+
run: echo "Warning: high retry count configured"
|
|
77
|
+
prevention:
|
|
78
|
+
- "Always compare workflow_dispatch boolean inputs against the string 'true' or 'false', never native boolean literals"
|
|
79
|
+
- "Use fromJSON(inputs.my_number) before any arithmetic or numeric comparison on number inputs"
|
|
80
|
+
- "Add an early diagnostic step echoing ${{ toJSON(inputs) }} to inspect actual runtime types during development"
|
|
81
|
+
- "Document in workflow comments that all workflow_dispatch inputs are strings at runtime, regardless of declared type"
|
|
82
|
+
- "When passing inputs via API or gh CLI, always pass boolean values as the strings 'true' or 'false'"
|
|
83
|
+
docs:
|
|
84
|
+
- url: "https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#providing-inputs"
|
|
85
|
+
label: "workflow_dispatch inputs documentation — GitHub Actions"
|
|
86
|
+
- url: "https://github.com/actions/runner/issues/1483"
|
|
87
|
+
label: "actions/runner#1483 — Boolean workflow_dispatch inputs treated as strings"
|
|
88
|
+
- url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/evaluate-expressions-in-workflows-and-actions#fromjson"
|
|
89
|
+
label: "fromJSON() expression function — GitHub Actions"
|
package/package.json
CHANGED