Skip to content
This repository was archived by the owner on May 24, 2026. It is now read-only.

Commit 29482b1

Browse files
PureWeenCopilot
andauthored
feat: auto-fix feedback loop — tests fail → /fix → retest (#750)
Closes the loop between test failures and the fix agent. ``` agent-fix creates PR → tests fail → auto-fix-on-failure fires → dispatches /fix on the PR → /fix reads failure, fixes code → pushes to PR → tests re-run → pass ✅ (or loop up to 3x) ``` Uses `workflow_run` trigger on verify-build + polypilot-integration completion. Max 3 attempts with comment tracking to prevent infinite loops. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 9c56986 commit 29482b1

1 file changed

Lines changed: 112 additions & 0 deletions

File tree

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
name: "Auto-Fix on Test Failure"
2+
3+
# Triggers when verify-build or polypilot-integration completes.
4+
# If any job failed AND the run was for a PR, dispatches /fix to
5+
# read the failure logs and fix the code — creating a feedback loop.
6+
7+
on:
8+
workflow_run:
9+
workflows:
10+
- "Verify Build (Cross-Platform)"
11+
- "PolyPilot Integration Test"
12+
types: [completed]
13+
branches-ignore:
14+
- main
15+
16+
env:
17+
GH_TOKEN: ${{ github.token }}
18+
19+
jobs:
20+
check-and-fix:
21+
name: Check results and trigger fix if needed
22+
runs-on: ubuntu-latest
23+
if: github.event.workflow_run.conclusion == 'failure'
24+
permissions:
25+
actions: write
26+
pull-requests: read
27+
28+
steps:
29+
- name: Find associated PR
30+
id: find-pr
31+
run: |
32+
BRANCH="${{ github.event.workflow_run.head_branch }}"
33+
FAILED_WORKFLOW="${{ github.event.workflow_run.name }}"
34+
FAILED_RUN="${{ github.event.workflow_run.id }}"
35+
echo "Branch: $BRANCH"
36+
echo "Failed workflow: $FAILED_WORKFLOW"
37+
echo "Failed run: $FAILED_RUN"
38+
39+
# Find open PR for this branch
40+
PR_NUMBER=$(gh pr list --repo ${{ github.repository }} \
41+
--head "$BRANCH" --state open \
42+
--json number --jq '.[0].number // empty')
43+
44+
if [ -z "$PR_NUMBER" ]; then
45+
echo "No open PR found for branch $BRANCH — skipping"
46+
echo "has_pr=false" >> $GITHUB_OUTPUT
47+
exit 0
48+
fi
49+
50+
echo "Found PR #$PR_NUMBER"
51+
echo "pr_number=$PR_NUMBER" >> $GITHUB_OUTPUT
52+
echo "has_pr=true" >> $GITHUB_OUTPUT
53+
echo "branch=$BRANCH" >> $GITHUB_OUTPUT
54+
echo "failed_workflow=$FAILED_WORKFLOW" >> $GITHUB_OUTPUT
55+
echo "failed_run=$FAILED_RUN" >> $GITHUB_OUTPUT
56+
57+
- name: Check fix attempt count
58+
id: check-count
59+
if: steps.find-pr.outputs.has_pr == 'true'
60+
run: |
61+
PR=${{ steps.find-pr.outputs.pr_number }}
62+
# Count how many auto-fix comments already exist on this PR
63+
# to prevent infinite loops
64+
FIX_COUNT=$(gh pr view "$PR" --repo ${{ github.repository }} \
65+
--json comments --jq '[.comments[].body | select(contains("Auto-fix triggered"))] | length')
66+
echo "Previous auto-fix attempts: $FIX_COUNT"
67+
echo "fix_count=$FIX_COUNT" >> $GITHUB_OUTPUT
68+
69+
if [ "$FIX_COUNT" -ge 3 ]; then
70+
echo "Max auto-fix attempts (3) reached — stopping loop"
71+
echo "should_fix=false" >> $GITHUB_OUTPUT
72+
else
73+
echo "should_fix=true" >> $GITHUB_OUTPUT
74+
fi
75+
76+
- name: Dispatch /fix on the PR
77+
if: steps.find-pr.outputs.has_pr == 'true' && steps.check-count.outputs.should_fix == 'true'
78+
run: |
79+
PR=${{ steps.find-pr.outputs.pr_number }}
80+
BRANCH="${{ steps.find-pr.outputs.branch }}"
81+
FAILED="${{ steps.find-pr.outputs.failed_workflow }}"
82+
FAILED_RUN="${{ steps.find-pr.outputs.failed_run }}"
83+
ATTEMPT=$(( ${{ steps.check-count.outputs.fix_count }} + 1 ))
84+
85+
echo "Dispatching /fix on PR #$PR (attempt $ATTEMPT)"
86+
87+
# Post a comment so the fix agent has context about what failed
88+
gh pr comment "$PR" --repo ${{ github.repository }} --body \
89+
"## 🔄 Auto-fix triggered (attempt $ATTEMPT/3)
90+
91+
**$FAILED** [failed](https://github.com/${{ github.repository }}/actions/runs/$FAILED_RUN) on branch \`$BRANCH\`.
92+
93+
Dispatching \`/fix\` to review the failure and apply corrections.
94+
[Failed run logs](https://github.com/${{ github.repository }}/actions/runs/$FAILED_RUN)"
95+
96+
# Dispatch the fix.agent workflow against this PR
97+
gh workflow run fix.agent.lock.yml \
98+
--repo ${{ github.repository }} \
99+
--ref main \
100+
-f pr_number="$PR"
101+
102+
- name: Post max-attempts notice
103+
if: steps.find-pr.outputs.has_pr == 'true' && steps.check-count.outputs.should_fix == 'false'
104+
run: |
105+
PR=${{ steps.find-pr.outputs.pr_number }}
106+
gh pr comment "$PR" --repo ${{ github.repository }} --body \
107+
"## ⚠️ Auto-fix loop stopped (3/3 attempts)
108+
109+
The automated fix loop has reached the maximum of 3 attempts.
110+
The test failures require manual investigation.
111+
112+
[Latest failed run](https://github.com/${{ github.repository }}/actions/runs/${{ steps.find-pr.outputs.failed_run }})"

0 commit comments

Comments
 (0)