Skip to content

Возможно полезные измненеия: #209

@skulidropek

Description

@skulidropek
meadav_david@meadav:~/docker-git$ git status
On branch main
Your branch is behind 'origin/main' by 31 commits, and can be fast-forwarded.
  (use "git pull" to update your local branch)

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   .gitignore
	modified:   package.json
	modified:   packages/app/package.json
	modified:   packages/app/src/docker-git/main.ts
	modified:   packages/app/vite.config.ts
	modified:   packages/app/vite.docker-git.config.ts
	modified:   packages/lib/src/shell/clone.ts
	modified:   packages/lib/src/shell/docker-auth.ts
	modified:   packages/lib/src/shell/docker-compose-env.ts
	modified:   packages/lib/src/usecases/auth-sync-claude-seed.ts
	modified:   packages/lib/src/usecases/path-helpers.ts
	modified:   packages/lib/tests/usecases/path-helpers.test.ts
	modified:   scripts/e2e/issue-61-auth-labels.sh
	modified:   scripts/e2e/local-package-cli.sh

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	packages/app/dist-verify/
	packages/lib/src/shell/home-dir.ts

no changes added to commit (use "git add" and/or "git commit -a")
meadav_david@meadav:~/docker-git$ git diff | cat
diff --git a/.gitignore b/.gitignore
index ebc26f4..784a62b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,6 +17,8 @@ dist/
 build/
 coverage/
 packages/*/dist/
+packages/*/dist-app/
+packages/*/dist-docker-git/
 npm-debug.log*
 yarn-debug.log*
 yarn-error.log*
diff --git a/package.json b/package.json
index e5c7b67..c5c4166 100644
--- a/package.json
+++ b/package.json
@@ -21,14 +21,14 @@
     "changeset": "changeset",
     "changeset-publish": "node -e \"if (!process.env.NPM_TOKEN) { console.log('Skipping publish: NPM_TOKEN is not set'); process.exit(0); }\" && changeset publish",
     "changeset-version": "changeset version",
-    "clone": "pnpm --filter ./packages/app build && node packages/app/dist/main.js clone",
-    "open": "pnpm --filter ./packages/app build && node packages/app/dist/main.js open",
-    "docker-git": "pnpm --filter ./packages/app build:docker-git && node packages/app/dist/src/docker-git/main.js",
+    "clone": "pnpm --filter ./packages/app build && node packages/app/dist-app/main.js clone",
+    "open": "pnpm --filter ./packages/app build && node packages/app/dist-app/main.js open",
+    "docker-git": "pnpm --filter ./packages/app build:docker-git && node packages/app/dist-docker-git/src/docker-git/main.js",
     "e2e": "bash scripts/e2e/run-all.sh",
     "e2e:clone-cache": "bash scripts/e2e/clone-cache.sh",
     "e2e:login-context": "bash scripts/e2e/login-context.sh",
     "e2e:opencode-autoconnect": "bash scripts/e2e/opencode-autoconnect.sh",
-    "list": "pnpm --filter ./packages/app build && node packages/app/dist/main.js list",
+    "list": "pnpm --filter ./packages/app build && node packages/app/dist-app/main.js list",
     "dev": "pnpm --filter ./packages/app dev",
     "lint": "pnpm --filter ./packages/app lint && pnpm --filter ./packages/lib lint",
     "lint:tests": "pnpm --filter ./packages/app lint:tests",
diff --git a/packages/app/package.json b/packages/app/package.json
index d017359..c330649 100644
--- a/packages/app/package.json
+++ b/packages/app/package.json
@@ -2,12 +2,12 @@
   "name": "@prover-coder-ai/docker-git",
   "version": "1.0.73",
   "description": "Minimal Vite-powered TypeScript console starter using Effect",
-  "main": "dist/src/docker-git/main.js",
+  "main": "dist-docker-git/src/docker-git/main.js",
   "bin": {
-    "docker-git": "dist/src/docker-git/main.js"
+    "docker-git": "dist-docker-git/src/docker-git/main.js"
   },
   "files": [
-    "dist"
+    "dist-docker-git"
   ],
   "directories": {
     "doc": "doc"
@@ -27,10 +27,10 @@
     "check": "pnpm run typecheck",
     "clone": "pnpm -C ../.. run clone",
     "open": "pnpm -C ../.. run open",
-    "docker-git": "node dist/src/docker-git/main.js",
+    "docker-git": "node dist-docker-git/src/docker-git/main.js",
     "list": "pnpm -C ../.. run list",
     "prestart": "pnpm run build",
-    "start": "node dist/main.js",
+    "start": "node dist-app/main.js",
     "pretest": "pnpm -C ../lib build",
     "test": "pnpm run lint:tests && vitest run",
     "pretypecheck": "pnpm -C ../lib build",
diff --git a/packages/app/src/docker-git/main.ts b/packages/app/src/docker-git/main.ts
index b82e82e..8d6f466 100644
--- a/packages/app/src/docker-git/main.ts
+++ b/packages/app/src/docker-git/main.ts
@@ -1,6 +1,7 @@
 #!/usr/bin/env node

 import { NodeContext, NodeRuntime } from "@effect/platform-node"
+import { normalizeHomeEnvironmentForSudo } from "@effect-template/lib/shell/home-dir"
 import { Effect } from "effect"

 import { program } from "./program.js"
@@ -15,6 +16,8 @@ import { program } from "./program.js"
 // EFFECT: Effect<void, unknown, NodeContext>
 // INVARIANT: program runs with NodeContext.layer
 // COMPLEXITY: O(n)
+normalizeHomeEnvironmentForSudo()
+
 const main = Effect.provide(program, NodeContext.layer)

 NodeRuntime.runMain(main)
diff --git a/packages/app/vite.config.ts b/packages/app/vite.config.ts
index cfd0bb5..d595d83 100644
--- a/packages/app/vite.config.ts
+++ b/packages/app/vite.config.ts
@@ -16,7 +16,7 @@ export default defineConfig({
   },
   build: {
     target: "node20",
-    outDir: "dist",
+    outDir: "dist-app",
     sourcemap: true,
     ssr: "src/app/main.ts",
     rollupOptions: {
diff --git a/packages/app/vite.docker-git.config.ts b/packages/app/vite.docker-git.config.ts
index 7605ac4..f39b2ae 100644
--- a/packages/app/vite.docker-git.config.ts
+++ b/packages/app/vite.docker-git.config.ts
@@ -17,7 +17,7 @@ export default defineConfig({
   },
   build: {
     target: "node20",
-    outDir: "dist",
+    outDir: "dist-docker-git",
     sourcemap: true,
     ssr: "src/docker-git/main.ts",
     rollupOptions: {
diff --git a/packages/lib/src/shell/clone.ts b/packages/lib/src/shell/clone.ts
index e59df91..8db08e0 100644
--- a/packages/lib/src/shell/clone.ts
+++ b/packages/lib/src/shell/clone.ts
@@ -36,7 +36,7 @@ const runDockerGitCommand = (
     const path = yield* _(Path.Path)
     const workspaceRoot = process.cwd()
     const appRoot = path.join(workspaceRoot, "packages", "app")
-    const dockerGitCli = path.join(appRoot, "dist", "src", "docker-git", "main.js")
+    const dockerGitCli = path.join(appRoot, "dist-docker-git", "src", "docker-git", "main.js")
     const buildLabel = `pnpm -C ${appRoot} build:docker-git`
     const runLabel = `node ${dockerGitCli} ${commandName}`

diff --git a/packages/lib/src/shell/docker-auth.ts b/packages/lib/src/shell/docker-auth.ts
index 5e739a6..7c75c91 100644
--- a/packages/lib/src/shell/docker-auth.ts
+++ b/packages/lib/src/shell/docker-auth.ts
@@ -3,6 +3,7 @@ import type { PlatformError } from "@effect/platform/Error"
 import { Effect } from "effect"

 import { runCommandCapture, runCommandExitCode, runCommandWithExitCodes } from "./command-runner.js"
+import { resolveEffectiveHomeDir } from "./home-dir.js"

 export type DockerVolume = {
   readonly hostPath: string
@@ -56,7 +57,7 @@ const resolveContainerProjectsRoot = (): string | null => {
     return explicit
   }

-  const home = resolveDockerEnvValue("HOME") ?? resolveDockerEnvValue("USERPROFILE")
+  const home = resolveEffectiveHomeDir() ?? resolveDockerEnvValue("HOME") ?? resolveDockerEnvValue("USERPROFILE")
   return home === null ? null : `${trimDockerPathTrailingSlash(home)}/.docker-git`
 }

diff --git a/packages/lib/src/shell/docker-compose-env.ts b/packages/lib/src/shell/docker-compose-env.ts
index a2743ad..63ebf34 100644
--- a/packages/lib/src/shell/docker-compose-env.ts
+++ b/packages/lib/src/shell/docker-compose-env.ts
@@ -2,6 +2,7 @@ import type * as CommandExecutor from "@effect/platform/CommandExecutor"
 import { Effect } from "effect"

 import { resolveDockerEnvValue, resolveDockerVolumeHostPath, trimDockerPathTrailingSlash } from "./docker-auth.js"
+import { resolveEffectiveHomeDir } from "./home-dir.js"

 export const composeSpec = (cwd: string, args: ReadonlyArray<string>) => ({
   cwd,
@@ -15,7 +16,7 @@ const resolveProjectsRootCandidate = (): string | null => {
     return explicit
   }

-  const home = resolveDockerEnvValue("HOME") ?? resolveDockerEnvValue("USERPROFILE")
+  const home = resolveEffectiveHomeDir() ?? resolveDockerEnvValue("HOME") ?? resolveDockerEnvValue("USERPROFILE")
   return home === null ? null : `${trimDockerPathTrailingSlash(home)}/.docker-git`
 }

diff --git a/packages/lib/src/usecases/auth-sync-claude-seed.ts b/packages/lib/src/usecases/auth-sync-claude-seed.ts
index 36314b4..2c61ff2 100644
--- a/packages/lib/src/usecases/auth-sync-claude-seed.ts
+++ b/packages/lib/src/usecases/auth-sync-claude-seed.ts
@@ -3,6 +3,7 @@ import type * as FileSystem from "@effect/platform/FileSystem"
 import type * as Path from "@effect/platform/Path"
 import { Effect } from "effect"

+import { resolveEffectiveHomeDir } from "../shell/home-dir.js"
 import {
   hasClaudeCredentials,
   hasClaudeOauthAccount,
@@ -112,8 +113,8 @@ export const ensureClaudeAuthSeedFromHome = (
 ): Effect.Effect<void, PlatformError, FileSystem.FileSystem | Path.Path> =>
   withFsPathContext(({ fs, path }) =>
     Effect.gen(function*(_) {
-      const homeDir = (process.env["HOME"] ?? "").trim()
-      if (homeDir.length === 0) {
+      const homeDir = resolveEffectiveHomeDir()
+      if (homeDir === null || homeDir.length === 0) {
         return
       }

diff --git a/packages/lib/src/usecases/path-helpers.ts b/packages/lib/src/usecases/path-helpers.ts
index a4e3349..7f67ada 100644
--- a/packages/lib/src/usecases/path-helpers.ts
+++ b/packages/lib/src/usecases/path-helpers.ts
@@ -3,6 +3,8 @@ import type * as FileSystem from "@effect/platform/FileSystem"
 import type * as Path from "@effect/platform/Path"
 import { Effect } from "effect"

+import { resolveEffectiveHomeDir } from "../shell/home-dir.js"
+
 export const resolveAuthorizedKeysPath = (
   path: Path.Path,
   baseDir: string,
@@ -13,9 +15,8 @@ export const resolveAuthorizedKeysPath = (
     : path.resolve(baseDir, authorizedKeysPath)

 const resolveHomeDir = (): string | null => {
-  const raw = process.env["HOME"] ?? process.env["USERPROFILE"]
-  const home = raw?.trim() ?? ""
-  return home.length > 0 ? home : null
+  const home = resolveEffectiveHomeDir()
+  return home === null ? null : home.trim()
 }

 const expandHome = (value: string, home: string | null): string => {
diff --git a/packages/lib/tests/usecases/path-helpers.test.ts b/packages/lib/tests/usecases/path-helpers.test.ts
index 157f822..614380f 100644
--- a/packages/lib/tests/usecases/path-helpers.test.ts
+++ b/packages/lib/tests/usecases/path-helpers.test.ts
@@ -5,6 +5,11 @@ import { describe, expect, it } from "@effect/vitest"
 import { Effect } from "effect"

 import { findAuthorizedKeysSource, findSshPrivateKey } from "../../src/usecases/path-helpers.js"
+import {
+  normalizeHomeEnvironmentForSudo,
+  resolveEffectiveHomeDir,
+  resolveHomeDirFromPasswdContents
+} from "../../src/shell/home-dir.js"

 const withTempDir = <A, E, R>(
   use: (tempDir: string) => Effect.Effect<A, E, R>
@@ -52,6 +57,34 @@ const withPatchedEnv = <A, E, R>(
   )

 describe("path helpers", () => {
+  it.effect("prefers SUDO_HOME over /root when docker-git runs under sudo", () =>
+    withPatchedEnv(
+      {
+        HOME: "/root",
+        SUDO_USER: "alice",
+        SUDO_HOME: "/home/alice",
+        USERPROFILE: undefined
+      },
+      Effect.sync(() => {
+        expect(resolveHomeDirFromPasswdContents("alice:x:1000:1000::/home/alice:/bin/bash\n", "alice")).toBe("/home/alice")
+        expect(resolveEffectiveHomeDir()).toBe("/home/alice")
+      })
+    ))
+
+  it.effect("normalizes HOME to the invoking user's home in sudo flows", () =>
+    withPatchedEnv(
+      {
+        HOME: "/root",
+        SUDO_USER: "alice",
+        SUDO_HOME: "/home/alice",
+        USERPROFILE: undefined
+      },
+      Effect.sync(() => {
+        expect(normalizeHomeEnvironmentForSudo()).toBe("/home/alice")
+        expect(process.env["HOME"]).toBe("/home/alice")
+      })
+    ))
+
   it.effect("prefers the docker-git projects root public key over generic ~/.ssh keys", () =>
     withTempDir((root) =>
       Effect.gen(function*(_) {
diff --git a/scripts/e2e/issue-61-auth-labels.sh b/scripts/e2e/issue-61-auth-labels.sh
index 17f42e2..2e13333 100755
--- a/scripts/e2e/issue-61-auth-labels.sh
+++ b/scripts/e2e/issue-61-auth-labels.sh
@@ -111,8 +111,8 @@ import { Effect } from "effect"
 import { mkdirSync, writeFileSync } from "node:fs"
 import { join } from "node:path"

-import { writeAuthFlow } from "./dist/src/docker-git/menu-auth-data.js"
-import { writeProjectAuthFlow } from "./dist/src/docker-git/menu-project-auth-data.js"
+import { writeAuthFlow } from "./dist-docker-git/src/docker-git/menu-auth-data.js"
+import { writeProjectAuthFlow } from "./dist-docker-git/src/docker-git/menu-project-auth-data.js"

 const projectDir = process.env.PROJECT_DIR ?? ""
 const envProjectPath = process.env.PROJECT_ENV_PATH ?? ""
diff --git a/scripts/e2e/local-package-cli.sh b/scripts/e2e/local-package-cli.sh
index 8b80bd0..87a778d 100755
--- a/scripts/e2e/local-package-cli.sh
+++ b/scripts/e2e/local-package-cli.sh
@@ -62,7 +62,7 @@ PACKED_TARBALL="$REPO_ROOT/packages/app/$tarball_name"
 tar -tf "$PACKED_TARBALL" >"$TAR_LIST"
 while IFS= read -r entry; do
   case "$entry" in
-    package/package.json|package/README*|package/LICENSE*|package/CHANGELOG*|package/dist/*)
+    package/package.json|package/README*|package/LICENSE*|package/CHANGELOG*|package/dist-docker-git/*)
       ;;
     *)
       fail "unexpected file in packed tarball: $entry"
@@ -70,11 +70,11 @@ while IFS= read -r entry; do
   esac
 done <"$TAR_LIST"

-grep -Fxq "package/dist/src/docker-git/main.js" "$TAR_LIST" \
-  || fail "packed tarball does not include dist/src/docker-git/main.js"
+grep -Fxq "package/dist-docker-git/src/docker-git/main.js" "$TAR_LIST" \
+  || fail "packed tarball does not include dist-docker-git/src/docker-git/main.js"

 main_entry_tmp="$ROOT/main-entry.js"
-tar -xOf "$PACKED_TARBALL" package/dist/src/docker-git/main.js >"$main_entry_tmp"
+tar -xOf "$PACKED_TARBALL" package/dist-docker-git/src/docker-git/main.js >"$main_entry_tmp"
 main_first_line="$(head -n 1 "$main_entry_tmp" | tr -d '\r')"
 [[ "$main_first_line" == "#!/usr/bin/env node" ]] \
   || fail "packed CLI entrypoint missing shebang: expected '#!/usr/bin/env node', got '$main_first_line'"
meadav_david@meadav:~/docker-git$

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions