Skip to content

Commit 55169a8

Browse files
authored
Merge pull request #414 from konard/issue-413-cb2a359e0ffa
fix(entrypoint): clone into dev home for tilde TARGET_DIR (empty app folder)
2 parents 6ce2105 + 6e2e0bf commit 55169a8

3 files changed

Lines changed: 49 additions & 2 deletions

File tree

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
"@prover-coder-ai/docker-git": patch
3+
---
4+
5+
Fix `docker-git clone` leaving the workspace `app` folder empty when `TARGET_DIR`
6+
is a tilde path.
7+
8+
The generated entrypoint runs as `root` (sshd), so `$HOME` resolves to `/root`.
9+
When a `~`/`~/...` `TARGET_DIR` reached the entrypoint (e.g. via the `TARGET_DIR`
10+
env override), it was expanded against `$HOME`, resolving to `/root/app`. Because
11+
the auto-clone runs as `su - <sshUser>`, cloning into the root-owned `/root/app`
12+
failed with "permission denied", so the repository never landed in the prepared
13+
home and the workspace `app` folder stayed empty. The tilde is now expanded
14+
against the unprivileged user's home `/home/<sshUser>`, so the clone always lands
15+
in the dev-owned workspace.

packages/container/src/core/templates-entrypoint/base.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ REPO_REF="\${REPO_REF:-}"
1717
FORK_REPO_URL="\${FORK_REPO_URL:-}"
1818
${renderTargetDirDefault(config)}
1919
if [[ "$TARGET_DIR" == "~" ]]; then
20-
TARGET_DIR="$HOME"
20+
TARGET_DIR="/home/${config.sshUser}"
2121
elif [[ "$TARGET_DIR" == "~/"* ]]; then
22-
TARGET_DIR="$HOME\${TARGET_DIR:1}"
22+
TARGET_DIR="/home/${config.sshUser}\${TARGET_DIR:1}"
2323
fi
2424
CLAUDE_AUTH_LABEL="\${CLAUDE_AUTH_LABEL:-}"
2525
CODEX_AUTH_LABEL="\${CODEX_AUTH_LABEL:-}"

packages/container/tests/core/templates.test.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,38 @@ describe("renderEntrypoint clone cache", () => {
465465
})
466466
})
467467

468+
describe("renderEntrypoint tilde target dir expansion", () => {
469+
// CHANGE: assert runtime `~`/`~/...` TARGET_DIR overrides resolve to the dev-owned home
470+
// WHY: the entrypoint runs as root (sshd), so `$HOME` is /root; expanding a tilde TARGET_DIR
471+
// against `$HOME` resolved the clone target to /root/app, which `su - dev` cannot write,
472+
// so `git clone` failed and the workspace `app` folder stayed EMPTY (issue #413)
473+
// QUOTE(ТЗ): "Почему-то при docker-git clone не делается git clone в папку app"
474+
// REF: issue-413
475+
// FORMAT THEOREM: expand("~") = /home/<sshUser> ∧ expand("~/p") = /home/<sshUser>/p
476+
it("expands a bare `~` against the dev home, not root's $HOME", () => {
477+
const entrypoint = renderEntrypoint(makeTemplateConfig({ sshUser: "dev" }))
478+
479+
expect(entrypoint).toContain('if [[ "$TARGET_DIR" == "~" ]]; then')
480+
expect(entrypoint).toContain('TARGET_DIR="/home/dev"')
481+
expect(entrypoint).toContain('TARGET_DIR="/home/dev${TARGET_DIR:1}"')
482+
expect(entrypoint).not.toContain('TARGET_DIR="$HOME"')
483+
expect(entrypoint).not.toContain('TARGET_DIR="$HOME${TARGET_DIR:1}"')
484+
})
485+
486+
it("expands the tilde against the configured ssh user for generated configs", () => {
487+
fc.assert(
488+
fc.property(generatedTemplateConfigArbitrary, (config) => {
489+
const entrypoint = renderEntrypoint(config)
490+
491+
expect(entrypoint).toContain(`TARGET_DIR="/home/${config.sshUser}"`)
492+
expect(entrypoint).toContain(`TARGET_DIR="/home/${config.sshUser}\${TARGET_DIR:1}"`)
493+
expect(entrypoint).not.toContain('TARGET_DIR="$HOME"')
494+
expect(entrypoint).not.toContain('TARGET_DIR="$HOME${TARGET_DIR:1}"')
495+
})
496+
)
497+
})
498+
})
499+
468500
describe("renderEntrypointGitHooks", () => {
469501
it("installs pre-push protection checks, plan sync, and a global git post-push runtime", () => {
470502
const hooks = renderEntrypointGitHooks()

0 commit comments

Comments
 (0)