Skip to content

feat(repository_hub): report build status via GitHub Checks API for App repos#1049

Draft
skipi wants to merge 1 commit into
mainfrom
mk/checks-api
Draft

feat(repository_hub): report build status via GitHub Checks API for App repos#1049
skipi wants to merge 1 commit into
mainfrom
mk/checks-api

Conversation

@skipi

@skipi skipi commented Jun 2, 2026

Copy link
Copy Markdown
Collaborator

What

Adds a path to report CI build status to GitHub via the Checks API (check-runs) for GitHub App-connected repositories, behind the :github_checks_api org feature flag. OAuth-connected repos and flag-off App repos keep the legacy Commit Status API.

Why

The Commit Status API is append-only — every update creates a new status object, and GitHub caps a commit at 1000 statuses per (sha, context). High-block pipelines hit that ceiling. Check-runs are a single mutable object per (sha, name), updated through its lifecycle — removing the cap and unlocking richer PR UX (annotations, re-run actions) as future work.

How

  • New RepositoryHub.GithubChecksClient (Tesla) — create_check_run / update_check_run / find_check_run; find returns the latest run by id (GitHub's list order is not guaranteed).
  • create_build_status_action (GitHub adapter) chooses the path: github_app + flag on → check-run upsert by (commit_sha, name); otherwise the legacy commit status. The decision is local to repository_hub — no proto and no github_notifier change.
  • repository_hub gains the feature_provider dependency + provider module, plus a test-env YAML provider so the existing suite makes no network calls.
  • The check-run name equals the legacy status context string (ci/semaphoreci/{push|pr|tag}: {name}), so branch-protection "required status checks" keep matching with no user action.

Lifecycle (upsert)

  • PENDING → update the latest open run, or create in_progress (never re-opens a completed run, so a rebuild starts a fresh run).
  • SUCCESS / FAILURE / STOPPED → update the latest run to completed with conclusion success / failure / cancelled, or create it.
  • A check-run write failure fails the request — the flag is the revert; there is no dual-write.

Constraints / rollout

  • Check-runs require a GitHub App installation token; OAuth tokens get a 403. github_oauth_token repos therefore remain on commit statuses.
  • Requires the :github_checks_api feature to be registered and enabled per org before any behavior changes — merging alone changes nothing.
  • A PR whose head commit already has a pending commit-status of the same name (from before enabling) can stay blocked until a re-push, because GitHub requires both a same-named status and check. Ramp per org (internal → beta → GA).

Testing

mix test17 examples, 0 failures (--warnings-as-errors, OTP 25):

  • github_checks_client_test.exs — create / update / find, including latest-by-id among several same-named runs.
  • create_build_status_action_test.exs — flag on/off, PENDING/SUCCESS, existing-in_progress reuse, completed-run rebuild → fresh run, find-miss fallback, error propagation, plus OAuth and App parity.

Draft: paused pending review and per-org flag rollout planning.

🤖 Generated with Claude Code

…pp repos

Behind the `:github_checks_api` org feature flag, `github_app`-integrated
repositories now report CI status as native GitHub check-runs instead of legacy
commit statuses. Check-runs are upserted per `(commit_sha, name)` — created on
the pending event, updated on completion — which removes the legacy
1000-statuses-per-`(sha, context)` cap and keeps a single mutable status object
per context.

`github_oauth_token` repositories and flag-off App repos keep the Commit Status
API: check-runs can only be created with a GitHub App installation token (OAuth
tokens 403). The check-run name equals the existing status context string, so
branch-protection "required status checks" keep matching with no customer action.

- New `RepositoryHub.GithubChecksClient` (Tesla): create/update/find check-run;
  find returns the latest run by id (GitHub's list order is not guaranteed).
- `repository_hub` gains the `feature_provider` dep + provider; the status-vs-check
  choice is made entirely in `create_build_status_action` — no proto or
  github_notifier change. A check-run write failure fails the request; the flag
  is the revert.

Co-Authored-By: Claude Opus 4.8 (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

Status: Backlog

Development

Successfully merging this pull request may close these issues.

1 participant