diff --git a/agent-queue/agent-queue.sh b/agent-queue/agent-queue.sh index 1a3ceec..c5ef925 100755 --- a/agent-queue/agent-queue.sh +++ b/agent-queue/agent-queue.sh @@ -643,39 +643,44 @@ build_agent_cmd() { _fleet_pr_prepare() { local repo=$1 base=${2:-main} jid=$3 logf=$4 local reposdir="${AQ_FLEET_REPOS_DIR:-$STATE/repos}"; mkdir -p "$reposdir" - local safe dir url br src="" origin_url="" - safe=$(printf '%s' "$repo" | tr -c 'A-Za-z0-9._-' '_'); dir="$reposdir/$safe" - # MVP: if AQ_FLEET_REPO_BASE/ is an existing local repo, use it as the clone - # SOURCE (fast, no network) and push/PR to its GitHub origin. Credentials embedded - # in the local origin URL are stripped — gh's credential helper handles auth. + local safe dir url br sp; safe=$(printf '%s' "$repo" | tr -c 'A-Za-z0-9._-' '_') + br="aq/job/$jid" + + # MVP: if AQ_FLEET_REPO_BASE/ is an existing local checkout, use it via a + # git WORKTREE — no clone. The worktree shares the repo's objects + remotes (push/ + # PR go to its origin) and leaves the main checkout untouched. One worktree dir per + # repo, force-recreated each job. if [[ -n "${AQ_FLEET_REPO_BASE:-}" && -d "$AQ_FLEET_REPO_BASE/$repo/.git" ]]; then - src="$AQ_FLEET_REPO_BASE/$repo" - origin_url=$(git -C "$src" remote get-url origin 2>/dev/null | sed -E 's#://[^@/]*@#://#') - fi - # Resolve a clone URL: local source wins; else full URLs pass through; absolute/ - # existing local paths used as-is; otherwise `owner/name` -> GitHub HTTPS. - if [[ -n "$src" ]]; then url="$src"; else - case "$repo" in - *://*|git@*) url="$repo";; - /*) url="$repo";; - *) [[ -e "$repo" ]] && url="$repo" || url="https://github.com/$repo.git";; - esac + local src="$AQ_FLEET_REPO_BASE/$repo" wt="$reposdir/${safe}__wt" + git -C "$src" fetch --quiet origin "$base" >>"$logf" 2>&1 || true + git -C "$src" worktree remove --force "$wt" >>"$logf" 2>&1 || true + git -C "$src" worktree prune >>"$logf" 2>&1 || true + rm -rf "$wt" 2>/dev/null || true + sp="origin/$base"; git -C "$src" rev-parse -q --verify "$sp" >/dev/null 2>&1 || sp="$base" + git -C "$src" worktree add --force -B "$br" "$wt" "$sp" >>"$logf" 2>&1 \ + || { echo "PR: worktree add failed ($src $sp)" >>"$logf"; return 1; } + git -C "$wt" config user.email >/dev/null 2>&1 || git -C "$wt" config user.email "agent-queue@fleet.local" + git -C "$wt" config user.name >/dev/null 2>&1 || git -C "$wt" config user.name "agent-queue" + echo "$wt"; return 0 fi + + # Fallback (no local checkout): clone. Full URLs pass through; absolute/existing + # local paths used as-is; otherwise `owner/name` -> GitHub HTTPS. + dir="$reposdir/$safe" + case "$repo" in + *://*|git@*) url="$repo";; + /*) url="$repo";; + *) [[ -e "$repo" ]] && url="$repo" || url="https://github.com/$repo.git";; + esac if [[ -d "$dir/.git" ]]; then - [[ -n "$origin_url" ]] && git -C "$dir" remote set-url origin "$origin_url" >>"$logf" 2>&1 || true git -C "$dir" fetch --quiet origin "$base" >>"$logf" 2>&1 || { echo "PR: fetch failed for $base" >>"$logf"; return 1; } else git clone --quiet "$url" "$dir" >>"$logf" 2>&1 || { echo "PR: clone failed for $url" >>"$logf"; return 1; } - # Repoint to the upstream GitHub origin (when cloned from a local mirror). - [[ -n "$origin_url" ]] && git -C "$dir" remote set-url origin "$origin_url" >>"$logf" 2>&1 || true git -C "$dir" fetch --quiet origin "$base" >>"$logf" 2>&1 || true fi - br="aq/job/$jid" git -C "$dir" checkout --quiet -B "$br" "origin/$base" >>"$logf" 2>&1 \ || git -C "$dir" checkout --quiet -B "$br" "$base" >>"$logf" 2>&1 \ || { echo "PR: cannot branch $br off $base" >>"$logf"; return 1; } - # Ensure a commit identity exists (fall back to a bot identity if the host has - # no global git user configured) so the PR commit never fails. git -C "$dir" config user.email >/dev/null 2>&1 || git -C "$dir" config user.email "agent-queue@fleet.local" git -C "$dir" config user.name >/dev/null 2>&1 || git -C "$dir" config user.name "agent-queue" echo "$dir" diff --git a/agent-queue/selftest.sh b/agent-queue/selftest.sh index ac759f7..597ec0c 100755 --- a/agent-queue/selftest.sh +++ b/agent-queue/selftest.sh @@ -868,8 +868,10 @@ fi # 35d. PR mode: a fleet job carrying a `repo` -> agent works on aq/job/ in an # isolated checkout, PR is opened (gh stub), and the prUrl is reported on release. prbare="$tmp/pr-origin.git"; git init --bare -q "$prbare" -prseed="$tmp/pr-seed"; git clone -q "$prbare" "$prseed" 2>/dev/null -( cd "$prseed" && git config user.email t@t && git config user.name t \ +# Existing local checkout under a repo base (worktree source — no clone at job time). +prbase="$tmp/prbase"; mkdir -p "$prbase" +git clone -q "$prbare" "$prbase/learning_test" 2>/dev/null +( cd "$prbase/learning_test" && git config user.email t@t && git config user.name t \ && echo seed > README.md && git add -A && git commit -qm seed \ && git branch -M main && git push -q origin main ) >/dev/null 2>&1 prengine="$tmp/pr-engine" @@ -879,10 +881,10 @@ printf '#!/usr/bin/env bash\necho "$@" >> "%s"\necho "https://github.com/test/re export AGENT_QUEUE_ROOT="$tmp/queue-fl-pr"; export AQ_FLEET_CWD="$work" "$AQ" init >/dev/null export AQ_FSTUB_CALLS="$tmp/fl-pr-calls.log" AQ_FSTUB_CLAIM_FLAG="$tmp/fl-pr-claimed" \ - AQ_FSTUB_JOB_ID="fjob_pr" AQ_FSTUB_BODY="add a file" AQ_FSTUB_REPO="$prbare" AQ_FSTUB_BASE="main" \ + AQ_FSTUB_JOB_ID="fjob_pr" AQ_FSTUB_BODY="add a file" AQ_FSTUB_REPO="learning_test" AQ_FSTUB_BASE="main" \ AQ_FSTUB_VERIFY="true" AQ_FSTUB_AUTOMERGE="1" : > "$AQ_FSTUB_CALLS"; rm -f "$AQ_FSTUB_CLAIM_FLAG" -AQ_FLEET=1 AQ_FLEET_PR=1 AQ_FLEET_AUTOSHIP=1 AGENT_QUEUE_POLL=1 \ +AQ_FLEET=1 AQ_FLEET_PR=1 AQ_FLEET_AUTOSHIP=1 AGENT_QUEUE_POLL=1 AQ_FLEET_REPO_BASE="$prbase" \ AQ_FLEET_REPOS_DIR="$tmp/pr-repos" GH_BIN="$ghstub" DEVIN_BIN="$prengine" "$AQ" run --once >/dev/null 2>&1 if git -C "$prbare" rev-parse --verify aq/job/fjob_pr >/dev/null 2>&1 \ && grep -q -- '--title Add smoke marker file' "$tmp/gh-calls.log" 2>/dev/null \