github-actions.yml 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. # OPTIONAL scheduler — use this ONLY if your repo already lives on GitHub. The portable,
  2. # runner-agnostic path is loop-run.sh (cron / Windows Task Scheduler / systemd / by hand) —
  3. # no GitHub Actions dependency. This file just wraps the same loop-run.sh idea in Actions.
  4. # Copy to .github/workflows/pr-watch.yml, PIN the action/CLI versions, add the
  5. # ANTHROPIC_API_KEY secret. The SCHEDULER is the authorizer (no auto-mode session in the
  6. # loop), and the child runs gated (--permission-mode dontAsk + a narrow allowlist), never
  7. # bypassPermissions on a shared runner. See references/claude-code-loops.md.
  8. name: pr-watch
  9. on:
  10. schedule:
  11. - cron: "*/10 * * * *" # every 10 min (matches loop.config.yaml cadence: 10m)
  12. workflow_dispatch: {}
  13. permissions:
  14. contents: write # commit STATE.md / run-log.md back
  15. pull-requests: write # post the at-most-one summary comment (L1 stays report-only)
  16. concurrency:
  17. group: pr-watch # never overlap two ticks
  18. cancel-in-progress: false
  19. jobs:
  20. tick:
  21. runs-on: ubuntu-latest
  22. steps:
  23. - uses: actions/checkout@v4 # <-- pin to a SHA in production
  24. # Kill switch: a 'loop-pause' label on the repo, or a committed PAUSED sentinel.
  25. - name: Honor the kill switch
  26. id: gate
  27. env: { GH_TOKEN: "${{ github.token }}" }
  28. run: |
  29. if [ -f .loops/pr-watch/PAUSED ]; then echo "paused=1" >> "$GITHUB_OUTPUT"; fi
  30. if gh label list --limit 100 | grep -qi '^loop-pause'; then echo "paused=1" >> "$GITHUB_OUTPUT"; fi
  31. - name: Install Claude Code
  32. if: steps.gate.outputs.paused != '1'
  33. run: npm i -g @anthropic-ai/claude-code # <-- pin a version
  34. # The run: same prompt every tick (cache-friendly), gated with dontAsk + an
  35. # allowlist scoped to exactly what an L1 report loop needs (read-only + gh + STATE writes).
  36. - name: Run one tick
  37. if: steps.gate.outputs.paused != '1'
  38. env:
  39. ANTHROPIC_API_KEY: "${{ secrets.ANTHROPIC_API_KEY }}"
  40. run: |
  41. cd .loops/pr-watch
  42. claude -p "$(cat run.md)" \
  43. --permission-mode dontAsk \
  44. --append-system-prompt "$(cat STATE.md)" \
  45. --allowedTools 'Bash(gh pr list:*)' 'Bash(gh pr view:*)' 'Bash(gh pr comment:*)' 'Read' 'Write(STATE.md)' 'Write(run-log.md)' \
  46. --max-turns 30
  47. - name: Persist STATE + run-log
  48. if: steps.gate.outputs.paused != '1'
  49. run: |
  50. git config user.name "pr-watch-loop"
  51. git config user.email "loop@users.noreply.github.com"
  52. git add .loops/pr-watch/STATE.md .loops/pr-watch/run-log.md
  53. git diff --cached --quiet || git commit -m "chore(loop): pr-watch tick $(date -u +%FT%TZ)"
  54. git push