-
Notifications
You must be signed in to change notification settings - Fork 30
164 lines (149 loc) · 5.69 KB
/
fix-drift.yml
File metadata and controls
164 lines (149 loc) · 5.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
name: Fix Drift
on:
workflow_dispatch:
workflow_run:
workflows: ["Drift Tests"]
types: [completed]
branches: [main]
concurrency:
group: drift-fix
cancel-in-progress: false
jobs:
fix:
if: >-
github.event_name == 'workflow_dispatch' ||
github.event.workflow_run.conclusion == 'failure'
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: write
pull-requests: write
issues: write
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 24
cache: pnpm
- run: pnpm install --frozen-lockfile
# Step 0: Configure git identity and create fix branch
- name: Configure git
run: |
git config user.name "aimock-drift-bot"
git config user.email "[email protected]"
git checkout -B fix/drift-$(date +%Y-%m-%d)-${{ github.run_id }}
# Step 1: Detect drift and produce report
- name: Collect drift report
id: detect
run: |
set +e
npx tsx scripts/drift-report-collector.ts
EXIT_CODE=$?
set -e
echo "exit_code=$EXIT_CODE" >> $GITHUB_OUTPUT
if [ "$EXIT_CODE" -eq 2 ]; then
: # critical drift found, continue
elif [ "$EXIT_CODE" -ne 0 ]; then
echo "::error::Collector script crashed with exit code $EXIT_CODE"
exit $EXIT_CODE
fi
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
# Always upload the report as an artifact
- name: Upload drift report
if: always()
uses: actions/upload-artifact@v4
with:
name: drift-report
path: drift-report.json
if-no-files-found: warn
retention-days: 30
# Step 2: Exit if no critical drift
- name: Check for critical diffs
id: check
env:
DETECT_EXIT_CODE: ${{ steps.detect.outputs.exit_code }}
run: |
if [ "$DETECT_EXIT_CODE" = "2" ]; then
echo "skip=false" >> $GITHUB_OUTPUT
echo "Critical drift detected"
else
echo "skip=true" >> $GITHUB_OUTPUT
echo "No critical drift detected (exit code: $DETECT_EXIT_CODE) — skipping fix"
fi
# Step 3: Invoke Claude Code to fix
- name: Auto-fix drift
if: steps.check.outputs.skip != 'true'
run: npx tsx scripts/fix-drift.ts
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
# Upload Claude Code output for debugging
- name: Upload Claude Code logs
if: always()
uses: actions/upload-artifact@v4
with:
name: claude-code-output
path: claude-code-output.log
if-no-files-found: warn
retention-days: 30
# Step 4: Verify fix independently
- name: Verify conformance
if: steps.check.outputs.skip != 'true'
run: pnpm test
- name: Verify drift resolved
if: steps.check.outputs.skip != 'true'
run: pnpm test:drift
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
GOOGLE_API_KEY: ${{ secrets.GOOGLE_API_KEY }}
# Step 5: Create PR on success
- name: Create PR
id: pr
if: success() && steps.check.outputs.skip != 'true'
run: |
npx tsx scripts/fix-drift.ts --create-pr 2>&1 | tee /tmp/pr-output.txt
PR_URL=$(grep -oE 'https://github.com/[^ ]+/pull/[0-9]+' /tmp/pr-output.txt | head -1)
if [ -z "$PR_URL" ]; then echo "No PR URL found"; exit 1; fi
echo "url=$PR_URL" >> $GITHUB_OUTPUT
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Step 5.5: Auto-merge the drift fix PR
- name: Auto-merge PR
if: success() && steps.pr.outputs.url != ''
run: |
PR_URL="${{ steps.pr.outputs.url }}"
gh pr merge "$PR_URL" --merge --auto
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Step 6: Open issue on failure
- name: Create issue on failure
if: failure() && steps.check.outputs.skip != 'true'
run: npx tsx scripts/fix-drift.ts --create-issue
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# Step 7: Slack notification on successful fix
- name: Notify Slack on fix success
if: success() && steps.pr.outputs.url != ''
run: |
if [ -z "$SLACK_WEBHOOK" ]; then echo "SLACK_WEBHOOK not set, skipping"; exit 0; fi
curl -s -X POST "$SLACK_WEBHOOK" \
-H "Content-Type: application/json" \
-d "{\"text\":\"✅ *Drift auto-fixed and merged*\nPR: ${{ steps.pr.outputs.url }}\nRun: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}\"}"
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
# Step 8: Slack notification on fix failure
- name: Notify Slack on fix failure
if: failure() && steps.check.outputs.skip != 'true'
run: |
if [ -z "$SLACK_WEBHOOK" ]; then echo "SLACK_WEBHOOK not set, skipping"; exit 0; fi
curl -s -X POST "$SLACK_WEBHOOK" \
-H "Content-Type: application/json" \
-d "{\"text\":\"❌ *Drift auto-fix failed* — issue created\nRun: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}\"}"
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}