From 6d4298ce55d4bde9a102cbb02ab96f2500d3257b Mon Sep 17 00:00:00 2001 From: Hector Flores Date: Wed, 10 Jun 2026 19:06:26 -0500 Subject: [PATCH] feat: add 3 new error entries (permissions-auth x1, runner-environment x2) --- ...t-config-global-env-breaks-placeholder.yml | 118 +++++++++++++++ ...-case-insensitive-branch-ref-collision.yml | 123 ++++++++++++++++ ...analytics-prompt-breaks-ui-focus-tests.yml | 134 ++++++++++++++++++ 3 files changed, 375 insertions(+) create mode 100644 errors/permissions-auth/checkout-global-auth-git-config-global-env-breaks-placeholder.yml create mode 100644 errors/runner-environment/checkout-windows-case-insensitive-branch-ref-collision.yml create mode 100644 errors/runner-environment/macos-15-arm64-analytics-prompt-breaks-ui-focus-tests.yml diff --git a/errors/permissions-auth/checkout-global-auth-git-config-global-env-breaks-placeholder.yml b/errors/permissions-auth/checkout-global-auth-git-config-global-env-breaks-placeholder.yml new file mode 100644 index 0000000..8952e73 --- /dev/null +++ b/errors/permissions-auth/checkout-global-auth-git-config-global-env-breaks-placeholder.yml @@ -0,0 +1,118 @@ +id: permissions-auth-111 +title: "actions/checkout Global Auth Fails with 'Unable to replace auth placeholder' When GIT_CONFIG_GLOBAL Is Set" +category: permissions-auth +severity: error +tags: + - checkout + - submodules + - GIT_CONFIG_GLOBAL + - git-config + - self-hosted + - auth + - credential + - persist-credentials +patterns: + - regex: 'Unable to replace auth placeholder in .+\.gitconfig' + flags: 'i' + - regex: 'configureTempGlobalConfig|replaceTokenPlaceholder' + flags: 'i' +error_messages: + - "##[error]Unable to replace auth placeholder in /home/runner/_temp//.gitconfig" + - "Unable to replace auth placeholder in /runner/_work/_temp/.gitconfig" +root_cause: | + When `GIT_CONFIG_GLOBAL` is set in the environment (a common practice on self-hosted runners + to isolate git configuration per job), `actions/checkout` fails to inject the GITHUB_TOKEN + credential into its temporary gitconfig, producing "Unable to replace auth placeholder". + + `checkout`'s `configureTempGlobalConfig` function works in three steps: + 1. Copy `~/.gitconfig` into a temporary directory and override `HOME` to point there. + 2. Run `git config --global` to write an auth token placeholder into the temp config. + 3. Read the temp config and replace the placeholder with the real token. + + The bug: **`GIT_CONFIG_GLOBAL` overrides `HOME`** when git resolves the global config file. + If `GIT_CONFIG_GLOBAL` is already set in the environment, step 2 writes the placeholder to + *that* external file instead of the temp config. Step 3 then reads the temp config, finds no + placeholder, and throws "Unable to replace auth placeholder in .../.gitconfig". + + This affects any checkout scenario that uses global auth — primarily `submodules: true` and + `persist-credentials: true` (the default) combined with `submodules`. The `HOME`-only override + predates v6 so it affects v4, v5, and v6 equally. + + Common trigger: self-hosted runner startup scripts that set + `GIT_CONFIG_GLOBAL=/shared/git/config` to isolate global git settings per job/runner. + Container-based runners that set `GIT_CONFIG_GLOBAL` in their base image are also affected. +fix: | + **Workaround (works today):** Unset `GIT_CONFIG_GLOBAL` in the checkout step's `env` block + so that checkout's `HOME` override takes effect: + + - uses: actions/checkout@v6 + with: + submodules: true + env: + GIT_CONFIG_GLOBAL: '' # unset so checkout's HOME override takes effect + + **Permanent fix:** A patch is open (actions/checkout#2449) that pins `GIT_CONFIG_GLOBAL` + to the temp config alongside the `HOME` override. Use the version that ships this fix once + it is merged and released. + + If you cannot modify the checkout step, as an alternative use `submodules: false` and + authenticate submodule access in a separate step after checkout. +fix_code: + - language: yaml + label: 'Broken: GIT_CONFIG_GLOBAL set by runner causes auth placeholder failure' + code: | + # Self-hosted runner has GIT_CONFIG_GLOBAL=/etc/gitconfig set in its environment. + # checkout writes the placeholder to /etc/gitconfig (via GIT_CONFIG_GLOBAL), + # then reads the temp config and finds no placeholder → error. + jobs: + build: + runs-on: self-hosted + steps: + - uses: actions/checkout@v6 + with: + submodules: true + # ERROR: "Unable to replace auth placeholder in /tmp/runner/_temp/.gitconfig" + - language: yaml + label: 'Fixed: unset GIT_CONFIG_GLOBAL in the checkout step env' + code: | + jobs: + build: + runs-on: self-hosted + steps: + - uses: actions/checkout@v6 + with: + submodules: true + env: + GIT_CONFIG_GLOBAL: '' # ← force checkout to use its own HOME override + # instead of the runner-injected global config + - language: yaml + label: 'Alternative: authenticate submodules separately without submodules: true' + code: | + jobs: + build: + runs-on: self-hosted + steps: + - uses: actions/checkout@v6 + with: + submodules: false + persist-credentials: true + + - name: Init and update submodules manually + run: | + git submodule init + git submodule update --recursive + env: + # Explicitly set the token for git operations in this step + GIT_CONFIG_GLOBAL: '' +prevention: + - "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`." + - "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." + - "Audit self-hosted runner startup scripts and container base images for `GIT_CONFIG_GLOBAL` — it is a common source of intermittent checkout credential failures." + - "Use `persist-credentials: false` on checkout steps that do not need long-lived credentials after checkout, to avoid global auth setup entirely." +docs: + - url: 'https://github.com/actions/checkout/issues/2449' + label: 'actions/checkout #2449 — GIT_CONFIG_GLOBAL override breaks global auth (configureTempGlobalConfig)' + - url: 'https://git-scm.com/docs/git-config#Documentation/git-config.txt-GIT_CONFIG_GLOBAL' + label: 'git-scm.com — GIT_CONFIG_GLOBAL env var: overrides the global config file location, takes precedence over $HOME/.gitconfig' + - url: 'https://docs.github.com/en/actions/security-for-github-actions/security-guides/using-secrets-in-github-actions' + label: 'GitHub Docs — Using secrets in GitHub Actions (credential management)' diff --git a/errors/runner-environment/checkout-windows-case-insensitive-branch-ref-collision.yml b/errors/runner-environment/checkout-windows-case-insensitive-branch-ref-collision.yml new file mode 100644 index 0000000..b9d2df3 --- /dev/null +++ b/errors/runner-environment/checkout-windows-case-insensitive-branch-ref-collision.yml @@ -0,0 +1,123 @@ +id: runner-environment-432 +title: "actions/checkout Fails on Windows When Repository Contains Branch Name Prefixes Differing Only by Case" +category: runner-environment +severity: error +tags: + - checkout + - windows + - case-insensitive + - git-refs + - branch-naming + - filesystem + - ntfs + - case-collision +patterns: + - regex: 'cannot lock ref.*exists.*cannot create' + flags: 'i' + - regex: 'fatal: cannot create.+directory.+[Ff]ile exists' + flags: 'i' + - regex: 'error: refs/remotes/origin/.+: cannot lock ref' + flags: 'i' +error_messages: + - "error: cannot lock ref 'refs/remotes/origin/Feature/tarun': 'refs/remotes/origin/feature' exists; cannot create 'refs/remotes/origin/Feature'" + - "fatal: cannot create directory at 'Feature': File exists." + - "error: Your local changes to the following files would be overwritten by checkout" +root_cause: | + On Windows runners, `actions/checkout` fails during the "Determining the checkout info" + or subsequent git fetch phase when the repository contains branch names whose path + components differ only by case — for example, `feature/manu` and `Feature/tarun`. + + The root cause is that Windows uses the NTFS filesystem, which is case-insensitive + (case-preserving but not case-sensitive). Git stores remote-tracking refs as directory + structures: `refs/remotes/origin/feature/` and `refs/remotes/origin/Feature/` would + map to the same directory on Windows. When git attempts to create both, the second + ref creation fails with a lock error or "cannot create directory" error. + + Linux runners are not affected because Linux filesystems (ext4, etc.) are case-sensitive + and can store both `feature/` and `Feature/` as distinct directories simultaneously. + + This is ultimately a Git-on-Windows limitation rather than an actions/checkout bug, but + checkout surfaces it as an opaque error during the checkout phase. The issue affects + any version of actions/checkout (v4, v5, v6) on Windows runners. + + Common branch naming patterns that trigger this issue: + - `feature/foo` and `Feature/bar` (mixed case in the directory component) + - `fix/issue-1` and `Fix/issue-2` + - `release/v1` and `Release/v2` +fix: | + The fix requires changing branch names in the repository to avoid case-only collisions + in path prefixes. On Windows, two branches cannot coexist if their path components + are identical when lowercased. + + **Option 1 (recommended):** Rename branches to use a consistent case convention. + Most teams standardize on all-lowercase branch prefixes: + + git branch -m Feature/tarun feature/tarun-2 + + **Option 2:** Run the Windows CI workflow only after avoiding the fetch of conflicting + refs using a sparse fetch: + + - uses: actions/checkout@v6 + with: + fetch-depth: 1 + # fetch-depth: 1 avoids fetching all remote refs, which may avoid the collision + + Note: this only helps if the checkout target branch is not itself one of the conflicting + refs. All remote-tracking refs are still fetched by default. + + **Option 3:** Run Windows CI on Linux or macOS where the case collision does not apply, + and file a repository convention to standardize branch name casing. +fix_code: + - language: yaml + label: 'Broken: repo has feature/manu and Feature/tarun — fails on Windows' + code: | + # This workflow fails on windows-latest when the repo has: + # branch: feature/manu + # branch: Feature/tarun + # Git cannot create both refs/remotes/origin/feature/ and + # refs/remotes/origin/Feature/ on Windows NTFS. + jobs: + build: + runs-on: windows-latest + steps: + - uses: actions/checkout@v6 + # ERROR on Windows: + # error: cannot lock ref 'refs/remotes/origin/Feature/tarun': + # 'refs/remotes/origin/feature' exists; cannot create 'refs/remotes/origin/Feature' + - language: yaml + label: 'Workaround: use fetch-depth: 1 to limit which remote refs are fetched' + code: | + jobs: + build: + runs-on: windows-latest + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 1 # fetch only the checked-out commit, not all remote refs + # This avoids fetching the conflicting case refs from origin. + # Note: git log history and other branch refs are unavailable. + - language: yaml + label: 'Fix: enforce lowercase branch naming convention via branch protection' + code: | + # In GitHub repository settings, add a branch name pattern rule that + # requires all new branches to match a lowercase pattern, preventing + # future case collisions: + # + # Repository Settings → Branches → Branch protection rules → Add rule + # Branch name pattern: [^A-Z]* (no uppercase letters allowed) + # + # To fix existing conflicting branches, rename them: + # git push origin :Feature/tarun # delete remote branch + # git push origin Feature/tarun:feature/tarun-v2 # recreate with lowercase +prevention: + - "Establish a branch naming convention that disallows uppercase letters in the path prefix component (e.g., always use `feature/`, never `Feature/`)." + - "Add a GitHub Actions workflow or branch protection rule that rejects branch names with uppercase in the prefix to prevent future case collisions." + - "Before migrating Windows runners into a repository's CI, audit branch names for case-insensitive prefix collisions using `git branch -r | sort -f`." + - "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." +docs: + - url: 'https://github.com/actions/checkout/issues/2448' + label: 'actions/checkout #2448 — checkout fails on Windows when branches differ only by case' + - url: 'https://git-scm.com/docs/git-fetch#Documentation/git-fetch.txt-ltrefspecgt' + label: 'git-scm.com — git fetch refspec: how remote-tracking refs are stored as directory trees' + - url: 'https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches' + label: 'GitHub Docs — Protected branches: enforcing naming conventions' diff --git a/errors/runner-environment/macos-15-arm64-analytics-prompt-breaks-ui-focus-tests.yml b/errors/runner-environment/macos-15-arm64-analytics-prompt-breaks-ui-focus-tests.yml new file mode 100644 index 0000000..4ce8f8d --- /dev/null +++ b/errors/runner-environment/macos-15-arm64-analytics-prompt-breaks-ui-focus-tests.yml @@ -0,0 +1,134 @@ +id: runner-environment-431 +title: "macOS 15 Arm64 Runner Shows Analytics Setup Prompt — Breaks UI Focus-Dependent Tests" +category: runner-environment +severity: error +tags: + - macos + - macos-15 + - analytics + - arm64 + - electron + - ui-tests + - focus + - prompt + - runner-image + - regression +patterns: + - regex: 'runs-on:\s*macos-15' + flags: 'i' + - regex: 'macos-15[-_]arm64' + flags: 'i' + - regex: 'BrowserWindow.*focus|element.*not.*interactable.*macos' + flags: 'si' +error_messages: + - "Error: BrowserWindow can't grab focus on macos-15-arm64 runner" + - "element not interactable: Element is not reachable by keyboard" + - "Accessibility test failed: application window does not have focus" + - "osascript: unable to activate application: window focus stolen by system dialog" +root_cause: | + Starting with macOS 15 arm64 runner image version `20260520.0085.1`, a macOS system dialog + prompts to "Set Up Analytics" (or a similar OS-level analytics/privacy onboarding prompt) + when the runner VM session starts. This dialog appears in the foreground, captures keyboard + focus, and causes any CI test that requires the foreground window or keyboard/mouse focus + to fail. + + Affected test categories include: + - Electron app tests using `BrowserWindow.focus()` or any call that expects the app window + to have foreground focus + - Eclipse IDE tests (confirmed: Eclipse GEF, Eclipse SWT) + - Browser-based UI tests using focus APIs (`element.focus()`, `sendKeys`, etc.) + - Screenshot-based or accessibility tests that depend on the active window + - Any test using macOS accessibility APIs or `osascript` to interact with windows + + The prompt behavior is a regression introduced in image `20260520.0085.1` on + macOS 15 arm64. Image version `20260428.0039.1` and earlier did not show this prompt. + macOS 14 (arm64), macOS 26, and all x64 macOS runners are **not** affected. + + Multiple major projects confirmed the regression: + - GitHub Electron (actions/runs/26368726651) + - Eclipse GEF (eclipse-gef/gef-classic#1123) + - Eclipse SWT (eclipse-platform/eclipse.platform.swt#3327) +fix: | + **Option 1 (recommended):** Add a step to dismiss the macOS Analytics prompt + programmatically before running UI tests: + + - name: Dismiss macOS system prompts (prevents focus theft in UI tests) + run: | + osascript -e 'tell application "System Events" to key code 53' 2>/dev/null || true + sleep 1 + + `key code 53` is the Escape key — pressing Escape dismisses the Analytics/privacy dialog. + Adding `|| true` prevents the step from failing if no dialog is present. + + **Option 2:** Switch to macOS 14 or macOS 26 (neither is affected by this regression): + + runs-on: macos-14 # or: macos-26 + + Note: `macos-latest` will switch to macOS 26 in mid-June 2026, which also avoids + the regression. + + **Option 3:** If your workflow specifically requires macOS 15 and you cannot switch, + disable analytics at the system level in a setup step: + + - name: Disable macOS analytics (prevents prompts) + run: | + defaults write com.apple.assistant.support 'Assistant Enabled' -bool false + defaults write com.apple.SubmitDiagInfo AutoSubmit -bool false +fix_code: + - language: yaml + label: 'Workaround: dismiss the Analytics prompt before UI tests' + code: | + jobs: + test: + runs-on: macos-15 + steps: + - uses: actions/checkout@v6 + + - name: Dismiss macOS system prompts (prevents focus theft in UI tests) + run: | + # Dismiss analytics/setup dialogs introduced in image 20260520.0085.1 + osascript -e 'tell application "System Events" to key code 53' 2>/dev/null || true + sleep 1 # allow the dismiss to take effect + + - name: Run UI tests + run: npm test # or your test command + - language: yaml + label: 'Workaround: switch to macOS 14 or macOS 26 (unaffected runners)' + code: | + jobs: + test: + # macOS 14 arm64 and macOS 26 do not show the Analytics prompt + runs-on: macos-14 # or: runs-on: macos-26 + steps: + - uses: actions/checkout@v6 + - name: Run UI tests + run: npm test + - language: yaml + label: 'Workaround: disable analytics via defaults write in setup step' + code: | + jobs: + test: + runs-on: macos-15 + steps: + - uses: actions/checkout@v6 + + - name: Disable macOS analytics (prevents onboarding prompts from appearing) + run: | + defaults write com.apple.assistant.support 'Assistant Enabled' -bool false + defaults write com.apple.SubmitDiagInfo AutoSubmit -bool false + defaults write com.apple.PrivacyPreferences OptedOutForDiagnosticSubmission -bool true + + - name: Run UI tests + run: npm test +prevention: + - "If your macOS 15 CI runs UI tests that require window focus, always add a prompt-dismissal step before the test runner." + - "Monitor the actions/runner-images issue tracker for macOS image regressions — subscribe to announcements before major image version bumps." + - "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." + - "Pin a specific macOS image version in your runner config if you need to reproduce test failures across image versions." +docs: + - url: 'https://github.com/actions/runner-images/issues/14161' + label: 'actions/runner-images #14161 — macOS 15 arm64 runner shows Analytics prompt (regression since 20260520.0085.1)' + - url: 'https://github.com/electron/electron/actions/runs/26368726651/job/77802729527' + label: 'Electron CI example run — tests fail due to Analytics prompt stealing focus' + - url: 'https://github.com/eclipse-gef/gef-classic/issues/1123' + label: 'Eclipse GEF — several IDE tests fail on macOS due to Analytics prompt'