Skip to content

Fix #86: Monitor CI on clayde PRs and self-fix failing pipelines#87

Open
ClaydeCode wants to merge 1 commit into
mainfrom
clayde/issue-86
Open

Fix #86: Monitor CI on clayde PRs and self-fix failing pipelines#87
ClaydeCode wants to merge 1 commit into
mainfrom
clayde/issue-86

Conversation

@ClaydeCode
Copy link
Copy Markdown
Owner

Summary

Closes #86.

Clayde now treats a failing CI pipeline on one of its own PRs as a blocking signal and fixes it autonomously, instead of only reacting to human review comments.

When an issue's PR is open and there is no new human activity in a cycle, _handle_ci_fix() checks the PR head commit's check runs:

  1. Fetches failed check runs via the GitHub Checks API (get_check_runs).
  2. Filters to required checks when branch protection defines them (get_required_check_names); on unprotected branches every failed check is treated as blocking.
  3. If a required check failed and no fix has been attempted for that head SHA, invokes the new fix_ci task — Claude reads the failing job logs (gh run view --log-failed), pushes a fix to the PR branch, and posts an issue comment summarising what failed and what changed.
  4. Re-checks each cycle. A new push produces a new SHA, so the next failure is eligible for another attempt — capped at CLAYDE_CI_FIX_MAX_ATTEMPTS (default 3) per PR.
  5. Once the budget is spent, the operator is notified once via ntfy ("Clayde: CI still failing after N attempts") and Clayde stops attempting.
  6. Green or pending CI falls through to the existing review-monitoring logic unchanged.

Loop-safety

The attempt counter and attempted head SHA are recorded before invoking Claude, so a crash or usage limit can never cause an endless retry on the same commit. last_ci_fix_attempt_sha dedupes per-commit; ci_fix_attempts enforces the global per-PR cap.

New state fields

ci_fix_attempts, last_ci_fix_attempt_sha, ci_fix_exhausted_notified.

Testing

uv run pytest — 371 passed (30 new: check-run helpers, the fix_ci task, _handle_ci_fix, and the _handle_issue integration).

Recommended reading order

  1. src/clayde/github.py — new get_check_runs() / get_required_check_names() helpers (the data layer).
  2. src/clayde/config.pyci_fix_max_attempts setting.
  3. src/clayde/prompts/fix_ci.j2 — the prompt Claude receives.
  4. src/clayde/tasks/fix_ci.py — the CI-fix task (mirrors tasks/work.py).
  5. src/clayde/orchestrator.py_handle_issue restructure + _handle_ci_fix() / _notify_ci_exhausted() (how it all wires together).
  6. tests/test_github.py, test_tasks_fix_ci.py, test_orchestrator.py.
  7. DocsREADME.md, CLAUDE.md, config.env.template.

🤖 Generated with Claude Code

When an issue's PR is open and there is no new human activity, the
orchestrator now checks the PR head commit's check runs. If a required
check has failed and a fix has not yet been attempted for that head SHA,
the new fix_ci task invokes Claude to diagnose the failing job logs and
push a fix to the branch. Attempts are capped per PR by
CLAYDE_CI_FIX_MAX_ATTEMPTS (default 3); once exhausted the operator is
notified once via ntfy. Green/pending CI falls through to normal review
monitoring unchanged.

- github.py: get_check_runs() (failed check runs for a SHA),
  get_required_check_names() (required checks from branch protection)
- tasks/fix_ci.py + prompts/fix_ci.j2: the CI-fix task and its prompt
- orchestrator._handle_ci_fix(): CI monitoring, per-SHA + max-attempts
  loop-safety, exhaustion notification
- state: ci_fix_attempts, last_ci_fix_attempt_sha, ci_fix_exhausted_notified
- config: ci_fix_max_attempts setting
- docs: README, CLAUDE.md, config.env.template

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Monitor CI status on clayde-opened PRs and self-fix failing pipelines

1 participant