ci(config): add Slack notifications to the config release pipeline - #6436
Merged
Conversation
Reuses the CLI release train's Slack webhook (cli-deployer-notifier) for the @supabase/config release pipeline: - slack-notify.yml generalized beyond the CLI: required package display-name input, tag_prefix for config-v changelog links, optional npm_package version-page link, and two new statuses (awaiting-approval, declined). release.yml call sites updated for the new required input; CLI firing conditions unchanged. - release-config.yml pages the channel when a real release arms the config-release approval gate, verifies the published version is registry-visible with the reviewed tarball's integrity and expected dist-tag before the tag push, and reports the outcome — with a fail-open classifier that reads the run's approvals record so a reviewer rejection is announced as declined rather than a broken release.
Contributor
Supabase CLI previewnpx --yes https://pkg.pr.new/supabase/cli/supabase@c7033be22eff249f8305c732fa9dda8514f68f46Preview package for commit |
Contributor
There was a problem hiding this comment.
🤖 AI Review
Both independent reviews completed. Their 7 reports deduplicate to 5 findings, all confirmed by the checked-out code. The most significant issue is that the new dist-tag loop exits on any nonempty version instead of waiting for the expected version. The remaining findings concern misleading failure notifications, publish/tag ordering, and suppressed npm diagnostics. No critical or major issues were verified.
Findings
| Severity | Location | Category | Sources | Claim |
|---|---|---|---|---|
| 🟡 MINOR | .github/workflows/release-config.yml:338 |
ci-correctness |
claude | The dist-tag retry loop stops on any nonempty value rather than the expected version, so a stale registry response bypasses all remaining retries and fails the already-published release. |
| 🟡 MINOR | .github/workflows/release-config.yml:458 |
notification-correctness |
claude+codex | A rejection from an earlier run attempt can cause a later planning failure to be reported as a reviewer-declined release. |
| 🟡 MINOR | .github/workflows/release-config.yml:313 |
release-consistency |
claude | The new npm verification step can fail after publication but before the version tag is pushed, leaving npm published while origin remains untagged and requiring another approval to recover. |
| 🟡 MINOR | .github/workflows/release-config.yml:437 |
notification-correctness |
claude+codex | A workflow-dispatch dry run can send a real release-failure notification if the plan job fails before its plan step writes the dry_run output. |
| ⚪ NIT | .github/workflows/release-config.yml:322 |
observability |
claude | The npm verification probes discard stderr on every attempt, so terminal failures omit the underlying registry, authentication, or network error. |
Stats
Claude findings: 5 · Codex findings: 2 · Confirmed: 5 · Refuted: 0 · Uncertain: 0
Models: claude-opus-5 + gpt-5.6-sol · Trigger: auto · Workflow run
This review runs once per PR. A maintainer can request another with a /ai-review comment.
- Verify step split: pre-tag-push verification is now integrity-only (the tag-push precondition), and the dist-tag assertion moved to its own step after the tag push — a dist-tag propagation hiccup can no longer strand the release npm-published but origin-untagged, and the retry loop now waits for the EXPECTED version instead of breaking on a stale nonempty value. - classify-failure only reports declined when the publish job itself is the failed job (a rejection can only manifest there), so a plan failure after an earlier attempt's rejection pages as a plain failure. - Dry-run guards on the failure notify paths (both trains) read the workflow_dispatch input directly, so a plan job that dies before recording dry_run can't page for an operator-watched dry run. - npm probes capture stderr and surface it on terminal failures.
jgoux
approved these changes
Sep 2, 2026
github-merge-queue
Bot
removed this pull request from the merge queue due to failed status checks
Sep 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Reuses the CLI release train's Slack webhook (
SLACK_RELEASE_WEBHOOK, the cli-deployer-notifier app) for the@supabase/configrelease pipeline, covering both halves of the release lifecycle: paging reviewers when a release is awaiting approval, and confirming the publish actually landed.What changed
slack-notify.ymlis generalized beyond the CLI: a requiredpackagedisplay-name input,tag_prefixso changelog links can point atconfig-v*tags, an optionalnpm_packageinput that adds an npm version-page link to success messages, and two new statuses —awaiting-approvalanddeclined. Unknown statuses now fail the step instead of silently rendering as success.release.ymlpasses the new requiredpackageinput at both call sites. CLI notification firing conditions are unchanged; payload deltas are cosmetic copy only.release-config.yml:notify-slack-approvalpings the channel when a real (non-dry) release arms theconfig-releaseenvironment gate. It needs onlyplan, so it runs while the publish job sits inwaiting— the message links to the run, where the Approve button and the plan job's evidence summary live. The webhook is one-way, so the approval click itself deliberately stays on GitHub.npm publishand before the tag push: it probes the registry with backoff (~2 min budget,--prefer-online) until the version resolves, then requires the packument'sdist.integrityto match the reviewed tarball and the dist-tag to point at the published version. The success notification therefore means registry-visible with the approved bytes, not merely "the job didn't error". The step runs no package-controlled code, preserving the publish job'sid-token: writeboundary.notify-slackposts the success message (npm + changelog links) via the implicitsuccess()gate — dry runs and no-release pushes skip publish and stay silent.classify-failure+notify-slack-failurereport broken releases. The classifier reads the run's approvals record (GET .../actions/runs/{run_id}/approvals) and classifies on the last review's state, so a reviewer rejection is announced as "release not approved" instead of a broken release, while a reject → re-run → approve → genuine-failure sequence still pages as a real failure. The notify job fails open: if the classifier itself breaks, the page still goes out as a plain failure.packages/config/AGENTS.mddocuments the webhook secret as standing invariant 5 (notify jobs are terminal — a missing/rotated webhook reddens the run but cannot affect the release) and the verify step in the publish sequence.Reviewer notes
failure()fires and the declined path is reachable; the approvals endpoint returnsstate ∈ approved|rejected|pendingand is readable with the default token plus job-levelpermissions: actions: read.jq --arg: every new input is a workflow-file literal at all five call sites, and ajq --argmigration would re-escape the literal\nsequences the message bodies rely on. Considered and deliberately not done here.