fix: dev-agent worktree pushes to origin (Codeberg) instead of forgejo (local) — PR creation fails (#653)
Detect which git remote matches FORGE_URL by comparing the host portion of FORGE_URL against remote push URLs. Store the result in FORGE_REMOTE (defaults to "origin" when no match — preserving existing behavior for Codeberg-direct setups). Replace every hardcoded "origin" in fetch, push, worktree-add, and prompt-injection commands across: - dev/dev-agent.sh (worktree setup, phase protocol prompt) - dev/phase-handler.sh (CI retrigger, review feedback, rebase instructions) - review/review-poll.sh (review feedback injection) - action/action-agent.sh (worktree setup, push instructions) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
0e5090bd51
commit
ac5448323b
4 changed files with 43 additions and 26 deletions
|
|
@ -203,8 +203,15 @@ fi
|
|||
# --- Create isolated worktree ---
|
||||
log "creating worktree: ${WORKTREE}"
|
||||
cd "${PROJECT_REPO_ROOT}"
|
||||
git fetch origin "${PRIMARY_BRANCH}" 2>/dev/null || true
|
||||
if ! git worktree add "$WORKTREE" "origin/${PRIMARY_BRANCH}" 2>&1; then
|
||||
|
||||
# Determine which git remote corresponds to FORGE_URL
|
||||
_forge_host=$(echo "$FORGE_URL" | sed 's|https\?://||; s|/.*||')
|
||||
FORGE_REMOTE=$(git remote -v | awk -v host="$_forge_host" '$2 ~ host && /\(push\)/ {print $1; exit}')
|
||||
FORGE_REMOTE="${FORGE_REMOTE:-origin}"
|
||||
export FORGE_REMOTE
|
||||
|
||||
git fetch "${FORGE_REMOTE}" "${PRIMARY_BRANCH}" 2>/dev/null || true
|
||||
if ! git worktree add "$WORKTREE" "${FORGE_REMOTE}/${PRIMARY_BRANCH}" 2>&1; then
|
||||
log "ERROR: worktree creation failed"
|
||||
notify "failed to create worktree for #${ISSUE}"
|
||||
exit 1
|
||||
|
|
@ -266,7 +273,7 @@ ${PRIOR_SECTION}## Instructions
|
|||
### Path A: If this action produces code changes (e.g. config updates, baselines):
|
||||
- You are already in an isolated worktree at: ${WORKTREE}
|
||||
- Create and switch to branch: git checkout -b ${BRANCH}
|
||||
- Make your changes, commit, and push: git push origin ${BRANCH}
|
||||
- Make your changes, commit, and push: git push ${FORGE_REMOTE} ${BRANCH}
|
||||
- **IMPORTANT:** The worktree is destroyed after completion. Push all
|
||||
results before signaling done — unpushed work will be lost.
|
||||
- Follow the phase protocol below — the orchestrator handles PR creation,
|
||||
|
|
|
|||
|
|
@ -460,8 +460,18 @@ fi
|
|||
status "setting up worktree"
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
# Determine which git remote corresponds to FORGE_URL.
|
||||
# When the forge is local Forgejo (not Codeberg), the remote is typically named
|
||||
# "forgejo" rather than "origin". Matching by host ensures pushes target the
|
||||
# correct forge regardless of remote naming conventions.
|
||||
_forge_host=$(echo "$FORGE_URL" | sed 's|https\?://||; s|/.*||')
|
||||
FORGE_REMOTE=$(git remote -v | awk -v host="$_forge_host" '$2 ~ host && /\(push\)/ {print $1; exit}')
|
||||
FORGE_REMOTE="${FORGE_REMOTE:-origin}"
|
||||
export FORGE_REMOTE # used by phase-handler.sh
|
||||
log "forge remote: ${FORGE_REMOTE} (FORGE_URL=${FORGE_URL})"
|
||||
|
||||
if [ "$RECOVERY_MODE" = true ]; then
|
||||
git fetch origin "$BRANCH" 2>/dev/null
|
||||
git fetch "${FORGE_REMOTE}" "$BRANCH" 2>/dev/null
|
||||
|
||||
# Reuse existing worktree if on the right branch (preserves session context)
|
||||
REUSE_WORKTREE=false
|
||||
|
|
@ -470,14 +480,14 @@ if [ "$RECOVERY_MODE" = true ]; then
|
|||
if [ "$WT_BRANCH" = "$BRANCH" ]; then
|
||||
log "reusing existing worktree (preserves session)"
|
||||
cd "$WORKTREE"
|
||||
git pull --ff-only origin "$BRANCH" 2>/dev/null || git reset --hard "origin/${BRANCH}" 2>/dev/null || true
|
||||
git pull --ff-only "${FORGE_REMOTE}" "$BRANCH" 2>/dev/null || git reset --hard "${FORGE_REMOTE}/${BRANCH}" 2>/dev/null || true
|
||||
REUSE_WORKTREE=true
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$REUSE_WORKTREE" = false ]; then
|
||||
cleanup_worktree
|
||||
git worktree add "$WORKTREE" "origin/${BRANCH}" -B "$BRANCH" 2>&1 || {
|
||||
git worktree add "$WORKTREE" "${FORGE_REMOTE}/${BRANCH}" -B "$BRANCH" 2>&1 || {
|
||||
log "ERROR: worktree creation failed for recovery"
|
||||
cleanup_labels
|
||||
exit 1
|
||||
|
|
@ -499,17 +509,17 @@ else
|
|||
git checkout "${PRIMARY_BRANCH}" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
git fetch origin "${PRIMARY_BRANCH}" 2>/dev/null
|
||||
git pull --ff-only origin "${PRIMARY_BRANCH}" 2>/dev/null || true
|
||||
git fetch "${FORGE_REMOTE}" "${PRIMARY_BRANCH}" 2>/dev/null
|
||||
git pull --ff-only "${FORGE_REMOTE}" "${PRIMARY_BRANCH}" 2>/dev/null || true
|
||||
cleanup_worktree
|
||||
git worktree add "$WORKTREE" "origin/${PRIMARY_BRANCH}" -B "$BRANCH" 2>&1 || {
|
||||
git worktree add "$WORKTREE" "${FORGE_REMOTE}/${PRIMARY_BRANCH}" -B "$BRANCH" 2>&1 || {
|
||||
log "ERROR: worktree creation failed"
|
||||
git worktree add "$WORKTREE" "origin/${PRIMARY_BRANCH}" -B "$BRANCH" 2>&1 | while read -r wt_line; do log " $wt_line"; done || true
|
||||
git worktree add "$WORKTREE" "${FORGE_REMOTE}/${PRIMARY_BRANCH}" -B "$BRANCH" 2>&1 | while read -r wt_line; do log " $wt_line"; done || true
|
||||
cleanup_labels
|
||||
exit 1
|
||||
}
|
||||
cd "$WORKTREE"
|
||||
git checkout -B "$BRANCH" "origin/${PRIMARY_BRANCH}" 2>/dev/null
|
||||
git checkout -B "$BRANCH" "${FORGE_REMOTE}/${PRIMARY_BRANCH}" 2>/dev/null
|
||||
git submodule update --init --recursive 2>/dev/null || true
|
||||
|
||||
# Symlink lib node_modules from main repo (submodule init doesn't run npm install)
|
||||
|
|
@ -550,7 +560,7 @@ SUMMARY_FILE=\"${IMPL_SUMMARY_FILE}\"
|
|||
|
||||
**After committing and pushing your branch:**
|
||||
\`\`\`bash
|
||||
git push origin ${BRANCH}
|
||||
git push ${FORGE_REMOTE} ${BRANCH}
|
||||
# Write a short summary of what you implemented:
|
||||
printf '%s' \"<your summary>\" > \"\${SUMMARY_FILE}\"
|
||||
# Signal the orchestrator to create the PR and watch for CI:
|
||||
|
|
@ -604,7 +614,7 @@ write_compact_context "$PHASE_FILE" "$PHASE_PROTOCOL_INSTRUCTIONS"
|
|||
|
||||
if [ "$RECOVERY_MODE" = true ]; then
|
||||
# Build recovery context
|
||||
GIT_DIFF_STAT=$(git -C "$WORKTREE" diff "origin/${PRIMARY_BRANCH}..HEAD" --stat 2>/dev/null | head -20 || echo "(no diff)")
|
||||
GIT_DIFF_STAT=$(git -C "$WORKTREE" diff "${FORGE_REMOTE}/${PRIMARY_BRANCH}..HEAD" --stat 2>/dev/null | head -20 || echo "(no diff)")
|
||||
LAST_PHASE=$(read_phase)
|
||||
rm -f "$PHASE_FILE" # Clear stale phase — new session starts clean
|
||||
CI_RESULT=$(cat "/tmp/ci-result-${PROJECT_NAME}-${ISSUE}.txt" 2>/dev/null || echo "")
|
||||
|
|
|
|||
|
|
@ -114,10 +114,10 @@ ${tmux_output}
|
|||
|
||||
# --- Build phase protocol prompt (shared across agents) ---
|
||||
# Generates the phase-signaling instructions for Claude prompts.
|
||||
# Args: phase_file summary_file branch
|
||||
# Args: phase_file summary_file branch [remote]
|
||||
# Output: The protocol text (stdout)
|
||||
build_phase_protocol_prompt() {
|
||||
local _pf="$1" _sf="$2" _br="$3"
|
||||
local _pf="$1" _sf="$2" _br="$3" _remote="${4:-${FORGE_REMOTE:-origin}}"
|
||||
cat <<_PHASE_PROTOCOL_EOF_
|
||||
## Phase-Signaling Protocol (REQUIRED)
|
||||
|
||||
|
|
@ -135,7 +135,7 @@ SUMMARY_FILE="${_sf}"
|
|||
|
||||
**After committing and pushing your branch:**
|
||||
\`\`\`bash
|
||||
git push origin ${_br}
|
||||
git push ${_remote} ${_br}
|
||||
# Write a short summary of what you implemented:
|
||||
printf '%s' "<your summary>" > "\${SUMMARY_FILE}"
|
||||
# Signal the orchestrator to create the PR and watch for CI:
|
||||
|
|
@ -315,7 +315,7 @@ _on_phase_change() {
|
|||
else
|
||||
log "ERROR: PR creation failed (HTTP ${PR_HTTP_CODE})"
|
||||
notify "failed to create PR (HTTP ${PR_HTTP_CODE})"
|
||||
agent_inject_into_session "$SESSION_NAME" "ERROR: Could not create PR (HTTP ${PR_HTTP_CODE}). Check branch was pushed: git push origin ${BRANCH}. Then write PHASE:awaiting_ci again."
|
||||
agent_inject_into_session "$SESSION_NAME" "ERROR: Could not create PR (HTTP ${PR_HTTP_CODE}). Check branch was pushed: git push ${FORGE_REMOTE:-origin} ${BRANCH}. Then write PHASE:awaiting_ci again."
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
|
@ -398,7 +398,7 @@ Write PHASE:awaiting_review to the phase file, then stop and wait for review fee
|
|||
log "infra failure — retrigger CI (retry ${CI_RETRY_COUNT})"
|
||||
(cd "$WORKTREE" && git commit --allow-empty \
|
||||
-m "ci: retrigger after infra failure (#${ISSUE})" --no-verify 2>&1 | tail -1)
|
||||
(cd "$WORKTREE" && git push origin "$BRANCH" --force 2>&1 | tail -3)
|
||||
(cd "$WORKTREE" && git push "${FORGE_REMOTE:-origin}" "$BRANCH" --force 2>&1 | tail -3)
|
||||
# Touch phase file so we recheck CI on the new SHA
|
||||
# Do NOT update LAST_PHASE_MTIME here — let the main loop detect the fresh mtime
|
||||
touch "$PHASE_FILE"
|
||||
|
|
@ -451,7 +451,7 @@ Instructions:
|
|||
1. Run ci-debug.sh failures to get the full error output.
|
||||
2. Read the failing test file(s) — understand what the tests EXPECT.
|
||||
3. Fix the root cause — do NOT weaken tests.
|
||||
4. Commit your fix and push: git push origin ${BRANCH}
|
||||
4. Commit your fix and push: git push ${FORGE_REMOTE:-origin} ${BRANCH}
|
||||
5. Write: echo \"PHASE:awaiting_ci\" > \"${PHASE_FILE}\"
|
||||
6. Stop and wait."
|
||||
fi
|
||||
|
|
@ -471,7 +471,7 @@ Instructions:
|
|||
PR_NUMBER="$FOUND_PR"
|
||||
log "found PR #${PR_NUMBER}"
|
||||
else
|
||||
agent_inject_into_session "$SESSION_NAME" "ERROR: Cannot find open PR for branch ${BRANCH}. Did you push? Verify with git status and git push origin ${BRANCH}, then write PHASE:awaiting_ci."
|
||||
agent_inject_into_session "$SESSION_NAME" "ERROR: Cannot find open PR for branch ${BRANCH}. Did you push? Verify with git status and git push ${FORGE_REMOTE:-origin} ${BRANCH}, then write PHASE:awaiting_ci."
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
|
|
@ -556,9 +556,9 @@ Instructions:
|
|||
"${API}/issues/${ISSUE}" \
|
||||
-d '{"state":"closed"}' >/dev/null 2>&1 || true
|
||||
# Pull merged primary branch and push to mirrors
|
||||
git -C "$PROJECT_REPO_ROOT" fetch origin "$PRIMARY_BRANCH" 2>/dev/null || true
|
||||
git -C "$PROJECT_REPO_ROOT" fetch "${FORGE_REMOTE:-origin}" "$PRIMARY_BRANCH" 2>/dev/null || true
|
||||
git -C "$PROJECT_REPO_ROOT" checkout "$PRIMARY_BRANCH" 2>/dev/null || true
|
||||
git -C "$PROJECT_REPO_ROOT" pull --ff-only origin "$PRIMARY_BRANCH" 2>/dev/null || true
|
||||
git -C "$PROJECT_REPO_ROOT" pull --ff-only "${FORGE_REMOTE:-origin}" "$PRIMARY_BRANCH" 2>/dev/null || true
|
||||
mirror_push
|
||||
printf 'PHASE:done\n' > "$PHASE_FILE"
|
||||
elif [ "$_merge_rc" -ne 2 ]; then
|
||||
|
|
@ -566,8 +566,8 @@ Instructions:
|
|||
agent_inject_into_session "$SESSION_NAME" "Approved! PR #${PR_NUMBER} has been approved, but the merge failed (likely conflicts).
|
||||
|
||||
Rebase onto ${PRIMARY_BRANCH} and push:
|
||||
git fetch origin ${PRIMARY_BRANCH} && git rebase origin/${PRIMARY_BRANCH}
|
||||
git push --force-with-lease origin ${BRANCH}
|
||||
git fetch ${FORGE_REMOTE:-origin} ${PRIMARY_BRANCH} && git rebase ${FORGE_REMOTE:-origin}/${PRIMARY_BRANCH}
|
||||
git push --force-with-lease ${FORGE_REMOTE:-origin} ${BRANCH}
|
||||
echo \"PHASE:awaiting_ci\" > \"${PHASE_FILE}\"
|
||||
|
||||
Do NOT merge or close the issue — the orchestrator handles that after CI passes.
|
||||
|
|
@ -590,7 +590,7 @@ ${REVIEW_TEXT}
|
|||
Instructions:
|
||||
1. Address each piece of feedback carefully.
|
||||
2. Run lint and tests when done.
|
||||
3. Commit your changes and push: git push origin ${BRANCH}
|
||||
3. Commit your changes and push: git push ${FORGE_REMOTE:-origin} ${BRANCH}
|
||||
4. Write: echo \"PHASE:awaiting_ci\" > \"${PHASE_FILE}\"
|
||||
5. Stop and wait for the next CI result."
|
||||
log "review REQUEST_CHANGES received (round ${REVIEW_ROUND})"
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ ${review_text}
|
|||
Instructions:
|
||||
1. Address each piece of feedback carefully.
|
||||
2. Run lint and tests when done.
|
||||
3. Commit your changes and push: git push origin ${pr_branch}
|
||||
3. Commit your changes and push: git push ${FORGE_REMOTE:-origin} ${pr_branch}
|
||||
4. Write: echo \"PHASE:awaiting_ci\" > \"${phase_file}\"
|
||||
5. Stop and wait for the next CI result."
|
||||
fi
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue