Skip to content

Commit 2538867

Browse files
committed
merge: resolve conflicts with upstream/main
2 parents 093b72c + da0bd31 commit 2538867

7 files changed

Lines changed: 193 additions & 56 deletions

File tree

.github/workflows/check.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,17 @@ jobs:
8585
- name: Lint Effect-TS (lib)
8686
run: pnpm --filter ./packages/lib lint:effect
8787

88+
e2e-local-package:
89+
name: E2E (Local package CLI)
90+
runs-on: ubuntu-latest
91+
timeout-minutes: 15
92+
steps:
93+
- uses: actions/checkout@v6
94+
- name: Install dependencies
95+
uses: ./.github/actions/setup
96+
- name: Pack and run local package via pnpm
97+
run: bash scripts/e2e/local-package-cli.sh
98+
8899
e2e-opencode:
89100
name: E2E (OpenCode)
90101
runs-on: ubuntu-latest

packages/app/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,14 @@
1313
"prebuild": "pnpm -C ../lib build",
1414
"build": "pnpm run build:app && pnpm run build:docker-git",
1515
"build:app": "vite build --ssr src/app/main.ts",
16+
"prepack": "pnpm run build:docker-git",
1617
"dev": "vite build --watch --ssr src/app/main.ts",
1718
"prelint": "pnpm -C ../lib build",
1819
"lint": "PATH=../../scripts:$PATH vibecode-linter src/",
1920
"lint:tests": "PATH=../../scripts:$PATH vibecode-linter tests/",
2021
"lint:effect": "PATH=../../scripts:$PATH eslint --config eslint.effect-ts-check.config.mjs .",
2122
"prebuild:docker-git": "pnpm -C ../lib build",
22-
"build:docker-git": "tsc -p tsconfig.build.json",
23+
"build:docker-git": "vite build --config vite.docker-git.config.ts",
2324
"check": "pnpm run typecheck",
2425
"clone": "pnpm -C ../.. run clone",
2526
"docker-git": "node dist/src/docker-git/main.js",
@@ -53,7 +54,6 @@
5354
"homepage": "https://github.com/ProverCoderAI/docker-git#readme",
5455
"packageManager": "pnpm@10.28.0",
5556
"dependencies": {
56-
"@effect-template/lib": "workspace:*",
5757
"@effect/cli": "^0.73.0",
5858
"@effect/cluster": "^0.56.1",
5959
"@effect/experimental": "^0.58.0",
@@ -73,6 +73,7 @@
7373
"ts-morph": "^27.0.2"
7474
},
7575
"devDependencies": {
76+
"@effect-template/lib": "workspace:*",
7677
"@biomejs/biome": "^2.3.11",
7778
"@effect/eslint-plugin": "^0.3.2",
7879
"@effect/language-service": "latest",
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import path from "node:path"
2+
import { fileURLToPath } from "node:url"
3+
import { defineConfig } from "vite"
4+
import tsconfigPaths from "vite-tsconfig-paths"
5+
6+
const __filename = fileURLToPath(import.meta.url)
7+
const __dirname = path.dirname(__filename)
8+
9+
export default defineConfig({
10+
plugins: [tsconfigPaths()],
11+
publicDir: false,
12+
resolve: {
13+
alias: {
14+
"@": path.resolve(__dirname, "src"),
15+
"@effect-template/lib": path.resolve(__dirname, "../lib/src")
16+
}
17+
},
18+
build: {
19+
target: "node20",
20+
outDir: "dist",
21+
sourcemap: true,
22+
ssr: "src/docker-git/main.ts",
23+
rollupOptions: {
24+
output: {
25+
format: "es",
26+
entryFileNames: "src/docker-git/main.js",
27+
inlineDynamicImports: true
28+
}
29+
}
30+
},
31+
ssr: {
32+
target: "node"
33+
}
34+
})

packages/lib/src/core/command-builders.ts

Lines changed: 73 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -200,46 +200,68 @@ const resolvePaths = (
200200
}
201201
})
202202

203+
type CreateBehavior = {
204+
readonly runUp: boolean
205+
readonly openSsh: boolean
206+
readonly force: boolean
207+
readonly forceEnv: boolean
208+
readonly enableMcpPlaywright: boolean
209+
}
210+
211+
const resolveCreateBehavior = (raw: RawOptions): CreateBehavior => ({
212+
runUp: raw.up ?? true,
213+
openSsh: raw.openSsh ?? false,
214+
force: raw.force ?? false,
215+
forceEnv: raw.forceEnv ?? false,
216+
enableMcpPlaywright: raw.enableMcpPlaywright ?? false
217+
})
218+
203219
type BuildTemplateConfigInput = {
204-
readonly raw: RawOptions
205220
readonly repo: RepoBasics
206221
readonly names: NameConfig
207222
readonly paths: PathConfig
208223
readonly dockerNetworkMode: CreateCommand["config"]["dockerNetworkMode"]
209224
readonly dockerSharedNetworkName: string
225+
readonly gitTokenLabel: string | undefined
226+
readonly codexAuthLabel: string | undefined
227+
readonly claudeAuthLabel: string | undefined
228+
readonly enableMcpPlaywright: boolean
210229
}
211230

212-
const buildTemplateConfig = (input: BuildTemplateConfigInput): CreateCommand["config"] => {
213-
const enableMcpPlaywright = input.raw.enableMcpPlaywright ?? false
214-
const gitTokenLabel = normalizeGitTokenLabel(input.raw.gitTokenLabel)
215-
const codexAuthLabel = normalizeAuthLabel(input.raw.codexTokenLabel)
216-
const claudeAuthLabel = normalizeAuthLabel(input.raw.claudeTokenLabel)
217-
218-
return {
219-
containerName: input.names.containerName,
220-
serviceName: input.names.serviceName,
221-
sshUser: input.repo.sshUser,
222-
sshPort: input.repo.sshPort,
223-
repoUrl: input.repo.repoUrl,
224-
repoRef: input.repo.repoRef,
225-
gitTokenLabel,
226-
codexAuthLabel,
227-
claudeAuthLabel,
228-
targetDir: input.repo.targetDir,
229-
volumeName: input.names.volumeName,
230-
dockerGitPath: input.paths.dockerGitPath,
231-
authorizedKeysPath: input.paths.authorizedKeysPath,
232-
envGlobalPath: input.paths.envGlobalPath,
233-
envProjectPath: input.paths.envProjectPath,
234-
codexAuthPath: input.paths.codexAuthPath,
235-
codexSharedAuthPath: input.paths.codexSharedAuthPath,
236-
codexHome: input.paths.codexHome,
237-
dockerNetworkMode: input.dockerNetworkMode,
238-
dockerSharedNetworkName: input.dockerSharedNetworkName,
239-
enableMcpPlaywright,
240-
pnpmVersion: defaultTemplateConfig.pnpmVersion
241-
}
242-
}
231+
const buildTemplateConfig = ({
232+
claudeAuthLabel,
233+
codexAuthLabel,
234+
dockerNetworkMode,
235+
dockerSharedNetworkName,
236+
enableMcpPlaywright,
237+
gitTokenLabel,
238+
names,
239+
paths,
240+
repo
241+
}: BuildTemplateConfigInput): CreateCommand["config"] => ({
242+
containerName: names.containerName,
243+
serviceName: names.serviceName,
244+
sshUser: repo.sshUser,
245+
sshPort: repo.sshPort,
246+
repoUrl: repo.repoUrl,
247+
repoRef: repo.repoRef,
248+
gitTokenLabel,
249+
codexAuthLabel,
250+
claudeAuthLabel,
251+
targetDir: repo.targetDir,
252+
volumeName: names.volumeName,
253+
dockerGitPath: paths.dockerGitPath,
254+
authorizedKeysPath: paths.authorizedKeysPath,
255+
envGlobalPath: paths.envGlobalPath,
256+
envProjectPath: paths.envProjectPath,
257+
codexAuthPath: paths.codexAuthPath,
258+
codexSharedAuthPath: paths.codexSharedAuthPath,
259+
codexHome: paths.codexHome,
260+
dockerNetworkMode,
261+
dockerSharedNetworkName,
262+
enableMcpPlaywright,
263+
pnpmVersion: defaultTemplateConfig.pnpmVersion
264+
})
243265

244266
// CHANGE: build a typed create command from raw options (CLI or API)
245267
// WHY: share deterministic command construction across CLI and server
@@ -258,31 +280,33 @@ export const buildCreateCommand = (
258280
const repo = yield* _(resolveRepoBasics(raw))
259281
const names = yield* _(resolveNames(raw, repo.projectSlug))
260282
const paths = yield* _(resolvePaths(raw, repo.repoPath))
261-
const runUp = raw.up ?? true
262-
const openSsh = raw.openSsh ?? false
263-
const force = raw.force ?? false
264-
const forceEnv = raw.forceEnv ?? false
283+
const behavior = resolveCreateBehavior(raw)
284+
const gitTokenLabel = normalizeGitTokenLabel(raw.gitTokenLabel)
285+
const codexAuthLabel = normalizeAuthLabel(raw.codexTokenLabel)
286+
const claudeAuthLabel = normalizeAuthLabel(raw.claudeTokenLabel)
265287
const dockerNetworkMode = yield* _(parseDockerNetworkMode(raw.dockerNetworkMode))
266288
const dockerSharedNetworkName = yield* _(
267289
nonEmpty("--shared-network", raw.dockerSharedNetworkName, defaultTemplateConfig.dockerSharedNetworkName)
268290
)
269-
const config = buildTemplateConfig({
270-
raw,
271-
repo,
272-
names,
273-
paths,
274-
dockerNetworkMode,
275-
dockerSharedNetworkName
276-
})
277291

278292
return {
279293
_tag: "Create",
280294
outDir: paths.outDir,
281-
runUp,
282-
openSsh,
283-
force,
284-
forceEnv,
295+
runUp: behavior.runUp,
296+
openSsh: behavior.openSsh,
297+
force: behavior.force,
298+
forceEnv: behavior.forceEnv,
285299
waitForClone: false,
286-
config
300+
config: buildTemplateConfig({
301+
repo,
302+
names,
303+
paths,
304+
dockerNetworkMode,
305+
dockerSharedNetworkName,
306+
gitTokenLabel,
307+
codexAuthLabel,
308+
claudeAuthLabel,
309+
enableMcpPlaywright: behavior.enableMcpPlaywright
310+
})
287311
}
288312
})

pnpm-lock.yaml

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scripts/e2e/local-package-cli.sh

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
RUN_ID="$(date +%s)-$RANDOM"
5+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6+
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
7+
ROOT_BASE="${DOCKER_GIT_E2E_ROOT_BASE:-/tmp/docker-git-e2e-root}"
8+
mkdir -p "$ROOT_BASE"
9+
ROOT="$(mktemp -d "$ROOT_BASE/local-package-cli.XXXXXX")"
10+
KEEP="${KEEP:-0}"
11+
12+
PACK_LOG="$ROOT/npm-pack.log"
13+
HELP_LOG="$ROOT/docker-git-help.log"
14+
PACKED_TARBALL=""
15+
16+
fail() {
17+
echo "e2e/local-package-cli: $*" >&2
18+
exit 1
19+
}
20+
21+
on_error() {
22+
local line="$1"
23+
echo "e2e/local-package-cli: failed at line $line" >&2
24+
if [[ -f "$PACK_LOG" ]]; then
25+
echo "--- npm pack log ---" >&2
26+
cat "$PACK_LOG" >&2 || true
27+
fi
28+
if [[ -f "$HELP_LOG" ]]; then
29+
echo "--- docker-git --help log ---" >&2
30+
cat "$HELP_LOG" >&2 || true
31+
fi
32+
}
33+
34+
cleanup() {
35+
if [[ "$KEEP" == "1" ]]; then
36+
echo "e2e/local-package-cli: KEEP=1 set; preserving temp dir: $ROOT" >&2
37+
return
38+
fi
39+
if [[ -n "$PACKED_TARBALL" ]] && [[ -f "$PACKED_TARBALL" ]]; then
40+
rm -f "$PACKED_TARBALL" >/dev/null 2>&1 || true
41+
fi
42+
rm -rf "$ROOT" >/dev/null 2>&1 || true
43+
}
44+
45+
trap 'on_error $LINENO' ERR
46+
trap cleanup EXIT
47+
48+
cd "$REPO_ROOT/packages/app"
49+
npm pack --silent >"$PACK_LOG"
50+
tarball_name="$(tail -n 1 "$PACK_LOG" | tr -d '\r')"
51+
[[ -n "$tarball_name" ]] || fail "npm pack did not return tarball name"
52+
53+
PACKED_TARBALL="$REPO_ROOT/packages/app/$tarball_name"
54+
[[ -f "$PACKED_TARBALL" ]] || fail "packed tarball not found: $PACKED_TARBALL"
55+
56+
dep_keys="$(tar -xOf "$PACKED_TARBALL" package/package.json | node -e 'let s="";process.stdin.on("data",(c)=>{s+=c});process.stdin.on("end",()=>{const pkg=JSON.parse(s);const deps=Object.keys(pkg.dependencies ?? {});if (deps.includes("@effect-template/lib")) {console.error("@effect-template/lib must not be a runtime dependency in packed package");process.exit(1)}process.stdout.write(deps.join(","));});')"
57+
[[ "$dep_keys" == *"effect"* ]] || fail "packed dependency set looks invalid: $dep_keys"
58+
59+
mkdir -p "$ROOT/project"
60+
cd "$ROOT/project"
61+
npm init -y >/dev/null
62+
pnpm add "$PACKED_TARBALL" --silent --lockfile=false
63+
pnpm docker-git --help >"$HELP_LOG" 2>&1
64+
65+
grep -Fq -- "docker-git clone <url> [options]" "$HELP_LOG" \
66+
|| fail "expected docker-git help output from local packed package"
67+
68+
echo "e2e/local-package-cli: local tarball install + pnpm docker-git --help OK" >&2

scripts/e2e/run-all.sh

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
55

66
cases=("$@")
77
if [[ "${#cases[@]}" -eq 0 ]]; then
8-
cases=("clone-cache" "login-context" "opencode-autoconnect")
8+
cases=("local-package-cli" "clone-cache" "login-context" "opencode-autoconnect")
99
fi
1010

1111
for case_name in "${cases[@]}"; do
@@ -20,4 +20,3 @@ for case_name in "${cases[@]}"; do
2020
done
2121

2222
echo "e2e/run-all: all cases OK" >&2
23-

0 commit comments

Comments
 (0)