Skip to content

Commit 57fc680

Browse files
committed
fix(auto): remap shared docker-git root for compose
1 parent fd104d8 commit 57fc680

5 files changed

Lines changed: 61 additions & 71 deletions

File tree

packages/lib/src/core/templates-entrypoint/agent.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,10 @@ const renderAgentAutoLaunchCommand = (
5454
config: TemplateConfig,
5555
mode: "claude" | "codex"
5656
): string =>
57-
String.raw`su - ${config.sshUser} -s /bin/bash -c "bash -lc '. /etc/profile 2>/dev/null || true; . \"$AGENT_ENV_FILE\" 2>/dev/null || true; cd \"$TARGET_DIR\" && ${renderAgentPromptCommand(mode)}'"`
57+
String
58+
.raw`su - ${config.sshUser} -s /bin/bash -c "bash -lc '. /etc/profile 2>/dev/null || true; . \"$AGENT_ENV_FILE\" 2>/dev/null || true; cd \"$TARGET_DIR\" && ${
59+
renderAgentPromptCommand(mode)
60+
}'"`
5861

5962
const renderAgentModeBlock = (
6063
config: TemplateConfig,

packages/lib/src/shell/docker-auth.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@ type DockerMountBinding = {
2525
readonly destination: string
2626
}
2727

28-
const resolveEnvValue = (key: string): string | null => {
28+
export const resolveDockerEnvValue = (key: string): string | null => {
2929
const value = process.env[key]?.trim()
3030
return value && value.length > 0 ? value : null
3131
}
3232

33-
const trimTrailingSlash = (value: string): string => {
33+
export const trimDockerPathTrailingSlash = (value: string): string => {
3434
let end = value.length
3535
while (end > 0) {
3636
const char = value[end - 1]
@@ -51,21 +51,21 @@ const translatePathPrefix = (candidate: string, sourcePrefix: string, targetPref
5151
: null
5252

5353
const resolveContainerProjectsRoot = (): string | null => {
54-
const explicit = resolveEnvValue("DOCKER_GIT_PROJECTS_ROOT")
54+
const explicit = resolveDockerEnvValue("DOCKER_GIT_PROJECTS_ROOT")
5555
if (explicit !== null) {
5656
return explicit
5757
}
5858

59-
const home = resolveEnvValue("HOME") ?? resolveEnvValue("USERPROFILE")
60-
return home === null ? null : `${trimTrailingSlash(home)}/.docker-git`
59+
const home = resolveDockerEnvValue("HOME") ?? resolveDockerEnvValue("USERPROFILE")
60+
return home === null ? null : `${trimDockerPathTrailingSlash(home)}/.docker-git`
6161
}
6262

63-
const resolveProjectsRootHostOverride = (): string | null => resolveEnvValue("DOCKER_GIT_PROJECTS_ROOT_HOST")
63+
const resolveProjectsRootHostOverride = (): string | null => resolveDockerEnvValue("DOCKER_GIT_PROJECTS_ROOT_HOST")
6464

6565
const resolveCurrentContainerId = (
6666
cwd: string
6767
): Effect.Effect<string | null, never, CommandExecutor.CommandExecutor> => {
68-
const fromEnv = resolveEnvValue("HOSTNAME")
68+
const fromEnv = resolveDockerEnvValue("HOSTNAME")
6969
if (fromEnv !== null) {
7070
return Effect.succeed(fromEnv)
7171
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import type * as CommandExecutor from "@effect/platform/CommandExecutor"
2+
import { Effect } from "effect"
3+
4+
import { resolveDockerEnvValue, resolveDockerVolumeHostPath, trimDockerPathTrailingSlash } from "./docker-auth.js"
5+
6+
export const composeSpec = (cwd: string, args: ReadonlyArray<string>) => ({
7+
cwd,
8+
command: "docker",
9+
args: ["compose", "--ansi", "never", "--progress", "plain", ...args]
10+
})
11+
12+
const resolveProjectsRootCandidate = (): string | null => {
13+
const explicit = resolveDockerEnvValue("DOCKER_GIT_PROJECTS_ROOT")
14+
if (explicit !== null) {
15+
return explicit
16+
}
17+
18+
const home = resolveDockerEnvValue("HOME") ?? resolveDockerEnvValue("USERPROFILE")
19+
return home === null ? null : `${trimDockerPathTrailingSlash(home)}/.docker-git`
20+
}
21+
22+
export const resolveDockerComposeEnv = (
23+
cwd: string
24+
): Effect.Effect<Readonly<Record<string, string>>, never, CommandExecutor.CommandExecutor> =>
25+
Effect.gen(function*(_) {
26+
const projectsRoot = resolveProjectsRootCandidate()
27+
if (projectsRoot === null) {
28+
return {}
29+
}
30+
31+
const remappedProjectsRoot = yield* _(resolveDockerVolumeHostPath(cwd, projectsRoot))
32+
return remappedProjectsRoot === projectsRoot ? {} : { DOCKER_GIT_PROJECTS_ROOT_HOST: remappedProjectsRoot }
33+
})
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
export const parseInspectNetworkEntry = (line: string): ReadonlyArray<readonly [string, string]> => {
2+
const idx = line.indexOf("=")
3+
if (idx <= 0) {
4+
return []
5+
}
6+
const network = line.slice(0, idx).trim()
7+
const ip = line.slice(idx + 1).trim()
8+
if (network.length === 0 || ip.length === 0) {
9+
return []
10+
}
11+
const entry: readonly [string, string] = [network, ip]
12+
return [entry]
13+
}

packages/lib/src/shell/docker.ts

Lines changed: 4 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -5,79 +5,20 @@ import type { PlatformError } from "@effect/platform/Error"
55
import { Duration, Effect, pipe, Schedule } from "effect"
66

77
import { runCommandCapture, runCommandExitCode, runCommandWithExitCodes } from "./command-runner.js"
8-
import { resolveDockerVolumeHostPath } from "./docker-auth.js"
8+
import { composeSpec, resolveDockerComposeEnv } from "./docker-compose-env.js"
9+
import { parseInspectNetworkEntry } from "./docker-inspect-parse.js"
910
import { CommandFailedError, DockerCommandError } from "./errors.js"
1011

1112
export { classifyDockerAccessIssue, ensureDockerDaemonAccess } from "./docker-daemon-access.js"
1213
export { parseDockerPublishedHostPorts, runDockerPsPublishedHostPorts } from "./docker-published-ports.js"
1314

14-
const composeSpec = (cwd: string, args: ReadonlyArray<string>) => ({
15-
cwd,
16-
command: "docker",
17-
args: ["compose", "--ansi", "never", "--progress", "plain", ...args]
18-
})
19-
20-
const resolveEnvValue = (key: string): string | null => {
21-
const value = process.env[key]?.trim()
22-
return value && value.length > 0 ? value : null
23-
}
24-
25-
const trimTrailingSlash = (value: string): string => {
26-
let end = value.length
27-
while (end > 0) {
28-
const char = value[end - 1]
29-
if (char !== "/" && char !== "\\") {
30-
break
31-
}
32-
end -= 1
33-
}
34-
return value.slice(0, end)
35-
}
36-
37-
const resolveProjectsRootCandidate = (): string | null => {
38-
const explicit = resolveEnvValue("DOCKER_GIT_PROJECTS_ROOT")
39-
if (explicit !== null) {
40-
return explicit
41-
}
42-
43-
const home = resolveEnvValue("HOME") ?? resolveEnvValue("USERPROFILE")
44-
return home === null ? null : `${trimTrailingSlash(home)}/.docker-git`
45-
}
46-
47-
const resolveComposeEnv = (
48-
cwd: string
49-
): Effect.Effect<Readonly<Record<string, string>>, never, CommandExecutor.CommandExecutor> =>
50-
Effect.gen(function*(_) {
51-
const projectsRoot = resolveProjectsRootCandidate()
52-
if (projectsRoot === null) {
53-
return {}
54-
}
55-
56-
const remappedProjectsRoot = yield* _(resolveDockerVolumeHostPath(cwd, projectsRoot))
57-
return remappedProjectsRoot === projectsRoot ? {} : { DOCKER_GIT_PROJECTS_ROOT_HOST: remappedProjectsRoot }
58-
})
59-
60-
const parseInspectNetworkEntry = (line: string): ReadonlyArray<readonly [string, string]> => {
61-
const idx = line.indexOf("=")
62-
if (idx <= 0) {
63-
return []
64-
}
65-
const network = line.slice(0, idx).trim()
66-
const ip = line.slice(idx + 1).trim()
67-
if (network.length === 0 || ip.length === 0) {
68-
return []
69-
}
70-
const entry: readonly [string, string] = [network, ip]
71-
return [entry]
72-
}
73-
7415
const runCompose = (
7516
cwd: string,
7617
args: ReadonlyArray<string>,
7718
okExitCodes: ReadonlyArray<number>
7819
): Effect.Effect<void, DockerCommandError | PlatformError, CommandExecutor.CommandExecutor> =>
7920
Effect.gen(function*(_) {
80-
const env = yield* _(resolveComposeEnv(cwd))
21+
const env = yield* _(resolveDockerComposeEnv(cwd))
8122
yield* _(
8223
runCommandWithExitCodes(
8324
{
@@ -96,7 +37,7 @@ const runComposeCapture = (
9637
okExitCodes: ReadonlyArray<number>
9738
): Effect.Effect<string, DockerCommandError | PlatformError, CommandExecutor.CommandExecutor> =>
9839
Effect.gen(function*(_) {
99-
const env = yield* _(resolveComposeEnv(cwd))
40+
const env = yield* _(resolveDockerComposeEnv(cwd))
10041
return yield* _(
10142
runCommandCapture(
10243
{

0 commit comments

Comments
 (0)