Fix git config failures when HOME is unreadable with FF_GIT_URLS_WITHOUT_TOKENS enabled

What does this MR do?

With FF_GIT_URLS_WITHOUT_TOKENS enabled, the GIT_CONFIG_GLOBAL seed file includes $HOME/.gitconfig and $HOME/.config/git/config unconditionally. git skips an unreadable global config silently (ACCESS_EACCES_OK, since v1.8.3.1) but dies on an unreadable include.path target. In a non-root container that keeps HOME=/root (the Kubernetes default: HOME is not derived from the security context user), access() returns EACCES even though /root/.gitconfig does not exist, so every git invocation fails with fatal: unable to access '/root/.gitconfig': Permission denied and the job dies during Getting source from Git repository.

This MR emits each $HOME include behind a new ShellWriter conditional, IfFileReadable:

  • [ -r ] in bash
  • [System.IO.File]::OpenRead in PowerShell

A readable config is included as before, and git config --global writes keep landing in the seed file. A troubleshooting entry keyed on the error messages points to the existing writable HOME recipe.

Why was this MR needed?

Regression introduced in 19.2.0 by !6729 (merged). The failure hits the seeding sequence itself: GIT_CONFIG_GLOBAL is exported before the seed is written, so the second of the git config --file calls that write the seed re-reads the half-written file and exits 128 before get_sources produces any output.

What's the best way to test this MR?

Unit and integration tests:

go test ./shells/ -run 'IfFileReadable|SetupGlobalGitConfigSeed'
go test -tags=integration ./shells/ -run TestIfFileReadable

End-to-end with the docker executor, where a non-root build container keeps HOME=/root, a 0700 directory it cannot read:

[[runners]]
  executor = "docker"
  [runners.docker]
    user = "1000"
  [runners.feature_flags]
    FF_GIT_URLS_WITHOUT_TOKENS = true
job:
  image:
    name: alpine/git
    entrypoint: [""]
  variables:
    HOME: /root
  script:
    - git config --global user.name example

Before, the script step exits 128 on fatal: unable to access '/root/.gitconfig': Permission denied. After, it passes. Here the failure surfaces in the job script rather than during checkout, because get_sources runs in the helper container, which is root and reads /root fine.

The same before and after was verified on the shell executor, where the failure does land during Getting source from Git repository, against a 19.2 baseline built from this branch point. The conditional is exercised on bash, PowerShell, and pwsh, including a permission-denied case that removes read access from a file (an ACL deny on Windows, a mode change on Linux) and asserts the guard skips the unreadable file. It was also checked over SSH to a Windows target.

What are the relevant issue numbers?

Closes #39617 (closed)
Related #37408, #26618
MR !7003, !7019 (closed)
The docs entry is the one planned in #37408.

Edited by Guillaume Chauvel

Merge request reports

Loading