@htekdev/actions-debugger 1.0.99 → 1.0.101

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,104 @@
1
+ id: caching-artifacts-055
2
+ title: 'setup-python cache: poetry broken when poetry is installed before setup-python — virtualenv 20.33.0+ Python version mismatch'
3
+ category: caching-artifacts
4
+ severity: error
5
+ tags:
6
+ - setup-python
7
+ - poetry
8
+ - cache
9
+ - virtualenv
10
+ - python-version
11
+ - pipx
12
+ - ordering
13
+ patterns:
14
+ - regex: 'Current Python version \([\d.]+\) is not allowed by the project'
15
+ flags: 'i'
16
+ - regex: 'poetry.*install.*exit code 1'
17
+ flags: 'i'
18
+ - regex: 'Please change python executable via the "env use" command'
19
+ flags: 'i'
20
+ - regex: 'installed package poetry.*using Python \d+\.\d+'
21
+ flags: 'i'
22
+ error_messages:
23
+ - "Current Python version (3.12.3) is not allowed by the project (>= 3.13, < 4). Please change python executable via the \"env use\" command."
24
+ - "Current Python version (3.11.9) is not allowed by the project (>=3.12,<3.13). Please change python executable via the \"env use\" command."
25
+ - "Error: Process completed with exit code 1."
26
+ root_cause: |
27
+ When using actions/setup-python with cache: 'poetry', the action requires
28
+ poetry to be installed BEFORE it runs (to resolve the cache path). Developers
29
+ commonly install poetry via pipx before calling setup-python, which causes
30
+ pipx to anchor poetry to the runner's pre-installed system Python (e.g., 3.12.3).
31
+
32
+ After setup-python runs and installs the project's target Python version
33
+ (e.g., 3.13), poetry's internal virtualenv logic still references the Python
34
+ version it was originally installed with. Consequently, when poetry creates
35
+ or activates a virtual environment, it resolves to the old Python version —
36
+ which violates the project's python requirement and produces the
37
+ "Current Python version is not allowed" error.
38
+
39
+ This became a consistent failure in August 2025 when virtualenv 20.33.0
40
+ changed how it resolves the Python interpreter for new virtual environments,
41
+ making the version mismatch explicit and fatal rather than silently using
42
+ the wrong interpreter.
43
+
44
+ The fundamental issue is a circular dependency in the documented workflow:
45
+ setup-python needs poetry installed to set up caching, but poetry must be
46
+ installed after setup-python to use the correct Python version.
47
+ fix: |
48
+ Use actions/cache manually instead of setup-python's built-in poetry cache.
49
+ Install poetry AFTER setup-python so it is anchored to the correct Python.
50
+ This avoids the circular ordering problem entirely.
51
+ fix_code:
52
+ - language: yaml
53
+ label: 'Workaround — Manual cache + install poetry after setup-python'
54
+ code: |
55
+ steps:
56
+ - uses: actions/setup-python@v5
57
+ id: setup-python
58
+ with:
59
+ python-version: '3.13'
60
+ # Do NOT use cache: 'poetry' here
61
+
62
+ - name: Install poetry
63
+ run: pipx install poetry
64
+
65
+ - name: Cache poetry virtualenv
66
+ uses: actions/cache@v4
67
+ with:
68
+ path: ~/.cache/pypoetry/virtualenvs
69
+ key: ${{ runner.os }}-poetry-${{ steps.setup-python.outputs.python-version }}-${{ hashFiles('**/poetry.lock') }}
70
+ restore-keys: |
71
+ ${{ runner.os }}-poetry-${{ steps.setup-python.outputs.python-version }}-
72
+
73
+ - name: Install dependencies
74
+ run: poetry install
75
+ - language: yaml
76
+ label: 'Alternative — pin virtualenv version as a short-term patch'
77
+ code: |
78
+ steps:
79
+ - name: Install poetry (with pinned virtualenv)
80
+ run: |
81
+ pipx install poetry
82
+ pipx inject poetry virtualenv==20.26.6
83
+
84
+ - uses: actions/setup-python@v5
85
+ with:
86
+ python-version: '3.13'
87
+ cache: 'poetry'
88
+
89
+ - name: Install dependencies
90
+ run: poetry install
91
+ prevention:
92
+ - "Never use setup-python cache: poetry in combination with a poetry install step that runs before setup-python."
93
+ - "Use actions/cache manually to avoid the circular dependency between poetry installation and Python version resolution."
94
+ - "Keep poetry updated — poetry 2.1.4+ partially mitigates the virtualenv version mismatch for some project configurations."
95
+ - "Use uv as an alternative to poetry; uv is installed on GitHub-hosted runners and handles Python version resolution differently."
96
+ docs:
97
+ - url: 'https://github.com/actions/setup-python/issues/1167'
98
+ label: 'actions/setup-python #1167 — Issues with poetry caching (Aug 2025)'
99
+ - url: 'https://github.com/python-poetry/poetry/issues/10490'
100
+ label: 'python-poetry/poetry #10490 — virtualenv 20.33.0 compatibility issue'
101
+ - url: 'https://github.com/pypa/virtualenv/issues/2931'
102
+ label: 'pypa/virtualenv #2931 — Python interpreter resolution change'
103
+ - url: 'https://github.com/actions/setup-python/blob/main/docs/advanced-usage.md#caching-packages'
104
+ label: 'actions/setup-python — Caching packages documentation'
@@ -0,0 +1,113 @@
1
+ id: caching-artifacts-056
2
+ title: 'actions/cache v1 and v2 deprecated — workflows fail hard with "automatically failed" error'
3
+ category: caching-artifacts
4
+ severity: error
5
+ tags:
6
+ - actions/cache
7
+ - deprecated
8
+ - v1
9
+ - v2
10
+ - hard-failure
11
+ - breaking-change
12
+ - upgrade
13
+ patterns:
14
+ - regex: 'automatically failed.*deprecated version.*actions/cache'
15
+ flags: 'i'
16
+ - regex: 'deprecated version of.{0,30}actions/cache'
17
+ flags: 'i'
18
+ - regex: 'actions/cache@v[12]\b'
19
+ flags: 'i'
20
+ error_messages:
21
+ - "This request has been automatically failed because it uses a deprecated version of `actions/cache: 6849a6489940f00c2f30c0fb92c6274307ccb58a`"
22
+ - "Error: This request has been automatically failed because it uses a deprecated version of `actions/cache`"
23
+ root_cause: |
24
+ GitHub announced in December 2024 (GitHub Changelog) that `actions/cache` versions 1 and 2
25
+ were deprecated and would be hard-failed starting February 1, 2025. Any workflow still
26
+ pinned to `actions/cache@v1` or `actions/cache@v2` (or to a full SHA that resolves to
27
+ those versions) now fails immediately with a hard error — no cache operation is attempted
28
+ and the entire step fails.
29
+
30
+ The error message includes the SHA of the deprecated action version:
31
+ "This request has been automatically failed because it uses a deprecated version
32
+ of `actions/cache: <SHA>`"
33
+
34
+ This is a hard failure, not a graceful degradation — the step exit code is non-zero and
35
+ causes the job to fail unless `continue-on-error: true` is set on the step (which is
36
+ not a recommended fix).
37
+
38
+ Common reasons workflows are still on v1/v2:
39
+ 1. The workflow was written years ago and never updated
40
+ 2. The action is referenced by a full commit SHA from before v3 was released
41
+ 3. A reusable workflow or composite action calls an outdated dependency that pins v1/v2
42
+ 4. `Dependabot` is not enabled on the repo for GitHub Actions
43
+
44
+ Note: `actions/cache@v3` and `actions/cache@v4` are both supported. V4 is the current
45
+ recommended version.
46
+ fix: |
47
+ Upgrade all `actions/cache` references from v1 or v2 to v4 (recommended) or v3.
48
+ Search your repository for `actions/cache@v1` and `actions/cache@v2` references,
49
+ including in nested composite actions and reusable workflows.
50
+
51
+ If you are migrating from v3 to v4, note the breaking changes documented in the
52
+ v3-to-v4 migration guide (see caching-artifacts-009). The v1/v2 to v4 migration
53
+ follows the same v3-to-v4 guidance since v3 and v4 share the same input API except
54
+ for `save-always`.
55
+
56
+ Enable Dependabot for GitHub Actions updates to automatically receive future
57
+ deprecation PRs.
58
+ fix_code:
59
+ - language: yaml
60
+ label: 'Problem: workflow pinned to deprecated actions/cache v1 or v2'
61
+ code: |
62
+ steps:
63
+ - uses: actions/checkout@v4
64
+
65
+ # FAILS: v1 and v2 are deprecated — hard failure since Feb 1, 2025
66
+ - uses: actions/cache@v1
67
+ with:
68
+ path: ~/.npm
69
+ key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
70
+
71
+ # Also fails — v2 is deprecated
72
+ - uses: actions/cache@v2
73
+ with:
74
+ path: ~/.npm
75
+ key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
76
+ - language: yaml
77
+ label: 'Fix: upgrade to actions/cache v4 (recommended)'
78
+ code: |
79
+ steps:
80
+ - uses: actions/checkout@v4
81
+
82
+ # CORRECT: use v4 (or v3 if v3-to-v4 migration is not yet done)
83
+ - uses: actions/cache@v4
84
+ with:
85
+ path: ~/.npm
86
+ key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
87
+ restore-keys: |
88
+ ${{ runner.os }}-npm-
89
+ - language: yaml
90
+ label: 'Dependabot config to automatically receive Actions version updates'
91
+ code: |
92
+ # .github/dependabot.yml
93
+ version: 2
94
+ updates:
95
+ - package-ecosystem: github-actions
96
+ directory: /
97
+ schedule:
98
+ interval: weekly
99
+ # Dependabot will open PRs to upgrade actions/cache@v1/v2 → v4 automatically
100
+ prevention:
101
+ - "Enable Dependabot for GitHub Actions in `.github/dependabot.yml` to receive automated upgrade PRs."
102
+ - "Search your `.github/workflows/` directory for `actions/cache@v1` and `actions/cache@v2` before the deprecation deadline."
103
+ - "Check composite actions and reusable workflows — they may internally call deprecated cache versions."
104
+ - "Audit SHA-pinned action references to ensure the SHA does not point to a v1/v2 release."
105
+ docs:
106
+ - url: 'https://github.blog/changelog/2024-12-05-notice-of-upcoming-releases-and-breaking-changes-for-github-actions/#actions-cache-v1-v2-and-actions-toolkit-cache-package-closing-down'
107
+ label: 'GitHub Changelog Dec 2024: actions/cache v1/v2 deprecation notice'
108
+ - url: 'https://github.com/actions/cache/discussions/1510'
109
+ label: 'actions/cache Discussion #1510: deprecated version hard failure reports'
110
+ - url: 'https://github.com/actions/cache'
111
+ label: 'actions/cache repository — upgrade instructions'
112
+ - url: 'https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot'
113
+ label: 'GitHub Docs: Keeping your actions up to date with Dependabot'
@@ -0,0 +1,98 @@
1
+ id: caching-artifacts-057
2
+ title: '`actions/cache` Never Refreshes Cached Content — Cache Keys Are Immutable Once Stored'
3
+ category: caching-artifacts
4
+ severity: silent-failure
5
+ tags:
6
+ - cache
7
+ - stale
8
+ - immutable
9
+ - cache-hit
10
+ - refresh
11
+ - node-modules
12
+ patterns:
13
+ - regex: 'cache-hit.*true.*post.*skip'
14
+ flags: 'i'
15
+ error_messages:
16
+ - "Cache hit occurred on the primary key, not saving cache."
17
+ - "Cache hit occurred on the primary key runner-os-node-"
18
+ root_cause: |
19
+ `actions/cache` uses immutable cache keys. Once a cache entry is stored for a given
20
+ key, it cannot be updated or overwritten — any subsequent run that produces an exact
21
+ key match will restore the cached content and the post step will NOT save a new cache
22
+ entry because one already exists for that key.
23
+
24
+ This means cached content (node_modules, pip packages, Maven artifacts, etc.) is
25
+ frozen at the point of first creation and will not reflect package updates until:
26
+ - The cache entry expires (GitHub-hosted caches expire after 7 days of no access)
27
+ - The cache key changes (e.g., lockfile hash changes)
28
+ - The cache entry is manually deleted via the GitHub UI or API
29
+
30
+ Common misconception: developers expect that running `npm ci` inside a cached
31
+ node_modules hit will update the cache if packages changed. It won't. The cache key
32
+ (usually `${{ hashFiles('package-lock.json') }}`) must change for a new cache to be
33
+ saved.
34
+
35
+ Related gotcha: if restore-keys produce a partial hit (different key prefix), the
36
+ post step DOES save a new cache — but for the full key, not the partial restore key.
37
+ This creates unexpected cache churn from the developer's perspective where cache hit
38
+ rate is high but actual content is outdated.
39
+
40
+ This is intentional GitHub design but frequently misunderstood, leading to:
41
+ - Stale node_modules with old transitive dependencies
42
+ - pip packages that don't receive security patches within 7 days
43
+ - Build artifacts compiled against old toolchain versions
44
+ fix: |
45
+ To force periodic cache refresh without changing your lockfile, use one of these patterns:
46
+
47
+ 1. Include a date-based component in the cache key (weekly rotation).
48
+ 2. Use `actions/cache/restore` + `actions/cache/save` with explicit control of when
49
+ to save (allows saving even on hits).
50
+ 3. Delete the cache manually via GitHub UI (Actions > Caches) or the API when you
51
+ need an immediate refresh.
52
+ fix_code:
53
+ - language: yaml
54
+ label: "Weekly-rotating cache key to prevent indefinitely stale caches"
55
+ code: |
56
+ - name: Get week number for cache rotation
57
+ id: date
58
+ run: echo "week=$(date +'%Y-%U')" >> "$GITHUB_OUTPUT"
59
+
60
+ - name: Cache node_modules (refreshes weekly)
61
+ uses: actions/cache@v4
62
+ with:
63
+ path: ~/.npm
64
+ key: ${{ runner.os }}-node-${{ steps.date.outputs.week }}-${{ hashFiles('**/package-lock.json') }}
65
+ restore-keys: |
66
+ ${{ runner.os }}-node-${{ steps.date.outputs.week }}-
67
+ ${{ runner.os }}-node-
68
+ - language: yaml
69
+ label: "Separate restore + save for explicit cache update control"
70
+ code: |
71
+ - name: Restore cache
72
+ id: cache-restore
73
+ uses: actions/cache/restore@v4
74
+ with:
75
+ path: ~/.npm
76
+ key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
77
+ restore-keys: ${{ runner.os }}-node-
78
+
79
+ - run: npm ci
80
+
81
+ - name: Save updated cache (always saves, even on hit)
82
+ uses: actions/cache/save@v4
83
+ if: always()
84
+ with:
85
+ path: ~/.npm
86
+ key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}-${{ github.run_id }}
87
+ prevention:
88
+ - "Understand that GitHub cache keys are immutable — a key that already exists in the cache will never be overwritten"
89
+ - "Use time-based or run-id-based cache key suffixes when cached content must be refreshed more frequently than lockfile changes"
90
+ - "Monitor cache age in the GitHub UI (Actions > Caches) and manually purge entries that appear stale"
91
+ - "For security-sensitive dependencies, prefer short cache TTLs via run-id keys or disable caching entirely"
92
+ docs:
93
+ - url: "https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows"
94
+ label: "GitHub Docs — Caching dependencies to speed up workflows"
95
+ - url: "https://github.com/actions/cache/blob/main/tips-and-workarounds.md"
96
+ label: "actions/cache tips and workarounds"
97
+ - url: "https://github.com/actions/cache/issues/1380"
98
+ label: "actions/cache #1380 — cache never updates on key hit"
@@ -0,0 +1,124 @@
1
+ id: known-unsolved-055
2
+ title: 'github.event.workflow_run.pull_requests is empty for fork PRs — PR context unavailable in triggered workflow'
3
+ category: known-unsolved
4
+ severity: silent-failure
5
+ tags:
6
+ - workflow_run
7
+ - fork
8
+ - pull-requests
9
+ - event-context
10
+ - security
11
+ - limitation
12
+ - pull_request
13
+ patterns:
14
+ - regex: 'github\.event\.workflow_run\.pull_requests'
15
+ flags: 'i'
16
+ - regex: 'pull_requests.*\[\]|workflow_run.*pull_requests.*empty'
17
+ flags: 'i'
18
+ error_messages:
19
+ - "# No error thrown — github.event.workflow_run.pull_requests evaluates to [] for fork PRs"
20
+ - "Error: PR number is empty or undefined"
21
+ - "Cannot read properties of undefined (reading 'number')"
22
+ root_cause: |
23
+ When a workflow is triggered by on: workflow_run: and the upstream workflow
24
+ was triggered by a pull_request event from a fork, the
25
+ github.event.workflow_run.pull_requests array is deliberately empty ([]).
26
+
27
+ For same-repository PRs, the pull_requests array is populated with PR
28
+ metadata (number, head.sha, head.ref, base.ref, etc.). For fork PRs, it
29
+ is always an empty array for security reasons: GitHub does not expose PR
30
+ metadata from fork branches through this event payload to prevent
31
+ untrusted code from accessing repository information via the privileged
32
+ workflow_run context.
33
+
34
+ This is a known, by-design limitation (GitHub closed the tracker issue as
35
+ "not planned"). The result is that workflows designed to comment on PRs,
36
+ post status checks, or download artifacts using the PR number silently
37
+ fail or crash when run against fork-originated pull requests because
38
+ github.event.workflow_run.pull_requests[0].number evaluates to undefined.
39
+
40
+ The limitation is easy to miss during development because the workflow
41
+ works correctly for PRs from within the same organization — the failure
42
+ only appears when an external contributor opens a fork PR.
43
+ fix: |
44
+ Pass the required PR information as an artifact from the upstream
45
+ (untrusted) workflow to the downstream (privileged) workflow_run workflow.
46
+ The upstream workflow writes the PR number to a file and uploads it as
47
+ an artifact; the downstream workflow downloads the artifact and reads
48
+ the PR number from it.
49
+
50
+ This is the officially documented pattern for safe fork PR workflows.
51
+ fix_code:
52
+ - language: yaml
53
+ label: 'Upstream (untrusted) workflow — upload PR number as artifact'
54
+ code: |
55
+ # .github/workflows/pr-checks.yml (runs on pull_request, limited privileges)
56
+ name: PR Checks
57
+ on:
58
+ pull_request:
59
+
60
+ jobs:
61
+ test:
62
+ runs-on: ubuntu-latest
63
+ steps:
64
+ - uses: actions/checkout@v4
65
+ - run: echo "${{ github.event.number }}" > pr_number.txt
66
+ - uses: actions/upload-artifact@v4
67
+ with:
68
+ name: pr-number
69
+ path: pr_number.txt
70
+ - language: yaml
71
+ label: 'Downstream (privileged) workflow — download artifact to get PR number'
72
+ code: |
73
+ # .github/workflows/pr-comment.yml (runs on workflow_run, full privileges)
74
+ name: PR Comment
75
+ on:
76
+ workflow_run:
77
+ workflows: ["PR Checks"]
78
+ types: [completed]
79
+
80
+ jobs:
81
+ comment:
82
+ runs-on: ubuntu-latest
83
+ steps:
84
+ - name: Download PR number artifact
85
+ uses: actions/github-script@v7
86
+ with:
87
+ script: |
88
+ const artifacts = await github.rest.actions.listWorkflowRunArtifacts({
89
+ owner: context.repo.owner,
90
+ repo: context.repo.repo,
91
+ run_id: context.payload.workflow_run.id,
92
+ });
93
+ const prArtifact = artifacts.data.artifacts.find(a => a.name === 'pr-number');
94
+ if (!prArtifact) { core.setFailed('No pr-number artifact'); return; }
95
+ const download = await github.rest.actions.downloadArtifact({
96
+ owner: context.repo.owner,
97
+ repo: context.repo.repo,
98
+ artifact_id: prArtifact.id,
99
+ archive_format: 'zip',
100
+ });
101
+ require('fs').writeFileSync('pr_number.zip', Buffer.from(download.data));
102
+ - run: unzip pr_number.zip && echo "PR=$(cat pr_number.txt)" >> $GITHUB_ENV
103
+ - name: Post comment
104
+ uses: actions/github-script@v7
105
+ with:
106
+ script: |
107
+ await github.rest.issues.createComment({
108
+ owner: context.repo.owner,
109
+ repo: context.repo.repo,
110
+ issue_number: Number(process.env.PR),
111
+ body: 'Checks passed!'
112
+ });
113
+ prevention:
114
+ - "Always use the artifact-passing pattern for workflow_run workflows that need PR context — never assume github.event.workflow_run.pull_requests is populated."
115
+ - "Check the triggering event type: if github.event.workflow_run.event == 'pull_request' and the array is empty, the PR came from a fork."
116
+ - "Use github.event.workflow_run.head_branch and head_sha for correlating runs, but not for PR numbers (which are unavailable for forks)."
117
+ - "Consider using the gh-action-pr-number community action which handles the artifact-based lookup pattern automatically."
118
+ docs:
119
+ - url: 'https://github.com/actions/runner/issues/3444'
120
+ label: 'actions/runner #3444 — workflow_run from fork pull_request lacks pull_requests payload'
121
+ - url: 'https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#using-data-from-the-triggering-workflow'
122
+ label: 'GitHub Docs — Using data from the triggering workflow (artifact pattern)'
123
+ - url: 'https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_run'
124
+ label: 'GitHub Docs — workflow_run event reference'
@@ -0,0 +1,101 @@
1
+ id: permissions-auth-058
2
+ title: 'actions/checkout does not rewrite ssh:// submodule URLs — only git@github.com: format is rewritten'
3
+ category: permissions-auth
4
+ severity: error
5
+ tags:
6
+ - checkout
7
+ - submodules
8
+ - ssh
9
+ - gitmodules
10
+ - URL-rewriting
11
+ - host-key-verification
12
+ - ssh-key
13
+ patterns:
14
+ - regex: 'Host key verification failed'
15
+ flags: 'i'
16
+ - regex: 'ssh://.*Permission denied|ssh://.*Could not read from remote'
17
+ flags: 'i'
18
+ - regex: 'fatal: clone of .ssh://. into submodule path .* failed'
19
+ flags: 'i'
20
+ - regex: 'git@github\.com.*vs.*ssh://github\.com'
21
+ flags: 'i'
22
+ error_messages:
23
+ - "Host key verification failed."
24
+ - "fatal: Could not read from remote repository."
25
+ - "Please make sure you have the correct access rights and the repository exists."
26
+ - "fatal: clone of 'ssh://git@github.com/Org/SubRepo.git' into submodule path '<path>' failed"
27
+ root_cause: |
28
+ actions/checkout rewrites submodule URLs in .gitmodules to inject the
29
+ provided ssh-key or GITHUB_TOKEN credentials, but the rewriting logic only
30
+ handles the git@github.com: URL format. URLs using the alternative
31
+ ssh://git@github.com/ scheme are NOT rewritten and are passed to git
32
+ as-is.
33
+
34
+ When git attempts to clone an ssh:// URL without an SSH agent providing
35
+ the key, and without the runner having github.com in ~/.ssh/known_hosts,
36
+ the clone fails with "Host key verification failed." or permission errors.
37
+
38
+ The affected code path is actions/checkout/src/git-auth-helper.ts which
39
+ contains an explicit regex that only matches the git@ style:
40
+ /^git@github\.com:/
41
+ The ssh:// variant does not match, so the credential injection and
42
+ known_hosts population steps are skipped for those URLs.
43
+
44
+ This is a confirmed open bug with a pending fix (PR #2367), but as of
45
+ early 2026 it remains unmerged and unreleased.
46
+ fix: |
47
+ Convert all submodule URLs in .gitmodules from ssh:// to git@github.com:
48
+ format. This ensures actions/checkout's URL rewriting logic applies the
49
+ SSH key and adds the host key to known_hosts.
50
+
51
+ If you cannot change .gitmodules (e.g., the submodule is a third-party
52
+ repo), use a manual git config insteadOf URL rewrite in a pre-checkout
53
+ step to normalize the URL before the checkout action runs.
54
+ fix_code:
55
+ - language: bash
56
+ label: 'Option A — Change .gitmodules to use git@ format instead of ssh://'
57
+ code: |
58
+ # .gitmodules — BEFORE (broken)
59
+ [submodule "MySubrepo"]
60
+ path = MySubrepo
61
+ url = ssh://git@github.com/Org/MySubrepo.git
62
+
63
+ # .gitmodules — AFTER (working)
64
+ [submodule "MySubrepo"]
65
+ path = MySubrepo
66
+ url = git@github.com:Org/MySubrepo.git
67
+ - language: yaml
68
+ label: 'Option B — Add git config URL rewrite step before checkout'
69
+ code: |
70
+ steps:
71
+ - name: Rewrite ssh:// submodule URLs to git@ format
72
+ run: |
73
+ git config --global url."git@github.com:".insteadOf "ssh://git@github.com/"
74
+
75
+ - uses: actions/checkout@v4
76
+ with:
77
+ submodules: recursive
78
+ ssh-key: ${{ secrets.SSH_DEPLOY_KEY }}
79
+ - language: yaml
80
+ label: 'Option C — Use HTTPS with token for submodule auth (avoids SSH entirely)'
81
+ code: |
82
+ steps:
83
+ - uses: actions/checkout@v4
84
+ with:
85
+ submodules: recursive
86
+ token: ${{ secrets.PAT_WITH_SUBMODULE_ACCESS }}
87
+ # Requires .gitmodules to use https:// URLs
88
+ prevention:
89
+ - "Standardize on git@github.com: format for all .gitmodules URLs in repositories using actions/checkout with SSH keys."
90
+ - "Use HTTPS URLs with a PAT for submodule access when possible — this is simpler and avoids SSH host key issues entirely."
91
+ - "Add a linting step (e.g., grep .gitmodules for ssh://) to your repo's pre-commit hooks to catch the wrong URL format early."
92
+ - "Track actions/checkout PR #2367 for the fix; upgrade once it is merged and released."
93
+ docs:
94
+ - url: 'https://github.com/actions/checkout/issues/2178'
95
+ label: 'actions/checkout #2178 — ssh:// URLs in .gitmodules do not work'
96
+ - url: 'https://github.com/actions/checkout/pull/2367'
97
+ label: 'actions/checkout PR #2367 — Fix: also rewrite ssh:// URLs'
98
+ - url: 'https://github.com/actions/checkout/blob/main/src/git-auth-helper.ts'
99
+ label: 'actions/checkout git-auth-helper.ts — URL rewriting source code'
100
+ - url: 'https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/using-conditions-to-control-job-execution'
101
+ label: 'GitHub Docs — Checking out submodules'