Skip to content

Run workspace-side mirror git commands with the checkout's git environment; adopt mirrors owned by another user - #53

Merged
piob-io merged 5 commits into
mainfrom
devin/1788902699-dissociate-safe-directory
Sep 9, 2026
Merged

piob-io merged 5 commits into
mainfrom
devin/1788902699-dissociate-safe-directory

Conversation

@piob-io

@piob-io piob-io commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Summary

Bug. In a job container (allow-inside-container: true, --privileged -v /dev:/dev) the runner creates /__w/<repo>/<repo> as the VM's runner user while the action runs git as root. The action handles that for its own commands by adding the workspace as safe.directory to a temporary global config and pointing the GitCommandManager's HOME at it. Two mirror-related paths in blacksmith-cache.ts ran git through @actions/exec with the plain process environment instead, so they never saw that config:

  • dissociate()git -C <workspace> repack -a -dfatal: detected dubious ownership in repository → exit 128 → checkout step fails whenever a mirror is mounted and dissociate: true is set on a top-level container checkout. (Sub-path checkouts pass only because the action creates that directory itself.)
  • copyRefsFromMirror() (fetch-depth: 0) — the workspace config/for-each-ref/update-ref/pack-refs calls fail the same way and silently fall back to the local fetch.

-c safe.directory=… is not a fix: git rejects it from the command line (it must come from a global/system config), verified on 2.34 — only the HOME route works.

Fix.

interface IGitCommandManager {
  getEnvironment(): {[key: string]: string}   // process.env + gitEnv (HOME override, GIT_TERMINAL_PROMPT, …)
}

fetchRefsFromMirror(workspacePath, mirrorPath, env?)   // → copyRefsFromMirror(…, env), local-fetch fallback
dissociate(workspacePath, env?)

git-source-provider.ts passes git.getEnvironment() to both. execGit now builds its env through the same method.

Related: mirror ownership. The same job mix (root container jobs and runner-user VM jobs) shares one sticky-disk mirror. A mirror hydrated by the other kind of job is dubiously owned to git and, for the runner user, not even writable, so every mirror sync/ref read would fail (fallback to network, no commit) until re-hydrated. ensureMirror now checks stat(mirrorPath).uid on an existing mirror and sudo chown -R the mirror dir to the current user when it differs (adoptMirrorOwnership, logged with duration; no-op in the common single-user case).

CI (test-blacksmith.yml).

  • test-git-mirror-container: runs-on: blacksmith with container: ubuntu:24.04, --privileged -v /dev:/dev, checking out as root with allow-inside-container: true + dissociate: true into a directory chown --reference=.'d to the runner user (same ownership check as the workspace root — git ≥2.36 checks the worktree owner — without wiping the local action, whose problem-matcher.json the runner reads asynchronously). Asserts the sticky disk is actually mounted in the container, the mirror ended up root-owned (taken over from uid 1001), alternates gone, HEAD == GITHUB_SHA, fsck clean. Fails on main with the dubious-ownership error.
  • test-git-mirror-after-container: VM job needs-chained after it — mirror runner-owned and used. Only a real takeover once a trusted-trigger (push to main) container job has committed a root-owned mirror; each checkout step mounts its own copy of the last commit, so ownership can't be flipped between steps of one job.

End-to-end control-vs-candidate on staging runners: useblacksmith/test-workflows#217.

Test. __test__/mirror-workspace-env-git.test.ts uses git's GIT_TEST_ASSUME_DIFFERENT_OWNER=1 to make a real workspace foreign-owned and a temp HOME/.gitconfig with safe.directory = <workspace>: dissociate with the plain env fails with exit 128 (the bug), and fetchRefsFromMirror + dissociate with the checkout env succeed and leave a self-contained workspace (fsck after deleting the mirror). Skipped on git builds without the knob.

dist/ rebuilt.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled. (Staging)

Link to Devin session: https://app.devin.ai/sessions/a3b42ef15226438faf3f9cdde9662918
Open in Devin Desktop: https://app.devin.ai/desktop/session/a3b42ef15226438faf3f9cdde9662918?variant=devin
Requested by: @piob-io

…nment; adopt mirrors owned by another user

In a job container the runner creates the workspace as the VM user while
the action runs git as root. The action marks the workspace as a
safe.directory in a temporary global config that only the git command
manager's environment (HOME override) points at. dissociate's
`git repack -a -d` and the mirror ref copy ran git with the plain
process environment, so git rejected the workspace as dubiously owned:
dissociate failed the checkout step outright, and the ref copy silently
fell back to a local fetch.

Both now receive IGitCommandManager.getEnvironment(). A shared sticky-disk
mirror can likewise have been hydrated by a job running as another user
(root container vs. runner VM); ensureMirror now chowns it to the current
user before it is read or synced.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

piob-io and others added 3 commits September 9, 2026 12:43
…ksmith runners

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…f the workspace root

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 9248df6. Configure here.

Comment thread .github/workflows/test-blacksmith.yml Outdated
Comment thread .github/workflows/test-blacksmith.yml
…es the in-job chown (each step mounts a fresh copy)

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@piob-io
piob-io merged commit 0647fdb into main Sep 9, 2026
18 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants