Skip to content

Commit 2c83f67

Browse files
committed
test(e2e): cover issue-61 labeled auth
1 parent c2790e1 commit 2c83f67

1 file changed

Lines changed: 163 additions & 0 deletions

File tree

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
# E2E regression test for Issue #61:
5+
# - multiple labeled auth entries in ~/.docker-git/.orch
6+
# - non-interactive auth storage
7+
# - project label binding (distributing the selected label into a project env)
8+
# - state auto-sync commits/pushes without user interaction
9+
10+
RUN_ID="$(date +%s)-$RANDOM"
11+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
12+
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
13+
source "$REPO_ROOT/scripts/e2e/_lib.sh"
14+
ROOT_BASE="${DOCKER_GIT_E2E_ROOT_BASE:-$REPO_ROOT/.docker-git/e2e-root}"
15+
mkdir -p "$ROOT_BASE"
16+
ROOT="$(mktemp -d "$ROOT_BASE/issue-61-auth-labels.XXXXXX")"
17+
chmod 0777 "$ROOT"
18+
KEEP="${KEEP:-0}"
19+
20+
export DOCKER_GIT_PROJECTS_ROOT="$ROOT"
21+
22+
# Keep the bare origin remote outside the state repo root so auto-sync commits
23+
# don't accidentally include its objects/refs.
24+
REMOTE="$(mktemp -d "$ROOT_BASE/issue-61-auth-labels-remote.XXXXXX")"
25+
26+
fail() {
27+
echo "e2e/issue-61-auth-labels: $*" >&2
28+
exit 1
29+
}
30+
31+
on_error() {
32+
local line="$1"
33+
echo "e2e/issue-61-auth-labels: failed at line $line" >&2
34+
if [[ -d "$ROOT/.git" ]]; then
35+
git -C "$ROOT" status -sb --porcelain=v1 || true
36+
git -C "$ROOT" log -n 10 --oneline || true
37+
fi
38+
}
39+
40+
cleanup() {
41+
if [[ "$KEEP" == "1" ]]; then
42+
echo "e2e/issue-61-auth-labels: KEEP=1 set; preserving temp dir: $ROOT" >&2
43+
echo "e2e/issue-61-auth-labels: preserving bare remote: $REMOTE" >&2
44+
return
45+
fi
46+
rm -rf "$ROOT" "$REMOTE" >/dev/null 2>&1 || true
47+
}
48+
49+
trap 'on_error $LINENO' ERR
50+
trap cleanup EXIT
51+
52+
# Prepare an isolated state repo at $ROOT with a local bare origin.
53+
mkdir -p "$ROOT/.orch/env"
54+
cat > "$ROOT/.orch/env/global.env" <<'EOF_ENV'
55+
# docker-git env
56+
# KEY=value
57+
EOF_ENV
58+
59+
git -C "$ROOT" init -b main >/dev/null
60+
git -C "$ROOT" config user.email "e2e@example.com"
61+
git -C "$ROOT" config user.name "docker-git e2e"
62+
git -C "$ROOT" add -A
63+
git -C "$ROOT" commit -m "chore(e2e): init state" >/dev/null
64+
git init --bare --initial-branch=main "$REMOTE" >/dev/null
65+
git -C "$ROOT" remote add origin "$REMOTE"
66+
git -C "$ROOT" push --no-verify -u origin main >/dev/null
67+
68+
# Enable auto-sync. This should commit+push to the local bare remote above.
69+
export DOCKER_GIT_STATE_AUTO_SYNC=1
70+
71+
default_token="token_default_$RUN_ID"
72+
agiens_token="token_agiens_$RUN_ID"
73+
git_token="git_token_$RUN_ID"
74+
claude_key="claude_key_$RUN_ID"
75+
76+
# 1) Store multiple GitHub tokens by label (non-interactive / CI path).
77+
(
78+
cd "$REPO_ROOT"
79+
pnpm run docker-git auth gh login --token "$default_token"
80+
)
81+
(
82+
cd "$REPO_ROOT"
83+
pnpm run docker-git auth gh login --token "$agiens_token" --label agiens
84+
)
85+
86+
grep -Fq -- "GITHUB_TOKEN=$default_token" "$ROOT/.orch/env/global.env" \
87+
|| fail "expected GITHUB_TOKEN to be stored in global.env"
88+
grep -Fq -- "GITHUB_TOKEN__AGIENS=$agiens_token" "$ROOT/.orch/env/global.env" \
89+
|| fail "expected GITHUB_TOKEN__AGIENS to be stored in global.env"
90+
91+
# Ensure state auto-sync actually committed and pushed.
92+
[[ -z "$(git -C "$ROOT" status --porcelain)" ]] || fail "state repo has uncommitted changes"
93+
[[ "$(git --git-dir "$REMOTE" log -1 --pretty=%s)" == "chore(state): auth gh AGIENS" ]] \
94+
|| fail "expected latest remote commit to come from labeled GH auth"
95+
96+
# 2) Set labeled Git credentials + Claude key via the same menu logic (non-interactive).
97+
PROJECT_DIR="$ROOT/e2e/project-1"
98+
PROJECT_ENV="$PROJECT_DIR/.orch/env/project.env"
99+
mkdir -p "$(dirname "$PROJECT_ENV")"
100+
cat > "$PROJECT_ENV" <<'EOF_ENV'
101+
# docker-git project env (e2e)
102+
EOF_ENV
103+
104+
(
105+
cd "$REPO_ROOT/packages/app"
106+
PROJECT_DIR="$PROJECT_DIR" \
107+
PROJECT_ENV_PATH="$PROJECT_ENV" \
108+
GIT_TOKEN_VALUE="$git_token" \
109+
CLAUDE_KEY_VALUE="$claude_key" \
110+
node --input-type=module <<'NODE'
111+
import { NodeContext, NodeRuntime } from "@effect/platform-node"
112+
import { Effect } from "effect"
113+
114+
import { writeAuthFlow } from "./dist/src/docker-git/menu-auth-data.js"
115+
import { writeProjectAuthFlow } from "./dist/src/docker-git/menu-project-auth-data.js"
116+
117+
const projectDir = process.env.PROJECT_DIR ?? ""
118+
const envProjectPath = process.env.PROJECT_ENV_PATH ?? ""
119+
if (projectDir.length === 0 || envProjectPath.length === 0) {
120+
throw new Error("missing PROJECT_DIR / PROJECT_ENV_PATH")
121+
}
122+
123+
const gitToken = process.env.GIT_TOKEN_VALUE ?? ""
124+
const claudeKey = process.env.CLAUDE_KEY_VALUE ?? ""
125+
if (gitToken.length === 0 || claudeKey.length === 0) {
126+
throw new Error("missing GIT_TOKEN_VALUE / CLAUDE_KEY_VALUE")
127+
}
128+
129+
const project = {
130+
projectDir,
131+
displayName: "e2e/project-1",
132+
envProjectPath
133+
}
134+
135+
const main = Effect.gen(function*(_) {
136+
// Create labeled profiles in ~/.docker-git/.orch/env/global.env
137+
yield* _(writeAuthFlow(process.cwd(), "GitSet", { label: "agiens", token: gitToken, user: "x-access-token" }))
138+
yield* _(writeAuthFlow(process.cwd(), "ClaudeSet", { label: "agiens", apiKey: claudeKey }))
139+
140+
// Bind them into the project env.
141+
yield* _(writeProjectAuthFlow(project, "ProjectGithubConnect", { label: "agiens" }))
142+
yield* _(writeProjectAuthFlow(project, "ProjectGitConnect", { label: "agiens" }))
143+
yield* _(writeProjectAuthFlow(project, "ProjectClaudeConnect", { label: "agiens" }))
144+
})
145+
146+
NodeRuntime.runMain(Effect.provide(main, NodeContext.layer))
147+
NODE
148+
)
149+
150+
grep -Fq -- "GITHUB_AUTH_LABEL=AGIENS" "$PROJECT_ENV" || fail "expected GITHUB_AUTH_LABEL=AGIENS in project.env"
151+
grep -Fq -- "GIT_AUTH_LABEL=AGIENS" "$PROJECT_ENV" || fail "expected GIT_AUTH_LABEL=AGIENS in project.env"
152+
grep -Fq -- "CLAUDE_AUTH_LABEL=AGIENS" "$PROJECT_ENV" || fail "expected CLAUDE_AUTH_LABEL=AGIENS in project.env"
153+
grep -Fq -- "GIT_AUTH_TOKEN=$git_token" "$PROJECT_ENV" || fail "expected bound GIT_AUTH_TOKEN in project.env"
154+
grep -Fq -- "GIT_AUTH_USER=x-access-token" "$PROJECT_ENV" || fail "expected bound GIT_AUTH_USER in project.env"
155+
grep -Fq -- "GH_TOKEN=$git_token" "$PROJECT_ENV" || fail "expected bound GH_TOKEN in project.env"
156+
grep -Fq -- "ANTHROPIC_API_KEY=$claude_key" "$PROJECT_ENV" || fail "expected bound ANTHROPIC_API_KEY in project.env"
157+
158+
[[ -z "$(git -C "$ROOT" status --porcelain)" ]] || fail "state repo not clean after project bindings"
159+
last_msg="$(git --git-dir "$REMOTE" log -1 --pretty=%s)"
160+
[[ "$last_msg" == "chore(state): project auth claude AGIENS e2e/project-1" ]] \
161+
|| fail "expected latest remote commit to come from project claude binding; got: $last_msg"
162+
163+
echo "e2e/issue-61-auth-labels: OK (multi-label auth + project bindings + state auto-sync)" >&2

0 commit comments

Comments
 (0)