Skip to content

Commit 4ea9ec3

Browse files
authored
feat: add 3 new error entries (permissions-auth x1, runner-environment x2) (#355)
1 parent a008731 commit 4ea9ec3

3 files changed

Lines changed: 375 additions & 0 deletions

File tree

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
id: permissions-auth-111
2+
title: "actions/checkout Global Auth Fails with 'Unable to replace auth placeholder' When GIT_CONFIG_GLOBAL Is Set"
3+
category: permissions-auth
4+
severity: error
5+
tags:
6+
- checkout
7+
- submodules
8+
- GIT_CONFIG_GLOBAL
9+
- git-config
10+
- self-hosted
11+
- auth
12+
- credential
13+
- persist-credentials
14+
patterns:
15+
- regex: 'Unable to replace auth placeholder in .+\.gitconfig'
16+
flags: 'i'
17+
- regex: 'configureTempGlobalConfig|replaceTokenPlaceholder'
18+
flags: 'i'
19+
error_messages:
20+
- "##[error]Unable to replace auth placeholder in /home/runner/_temp/<uuid>/.gitconfig"
21+
- "Unable to replace auth placeholder in /runner/_work/_temp/.gitconfig"
22+
root_cause: |
23+
When `GIT_CONFIG_GLOBAL` is set in the environment (a common practice on self-hosted runners
24+
to isolate git configuration per job), `actions/checkout` fails to inject the GITHUB_TOKEN
25+
credential into its temporary gitconfig, producing "Unable to replace auth placeholder".
26+
27+
`checkout`'s `configureTempGlobalConfig` function works in three steps:
28+
1. Copy `~/.gitconfig` into a temporary directory and override `HOME` to point there.
29+
2. Run `git config --global` to write an auth token placeholder into the temp config.
30+
3. Read the temp config and replace the placeholder with the real token.
31+
32+
The bug: **`GIT_CONFIG_GLOBAL` overrides `HOME`** when git resolves the global config file.
33+
If `GIT_CONFIG_GLOBAL` is already set in the environment, step 2 writes the placeholder to
34+
*that* external file instead of the temp config. Step 3 then reads the temp config, finds no
35+
placeholder, and throws "Unable to replace auth placeholder in .../.gitconfig".
36+
37+
This affects any checkout scenario that uses global auth — primarily `submodules: true` and
38+
`persist-credentials: true` (the default) combined with `submodules`. The `HOME`-only override
39+
predates v6 so it affects v4, v5, and v6 equally.
40+
41+
Common trigger: self-hosted runner startup scripts that set
42+
`GIT_CONFIG_GLOBAL=/shared/git/config` to isolate global git settings per job/runner.
43+
Container-based runners that set `GIT_CONFIG_GLOBAL` in their base image are also affected.
44+
fix: |
45+
**Workaround (works today):** Unset `GIT_CONFIG_GLOBAL` in the checkout step's `env` block
46+
so that checkout's `HOME` override takes effect:
47+
48+
- uses: actions/checkout@v6
49+
with:
50+
submodules: true
51+
env:
52+
GIT_CONFIG_GLOBAL: '' # unset so checkout's HOME override takes effect
53+
54+
**Permanent fix:** A patch is open (actions/checkout#2449) that pins `GIT_CONFIG_GLOBAL`
55+
to the temp config alongside the `HOME` override. Use the version that ships this fix once
56+
it is merged and released.
57+
58+
If you cannot modify the checkout step, as an alternative use `submodules: false` and
59+
authenticate submodule access in a separate step after checkout.
60+
fix_code:
61+
- language: yaml
62+
label: 'Broken: GIT_CONFIG_GLOBAL set by runner causes auth placeholder failure'
63+
code: |
64+
# Self-hosted runner has GIT_CONFIG_GLOBAL=/etc/gitconfig set in its environment.
65+
# checkout writes the placeholder to /etc/gitconfig (via GIT_CONFIG_GLOBAL),
66+
# then reads the temp config and finds no placeholder → error.
67+
jobs:
68+
build:
69+
runs-on: self-hosted
70+
steps:
71+
- uses: actions/checkout@v6
72+
with:
73+
submodules: true
74+
# ERROR: "Unable to replace auth placeholder in /tmp/runner/_temp/.gitconfig"
75+
- language: yaml
76+
label: 'Fixed: unset GIT_CONFIG_GLOBAL in the checkout step env'
77+
code: |
78+
jobs:
79+
build:
80+
runs-on: self-hosted
81+
steps:
82+
- uses: actions/checkout@v6
83+
with:
84+
submodules: true
85+
env:
86+
GIT_CONFIG_GLOBAL: '' # ← force checkout to use its own HOME override
87+
# instead of the runner-injected global config
88+
- language: yaml
89+
label: 'Alternative: authenticate submodules separately without submodules: true'
90+
code: |
91+
jobs:
92+
build:
93+
runs-on: self-hosted
94+
steps:
95+
- uses: actions/checkout@v6
96+
with:
97+
submodules: false
98+
persist-credentials: true
99+
100+
- name: Init and update submodules manually
101+
run: |
102+
git submodule init
103+
git submodule update --recursive
104+
env:
105+
# Explicitly set the token for git operations in this step
106+
GIT_CONFIG_GLOBAL: ''
107+
prevention:
108+
- "If your self-hosted runner sets `GIT_CONFIG_GLOBAL` in the environment (e.g. via /etc/environment or a container base image), always add `env: { GIT_CONFIG_GLOBAL: '' }` to checkout steps that use `submodules: true`."
109+
- "The error 'Unable to replace auth placeholder in .../.gitconfig' always indicates a `GIT_CONFIG_GLOBAL` conflict — it never means the GITHUB_TOKEN is missing or invalid."
110+
- "Audit self-hosted runner startup scripts and container base images for `GIT_CONFIG_GLOBAL` — it is a common source of intermittent checkout credential failures."
111+
- "Use `persist-credentials: false` on checkout steps that do not need long-lived credentials after checkout, to avoid global auth setup entirely."
112+
docs:
113+
- url: 'https://github.com/actions/checkout/issues/2449'
114+
label: 'actions/checkout #2449 — GIT_CONFIG_GLOBAL override breaks global auth (configureTempGlobalConfig)'
115+
- url: 'https://git-scm.com/docs/git-config#Documentation/git-config.txt-GIT_CONFIG_GLOBAL'
116+
label: 'git-scm.com — GIT_CONFIG_GLOBAL env var: overrides the global config file location, takes precedence over $HOME/.gitconfig'
117+
- url: 'https://docs.github.com/en/actions/security-for-github-actions/security-guides/using-secrets-in-github-actions'
118+
label: 'GitHub Docs — Using secrets in GitHub Actions (credential management)'
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
id: runner-environment-432
2+
title: "actions/checkout Fails on Windows When Repository Contains Branch Name Prefixes Differing Only by Case"
3+
category: runner-environment
4+
severity: error
5+
tags:
6+
- checkout
7+
- windows
8+
- case-insensitive
9+
- git-refs
10+
- branch-naming
11+
- filesystem
12+
- ntfs
13+
- case-collision
14+
patterns:
15+
- regex: 'cannot lock ref.*exists.*cannot create'
16+
flags: 'i'
17+
- regex: 'fatal: cannot create.+directory.+[Ff]ile exists'
18+
flags: 'i'
19+
- regex: 'error: refs/remotes/origin/.+: cannot lock ref'
20+
flags: 'i'
21+
error_messages:
22+
- "error: cannot lock ref 'refs/remotes/origin/Feature/tarun': 'refs/remotes/origin/feature' exists; cannot create 'refs/remotes/origin/Feature'"
23+
- "fatal: cannot create directory at 'Feature': File exists."
24+
- "error: Your local changes to the following files would be overwritten by checkout"
25+
root_cause: |
26+
On Windows runners, `actions/checkout` fails during the "Determining the checkout info"
27+
or subsequent git fetch phase when the repository contains branch names whose path
28+
components differ only by case — for example, `feature/manu` and `Feature/tarun`.
29+
30+
The root cause is that Windows uses the NTFS filesystem, which is case-insensitive
31+
(case-preserving but not case-sensitive). Git stores remote-tracking refs as directory
32+
structures: `refs/remotes/origin/feature/` and `refs/remotes/origin/Feature/` would
33+
map to the same directory on Windows. When git attempts to create both, the second
34+
ref creation fails with a lock error or "cannot create directory" error.
35+
36+
Linux runners are not affected because Linux filesystems (ext4, etc.) are case-sensitive
37+
and can store both `feature/` and `Feature/` as distinct directories simultaneously.
38+
39+
This is ultimately a Git-on-Windows limitation rather than an actions/checkout bug, but
40+
checkout surfaces it as an opaque error during the checkout phase. The issue affects
41+
any version of actions/checkout (v4, v5, v6) on Windows runners.
42+
43+
Common branch naming patterns that trigger this issue:
44+
- `feature/foo` and `Feature/bar` (mixed case in the directory component)
45+
- `fix/issue-1` and `Fix/issue-2`
46+
- `release/v1` and `Release/v2`
47+
fix: |
48+
The fix requires changing branch names in the repository to avoid case-only collisions
49+
in path prefixes. On Windows, two branches cannot coexist if their path components
50+
are identical when lowercased.
51+
52+
**Option 1 (recommended):** Rename branches to use a consistent case convention.
53+
Most teams standardize on all-lowercase branch prefixes:
54+
55+
git branch -m Feature/tarun feature/tarun-2
56+
57+
**Option 2:** Run the Windows CI workflow only after avoiding the fetch of conflicting
58+
refs using a sparse fetch:
59+
60+
- uses: actions/checkout@v6
61+
with:
62+
fetch-depth: 1
63+
# fetch-depth: 1 avoids fetching all remote refs, which may avoid the collision
64+
65+
Note: this only helps if the checkout target branch is not itself one of the conflicting
66+
refs. All remote-tracking refs are still fetched by default.
67+
68+
**Option 3:** Run Windows CI on Linux or macOS where the case collision does not apply,
69+
and file a repository convention to standardize branch name casing.
70+
fix_code:
71+
- language: yaml
72+
label: 'Broken: repo has feature/manu and Feature/tarun — fails on Windows'
73+
code: |
74+
# This workflow fails on windows-latest when the repo has:
75+
# branch: feature/manu
76+
# branch: Feature/tarun
77+
# Git cannot create both refs/remotes/origin/feature/ and
78+
# refs/remotes/origin/Feature/ on Windows NTFS.
79+
jobs:
80+
build:
81+
runs-on: windows-latest
82+
steps:
83+
- uses: actions/checkout@v6
84+
# ERROR on Windows:
85+
# error: cannot lock ref 'refs/remotes/origin/Feature/tarun':
86+
# 'refs/remotes/origin/feature' exists; cannot create 'refs/remotes/origin/Feature'
87+
- language: yaml
88+
label: 'Workaround: use fetch-depth: 1 to limit which remote refs are fetched'
89+
code: |
90+
jobs:
91+
build:
92+
runs-on: windows-latest
93+
steps:
94+
- uses: actions/checkout@v6
95+
with:
96+
fetch-depth: 1 # fetch only the checked-out commit, not all remote refs
97+
# This avoids fetching the conflicting case refs from origin.
98+
# Note: git log history and other branch refs are unavailable.
99+
- language: yaml
100+
label: 'Fix: enforce lowercase branch naming convention via branch protection'
101+
code: |
102+
# In GitHub repository settings, add a branch name pattern rule that
103+
# requires all new branches to match a lowercase pattern, preventing
104+
# future case collisions:
105+
#
106+
# Repository Settings → Branches → Branch protection rules → Add rule
107+
# Branch name pattern: [^A-Z]* (no uppercase letters allowed)
108+
#
109+
# To fix existing conflicting branches, rename them:
110+
# git push origin :Feature/tarun # delete remote branch
111+
# git push origin Feature/tarun:feature/tarun-v2 # recreate with lowercase
112+
prevention:
113+
- "Establish a branch naming convention that disallows uppercase letters in the path prefix component (e.g., always use `feature/`, never `Feature/`)."
114+
- "Add a GitHub Actions workflow or branch protection rule that rejects branch names with uppercase in the prefix to prevent future case collisions."
115+
- "Before migrating Windows runners into a repository's CI, audit branch names for case-insensitive prefix collisions using `git branch -r | sort -f`."
116+
- "If your repository may have case-conflicting branches (e.g., from contributors on macOS/Linux who don't notice), use `fetch-depth: 1` on Windows checkout steps to reduce the risk."
117+
docs:
118+
- url: 'https://github.com/actions/checkout/issues/2448'
119+
label: 'actions/checkout #2448 — checkout fails on Windows when branches differ only by case'
120+
- url: 'https://git-scm.com/docs/git-fetch#Documentation/git-fetch.txt-ltrefspecgt'
121+
label: 'git-scm.com — git fetch refspec: how remote-tracking refs are stored as directory trees'
122+
- url: 'https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches'
123+
label: 'GitHub Docs — Protected branches: enforcing naming conventions'
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
id: runner-environment-431
2+
title: "macOS 15 Arm64 Runner Shows Analytics Setup Prompt — Breaks UI Focus-Dependent Tests"
3+
category: runner-environment
4+
severity: error
5+
tags:
6+
- macos
7+
- macos-15
8+
- analytics
9+
- arm64
10+
- electron
11+
- ui-tests
12+
- focus
13+
- prompt
14+
- runner-image
15+
- regression
16+
patterns:
17+
- regex: 'runs-on:\s*macos-15'
18+
flags: 'i'
19+
- regex: 'macos-15[-_]arm64'
20+
flags: 'i'
21+
- regex: 'BrowserWindow.*focus|element.*not.*interactable.*macos'
22+
flags: 'si'
23+
error_messages:
24+
- "Error: BrowserWindow can't grab focus on macos-15-arm64 runner"
25+
- "element not interactable: Element is not reachable by keyboard"
26+
- "Accessibility test failed: application window does not have focus"
27+
- "osascript: unable to activate application: window focus stolen by system dialog"
28+
root_cause: |
29+
Starting with macOS 15 arm64 runner image version `20260520.0085.1`, a macOS system dialog
30+
prompts to "Set Up Analytics" (or a similar OS-level analytics/privacy onboarding prompt)
31+
when the runner VM session starts. This dialog appears in the foreground, captures keyboard
32+
focus, and causes any CI test that requires the foreground window or keyboard/mouse focus
33+
to fail.
34+
35+
Affected test categories include:
36+
- Electron app tests using `BrowserWindow.focus()` or any call that expects the app window
37+
to have foreground focus
38+
- Eclipse IDE tests (confirmed: Eclipse GEF, Eclipse SWT)
39+
- Browser-based UI tests using focus APIs (`element.focus()`, `sendKeys`, etc.)
40+
- Screenshot-based or accessibility tests that depend on the active window
41+
- Any test using macOS accessibility APIs or `osascript` to interact with windows
42+
43+
The prompt behavior is a regression introduced in image `20260520.0085.1` on
44+
macOS 15 arm64. Image version `20260428.0039.1` and earlier did not show this prompt.
45+
macOS 14 (arm64), macOS 26, and all x64 macOS runners are **not** affected.
46+
47+
Multiple major projects confirmed the regression:
48+
- GitHub Electron (actions/runs/26368726651)
49+
- Eclipse GEF (eclipse-gef/gef-classic#1123)
50+
- Eclipse SWT (eclipse-platform/eclipse.platform.swt#3327)
51+
fix: |
52+
**Option 1 (recommended):** Add a step to dismiss the macOS Analytics prompt
53+
programmatically before running UI tests:
54+
55+
- name: Dismiss macOS system prompts (prevents focus theft in UI tests)
56+
run: |
57+
osascript -e 'tell application "System Events" to key code 53' 2>/dev/null || true
58+
sleep 1
59+
60+
`key code 53` is the Escape key — pressing Escape dismisses the Analytics/privacy dialog.
61+
Adding `|| true` prevents the step from failing if no dialog is present.
62+
63+
**Option 2:** Switch to macOS 14 or macOS 26 (neither is affected by this regression):
64+
65+
runs-on: macos-14 # or: macos-26
66+
67+
Note: `macos-latest` will switch to macOS 26 in mid-June 2026, which also avoids
68+
the regression.
69+
70+
**Option 3:** If your workflow specifically requires macOS 15 and you cannot switch,
71+
disable analytics at the system level in a setup step:
72+
73+
- name: Disable macOS analytics (prevents prompts)
74+
run: |
75+
defaults write com.apple.assistant.support 'Assistant Enabled' -bool false
76+
defaults write com.apple.SubmitDiagInfo AutoSubmit -bool false
77+
fix_code:
78+
- language: yaml
79+
label: 'Workaround: dismiss the Analytics prompt before UI tests'
80+
code: |
81+
jobs:
82+
test:
83+
runs-on: macos-15
84+
steps:
85+
- uses: actions/checkout@v6
86+
87+
- name: Dismiss macOS system prompts (prevents focus theft in UI tests)
88+
run: |
89+
# Dismiss analytics/setup dialogs introduced in image 20260520.0085.1
90+
osascript -e 'tell application "System Events" to key code 53' 2>/dev/null || true
91+
sleep 1 # allow the dismiss to take effect
92+
93+
- name: Run UI tests
94+
run: npm test # or your test command
95+
- language: yaml
96+
label: 'Workaround: switch to macOS 14 or macOS 26 (unaffected runners)'
97+
code: |
98+
jobs:
99+
test:
100+
# macOS 14 arm64 and macOS 26 do not show the Analytics prompt
101+
runs-on: macos-14 # or: runs-on: macos-26
102+
steps:
103+
- uses: actions/checkout@v6
104+
- name: Run UI tests
105+
run: npm test
106+
- language: yaml
107+
label: 'Workaround: disable analytics via defaults write in setup step'
108+
code: |
109+
jobs:
110+
test:
111+
runs-on: macos-15
112+
steps:
113+
- uses: actions/checkout@v6
114+
115+
- name: Disable macOS analytics (prevents onboarding prompts from appearing)
116+
run: |
117+
defaults write com.apple.assistant.support 'Assistant Enabled' -bool false
118+
defaults write com.apple.SubmitDiagInfo AutoSubmit -bool false
119+
defaults write com.apple.PrivacyPreferences OptedOutForDiagnosticSubmission -bool true
120+
121+
- name: Run UI tests
122+
run: npm test
123+
prevention:
124+
- "If your macOS 15 CI runs UI tests that require window focus, always add a prompt-dismissal step before the test runner."
125+
- "Monitor the actions/runner-images issue tracker for macOS image regressions — subscribe to announcements before major image version bumps."
126+
- "Consider switching to `macos-26` instead of `macos-15` for new pipelines; macOS 26 is unaffected and will become the `macos-latest` default in June 2026."
127+
- "Pin a specific macOS image version in your runner config if you need to reproduce test failures across image versions."
128+
docs:
129+
- url: 'https://github.com/actions/runner-images/issues/14161'
130+
label: 'actions/runner-images #14161 — macOS 15 arm64 runner shows Analytics prompt (regression since 20260520.0085.1)'
131+
- url: 'https://github.com/electron/electron/actions/runs/26368726651/job/77802729527'
132+
label: 'Electron CI example run — tests fail due to Analytics prompt stealing focus'
133+
- url: 'https://github.com/eclipse-gef/gef-classic/issues/1123'
134+
label: 'Eclipse GEF — several IDE tests fail on macOS due to Analytics prompt'

0 commit comments

Comments
 (0)