@htekdev/actions-debugger 1.0.80 → 1.0.82

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,88 @@
1
+ id: caching-artifacts-048
2
+ title: "actions/cache lookup-only: true checks cache existence but does NOT restore files"
3
+ category: caching-artifacts
4
+ severity: silent-failure
5
+ tags:
6
+ - cache
7
+ - lookup-only
8
+ - cache-hit
9
+ - restore
10
+ - silent-no-op
11
+ patterns:
12
+ - regex: 'lookup-only.*true'
13
+ flags: 'i'
14
+ - regex: 'Cache found and can be restored from key'
15
+ flags: 'i'
16
+ error_messages:
17
+ - "Cache found and can be restored from key: node-modules-abc123"
18
+ - "lookup-only is set, skipping restore."
19
+ root_cause: |
20
+ The lookup-only: true input on actions/cache@v4 instructs the action to query
21
+ the cache service and report whether an entry exists (via the cache-hit output)
22
+ without transferring any data to the runner. No files are downloaded or written
23
+ to disk.
24
+
25
+ Developers who add lookup-only: true hoping to get a "lightweight restore that
26
+ skips the upload post-step" receive a misleading green step. The cache-hit output
27
+ reports 'true', the step log says "Cache found and can be restored from key",
28
+ and everything looks successful — but the working directory is empty.
29
+ Subsequent build steps that depend on the cached files fail with cryptic errors
30
+ (missing executables, import errors, or blank node_modules) that appear unrelated
31
+ to caching.
32
+
33
+ The intended use case for lookup-only is a two-job pipeline: Job A checks if the
34
+ cache exists (lookup-only: true) and, if not, builds and saves it; Job B restores
35
+ normally. It is NOT a performance shortcut for regular restore-and-save workflows.
36
+ fix: |
37
+ Remove lookup-only: true from any step that should actually restore cached files.
38
+ Use lookup-only: true only in a dedicated pre-check job that gates whether an
39
+ expensive build step needs to run, combined with a normal actions/cache step in
40
+ the subsequent job that performs the real restore.
41
+ fix_code:
42
+ - language: yaml
43
+ label: "Remove lookup-only for normal cache restore (most cases)"
44
+ code: |
45
+ - name: Restore node_modules cache
46
+ id: cache
47
+ uses: actions/cache@v4
48
+ with:
49
+ path: node_modules
50
+ key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
51
+ restore-keys: ${{ runner.os }}-node-
52
+ # Do NOT set lookup-only: true here — files must be restored
53
+ - language: yaml
54
+ label: "Correct pattern: lookup-only in check job, real restore in build job"
55
+ code: |
56
+ jobs:
57
+ check-cache:
58
+ runs-on: ubuntu-latest
59
+ outputs:
60
+ cache-hit: ${{ steps.lookup.outputs.cache-hit }}
61
+ steps:
62
+ - id: lookup
63
+ uses: actions/cache@v4
64
+ with:
65
+ path: node_modules
66
+ key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
67
+ lookup-only: true # only check — no download
68
+
69
+ build:
70
+ needs: check-cache
71
+ runs-on: ubuntu-latest
72
+ steps:
73
+ - uses: actions/cache@v4
74
+ with:
75
+ path: node_modules
76
+ key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
77
+ # no lookup-only — restores files and saves after build
78
+ - if: needs.check-cache.outputs.cache-hit != 'true'
79
+ run: npm ci
80
+ prevention:
81
+ - "Only use lookup-only: true in a dedicated cache-check job that feeds a conditional build gate."
82
+ - "After using lookup-only, always follow up with a standard actions/cache step (no lookup-only) in the job that needs the files."
83
+ - "If you want to skip the post-step cache save, use actions/cache/restore instead of setting lookup-only: true."
84
+ docs:
85
+ - url: "https://github.com/actions/cache#inputs"
86
+ label: "actions/cache README: inputs including lookup-only"
87
+ - url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/caching-dependencies-to-speed-up-workflows"
88
+ label: "GitHub Actions: Caching dependencies"
@@ -0,0 +1,67 @@
1
+ id: caching-artifacts-047
2
+ title: "Re-run job fails with 'artifact already exists' when artifact name includes github.run_id"
3
+ category: caching-artifacts
4
+ severity: error
5
+ tags:
6
+ - upload-artifact
7
+ - re-run
8
+ - run_id
9
+ - run_attempt
10
+ - artifact-name
11
+ - collision
12
+ patterns:
13
+ - regex: 'An artifact with this name already exists on the workflow run'
14
+ flags: 'i'
15
+ - regex: 'Unable to upload artifact.*already exists'
16
+ flags: 'i'
17
+ error_messages:
18
+ - "An artifact with this name already exists on the workflow run."
19
+ - "Unable to upload artifact: An artifact with this name already exists on the run."
20
+ root_cause: |
21
+ github.run_id identifies a workflow run and remains the same value across all
22
+ re-run attempts triggered from the GitHub UI or REST API. When an artifact name
23
+ is constructed using github.run_id (e.g., my-build-${{ github.run_id }}), the
24
+ first attempt uploads successfully. If the job fails and is re-run, the re-run
25
+ attempt tries to create an artifact with the identical name on the same run.
26
+
27
+ actions/upload-artifact@v4 enforces unique artifact names per run as a hard
28
+ error (changed from v3 which silently overwrote). The re-run therefore fails
29
+ immediately with "artifact already exists" before any meaningful work is done.
30
+
31
+ Teams reach for run_id because it appears to be a unique-per-execution
32
+ identifier. It is not: it is unique per workflow trigger, stable across all
33
+ re-run attempts within that trigger.
34
+ fix: |
35
+ Append github.run_attempt to the artifact name. run_attempt starts at 1 and
36
+ increments for each re-run of the same run_id, making the combined value unique
37
+ across attempts. Consumers of the artifact (download steps, workflow_run
38
+ triggers) must include run_attempt in their own references to locate the
39
+ correct artifact.
40
+ fix_code:
41
+ - language: yaml
42
+ label: "Include run_attempt to make artifact name unique across re-runs"
43
+ code: |
44
+ - name: Upload build artifact
45
+ uses: actions/upload-artifact@v4
46
+ with:
47
+ # run_attempt increments on each re-run, preventing name collision
48
+ name: my-build-${{ github.run_id }}-${{ github.run_attempt }}
49
+ path: dist/
50
+ - language: yaml
51
+ label: "Download the matching artifact in a downstream job"
52
+ code: |
53
+ - name: Download build artifact
54
+ uses: actions/download-artifact@v4
55
+ with:
56
+ name: my-build-${{ github.run_id }}-${{ github.run_attempt }}
57
+ path: dist/
58
+ prevention:
59
+ - "Never use github.run_id alone as an artifact name uniqueness guarantee — it is stable across all re-runs of the same run."
60
+ - "Combine github.run_id with github.run_attempt to produce a name that is unique within a run AND across re-run attempts."
61
+ - "Use a matrix value or job name as the differentiator instead of run_id when the artifact is consumed by a job in the same workflow."
62
+ - "Check the GitHub UI Actions > Artifacts list to inspect existing artifact names before debugging re-run failures."
63
+ docs:
64
+ - url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/storing-workflow-data-as-artifacts"
65
+ label: "GitHub Actions: Storing workflow data as artifacts"
66
+ - url: "https://github.com/actions/upload-artifact#not-uploading-to-the-same-artifact"
67
+ label: "actions/upload-artifact: unique artifact names per run"
@@ -0,0 +1,92 @@
1
+ id: concurrency-timing-041
2
+ title: "Workflow-level concurrency cancels entire workflow — job-level concurrency only gates that specific job"
3
+ category: concurrency-timing
4
+ severity: silent-failure
5
+ tags:
6
+ - concurrency
7
+ - cancel-in-progress
8
+ - workflow-level
9
+ - job-level
10
+ - scope
11
+ - deployment
12
+ - test-cancellation
13
+ patterns:
14
+ - regex: '^concurrency:\s*$'
15
+ flags: 'm'
16
+ - regex: 'jobs\.[a-zA-Z_][a-zA-Z0-9_-]*:\s*\n(\s+.*\n)*\s+concurrency:'
17
+ flags: 'm'
18
+ error_messages:
19
+ - "Run was cancelled. (workflow-level concurrency cancelled entire run including unrelated jobs)"
20
+ - "Skipping job deploy because it is not needed (cancelled by workflow-level concurrency group)"
21
+ root_cause: |
22
+ The concurrency: key in GitHub Actions behaves fundamentally differently depending on
23
+ where it is placed in the workflow file:
24
+
25
+ WORKFLOW-LEVEL (top-level key, outside jobs:):
26
+ Cancels or queues the ENTIRE workflow run. When a new run starts for the same concurrency
27
+ group, all pending or in-progress jobs in the workflow are affected — including build,
28
+ test, lint, and deploy jobs. The full workflow run is treated as the atomic unit.
29
+
30
+ JOB-LEVEL (inside jobs.<job_id>: as a sibling of runs-on: and steps:):
31
+ Only gates THAT SPECIFIC JOB. Other jobs in the same workflow run execute concurrently
32
+ without restriction. Serialization or cancellation applies only to the job that declares
33
+ the concurrency block.
34
+
35
+ Common mistake #1: developer adds workflow-level concurrency intending to prevent
36
+ duplicate deployments, but accidentally causes active test/build jobs to be cancelled
37
+ on every new push — wasting compute and breaking CI feedback.
38
+
39
+ Common mistake #2: developer adds job-level concurrency expecting the whole workflow
40
+ to be serialized, but parallel test runs from multiple pushes execute simultaneously.
41
+ fix: |
42
+ Use job-level concurrency on only the deploy job when you want to serialize
43
+ deployments without interrupting parallel test runs. Use workflow-level concurrency
44
+ only when you intend for the entire workflow to serialize or cancel on new push.
45
+ fix_code:
46
+ - language: yaml
47
+ label: "Correct: job-level concurrency on deploy only — tests run freely"
48
+ code: |
49
+ jobs:
50
+ test:
51
+ runs-on: ubuntu-latest
52
+ # No concurrency — multiple test runs execute in parallel across pushes
53
+ steps:
54
+ - run: npm test
55
+
56
+ deploy:
57
+ needs: test
58
+ runs-on: ubuntu-latest
59
+ concurrency:
60
+ group: deploy-${{ github.ref_name }}
61
+ cancel-in-progress: false # Queue deploys, never cancel in-flight
62
+ steps:
63
+ - run: ./deploy.sh
64
+ - language: yaml
65
+ label: "Caution: workflow-level concurrency cancels test and build jobs too"
66
+ code: |
67
+ # This cancels the ENTIRE workflow on new push — tests, build, and deploy all stop
68
+ concurrency:
69
+ group: ${{ github.workflow }}-${{ github.ref }}
70
+ cancel-in-progress: true
71
+
72
+ jobs:
73
+ test:
74
+ runs-on: ubuntu-latest
75
+ steps:
76
+ - run: npm test # Also cancelled when a new push arrives
77
+
78
+ deploy:
79
+ needs: test
80
+ runs-on: ubuntu-latest
81
+ steps:
82
+ - run: ./deploy.sh
83
+ prevention:
84
+ - "For deploy-only serialization, use job-level concurrency on only the deploy job"
85
+ - "Avoid cancel-in-progress: true at workflow level for deployment workflows — an interrupted deploy may leave infrastructure in an inconsistent state"
86
+ - "Use cancel-in-progress: ${{ github.event_name == 'pull_request' }} to cancel PR runs but preserve default-branch deployments"
87
+ - "Verify scope: if concurrency: is indented under a specific jobs.<id>: block it is job-level; if it is at the same indentation as jobs: it is workflow-level"
88
+ docs:
89
+ - url: "https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/using-concurrency"
90
+ label: "GitHub Docs: Using concurrency"
91
+ - url: "https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#concurrency"
92
+ label: "GitHub Docs: concurrency syntax reference"
@@ -0,0 +1,88 @@
1
+ id: known-unsolved-048
2
+ title: 'Organization required workflows block all repo PRs with no per-repo override'
3
+ category: known-unsolved
4
+ severity: limitation
5
+ tags:
6
+ - required-workflows
7
+ - organization
8
+ - branch-protection
9
+ - enterprise
10
+ - admin
11
+ patterns:
12
+ - regex: 'Required status checks have not passed for this branch'
13
+ flags: 'i'
14
+ - regex: 'required workflows? are not complete'
15
+ flags: 'i'
16
+ error_messages:
17
+ - 'Required status checks have not passed for this branch'
18
+ - 'The following required workflows are not complete: .github/workflows/required-check.yml'
19
+ - 'Required workflow failed: org-name/.github/.github/workflows/security-scan.yml'
20
+ root_cause: |
21
+ GitHub Enterprise Cloud allows org admins to configure "Required workflows"
22
+ under Org Settings → Actions → Required workflows. These workflows run on
23
+ every push and pull_request event across every repository in the organization
24
+ and are automatically added as required status checks on all branches.
25
+
26
+ When a required workflow fails — due to a misconfiguration, missing secret,
27
+ incompatibility with a specific repository's structure, or a transient error
28
+ — all open PRs in every affected repository are blocked from merging. There
29
+ is no mechanism for repo admins or developers to bypass or exempt their
30
+ repository from the org-level required workflow. Only the org admin can fix
31
+ the required workflow or remove the requirement.
32
+
33
+ This creates an org-wide single point of failure: a bug in the centralized
34
+ required workflow instantly blocks all engineering teams from shipping.
35
+ fix: |
36
+ There is no per-repository exemption for org required workflows. Mitigation
37
+ strategies for org admins:
38
+
39
+ 1. Use `if:` conditions in the required workflow to skip gracefully for
40
+ incompatible repositories instead of failing.
41
+ 2. Set `continue-on-error: true` on non-critical jobs within the required
42
+ workflow so that optional checks do not block merges.
43
+ 3. Maintain a staging version of the required workflow tested on a canary
44
+ repo before rolling changes org-wide.
45
+ 4. Set up alerting on required workflow failure rates to catch regressions
46
+ before they block the whole org.
47
+ fix_code:
48
+ - language: yaml
49
+ label: 'Use if: conditions to gracefully skip incompatible repos'
50
+ code: |
51
+ # In org's .github repo: .github/workflows/required-check.yml
52
+ name: Required Security Scan
53
+ on: [push, pull_request]
54
+ jobs:
55
+ security-scan:
56
+ runs-on: ubuntu-latest
57
+ # Skip repos that are explicitly opted out
58
+ if: >-
59
+ !contains(
60
+ fromJSON('["org/legacy-repo", "org/infra-repo"]'),
61
+ github.repository
62
+ )
63
+ steps:
64
+ - uses: actions/checkout@v4
65
+ - name: Run scan
66
+ run: ./scripts/security-scan.sh
67
+
68
+ - language: yaml
69
+ label: 'Use continue-on-error for non-blocking checks'
70
+ code: |
71
+ jobs:
72
+ lint:
73
+ runs-on: ubuntu-latest
74
+ continue-on-error: true # Won't block the required status check
75
+ steps:
76
+ - uses: actions/checkout@v4
77
+ - run: npm run lint
78
+ prevention:
79
+ - 'Test required workflows in a canary repository before enabling org-wide'
80
+ - 'Use `if:` guards to skip repos that cannot satisfy the required checks'
81
+ - 'Monitor required workflow failure rates with org-level Actions dashboards'
82
+ - 'Prefer `continue-on-error: true` for advisory checks that should not hard-block PRs'
83
+ - 'Keep required workflows minimal — only truly mandatory gates belong here'
84
+ docs:
85
+ - url: 'https://docs.github.com/en/actions/administering-github-actions/required-workflows'
86
+ label: 'Required workflows — GitHub Docs'
87
+ - url: 'https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches#require-status-checks-before-merging'
88
+ label: 'Required status checks — GitHub Docs'
@@ -0,0 +1,73 @@
1
+ id: runner-environment-144
2
+ title: '`runs-on` larger hosted runner labels require GitHub Teams or Enterprise plan'
3
+ category: runner-environment
4
+ severity: error
5
+ tags:
6
+ - runs-on
7
+ - larger-runners
8
+ - billing
9
+ - teams
10
+ - enterprise
11
+ - ubuntu-latest-4-cores
12
+ patterns:
13
+ - regex: 'No runner matching the required labels was found:\s+ubuntu-latest-[0-9]+-cores'
14
+ flags: 'i'
15
+ - regex: 'No runner matching the required labels was found:\s+windows-latest-[0-9]+-cores'
16
+ flags: 'i'
17
+ - regex: 'No runner matching the required labels was found:\s+macos-latest-[0-9]+-cores'
18
+ flags: 'i'
19
+ error_messages:
20
+ - 'No runner matching the required labels was found: ubuntu-latest-4-cores'
21
+ - 'No runner matching the required labels was found: ubuntu-latest-8-cores'
22
+ - 'No runner matching the required labels was found: windows-latest-8-cores'
23
+ - 'No runner matching the required labels was found: macos-latest-xlarge'
24
+ root_cause: |
25
+ GitHub offers larger hosted runners (4-core, 8-core, 16-core, 64-core) via
26
+ labels like `ubuntu-latest-4-cores`, `ubuntu-latest-8-cores`,
27
+ `ubuntu-22.04-8-cores`, `windows-latest-8-cores`, and `macos-latest-xlarge`.
28
+ These runners are only available on GitHub Teams and GitHub Enterprise Cloud
29
+ plans. On GitHub Free and GitHub Pro plans these labels are not provisioned,
30
+ so the queued job sits waiting until it times out or immediately fails with
31
+ "No runner matching the required labels was found."
32
+
33
+ GitHub does not display a clear billing-tier explanation in the error message,
34
+ leaving developers to guess whether the runner label is misspelled or simply
35
+ unavailable on their plan.
36
+ fix: |
37
+ Switch to the standard `ubuntu-latest` (2-core) runner for free/pro accounts,
38
+ upgrade to GitHub Teams/Enterprise to unlock larger runners, or use
39
+ self-hosted runners with more CPU/RAM as an alternative.
40
+ fix_code:
41
+ - language: yaml
42
+ label: 'Use standard runner on free/pro plans'
43
+ code: |
44
+ jobs:
45
+ build:
46
+ # ubuntu-latest is a 2-core runner available on all GitHub plans
47
+ runs-on: ubuntu-latest
48
+ steps:
49
+ - uses: actions/checkout@v4
50
+ - run: make build
51
+
52
+ - language: yaml
53
+ label: 'Conditionally use larger runner for orgs on Teams/Enterprise'
54
+ code: |
55
+ jobs:
56
+ build:
57
+ # Use larger runner for org workflows, fall back for personal repos
58
+ runs-on: >-
59
+ ${{ startsWith(github.repository, 'my-org/') &&
60
+ 'ubuntu-latest-8-cores' || 'ubuntu-latest' }}
61
+ steps:
62
+ - uses: actions/checkout@v4
63
+ - run: make build
64
+ prevention:
65
+ - 'Verify your GitHub plan tier before using larger runner labels — check under Billing & plans → GitHub Actions'
66
+ - 'Use self-hosted runners with additional CPU as a free alternative for resource-intensive builds'
67
+ - 'Document which runner labels require a paid plan in your repository CONTRIBUTING guide'
68
+ - 'Use `ubuntu-latest` (2-core) for most workflows; only reach for larger runners when build profiling shows a genuine bottleneck'
69
+ docs:
70
+ - url: 'https://docs.github.com/en/actions/using-github-hosted-runners/about-larger-runners/about-larger-runners'
71
+ label: 'About larger runners — GitHub Docs'
72
+ - url: 'https://docs.github.com/en/billing/managing-billing-for-your-products/managing-billing-for-github-actions/about-billing-for-github-actions'
73
+ label: 'About billing for GitHub Actions — GitHub Docs'
@@ -0,0 +1,110 @@
1
+ id: runner-environment-148
2
+ title: "macOS runners ship with bash 3.2 — bash 4.x/5.x features unavailable"
3
+ category: runner-environment
4
+ severity: error
5
+ tags:
6
+ - macos
7
+ - bash
8
+ - bash-version
9
+ - associative-arrays
10
+ - shell-scripting
11
+
12
+ patterns:
13
+ - regex: 'declare.*-A.*invalid option'
14
+ flags: i
15
+ - regex: 'mapfile.*command not found'
16
+ flags: i
17
+ - regex: 'readarray.*command not found'
18
+ flags: i
19
+ - regex: 'syntax error near unexpected token.*\|\&'
20
+ flags: i
21
+
22
+ error_messages:
23
+ - "/bin/bash: line N: declare: -A: invalid option"
24
+ - "declare: usage: declare [-afFirtx] [-p] [name[=value] ...]"
25
+ - "/bin/bash: mapfile: command not found"
26
+ - "/bin/bash: readarray: command not found"
27
+
28
+ root_cause: |
29
+ macOS ships with GNU Bash 3.2.57 at /bin/bash due to Apple's decision not to
30
+ include GPL v3 software in the base OS. Bash 4.0 (released 2009) and all later
31
+ versions are GPL v3. macOS has not updated the system bash beyond 3.2.x for
32
+ over 15 years as a result.
33
+
34
+ GitHub-hosted macOS runners (macos-13, macos-14, macos-15, macos-latest) all use
35
+ /bin/bash as the default shell for `shell: bash` run steps. This means all bash
36
+ scripts on macOS runners are subject to bash 3.2 limitations:
37
+
38
+ - Associative arrays: `declare -A map` — UNAVAILABLE (added in bash 4.0)
39
+ - mapfile / readarray built-ins — UNAVAILABLE (added in bash 4.0)
40
+ - `|&` (pipe stdout and stderr): syntax error (added in bash 4.0)
41
+ - `**` globbing for recursive matching — UNAVAILABLE (added in bash 4.0, requires shopt -s globstar)
42
+ - Case-modifying parameter expansion: `${var^^}`, `${var,,}` — UNAVAILABLE (bash 4.0)
43
+
44
+ Workflows that run on ubuntu runners may work fine because ubuntu ships bash 5.x,
45
+ then silently fail on macOS runners at the same step due to the bash version
46
+ difference.
47
+
48
+ fix: |
49
+ Install modern bash via Homebrew and either update the PATH or use the full path
50
+ to the installed bash in the shell setting or script shebang.
51
+
52
+ For cross-platform workflows, avoid bash 4.x/5.x-only features or add an explicit
53
+ setup step for macOS.
54
+
55
+ fix_code:
56
+ - language: yaml
57
+ label: "Install modern bash via Homebrew (macOS)"
58
+ code: |
59
+ jobs:
60
+ build:
61
+ runs-on: macos-latest
62
+ steps:
63
+ - name: Install modern bash
64
+ run: brew install bash
65
+
66
+ - name: Run script with bash 5
67
+ run: /opt/homebrew/bin/bash my-script.sh
68
+ # Intel macOS: /usr/local/bin/bash
69
+ # Apple Silicon (macos-14+): /opt/homebrew/bin/bash
70
+
71
+ - language: yaml
72
+ label: "Set shell to modern bash for all steps"
73
+ code: |
74
+ jobs:
75
+ build:
76
+ runs-on: macos-latest
77
+ steps:
78
+ - name: Install modern bash
79
+ run: brew install bash
80
+
81
+ - name: Script using bash 4+ features
82
+ shell: /opt/homebrew/bin/bash {0}
83
+ run: |
84
+ declare -A mymap
85
+ mymap[key]="value"
86
+ echo "${mymap[key]}"
87
+
88
+ - language: yaml
89
+ label: "Cross-platform workaround — avoid bash 4+ features"
90
+ code: |
91
+ - run: |
92
+ # Use python or node for associative arrays cross-platform
93
+ python3 -c "
94
+ mymap = {'key': 'value'}
95
+ print(mymap['key'])
96
+ "
97
+
98
+ prevention:
99
+ - Test macOS workflows explicitly — a step that passes on ubuntu may fail on macos.
100
+ - Avoid bash 4.x/5.x-only features (declare -A, mapfile, readarray) in scripts intended to run on macOS.
101
+ - Add `brew install bash` as the first step in any macOS job that uses modern bash syntax.
102
+ - Use `bash --version` in a debug step to confirm which bash is being used.
103
+
104
+ docs:
105
+ - url: https://www.gnu.org/software/bash/manual/bash.html#What-is-Bash_003f
106
+ label: "GNU Bash — version history and features"
107
+ - url: https://brew.sh
108
+ label: "Homebrew — install modern bash on macOS"
109
+ - url: https://github.com/actions/runner-images/blob/main/images/macos/macos-15-Readme.md
110
+ label: "macos-15 runner image — pre-installed software"
@@ -0,0 +1,83 @@
1
+ id: runner-environment-145
2
+ title: "ubuntu-22/24 pip install fails with 'externally-managed-environment' (PEP 668)"
3
+ category: runner-environment
4
+ severity: error
5
+ tags:
6
+ - ubuntu
7
+ - python
8
+ - pip
9
+ - pep-668
10
+ - packages
11
+ - setup-python
12
+
13
+ patterns:
14
+ - regex: 'externally.managed.environment'
15
+ flags: i
16
+ - regex: 'This environment is externally managed'
17
+ flags: i
18
+
19
+ error_messages:
20
+ - "error: externally-managed-environment"
21
+ - "× This environment is externally managed"
22
+ - "╰─> To install Python packages system-wide, try apt install"
23
+
24
+ root_cause: |
25
+ PEP 668, adopted in Python 3.11+ and backported by distros like Ubuntu 22.04 and
26
+ 24.04, prevents pip from installing packages into the system Python environment.
27
+ Ubuntu 22.04 ships Python 3.10 but enforces PEP 668 in the system pip. Ubuntu 24.04
28
+ ships Python 3.12 with full PEP 668 enforcement.
29
+
30
+ GitHub Actions runners expose the system Python when no setup-python step is used.
31
+ System pip blocks global installs and raises this error to prevent breaking
32
+ OS-managed packages that depend on system Python libraries.
33
+
34
+ Workflows that previously ran `pip install <pkg>` or `pip3 install <pkg>` directly
35
+ on ubuntu-20.04 succeed silently, but fail on ubuntu-22.04 and ubuntu-24.04 because
36
+ those images enforce the system-managed environment restriction.
37
+
38
+ fix: |
39
+ Use one of these approaches:
40
+
41
+ 1. Use actions/setup-python (recommended) — configures an isolated Python
42
+ environment that allows pip installs freely.
43
+
44
+ 2. Install with --break-system-packages flag — allows global install but may
45
+ conflict with apt-managed packages. Use only for CI where isolation is
46
+ acceptable.
47
+
48
+ 3. Create a virtual environment inline with python -m venv.
49
+
50
+ fix_code:
51
+ - language: yaml
52
+ label: "Use actions/setup-python (recommended)"
53
+ code: |
54
+ - uses: actions/setup-python@v5
55
+ with:
56
+ python-version: '3.12'
57
+ - run: pip install my-package # installs into the setup-python venv, no error
58
+
59
+ - language: yaml
60
+ label: "Virtual environment workaround"
61
+ code: |
62
+ - run: |
63
+ python3 -m venv .venv
64
+ source .venv/bin/activate
65
+ pip install my-package
66
+
67
+ - language: yaml
68
+ label: "Break system packages flag (use with caution)"
69
+ code: |
70
+ - run: pip install --break-system-packages my-package
71
+
72
+ prevention:
73
+ - Always use actions/setup-python before any pip install in workflows targeting ubuntu-22.04 or ubuntu-24.04.
74
+ - Pin ubuntu version explicitly — upgrading from ubuntu-20.04 to ubuntu-latest silently adopts PEP 668 enforcement.
75
+ - Prefer virtual environments over global installs in CI for reproducibility.
76
+
77
+ docs:
78
+ - url: https://peps.python.org/pep-0668/
79
+ label: "PEP 668 — Marking Python base environments as externally managed"
80
+ - url: https://github.com/actions/setup-python
81
+ label: "actions/setup-python — GitHub Actions"
82
+ - url: https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2404-Readme.md
83
+ label: "ubuntu-24.04 runner image — pre-installed software"
@@ -0,0 +1,74 @@
1
+ id: runner-environment-146
2
+ title: "ubuntu-24.04 runner — Ruby and gem not pre-installed"
3
+ category: runner-environment
4
+ severity: error
5
+ tags:
6
+ - ubuntu-24
7
+ - ruby
8
+ - gem
9
+ - tools-missing
10
+ - migration
11
+
12
+ patterns:
13
+ - regex: 'ruby\s*:\s*command not found'
14
+ flags: i
15
+ - regex: 'gem\s*:\s*command not found'
16
+ flags: i
17
+ - regex: 'No such file or directory.*ruby'
18
+ flags: i
19
+
20
+ error_messages:
21
+ - "/usr/bin/bash: ruby: command not found"
22
+ - "/usr/bin/bash: gem: command not found"
23
+ - "Error: ruby not found"
24
+
25
+ root_cause: |
26
+ GitHub's ubuntu-24.04 runner image does not include Ruby in its pre-installed
27
+ software list. Unlike ubuntu-22.04 (which ships Ruby 3.0.x from the Ubuntu 22
28
+ package repository), ubuntu-24.04 dropped Ruby as a default pre-installed tool.
29
+
30
+ Workflows that rely on `ruby`, `gem`, `bundle`, or `rake` being available without
31
+ an explicit setup step will fail with "command not found" when the runner image is
32
+ ubuntu-24.04 or when ubuntu-latest resolves to ubuntu-24.04.
33
+
34
+ This commonly affects:
35
+ - Workflows that run `gem install` or `bundle install` directly
36
+ - Custom scripts that call `ruby my-script.rb`
37
+ - Jekyll static site workflows without the setup-ruby action
38
+ - Workflows that inherited ubuntu-22.04 behavior when pinned to ubuntu-latest
39
+
40
+ fix: |
41
+ Use the ruby/setup-ruby action to install Ruby on any runner. This is the
42
+ recommended approach for cross-platform consistency and version pinning.
43
+
44
+ Alternatively, install Ruby via apt-get if a specific package-managed version
45
+ is acceptable, but ruby/setup-ruby is strongly preferred for version control.
46
+
47
+ fix_code:
48
+ - language: yaml
49
+ label: "Use ruby/setup-ruby action (recommended)"
50
+ code: |
51
+ - uses: ruby/setup-ruby@v1
52
+ with:
53
+ ruby-version: '3.3'
54
+ bundler-cache: true # runs bundle install and caches gems
55
+
56
+ - run: ruby my-script.rb
57
+
58
+ - language: yaml
59
+ label: "Install via apt-get (version uncontrolled)"
60
+ code: |
61
+ - run: sudo apt-get install -y ruby ruby-dev
62
+
63
+ prevention:
64
+ - Always use ruby/setup-ruby instead of relying on pre-installed Ruby.
65
+ - Test workflows against ubuntu-24.04 explicitly before switching ubuntu-latest.
66
+ - Check the ubuntu-24.04 pre-installed software list when migrating from ubuntu-22.04.
67
+
68
+ docs:
69
+ - url: https://github.com/ruby/setup-ruby
70
+ label: "ruby/setup-ruby — GitHub Actions"
71
+ - url: https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2404-Readme.md
72
+ label: "ubuntu-24.04 runner image — pre-installed software"
73
+ - url: https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2204-Readme.md
74
+ label: "ubuntu-22.04 runner image — Ruby pre-installed"