Skip to content

feat(workflow): replace dispatch-based ci-ready with centralized CI status poller#7674

Draft
BYK wants to merge 1 commit intomainfrom
feat/ci-status-poller
Draft

feat(workflow): replace dispatch-based ci-ready with centralized CI status poller#7674
BYK wants to merge 1 commit intomainfrom
feat/ci-status-poller

Conversation

@BYK
Copy link
Copy Markdown
Member

@BYK BYK commented Apr 1, 2026

Summary

Replace per-release idle polling inside Docker containers with a self-contained, self-dispatching CI status checker. Zero changes needed in craft or target repos.

How it works

The workflow handles the entire lifecycle:

  1. `issues: opened` → new publish issue created → adds `ci-pending` label
  2. `repository_dispatch: check-ci-status` → checks CI status for all `ci-pending` issues via GitHub API
  3. If CI passed → replaces `ci-pending` with `ci-ready` (using app token so the label event triggers `publish.yml`)
  4. If CI still pending → sleeps 3 min, self-dispatches to re-check (capped at 120 attempts / ~6 hours)
  5. If no pending issues → exits immediately

Zero runner cost when there are no pending releases. Each check run is ~30 seconds. Self-dispatching via `repository_dispatch` is one of the few events GitHub explicitly allows `GITHUB_TOKEN` to trigger.

Why

`craft publish` currently polls GitHub's commit status API every 30 seconds for up to 60 minutes inside a Docker container. This idle polling is billed as GitHub Actions minutes and steals from our available capacity — a publish job that waits 45 minutes for CI burns 45 minutes of runner time doing nothing but `sleep 30` in a loop. For repos like sentry-native (~1h 23m CI), it also exhausts the 1-hour GitHub App token lifetime, causing expired-token failures (getsentry/craft#788).

With the poller, the publish job doesn't start at all until CI passes — the expensive Docker job gets a fresh token and runs only for the actual publishing.

Backward Compatibility

  • Issues created by the existing craft action (no `ci-pending` label) → the `publish.yml` gate treats them as old-style and runs with legacy in-Docker polling. Zero behavioral change.
  • New issues (created after this merges) → automatically get `ci-pending` from the `issues: opened` handler, poller takes over.

ci-pending.yml: triggered on issues:opened, adds ci-pending label
  and sets CI_POLLER_HAS_PENDING repo variable to "true".

ci-poller.yml: cron (*/5 min) with job-level if that checks
  vars.CI_POLLER_HAS_PENDING — when "false", no runner is provisioned
  (zero cost). When "true", checks CI status for all ci-pending issues
  and flips to ci-ready when green. Resets variable to "false" when
  all pending issues are resolved.

Requires creating a CI_POLLER_HAS_PENDING repo variable (initial
value: "false") before deploying.
@BYK BYK force-pushed the feat/ci-status-poller branch from 80c8abd to b9db9cd Compare April 1, 2026 23:29
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.

1 participant