feat(agent-queue): per-repo verify + opt-in auto-merge for PR jobs
Claim now carries verify (drives the existing verify gate -> PR opens only if it passes) and autoMerge (squash-merge via gh pr merge after the PR opens, non-fatal). selftest covers both. Generated with [Devin](https://cli.devin.ai/docs) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
parent
e634d4915f
commit
b442b95728
@ -709,6 +709,17 @@ _fleet_pr_open() {
|
||||
printf '%s' "$url" | tr -d '\n'
|
||||
}
|
||||
|
||||
# Auto-merge a PR (opt-in via the job's autoMerge flag). Squash-merges and deletes
|
||||
# the branch; non-fatal — a failure (e.g. branch protection / required checks) leaves
|
||||
# the PR open. Returns 0 on merge.
|
||||
_fleet_pr_merge() {
|
||||
local dir=$1 url=$2 logf=$3
|
||||
if ( cd "$dir" && "$GH_BIN" pr merge "$url" --squash --delete-branch >>"$logf" 2>&1 ); then
|
||||
echo "PR auto-merged: $url" >>"$logf"; return 0
|
||||
fi
|
||||
echo "PR: auto-merge failed — left open: $url" >>"$logf"; return 1
|
||||
}
|
||||
|
||||
# ── Worker: runs one job to completion (invoked in background) ───────
|
||||
run_worker() {
|
||||
local doing_file=$1
|
||||
@ -796,10 +807,11 @@ run_worker() {
|
||||
# agent in an isolated checkout on branch aq/job/<id> instead of the static
|
||||
# cwd. The PR is opened after a passing verify. WIP checkpointing is skipped
|
||||
# for PR jobs — the pushed PR branch is the durable artifact. ──
|
||||
local pr_dir="" pr_base="" pr_repo="" pr_jid=""
|
||||
local pr_dir="" pr_base="" pr_repo="" pr_jid="" pr_automerge=""
|
||||
if [[ "${AQ_FLEET_PR:-0}" == 1 ]] && fleet_enabled && _fleet_is_job "$job"; then
|
||||
pr_repo=$(fm_get "$doing_file" fleet-repo "")
|
||||
pr_base=$(fm_get "$doing_file" fleet-base-branch "main")
|
||||
pr_automerge=$(fm_get "$doing_file" fleet-automerge "")
|
||||
# Branch off the stable fleet job id (not the transient local job name).
|
||||
pr_jid=$(fm_get "$doing_file" fleet-job-id "$job")
|
||||
if [[ -n "$pr_repo" ]]; then
|
||||
@ -966,6 +978,8 @@ run_worker() {
|
||||
if [[ -n "$_prurl" ]]; then
|
||||
{ echo "pr_url=$_prurl"; echo "pr_branch=aq/job/$pr_jid"; } >> "$metaf"
|
||||
echo "PR opened: $_prurl" >> "$logf"
|
||||
# Opt-in auto-merge (job autoMerge flag): squash-merge the PR now.
|
||||
[[ "$pr_automerge" == "true" ]] && _fleet_pr_merge "$pr_dir" "$_prurl" "$logf"
|
||||
if fleet_enabled && _fleet_is_job "$job"; then fleet_report_insights "$job" testing; fi
|
||||
fi
|
||||
fi
|
||||
|
||||
@ -185,12 +185,14 @@ fleet_claim() {
|
||||
case "$FLEET_CODE" in 2*) :;; *) err "fleet: claim failed (HTTP ${FLEET_CODE:-error})"; return 1;; esac
|
||||
printf '%s' "$FLEET_BODY" | grep -q '"claimed"[[:space:]]*:[[:space:]]*true' || return 2
|
||||
|
||||
local jid body_md epoch repo base_branch
|
||||
local jid body_md epoch repo base_branch verify automerge=""
|
||||
jid=$(printf '%s' "$FLEET_BODY" | _json_str id)
|
||||
body_md=$(printf '%s' "$FLEET_BODY" | _json_str bodyMd)
|
||||
epoch=$(printf '%s' "$FLEET_BODY" | _fleet_json_num leaseEpoch)
|
||||
repo=$(printf '%s' "$FLEET_BODY" | _json_str repo)
|
||||
base_branch=$(printf '%s' "$FLEET_BODY" | _json_str baseBranch)
|
||||
verify=$(printf '%s' "$FLEET_BODY" | _json_str verify)
|
||||
printf '%s' "$FLEET_BODY" | grep -q '"autoMerge"[[:space:]]*:[[:space:]]*true' && automerge=true
|
||||
[[ -n "$jid" ]] || { err "fleet: claim returned no job id"; return 1; }
|
||||
|
||||
# Materialize a transient local job .md (same approach as from-tracker) so the
|
||||
@ -208,6 +210,9 @@ fleet_claim() {
|
||||
echo "fleet-lease-epoch: ${epoch:-0}"
|
||||
[[ -n "$repo" ]] && echo "fleet-repo: $repo"
|
||||
[[ -n "$base_branch" ]] && echo "fleet-base-branch: $base_branch"
|
||||
# Per-repo verify command (drives the existing verify gate) + auto-merge flag.
|
||||
[[ -n "$verify" ]] && echo "verify: $verify"
|
||||
[[ -n "$automerge" ]] && echo "fleet-automerge: true"
|
||||
echo "idempotency-key: fleet-$jid"
|
||||
echo "---"
|
||||
echo
|
||||
|
||||
@ -775,6 +775,8 @@ case "$1 $2" in
|
||||
[ -n "${AQ_FSTUB_CLAIM_FLAG:-}" ] && : > "$AQ_FSTUB_CLAIM_FLAG"
|
||||
repo_field=""
|
||||
[ -n "${AQ_FSTUB_REPO:-}" ] && repo_field=",\"repo\":\"${AQ_FSTUB_REPO}\",\"baseBranch\":\"${AQ_FSTUB_BASE:-main}\""
|
||||
[ -n "${AQ_FSTUB_VERIFY:-}" ] && repo_field="${repo_field},\"verify\":\"${AQ_FSTUB_VERIFY}\""
|
||||
[ "${AQ_FSTUB_AUTOMERGE:-}" = "1" ] && repo_field="${repo_field},\"autoMerge\":true"
|
||||
printf '{"claimed":true,"job":{"id":"%s","bodyMd":"%s","leaseEpoch":1%s},"lease":{"leaseEpoch":1}}\n200\n' \
|
||||
"${AQ_FSTUB_JOB_ID:-fjob_1}" "${AQ_FSTUB_BODY:-do the work}" "$repo_field"
|
||||
fi ;;
|
||||
@ -877,23 +879,25 @@ 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="$prbare" 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_VERIFY=true AGENT_QUEUE_POLL=1 \
|
||||
AQ_FLEET=1 AQ_FLEET_PR=1 AQ_FLEET_AUTOSHIP=1 AGENT_QUEUE_POLL=1 \
|
||||
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 \
|
||||
&& grep -q 'pr merge' "$tmp/gh-calls.log" 2>/dev/null \
|
||||
&& git -C "$prbare" ls-tree -r aq/job/fjob_pr --name-only 2>/dev/null | grep -qx 'PR_CHANGE.md' \
|
||||
&& ! git -C "$prbare" ls-tree -r aq/job/fjob_pr --name-only 2>/dev/null | grep -qx '.aq_pr.md' \
|
||||
&& grep -q '/fleet/jobs/fjob_pr/lease/release :: .*"prUrl":"https://github.com/test/repo/pull/7"' "$AQ_FSTUB_CALLS"; then
|
||||
pass "fleet PR mode: agent-authored PR title used + .aq_pr.md not committed + prUrl reported"
|
||||
pass "fleet PR mode: authored title + verify gate + auto-merge (gh pr merge) + prUrl reported"
|
||||
else
|
||||
echo "gh-calls: $(cat "$tmp/gh-calls.log" 2>/dev/null)" >&2
|
||||
echo "tree: $(git -C "$prbare" ls-tree -r aq/job/fjob_pr --name-only 2>/dev/null | tr '\n' ' ')" >&2
|
||||
grep release "$AQ_FSTUB_CALLS" >&2 2>/dev/null
|
||||
fail "PR mode did not push branch / use authored title / report prUrl"
|
||||
fail "PR mode did not push branch / authored title / auto-merge / report prUrl"
|
||||
fi
|
||||
unset AQ_FSTUB_REPO AQ_FSTUB_BASE
|
||||
unset AQ_FSTUB_REPO AQ_FSTUB_BASE AQ_FSTUB_VERIFY AQ_FSTUB_AUTOMERGE
|
||||
|
||||
# 36. FENCING: PATCH returns conflict (stale epoch) → worker self-aborts, job is
|
||||
# quarantined to failed/ (NOT review/testing/shipped), fenced is recorded.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user