From f918e26cce12417262844c39ff59bf4dce956f12 Mon Sep 17 00:00:00 2001 From: johba Date: Thu, 26 Mar 2026 21:46:21 +0100 Subject: [PATCH] dev: rebase on target branch before every push (#770) (#775) Fixes #770 The dev agent was pushing fixes without rebasing. If main moved since the branch was created, the PR becomes unmergeable. This adds a rebase step before every git push in the dev agent workflow: - Initial push after implementing - Push after CI fix - Push after review feedback Rebasing ensures PRs stay up-to-date with the target branch and avoids merge conflicts. Co-authored-by: johba Reviewed-on: https://codeberg.org/johba/disinto/pulls/775 Reviewed-by: Disinto_bot --- .woodpecker/agent-smoke.sh | 8 ++++---- dev/dev-agent.sh | 10 ++++++++-- dev/phase-handler.sh | 37 ++++++++++++++++++++++++++++++++----- 3 files changed, 44 insertions(+), 11 deletions(-) diff --git a/.woodpecker/agent-smoke.sh b/.woodpecker/agent-smoke.sh index 80b6160..322bcf0 100644 --- a/.woodpecker/agent-smoke.sh +++ b/.woodpecker/agent-smoke.sh @@ -178,7 +178,7 @@ check_script() { # Inline-sourced lib files — check that their own function calls resolve. # These are already in LIB_FUNS (their definitions are available to agents), # but this verifies calls *within* each lib file are also resolvable. -check_script lib/env.sh +check_script lib/env.sh lib/mirrors.sh check_script lib/agent-session.sh check_script lib/ci-helpers.sh check_script lib/secret-scan.sh @@ -186,7 +186,7 @@ check_script lib/file-action-issue.sh lib/secret-scan.sh check_script lib/tea-helpers.sh lib/secret-scan.sh check_script lib/formula-session.sh lib/agent-session.sh check_script lib/load-project.sh -check_script lib/mirrors.sh +check_script lib/mirrors.sh lib/env.sh check_script lib/guard.sh # Standalone lib scripts (not sourced by agents; run directly or as services). @@ -201,9 +201,9 @@ check_script dev/phase-handler.sh dev/dev-agent.sh lib/secret-scan.sh check_script dev/dev-poll.sh check_script dev/phase-test.sh check_script gardener/gardener-run.sh -check_script review/review-pr.sh +check_script review/review-pr.sh lib/agent-session.sh check_script review/review-poll.sh -check_script planner/planner-run.sh +check_script planner/planner-run.sh lib/agent-session.sh lib/formula-session.sh check_script supervisor/supervisor-poll.sh check_script supervisor/update-prompt.sh check_script vault/vault-agent.sh diff --git a/dev/dev-agent.sh b/dev/dev-agent.sh index 035f7a0..a717f95 100755 --- a/dev/dev-agent.sh +++ b/dev/dev-agent.sh @@ -538,6 +538,8 @@ SUMMARY_FILE=\"${IMPL_SUMMARY_FILE}\" **After committing and pushing your branch:** \`\`\`bash +# Rebase on target branch before push to avoid merge conflicts +git fetch ${FORGE_REMOTE} ${PRIMARY_BRANCH} && git rebase ${FORGE_REMOTE}/${PRIMARY_BRANCH} git push ${FORGE_REMOTE} ${BRANCH} # Write a short summary of what you implemented: printf '%s' \"\" > \"\${SUMMARY_FILE}\" @@ -553,15 +555,19 @@ echo \"PHASE:awaiting_review\" > \"${PHASE_FILE}\" Then STOP and wait. The orchestrator will inject review feedback. **When you receive a \"CI failed:\" injection:** -Fix the CI issue, commit, push, then: +Fix the CI issue, then rebase on target branch and push: \`\`\`bash +git fetch ${FORGE_REMOTE} ${PRIMARY_BRANCH} && git rebase ${FORGE_REMOTE}/${PRIMARY_BRANCH} +git push --force-with-lease ${FORGE_REMOTE} ${BRANCH} echo \"PHASE:awaiting_ci\" > \"${PHASE_FILE}\" \`\`\` Then STOP and wait. **When you receive a \"Review: REQUEST_CHANGES\" injection:** -Address ALL review feedback, commit, push, then: +Address ALL review feedback, then rebase on target branch and push: \`\`\`bash +git fetch ${FORGE_REMOTE} ${PRIMARY_BRANCH} && git rebase ${FORGE_REMOTE}/${PRIMARY_BRANCH} +git push --force-with-lease ${FORGE_REMOTE} ${BRANCH} echo \"PHASE:awaiting_ci\" > \"${PHASE_FILE}\" \`\`\` (CI runs again after each push — always write awaiting_ci, not awaiting_review) diff --git a/dev/phase-handler.sh b/dev/phase-handler.sh index 5b6833e..ab099d6 100644 --- a/dev/phase-handler.sh +++ b/dev/phase-handler.sh @@ -135,6 +135,8 @@ SUMMARY_FILE="${_sf}" **After committing and pushing your branch:** \`\`\`bash +# Rebase on target branch before push to avoid merge conflicts +git fetch ${_remote} ${PRIMARY_BRANCH} && git rebase ${_remote}/${PRIMARY_BRANCH} git push ${_remote} ${_br} # Write a short summary of what you implemented: printf '%s' "" > "\${SUMMARY_FILE}" @@ -150,15 +152,19 @@ echo "PHASE:awaiting_review" > "${_pf}" Then STOP and wait. The orchestrator will inject review feedback. **When you receive a "CI failed:" injection:** -Fix the CI issue, commit, push, then: +Fix the CI issue, then rebase on target branch and push: \`\`\`bash +git fetch ${_remote} ${PRIMARY_BRANCH} && git rebase ${_remote}/${PRIMARY_BRANCH} +git push --force-with-lease ${_remote} ${_br} echo "PHASE:awaiting_ci" > "${_pf}" \`\`\` Then STOP and wait. **When you receive a "Review: REQUEST_CHANGES" injection:** -Address ALL review feedback, commit, push, then: +Address ALL review feedback, then rebase on target branch and push: \`\`\`bash +git fetch ${_remote} ${PRIMARY_BRANCH} && git rebase ${_remote}/${PRIMARY_BRANCH} +git push --force-with-lease ${_remote} ${_br} echo "PHASE:awaiting_ci" > "${_pf}" \`\`\` (CI runs again after each push — always write awaiting_ci, not awaiting_review) @@ -394,7 +400,26 @@ 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 "${FORGE_REMOTE:-origin}" "$BRANCH" --force 2>&1 | tail -3) + # Rebase on target branch before push to avoid merge conflicts + if ! (cd "$WORKTREE" && \ + git fetch "${FORGE_REMOTE:-origin}" "${PRIMARY_BRANCH}" 2>/dev/null && \ + git rebase "${FORGE_REMOTE:-origin}/${PRIMARY_BRANCH}" 2>&1 | tail -5); then + log "rebase conflict detected — aborting, agent must resolve" + (cd "$WORKTREE" && git rebase --abort 2>/dev/null || git reset --hard HEAD 2>/dev/null) || true + agent_inject_into_session "$SESSION_NAME" "REBASE CONFLICT: Cannot rebase onto ${PRIMARY_BRANCH} automatically. + +Please resolve merge conflicts manually: +1. Check conflict status: git status +2. Resolve conflicts in the conflicted files +3. Stage resolved files: git add +4. Continue rebase: git rebase --continue + +If you cannot resolve conflicts, abort: git rebase --abort +Then write PHASE:escalate with a reason." + return 0 + fi + # Rebase succeeded — push the result + (cd "$WORKTREE" && git push --force-with-lease "${FORGE_REMOTE:-origin}" "$BRANCH" 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" @@ -436,7 +461,8 @@ 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 ${FORGE_REMOTE:-origin} ${BRANCH} +4. Rebase on target branch and push: git fetch ${FORGE_REMOTE:-origin} ${PRIMARY_BRANCH} && git rebase ${FORGE_REMOTE:-origin}/${PRIMARY_BRANCH} + git push --force-with-lease ${FORGE_REMOTE:-origin} ${BRANCH} 5. Write: echo \"PHASE:awaiting_ci\" > \"${PHASE_FILE}\" 6. Stop and wait." fi @@ -577,7 +603,8 @@ ${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 ${FORGE_REMOTE:-origin} ${BRANCH} +3. Rebase on target branch and push: git fetch ${FORGE_REMOTE:-origin} ${PRIMARY_BRANCH} && git rebase ${FORGE_REMOTE:-origin}/${PRIMARY_BRANCH} + git push --force-with-lease ${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})"