Docs

Dependabot CI fix

Dependabot CI fix reacts when a dependency-update PR (Dependabot or Renovate) goes red in CI. When a check suite completes with a failure, Last Light brings the branch up to date with its base, diagnoses the breakage, and pushes the smallest fix that makes CI pass. It is fix-only: it never classifies, labels, or merges the PR. Once the push turns the checks green, the pr.checks_passed webhook hands off to dependabot-pr-merge, the single owner of the trivial-vs-functional classification and the auto-merge decision — so the two workflows never duplicate each other's work.

Permission profile: repo-write — it merges the base branch into the PR branch and pushes commits, but always with a plain (non-force) push so Dependabot / Renovate don't lose track of their own branch. It never labels or merges — that's dependabot-pr-merge's job once the checks go green.

Pipeline

Fix merge base + fix + push pr-merge once green: classify + merge

What it does

  • Clones the repo at the PR's head branch (the dependency bump is already committed there)
  • Merges the base branch into the PR branch first (plain git merge, no rebase or force-push) so the fix is built on current base and a behind PR is brought up to date — resolving any lockfile conflict by regenerating it
  • Reads the CI failures and diagnoses the cause — a stale lockfile, a breaking change in the new version, a call site or type that needs updating
  • Makes the smallest fix that turns CI green, runs the test / lint / typecheck gate, and plain-pushes to the PR branch
  • Stops there — it does not classify, comment, label (except the give-up case below), or merge. The push re-runs CI, and when it goes green the pr.checks_passed webhook fires dependabot-pr-merge to make the one classify / auto-merge decision
Because ci-fix brings the branch current with its base, the PR that dependabot-pr-merge later sees is clean rather than behind — so the merge workflow can act on it directly instead of asking the bot to rebase.

Triggers

  • GitHub webhook: a check_suite.completed event with a failure / timed_out conclusion (surfaced internally as pr.checks_failed). The router runs it through the intent classifier, which routes a recognised dependency-update PR here. Requires the GitHub App to subscribe to Check suite events (Checks: read).
  • Cron backstop: a daily job (fix-red-dependency-prs, 15:00 — one hour after the green sweep) whose runner finds, in code, the Dependabot / Renovate PRs across managed repos that can't merge on their own and that ci-fix can push toward: a settled-red check conclusion (failing/timed-out, so it never fires while checks are still running), or a mergeable_state of behind / dirty / blocked. It fans out one bounded run per PR — the same single-PR shape as the webhook, carrying the PR head branch (pre-clone) and the reason (checks-failing | behind | dirty | blocked; failing CI wins). It runs alongside webhooks — a safety net for PRs that went red, or fell out of a mergeable state, before boot or during a missed delivery. (clean is the green sweep's; unknown is left for a later tick.) Per-PR runs dedup by (repo, PR).
  • Maintainer mention: an @last-light comment on a red Dependabot / Renovate PR (e.g. "can you look at this?"). The router hands the PR author + check state to the classifier, which routes a red dependency PR here — the on-demand version of the webhook. (A green one routes to dependabot-pr-merge instead; an explicit "review this" still gets a normal review.)

Because routing goes through the classifier rather than a fixed rule, other workflows can react to the same failing-checks event by declaring their own classification block — this workflow simply claims the dependency-update case.

Labels

The dependency workflows share a small label state machine so status is visible and the crons don't churn. ci-fix touches labels in only one case: when it can't land the PR — it can't repair CI with a small, safe change, or there's nothing to push and it can't unblock the PR (e.g. a blocked PR awaiting a required human review) — it applies requires-human and stops. The verdict labels (dependency-trivial / dependency-functional) — and clearing a stale requires-human once a later fix lands green — are owned entirely by dependabot-pr-merge, which keeps the classification in one place. Both the red and green cron sweeps skip PRs labelled requires-human, so they never re-attempt what Last Light already gave up on — while the webhooks stay label-blind, so a genuinely new bot push is handled live and the success path clears the label. Labels are created on demand (github_ensure_labels).