Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
101 commits
Select commit Hold shift + click to select a range
0c35ecb
fix(cli): drop entitlements lookup at enveloped plan gates (#7395)
pamelachia Nov 2, 2026
3624bb3
fix(cli): skip docker's first health check wait (CLI-2901) (#7430)
7ttp Nov 2, 2026
c3f3ef2
ci(cli): judge block-scoped benchmark timings by per-block spread (#7…
Prashansa-K Nov 2, 2026
ba3329c
test(cli): mask default postgres image in container input goldens (#7…
avallete Nov 2, 2026
02398c6
fix(api): keep annotated binary request bodies typed as BinaryInput (…
avallete Nov 2, 2026
deeaf91
chore(stack): bump postgres to 17.11.0.016-r0 (#7408)
supabase-cli-releaser[bot] Nov 2, 2026
feb39e8
chore(api): sync Management API OpenAPI spec (#7418)
supabase-cli-releaser[bot] Nov 2, 2026
25cb580
chore(stack): bump postgres to 17.11.0.017-r0 (#7445)
supabase-cli-releaser[bot] Nov 2, 2026
9ae94dd
chore(stack): bump postgres to 15.19.0.017-r0 (#7444)
supabase-cli-releaser[bot] Nov 2, 2026
b14477c
test(cli): fix 1 flaky test in live branch create (#7326)
avallete Nov 2, 2026
0f6748a
test(stack): fix 1 flaky test in the Realtime catalog check (#7359)
avallete Nov 2, 2026
06149d7
test(stack): fix 1 flaky test in the native owner-logs check (#7434)
avallete Nov 2, 2026
cf1dc72
chore(stack): bump storage to v1.89.1-r0 (#7447)
supabase-cli-releaser[bot] Nov 2, 2026
a893e92
test(cli): fix 1 flaky test in live db reset (#7428)
avallete Nov 2, 2026
cf193a1
test(stack): fix 2 flaky tests in network pinning and docker storage …
avallete Nov 2, 2026
62cf836
test(stack): fix 1 flaky Mailpit test and share the stall guard (#7318)
avallete Nov 2, 2026
f57025d
chore(stack): add postgres 17.11.0.017-orioledb-r0 (#7446)
supabase-cli-releaser[bot] Nov 2, 2026
dd0e161
chore(stack): bump storage to v1.89.2-r0 (#7448)
supabase-cli-releaser[bot] Nov 2, 2026
8ef9f65
chore(stack): bump realtime to v2.151.4-r0 (#7449)
supabase-cli-releaser[bot] Nov 2, 2026
ce48e09
chore(repo): fold the effect lint into the repo lint (CLI-2899) (#7422)
7ttp Nov 2, 2026
03392ad
feat(cli): add `SUPABASE_API_MAX_RETRIES` to cap api retries (CLI-260…
7ttp Nov 2, 2026
d20aae3
chore(stack): bump realtime to v2.151.5-r0 (#7450)
supabase-cli-releaser[bot] Nov 2, 2026
44d4566
chore(stack): bump realtime to v2.151.6-r0 (#7453)
supabase-cli-releaser[bot] Nov 3, 2026
efa4540
chore(stack): bump postgres to 17.11.0.018-r0 (#7454)
supabase-cli-releaser[bot] Nov 3, 2026
de6117a
chore(stack): add postgres 17.11.0.018-orioledb-r0 (#7456)
supabase-cli-releaser[bot] Nov 3, 2026
c9473a7
chore(stack): bump postgres to 15.19.0.018-r0 (#7455)
supabase-cli-releaser[bot] Nov 3, 2026
b2cadc7
feat(cli): add inspect db toast-sizes command (#6528)
bruno222 Nov 3, 2026
ba71d22
test(stack): name the failing psql call when Commands stderr is empty…
avallete Nov 3, 2026
93e8290
fix(stack): keep a concurrent traverse grant when restricting a direc…
avallete Nov 3, 2026
46b5465
ci(repo): post the sync resolver comment when one artifact is downloa…
avallete Nov 3, 2026
6763aa4
fix(stack): report the helper container state when its readiness time…
avallete Nov 3, 2026
a9855d6
ci(repo): flag breaking changes in AI review (CLI-2904) (#7451)
7ttp Nov 3, 2026
4287d92
fix(stack): name the stalled engine command in timeout errors (#7407)
avallete Nov 3, 2026
cf9c0e9
fix(stack): keep port registry reads open while a peer commits (#7342)
avallete Nov 3, 2026
6840b8a
test(cli): use new api keys in live e2e (#7459)
7ttp Nov 3, 2026
fe5e89f
feat(cli): add inspect db xid-age command (#6527)
bruno222 Nov 3, 2026
c76bdbd
chore(stack): bump realtime to v2.151.7-r0 (#7462)
supabase-cli-releaser[bot] Nov 3, 2026
d6c3fe3
fix(cli): report a missing supabase_privileged_role on login-role min…
avallete Nov 3, 2026
a5e1884
feat(config): add [auth.email] require_current_password (CLI-1921) (#…
7ttp Nov 3, 2026
00c8a5b
feat(cli): point init's config.toml at the hosted schema and trust it…
Coly010 Nov 3, 2026
ffc2d55
chore(api): sync Management API OpenAPI spec (#7466)
supabase-cli-releaser[bot] Nov 3, 2026
41723ce
fix(cli): treat edge runtime exit 15 as a stop in functions serve (CL…
Coly010 Nov 3, 2026
497bf42
ci(release): fix recurring release failures since the v3 cut (CLI-291…
Coly010 Nov 3, 2026
96eab1d
ci(release): attest GitHub Release assets with build provenance (#7467)
jgoux Nov 3, 2026
f4212ae
chore(stack): bump realtime to v2.152.0-r0 (#7470)
supabase-cli-releaser[bot] Nov 3, 2026
0a245f2
feat(cli): record which config key failed in config-load telemetry (C…
Coly010 Nov 3, 2026
8f9903e
chore(stack): bump storage to v1.89.3-r0 (#7474)
supabase-cli-releaser[bot] Nov 3, 2026
b66f0f3
chore(stack): bump storage to v1.89.4-r0 (#7477)
supabase-cli-releaser[bot] Nov 3, 2026
c94ecf3
fix(cli): stop hanging on a closed output pipe (CLI-2507) (#7469)
7ttp Nov 3, 2026
2e1be9b
chore(stack): bump storage to v1.89.6-r0 (#7478)
supabase-cli-releaser[bot] Nov 4, 2026
a952b3a
chore(stack): bump realtime to v2.152.1-r0 (#7479)
supabase-cli-releaser[bot] Nov 4, 2026
d2e9c6d
chore(stack): bump realtime to v2.153.0-r0 (#7480)
supabase-cli-releaser[bot] Nov 4, 2026
2cbc0bb
chore(api): sync Management API OpenAPI spec (#7484)
supabase-cli-releaser[bot] Nov 4, 2026
6890ba8
fix(cli): drop old service versions when `link` switches projects (CL…
7ttp Nov 4, 2026
a2dad15
fix(stack): match legacy imgproxy tuning (CLI-2578) (#7483)
7ttp Nov 4, 2026
cd667d2
test(stack): fix 1 flaky test in whole-stack native loopback scenario…
avallete Nov 4, 2026
47a0f63
fix(stack): pass `[edge_runtime.secrets]` to functions like legacy (C…
7ttp Nov 4, 2026
bb34a18
fix(stack): leave CORS on /functions/v1 to the function (CLI-2923) (#…
avallete Nov 4, 2026
db30ec9
feat(cli): add inspect db collation-drift with report output (#7460)
avallete Nov 4, 2026
d966128
chore(cli): bump effect to 4.1.2 (#7473)
avallete Nov 4, 2026
beed8b8
fix(stack): pass local S3 keys to Studio (CLI-2578) (#7486)
7ttp Nov 4, 2026
05132b6
chore(stack): bump storage to v1.89.7-r0 (#7489)
supabase-cli-releaser[bot] Nov 4, 2026
35b4417
chore(stack): bump storage to v1.89.9-r0 (#7490)
supabase-cli-releaser[bot] Nov 4, 2026
ab7154a
fix(cli): explain `LOCK TABLE` migration failures (CLI-2261) (#7487)
7ttp Nov 4, 2026
c9c0ef8
chore(cli): link the pending Bun fix from the NodeWS patch (#7492)
avallete Nov 4, 2026
335b98b
chore(stack): bump realtime to v2.153.1-r0 (#7494)
supabase-cli-releaser[bot] Nov 4, 2026
4d88c8b
fix(cli): bound sso requests and surface unhealthy project status (CL…
avallete Nov 4, 2026
a51c49d
fix(cli): keep the windows drive in `db start --from-backup` (CLI-293…
7ttp Nov 4, 2026
192c6a5
chore(stack): bump realtime to v2.153.2-r0 (#7495)
supabase-cli-releaser[bot] Nov 4, 2026
5e4a927
chore(stack): bump storage to v1.89.12-r0 (#7500)
supabase-cli-releaser[bot] Nov 5, 2026
95e86b3
chore(stack): bump realtime to v2.153.3-r0 (#7501)
supabase-cli-releaser[bot] Nov 5, 2026
4adb0ec
chore(stack): bump edge-runtime to v1.78.0-r0 (#7502)
supabase-cli-releaser[bot] Nov 5, 2026
e52b729
fix(stack): resolve functions env like legacy start and serve (CLI-25…
7ttp Nov 5, 2026
5a07fe0
fix(cli): recognise newer docker daemon-down messages and split serve…
Prashansa-K Nov 5, 2026
88602ae
fix(stack): align gateway CORS with the platform (#7485)
avallete Nov 5, 2026
deccf04
test(repo): fix e2e port races and name storage crash-test stalls (#7…
avallete Nov 5, 2026
3217fb4
feat(config): read and write config.jsonc and commented JSON configs …
Coly010 Nov 5, 2026
f530933
fix(cli): classify functions deploy failures by their cause (CLI-2910…
Coly010 Nov 5, 2026
eb5a2fb
chore(api): sync Management API OpenAPI spec (#7511)
supabase-cli-releaser[bot] Nov 5, 2026
a4f9be0
chore(stack): bump realtime to v2.153.4-r0 (#7519)
supabase-cli-releaser[bot] Nov 5, 2026
d3c5cb0
fix(cli): follow views in the extra search path schemas in gen types …
jgoux Nov 5, 2026
6f153b7
fix(cli): cap erlang port tables on `supabase start` (CLI-2933) (#7512)
7ttp Nov 5, 2026
b3d1618
test(cli): add a consumer contract suite across backends (CLI-2574) (…
7ttp Nov 5, 2026
34f4125
test(cli): stop gen types e2e matching DB ports that start with 1 (#7…
jgoux Nov 5, 2026
a3e4904
fix(cli): fall back to plaintext under sslmode=prefer like libpq (#7509)
jgoux Nov 6, 2026
3394a54
chore(stack): bump storage to v1.89.13-r0 (#7523)
supabase-cli-releaser[bot] Nov 6, 2026
a7a820d
feat(cli): generate linked TypeScript types directly with Management …
jgoux Nov 6, 2026
dfd77c4
test(stack): fix 2 flaky tests that depend on GitHub Releases downloa…
avallete Nov 6, 2026
948d4d4
fix(cli): pin the Supabase CA on every linked database connection (#7…
jgoux Nov 6, 2026
7f8dae8
test(cli): cover migration and seed ordering (CLI-2581) (#7521)
7ttp Nov 6, 2026
4cc97fa
chore(api): sync Management API OpenAPI spec (#7526)
supabase-cli-releaser[bot] Nov 6, 2026
b5530dd
feat(cli): unify logs commands DEBUG-261 (#7437)
jordienr Nov 9, 2026
072fa64
chore(stack): bump storage to v1.90.0-r0 (#7533)
supabase-cli-releaser[bot] Nov 9, 2026
e874787
chore(stack): bump edge-runtime to v1.78.1-r0 (#7535)
supabase-cli-releaser[bot] Nov 9, 2026
fe9c9e9
chore(stack): bump pooler to v2.10.0-r0 (#7537)
supabase-cli-releaser[bot] Nov 9, 2026
141d792
chore(stack): bump storage to v1.90.1-r0 (#7538)
supabase-cli-releaser[bot] Nov 9, 2026
34d2512
feat(config): read the declared config schema version (CLI-2862) (#7514)
Coly010 Nov 9, 2026
811909a
chore(stack): bump studio to 2026.11.09-sha-1567384-r0 (#7536)
supabase-cli-releaser[bot] Nov 9, 2026
96efdbd
fix(cli): hide Studio's Logs pages when Logflare isn't running (CLI-2…
7ttp Nov 9, 2026
6433146
feat(stack): serve auth email templates from `content_path` (CLI-2583…
7ttp Nov 9, 2026
d4fc0e5
chore(stack): bump realtime to v2.154.0-r0 (#7534)
supabase-cli-releaser[bot] Nov 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ patches/*.patch text eol=lf
# can't leave a trailing `\r` on every entry and make every tag mismatch.
apps/cli/src/shared/telemetry/__fixtures__/error-tags.txt text eol=lf

# The Windows smoke-test runs this under Git Bash; a CRLF checkout breaks `set -euo pipefail`.
.github/scripts/wait-for-npm-version.sh text eol=lf

# Generated artifacts. `linguist-generated` keeps these out of GitHub's language
# statistics and collapses them in pull request diffs -- they are build output to
# be regenerated, not code to review, and together they outweigh the hand-written
Expand Down
1 change: 1 addition & 0 deletions .github/MAINTAINERS.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ Fast-forward PRs are the deploy PR (`develop` → `main`), the major cut
(`next` → `develop`), and the two sync PRs.

**Dispatch guards.** `release.yml` refuses `channel=next` off `next`,
`channel=next` while `next` has no commits beyond `develop`,
`channel=maintenance` off `v<N>.x`, `beta`/`stable` on `next` or `v<N>.x`, a
non-dry-run `stable` outside `main`, and a `version` that is not
`X.Y.Z[-prerelease]`.
Expand Down
6 changes: 6 additions & 0 deletions .github/ai-review/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ shown as `--remerge-diff`. Both sides were reviewed in their own PRs, so the
prompts limit findings to what the resolution introduced; `pr.diff` stays the
anchor for inline comments.

### Breaking changes

Only the Claude prompt asks for `breaking-change` findings, because only its job
has `pr.json` with the title and branches. They post as `major` and ask for a
`!` title, plus a retarget to `next` on `develop`.

## Once-per-PR semantics and manual re-runs

New commits never re-trigger a review — `resolve.ts`'s dedup guard skips a
Expand Down
10 changes: 10 additions & 0 deletions .github/ai-review/adjudicate-prompt.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,16 @@ when that file shows work on `next` the PR would fundamentally conflict with. If
the file is absent, refute it. Keep the category `next-impact` and a severity no
higher than `minor`; these findings are advisory and never block the PR.

### Breaking-change findings

Verify each `breaking-change` finding against the behavior the PR changes:
refute it only when no released, non-experimental use fails or changes meaning,
when the change only rejects a value that never had a meaning, or when the
change matches the old `SIDE_EFFECTS.md`. The PR's intent, tests and
`SIDE_EFFECTS.md` edits are not counter-evidence. Keep the category
`breaking-change`, severity `major` and the request ending its `claim`, even
when merged with a Codex finding.

### Merge into one deduplicated list

- When a Claude finding and a Codex finding concern the same file/line/
Expand Down
13 changes: 13 additions & 0 deletions .github/ai-review/claude-review-prompt.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,19 @@ higher than `minor`. These findings are advisory and never block the PR. Do not
flag ordinary merge conflicts or style differences, and report nothing when the
file does not exist.

## Breaking changes

Only when `pr.json` has `baseRefName` `develop` or `next`, a `headRefName` other
than `next` or `sync/*`, and no `!` before the title's colon: report any change
that makes existing use of a released command, flag, config key, env var or exit
code fail or change meaning, for example removing a fallback so a command now
errors, even when that is the fix the PR set out to make. Use category
`breaking-change`, with severity `major`, and end the `claim` by asking for a
`type(scope)!:` title, a `BREAKING CHANGE:` line in the PR description and, on
`develop`, a retarget to `next`. Do not report internal code, tests, CI,
additive changes, experimental commands, newly rejected values that never had a
meaning, or fixes that match the old `SIDE_EFFECTS.md`.

## Output

Your final response must be ONLY the JSON object described by the provided
Expand Down
35 changes: 35 additions & 0 deletions .github/scripts/wait-for-npm-version.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/usr/bin/env bash
# Usage: wait-for-npm-version.sh <version> <package>...
#
# npm lists a new version minutes after publish, and the registry CDN caches each packument per
# region and Accept header, so both the npm client and the abbreviated packument must serve it.
set -euo pipefail

if [[ $# -lt 2 ]]; then
echo "usage: $0 <version> <package>..." >&2
exit 2
fi

version="$1"
shift
timeout="${WAIT_TIMEOUT_SECONDS:-900}"

npm_serves_version() {
local pkg="$1"
npm view "${pkg}@${version}" version --prefer-online --fetch-timeout=30000 --fetch-retries=0 > /dev/null &&
curl -fsSL --max-time 30 -H 'Accept: application/vnd.npm.install-v1+json' "https://registry.npmjs.org/${pkg//\//%2f}" |
jq -e --arg v "$version" '.versions | has($v)' > /dev/null
}

deadline=$((SECONDS + timeout))
for pkg in "$@"; do
while true; do
if (( SECONDS >= deadline )); then
echo "::error::npm does not serve ${pkg}@${version} after ${timeout} seconds"
exit 1
fi
npm_serves_version "$pkg" && break
echo "Waiting for npm to serve ${pkg}@${version}..."
sleep 15
done
done
1 change: 0 additions & 1 deletion .github/workflows/propose-release-notes.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ jobs:
client-id: ${{ vars.GH_APP_CLIENT_ID }}
private-key: ${{ secrets.GH_APP_PRIVATE_KEY }}
permission-contents: write
permission-issues: read
permission-pull-requests: write

- uses: useblacksmith/checkout@6fd481652155169ed4d2f25ebaf97464f685175f # v1
Expand Down
13 changes: 12 additions & 1 deletion .github/workflows/release-shared.yml
Original file line number Diff line number Diff line change
Expand Up @@ -275,14 +275,15 @@ jobs:
# count as self-hosted from sigstore's POV, so this job must stay on a github-hosted runner
# (it's short and not compute-bound, so the cost is negligible).
runs-on: ubuntu-latest
timeout-minutes: 45
timeout-minutes: 60
env:
CHANNEL: ${{ inputs.channel }}
NPM_TAG: ${{ inputs.npm_tag }}
VERSION: ${{ inputs.version }}
LINEAR_CLI_STABLE_RELEASE_ACCESS_KEY: ${{ secrets.LINEAR_CLI_STABLE_RELEASE_ACCESS_KEY }}
LINEAR_CLI_BETA_RELEASE_ACCESS_KEY: ${{ secrets.LINEAR_CLI_BETA_RELEASE_ACCESS_KEY }}
permissions:
attestations: write
contents: write
id-token: write
steps:
Expand Down Expand Up @@ -409,6 +410,16 @@ jobs:
GH_TOKEN: ${{ github.token }}
run: bun apps/cli/scripts/upload-release-assets.ts verify --version "${VERSION}"

# Lets installers such as aqua and mise verify each asset with `gh attestation verify`; the
# unversioned tarball aliases share their versioned twin's digest, so they are covered too.
- name: Attest release assets
uses: actions/attest@1e69f48acb82d1966a394da916b4c1698aa569d6 # v4.2.2
with:
subject-path: |
dist/supabase_${{ inputs.version }}_*
dist/checksums.txt
install

- name: Publish GitHub Release (immutable)
env:
GH_TOKEN: ${{ github.token }}
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/release-smoke-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ jobs:
# dry_run here, but GitHub validates nested-workflow permissions at startup.
permissions:
actions: read
attestations: write
contents: write
id-token: write
pull-requests: write
Expand Down
122 changes: 111 additions & 11 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,36 @@ permissions:
contents: read

jobs:
# semantic-release reads channel notes per commit (semantic-release/semantic-release#4073), so
# releasing `next` on a commit develop already tagged misreads both tags.
next-ahead:
name: Check next has its own commits
if: github.ref_name == 'next'
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
outputs:
ahead: ${{ steps.compare.outputs.ahead }}
steps:
- id: compare
env:
GH_TOKEN: ${{ github.token }}
REPO: ${{ github.repository }}
SHA: ${{ github.sha }}
run: |
set -euo pipefail
ahead_by="$(gh api "repos/${REPO}/compare/develop...${SHA}" --jq .ahead_by)"
if [[ "$ahead_by" -gt 0 ]]; then
echo "ahead=true" >> "$GITHUB_OUTPUT"
else
echo "ahead=false" >> "$GITHUB_OUTPUT"
fi

test-next:
name: Test next
if: github.event_name == 'push' && github.ref_name == 'next'
needs: next-ahead
if: github.event_name == 'push' && github.ref_name == 'next' && needs.next-ahead.outputs.ahead == 'true'
permissions:
contents: read
actions: read
Expand All @@ -61,12 +88,20 @@ jobs:

plan:
name: Plan release
needs: test-next
# A skipped test-next (every non-next trigger) makes the implicit success() false, so the
# result is checked explicitly.
if: ${{ !cancelled() && contains(fromJSON('["success","skipped"]'), needs.test-next.result) }}
needs: [next-ahead, test-next]
# Skipped next-ahead and test-next jobs (every non-next trigger) make the implicit success()
# false, so their results are checked explicitly. A next push with no commits beyond develop
# plans nothing.
if: >-
${{ !cancelled() &&
contains(fromJSON('["success","skipped"]'), needs.next-ahead.result) &&
contains(fromJSON('["success","skipped"]'), needs.test-next.result) &&
!(github.event_name == 'push' && github.ref_name == 'next' && needs.next-ahead.outputs.ahead != 'true') }}
runs-on: ubuntu-latest
timeout-minutes: 15
timeout-minutes: 135
permissions:
contents: read
actions: read
outputs:
should_release: ${{ steps.compute.outputs.should_release }}
version: ${{ steps.compute.outputs.version }}
Expand All @@ -78,6 +113,59 @@ jobs:
dry_run: ${{ steps.compute.outputs.dry_run }}
channel: ${{ steps.compute.outputs.channel }}
steps:
- name: Refuse a next dispatch with no commits beyond develop
if: ${{ github.event_name == 'workflow_dispatch' && github.ref_name == 'next' && needs.next-ahead.outputs.ahead != 'true' }}
run: |
echo "::error::next has no commits beyond develop, so a next release would tag a commit develop already released"
exit 1
# The stable tag is pushed by main's publish job, so a prerelease planned before that job
# finishes misses it. The rest of the run (brew, scoop, smoke tests) does not affect the plan.
- name: Wait for an in-flight stable release
if: ${{ (github.ref_name == 'develop' || github.ref_name == 'next') && (github.event_name == 'push' || inputs.version == '') }}
env:
GH_TOKEN: ${{ github.token }}
REPO: ${{ github.repository }}
run: |
set -euo pipefail
deadline=$((SECONDS + 7200))
while true; do
pending=0
if run_ids="$(gh run list --repo "$REPO" --workflow release.yml --branch main --json databaseId,status --jq '.[] | select(.status != "completed") | .databaseId')"; then
for run_id in $run_ids; do
publish_status="$(gh api "repos/${REPO}/actions/runs/${run_id}/jobs" --paginate --jq '.jobs[] | select(.name == "Release / publish") | .status')" || publish_status=unknown
if [[ "$publish_status" != completed ]]; then
pending=$((pending + 1))
fi
done
else
echo "::warning::Could not list Release runs on main; retrying."
pending=1
fi
if [[ "$pending" -eq 0 ]]; then
break
fi
if (( SECONDS >= deadline )); then
echo "::error::The publish job of a Release run on main is still in progress after 120 minutes. Re-run this job once it finishes."
exit 1
fi
echo "Waiting for the publish job of ${pending} Release run(s) on main to finish..."
sleep 30
done
# A major cut can fast-forward develop onto next while the tests and the wait above run.
- id: next-still-ahead
if: ${{ github.ref_name == 'next' }}
env:
GH_TOKEN: ${{ github.token }}
REPO: ${{ github.repository }}
SHA: ${{ github.sha }}
run: |
set -euo pipefail
ahead_by="$(gh api "repos/${REPO}/compare/develop...${SHA}" --jq .ahead_by)"
if [[ "$ahead_by" -gt 0 ]]; then
echo "ahead=true" >> "$GITHUB_OUTPUT"
else
echo "ahead=false" >> "$GITHUB_OUTPUT"
fi
# semantic-release runs `git push --dry-run HEAD:<branch>` as part of verifyAuth even in
# `dry_run: true` mode, so the token needs push access to the protected develop/main
# branches — the default GITHUB_TOKEN doesn't have it.
Expand Down Expand Up @@ -110,6 +198,7 @@ jobs:
DISPATCH_CHANNEL: ${{ inputs.channel }}
DISPATCH_VERSION: ${{ inputs.version }}
DISPATCH_DRY_RUN: ${{ inputs.dry_run }}
NEXT_AHEAD: ${{ steps.next-still-ahead.outputs.ahead }}
SR_PUBLISHED: ${{ steps.semantic-release.outputs.new_release_published }}
SR_VERSION: ${{ steps.semantic-release.outputs.new_release_version }}
run: |
Expand All @@ -126,6 +215,15 @@ jobs:
next) natural=next ;;
*) [[ "$REF_NAME" =~ $maint_re ]] && natural=maintenance ;;
esac
if [[ "$REF_NAME" == next && "$NEXT_AHEAD" != true ]]; then
if [[ "$EVENT" == "workflow_dispatch" ]]; then
echo "::error::next has no commits beyond develop, so a next release would tag a commit develop already released"
exit 1
fi
echo "::notice::next has no commits beyond develop, so there is nothing to release"
echo "should_release=false" >> "$GITHUB_OUTPUT"
exit 0
fi
if [[ "$EVENT" == "workflow_dispatch" ]]; then
channel="$DISPATCH_CHANNEL"
dry_run="$DISPATCH_DRY_RUN"
Expand Down Expand Up @@ -243,6 +341,7 @@ jobs:
# those granted to the calling job, so this must be declared here too.
permissions:
actions: read
attestations: write
contents: write
id-token: write
pull-requests: write
Expand Down Expand Up @@ -394,13 +493,14 @@ jobs:
SLACK_RELEASE_WEBHOOK: ${{ secrets.SLACK_RELEASE_WEBHOOK }}

# Reports a broken release on every channel. `failure()` evaluates against the full `needs`
# chain, so this fires whenever `test-next`, `plan` or `release` (including the reusable
# release-shared workflow) fails. Skipped jobs don't count as failures. Dry runs are excluded
# via the dispatch input directly, so even a plan job that dies before recording its `dry_run`
# output stays quiet. A failed `test-next` skips `plan`, so the channel falls back to the ref.
# chain, so this fires whenever `next-ahead`, `test-next`, `plan` or `release` (including the
# reusable release-shared workflow) fails. Skipped jobs don't count as failures. Dry runs are
# excluded via the dispatch input directly, so even a plan job that dies before recording its
# `dry_run` output stays quiet. A failed `next-ahead` or `test-next` skips `plan`, so the
# channel falls back to the ref.
notify-slack-failure:
name: Notify Slack (failure)
needs: [test-next, plan, release]
needs: [next-ahead, test-next, plan, release]
if: ${{ failure() && !(github.event_name == 'workflow_dispatch' && inputs.dry_run) }}
uses: ./.github/workflows/slack-notify.yml
with:
Expand Down
Loading
Loading