@@ -65,28 +65,38 @@ jobs:
6565 with :
6666 gpg-private-key : ${{ secrets.BOT_GPG_PRIVATE_KEY }}
6767
68- - name : Run updating skill with Claude Code
69- id : claude
70- timeout-minutes : 30
68+ - name : Update dependencies (haiku)
69+ id : update
70+ timeout-minutes : 10
7171 env :
7272 ANTHROPIC_API_KEY : ${{ secrets.ANTHROPIC_API_KEY }}
7373 GITHUB_ACTIONS : ' true'
7474 run : |
75+ if [ -n "$SFW_BIN" ]; then
76+ mkdir -p /tmp/sfw-bin
77+ printf '#!/bin/bash\nexec "%s" pnpm "$@"\n' "$SFW_BIN" > /tmp/sfw-bin/pnpm
78+ chmod +x /tmp/sfw-bin/pnpm
79+ export PATH="/tmp/sfw-bin:$PATH"
80+ fi
81+
7582 if [ -z "$ANTHROPIC_API_KEY" ]; then
7683 echo "ANTHROPIC_API_KEY not set - skipping automated update"
7784 echo "success=false" >> $GITHUB_OUTPUT
7885 exit 0
7986 fi
8087
8188 set +e
82- pnpm exec claude --print --dangerously-skip-permissions \
83- --model sonnet \
89+ claude --print \
90+ --allowedTools "Bash(pnpm:*)" "Bash(git add:*)" "Bash(git commit:*)" "Bash(git status:*)" "Bash(git diff:*)" "Bash(git log:*)" "Bash(git rev-parse:*)" "Read" "Write" "Edit" "Glob" "Grep" \
91+ --model haiku \
92+ --max-turns 15 \
8493 "$(cat <<'PROMPT'
8594 /updating
8695
8796 <context>
8897 You are an automated CI agent in a weekly dependency update workflow.
8998 Git is configured with GPG signing. A branch has been created for you.
99+ The pnpm binary is on PATH (wrapped through Socket firewall).
90100 </context>
91101
92102 <instructions>
@@ -103,7 +113,95 @@ jobs:
103113 </success_criteria>
104114 PROMPT
105115 )" \
106- 2>&1 | tee claude-output.log
116+ 2>&1 | tee claude-update.log
117+ CLAUDE_EXIT=${PIPESTATUS[0]}
118+ set -e
119+
120+ if [ "$CLAUDE_EXIT" -eq 0 ]; then
121+ echo "success=true" >> $GITHUB_OUTPUT
122+ else
123+ echo "success=false" >> $GITHUB_OUTPUT
124+ fi
125+
126+ - name : Run tests
127+ id : tests
128+ if : steps.update.outputs.success == 'true'
129+ run : |
130+ if [ -n "$SFW_BIN" ]; then
131+ mkdir -p /tmp/sfw-bin
132+ printf '#!/bin/bash\nexec "%s" pnpm "$@"\n' "$SFW_BIN" > /tmp/sfw-bin/pnpm
133+ chmod +x /tmp/sfw-bin/pnpm
134+ export PATH="/tmp/sfw-bin:$PATH"
135+ fi
136+
137+ set +e
138+ pnpm build 2>&1 | tee build-output.log
139+ BUILD_EXIT=${PIPESTATUS[0]}
140+
141+ pnpm test 2>&1 | tee test-output.log
142+ TEST_EXIT=${PIPESTATUS[0]}
143+ set -e
144+
145+ if [ "$BUILD_EXIT" -eq 0 ] && [ "$TEST_EXIT" -eq 0 ]; then
146+ echo "success=true" >> $GITHUB_OUTPUT
147+ else
148+ echo "success=false" >> $GITHUB_OUTPUT
149+ {
150+ echo "BUILD_LOG<<GHEOF"
151+ tail -50 build-output.log
152+ echo "GHEOF"
153+ } >> $GITHUB_OUTPUT
154+ {
155+ echo "TEST_LOG<<GHEOF"
156+ tail -50 test-output.log
157+ echo "GHEOF"
158+ } >> $GITHUB_OUTPUT
159+ fi
160+
161+ - name : Fix test failures (sonnet)
162+ id : claude
163+ if : steps.update.outputs.success == 'true' && steps.tests.outputs.success == 'false'
164+ timeout-minutes : 15
165+ env :
166+ ANTHROPIC_API_KEY : ${{ secrets.ANTHROPIC_API_KEY }}
167+ GITHUB_ACTIONS : ' true'
168+ BUILD_LOG : ${{ steps.tests.outputs.BUILD_LOG }}
169+ TEST_LOG : ${{ steps.tests.outputs.TEST_LOG }}
170+ run : |
171+ if [ -n "$SFW_BIN" ]; then
172+ mkdir -p /tmp/sfw-bin
173+ printf '#!/bin/bash\nexec "%s" pnpm "$@"\n' "$SFW_BIN" > /tmp/sfw-bin/pnpm
174+ chmod +x /tmp/sfw-bin/pnpm
175+ export PATH="/tmp/sfw-bin:$PATH"
176+ fi
177+
178+ set +e
179+ claude --print \
180+ --allowedTools "Bash(pnpm:*)" "Bash(git add:*)" "Bash(git commit:*)" "Bash(git status:*)" "Bash(git diff:*)" "Bash(git log:*)" "Bash(git rev-parse:*)" "Read" "Write" "Edit" "Glob" "Grep" \
181+ --model sonnet \
182+ --max-turns 25 \
183+ "$(cat <<PROMPT
184+ Dependency updates were applied but tests are failing. Fix the failures.
185+ Git is configured with GPG signing.
186+ The pnpm binary is on PATH (wrapped through Socket firewall).
187+
188+ <build_output>
189+ $BUILD_LOG
190+ </build_output>
191+
192+ <test_output>
193+ $TEST_LOG
194+ </test_output>
195+
196+ <instructions>
197+ 1. Analyze the build and test failures above.
198+ 2. Fix the source code so tests pass (pnpm build && pnpm test).
199+ 3. Commit each fix with a conventional commit message.
200+ 4. Leave all changes local — the workflow handles pushing.
201+ </instructions>
202+ PROMPT
203+ )" \
204+ 2>&1 | tee claude-fix.log
107205 CLAUDE_EXIT=${PIPESTATUS[0]}
108206 set -e
109207
@@ -113,6 +211,40 @@ jobs:
113211 echo "success=false" >> $GITHUB_OUTPUT
114212 fi
115213
214+ - name : Set final status
215+ id : final
216+ if : always()
217+ run : |
218+ UPDATE="${{ steps.update.outputs.success }}"
219+ TESTS="${{ steps.tests.outputs.success }}"
220+ FIX="${{ steps.claude.outputs.success }}"
221+
222+ if [ "$UPDATE" != "true" ]; then
223+ echo "success=false" >> $GITHUB_OUTPUT
224+ elif [ "$TESTS" = "true" ]; then
225+ echo "success=true" >> $GITHUB_OUTPUT
226+ elif [ "$FIX" = "true" ]; then
227+ echo "success=true" >> $GITHUB_OUTPUT
228+ else
229+ echo "success=false" >> $GITHUB_OUTPUT
230+ fi
231+
232+ - name : Validate changes
233+ id : validate
234+ if : steps.final.outputs.success == 'true'
235+ run : |
236+ UNEXPECTED=""
237+ for file in $(git diff --name-only origin/main..HEAD); do
238+ case "$file" in
239+ package.json|*/package.json|pnpm-lock.yaml|*/pnpm-lock.yaml|.npmrc|pnpm-workspace.yaml) ;;
240+ *) UNEXPECTED="$UNEXPECTED $file" ;;
241+ esac
242+ done
243+ if [ -n "$UNEXPECTED" ]; then
244+ echo "::warning::Non-dependency files modified:$UNEXPECTED"
245+ fi
246+ echo "valid=true" >> $GITHUB_OUTPUT
247+
116248 - name : Check for changes
117249 id : changes
118250 run : |
@@ -123,13 +255,13 @@ jobs:
123255 fi
124256
125257 - name : Push branch
126- if : steps.claude .outputs.success == 'true' && steps.changes.outputs.has-changes == 'true'
258+ if : steps.final .outputs.success == 'true' && steps.validate.outputs.valid == 'true' && steps.changes.outputs.has-changes == 'true'
127259 env :
128260 BRANCH_NAME : ${{ steps.branch.outputs.branch }}
129261 run : git push origin "$BRANCH_NAME"
130262
131263 - name : Create Pull Request
132- if : steps.claude .outputs.success == 'true' && steps.changes.outputs.has-changes == 'true'
264+ if : steps.final .outputs.success == 'true' && steps.validate.outputs.valid == 'true' && steps.changes.outputs.has-changes == 'true'
133265 env :
134266 GH_TOKEN : ${{ github.token }}
135267 BRANCH_NAME : ${{ steps.branch.outputs.branch }}
@@ -158,7 +290,7 @@ jobs:
158290 --base main
159291
160292 - name : Add job summary
161- if : steps.claude .outputs.success == 'true' && steps.changes.outputs.has-changes == 'true'
293+ if : steps.final .outputs.success == 'true' && steps.validate.outputs.valid == 'true' && steps.changes.outputs.has-changes == 'true'
162294 env :
163295 BRANCH_NAME : ${{ steps.branch.outputs.branch }}
164296 run : |
@@ -173,7 +305,11 @@ jobs:
173305 uses : actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
174306 with :
175307 name : claude-output-${{ github.run_id }}
176- path : claude-output.log
308+ path : |
309+ claude-update.log
310+ claude-fix.log
311+ build-output.log
312+ test-output.log
177313 retention-days : 7
178314
179315 - uses : SocketDev/socket-registry/.github/actions/cleanup-git-signing@6096b06b1790f411714c89c40f72aade2eeaab7c # main
0 commit comments