Skip to content

feat: release workflow RC versioning and publish reliability#164

Merged
mandarini merged 6 commits intomainfrom
feat/release-process
Mar 2, 2026
Merged

feat: release workflow RC versioning and publish reliability#164
mandarini merged 6 commits intomainfrom
feat/release-process

Conversation

@mandarini
Copy link
Contributor

The release workflow had three issues:

  1. npm version failed with "Version not changed" when release-please had already updated package.json to the release version. Fixed by adding --allow-same-version.

  2. RC version always predicted a minor bump (e.g. 0.9.0-rc.N) regardless of whether the next release is a patch. Fixed by reading package.json directly from the release-please PR branch instead of parsing the PR title or guessing from git history. RC numbering now uses github.run_number instead of git describe (which was unreliable with no remote tags).

  3. Re-running a failed stable release workflow would error with "cannot publish over a previously published version". Fixed by checking npm before publishing and skipping if the version already exists.

@mandarini mandarini changed the title feat: fix release workflow RC versioning and publish reliability feat: release workflow RC versioning and publish reliability Mar 2, 2026
@coderabbitai
Copy link

coderabbitai bot commented Mar 2, 2026

📝 Walkthrough

Summary by CodeRabbit

  • Chores
    • Improved CI/CD workflow stability by pinning GitHub Actions versions to specific commits.
    • Enhanced release process with better version validation and publish checks.

Walkthrough

The release workflow's RC/versioning flow was rewritten to derive the base version from the package.json on the PR head branch (when present) instead of using git-describe. The job fetches PR details and PR head branch, reads and validates package.json version from that branch, and sets an RC like {next_version}-rc.{run_number}. RC creation is restricted to main. Build steps are hardened (set -euo pipefail, --allow-same-version), publish first checks npm for existing versions and skips if already published, and final publish uses provenance and explicit prerelease flags. Additional env vars expose RELEASE_CREATED, RELEASE_VERSION, and PR_HEAD_BRANCH.

Sequence Diagram(s)

sequenceDiagram
  participant Runner as GitHub Actions Runner
  participant GH as GitHub API
  participant Git as Git Repository
  participant NPM as npm Registry

  Runner->>GH: Determine context (refs, PR info)
  GH-->>Runner: PR details (including head branch) / repo refs
  alt PR_HEAD_BRANCH present and not on main
    Runner->>Git: fetch PR head branch
    Git-->>Runner: package.json from PR branch
    Runner->>Runner: validate NEXT_VERSION (semver)
    Runner->>Runner: set VERSION = NEXT_VERSION-rc.{run_number}
  else Not PR or main branch
    Runner->>Git: read package.json from main
    Git-->>Runner: base version
    Runner->>Runner: compute VERSION (release or rc rules)
  end
  Runner->>Runner: Build (set -euo pipefail, npm version --allow-same-version)
  Runner->>NPM: query for VERSION
  alt VERSION exists on npm
    NPM-->>Runner: version found
    Runner->>Runner: skip publish
  else VERSION not found
    Runner->>NPM: npm publish --provenance (with prerelease if set)
    NPM-->>Runner: publish result
  end
  Runner->>GH: create release (set RELEASE_CREATED, RELEASE_VERSION)
  GH-->>Runner: release created/updated
Loading

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@mandarini mandarini self-assigned this Mar 2, 2026
@mandarini mandarini marked this pull request as draft March 2, 2026 15:36
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/release.yml:
- Around line 103-109: The publish guard currently swallows all errors by using
`2>/dev/null || true` when assigning EXISTING from `npm view`, so update the
`EXISTING=$(npm view "@supabase/ssr@${{ steps.version.outputs.version }}" ...)`
logic to capture the command exit status and stderr, detect a genuine "not
found" (404/Not Found) response versus other failures, and only treat 404 as
“version missing”; for other non-zero exits (auth/network/registry errors) print
the captured stderr and exit non-zero to fail the workflow immediately.
Concretely, run `npm view` and save its stdout/stderr and exit code, set
`EXISTING` from stdout when exit code is 0, if exit code != 0 check stderr for
404/Not Found (treat as empty EXISTING), otherwise echo the stderr for
diagnostics and exit 1 before reaching `npm publish --provenance --tag ${{
steps.version.outputs.tag }}`.

ℹ️ Review info

Configuration used: Central YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Cache: Disabled due to Reviews > Disable Cache setting

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 0845d56 and a86fd4f.

📒 Files selected for processing (1)
  • .github/workflows/release.yml

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

♻️ Duplicate comments (1)
.github/workflows/release.yml (1)

116-122: ⚠️ Potential issue | 🟠 Major

Do not swallow non-404 npm view failures in publish guard.
At Line 116, 2>/dev/null || true collapses auth/network/registry errors into the same path as “version not found”. That hides the real failure mode and can lead to a misleading publish failure later.

Suggested fix
-          EXISTING=$(npm view "@supabase/ssr@${{ steps.version.outputs.version }}" version 2>/dev/null || true)
-          if [ -n "$EXISTING" ]; then
+          PKG="@supabase/ssr@${{ steps.version.outputs.version }}"
+          ERR_FILE="$(mktemp)"
+          if EXISTING=$(npm view "$PKG" version 2>"$ERR_FILE"); then
             echo "Version ${{ steps.version.outputs.version }} already published on npm, skipping."
             exit 0
+          elif grep -qE 'E404|404 Not Found' "$ERR_FILE"; then
+            : # not published yet; continue
+          else
+            echo "npm lookup failed for $PKG" >&2
+            cat "$ERR_FILE" >&2
+            exit 1
           fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/release.yml around lines 116 - 122, The publish guard
currently silences all errors by using `2>/dev/null || true` when running `npm
view "@supabase/ssr@${{ steps.version.outputs.version }}" version`, which
conflates “not found” with auth/network/registry failures; change the logic
around the `npm view` call (the EXISTING check) to capture the command exit code
and stderr separately, treat a successful (exit code 0) run as the version
existing (set `EXISTING`), treat a 404/not-found error explicitly as “not
existing” and continue, but for any other non-zero exit code
(auth/network/registry errors) fail the workflow with a clear error message
instead of proceeding to `npm publish`; update the step that defines `EXISTING`
to implement this explicit error handling rather than swallowing stderr.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In @.github/workflows/release.yml:
- Around line 116-122: The publish guard currently silences all errors by using
`2>/dev/null || true` when running `npm view "@supabase/ssr@${{
steps.version.outputs.version }}" version`, which conflates “not found” with
auth/network/registry failures; change the logic around the `npm view` call (the
EXISTING check) to capture the command exit code and stderr separately, treat a
successful (exit code 0) run as the version existing (set `EXISTING`), treat a
404/not-found error explicitly as “not existing” and continue, but for any other
non-zero exit code (auth/network/registry errors) fail the workflow with a clear
error message instead of proceeding to `npm publish`; update the step that
defines `EXISTING` to implement this explicit error handling rather than
swallowing stderr.

ℹ️ Review info

Configuration used: Central YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Cache: Disabled due to Reviews > Disable Cache setting

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a86fd4f and df4b89c.

📒 Files selected for processing (3)
  • .github/workflows/ci.yml
  • .github/workflows/conventional-commits.yml
  • .github/workflows/release.yml

@mandarini mandarini marked this pull request as ready for review March 2, 2026 16:00
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
.github/workflows/release.yml (1)

133-142: Make RC pre-release creation idempotent for reruns.

gh release create fails when the tag/release already exists. Without idempotency, reruns of the workflow will fail at this step if the RC release was partially created in a prior attempt.

♻️ Proposed refactor
       - name: Create GitHub pre-release
         if: ${{ steps.version.outputs.tag == 'rc' }}
         env:
           GH_TOKEN: ${{ steps.generate-token.outputs.token }}
         run: |
           set -euo pipefail
-          gh release create "v${{ steps.version.outputs.version }}" \
-            --title "v${{ steps.version.outputs.version }}" \
-            --generate-notes \
-            --prerelease
+          TAG="v${{ steps.version.outputs.version }}"
+          if gh release view "$TAG" >/dev/null 2>&1; then
+            echo "GitHub release $TAG already exists, skipping."
+          else
+            gh release create "$TAG" \
+              --title "$TAG" \
+              --generate-notes \
+              --prerelease
+          fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/release.yml around lines 133 - 142, The Create GitHub
pre-release step is not idempotent because gh release create fails if the
tag/release already exists; change the step that currently runs gh release
create "v${{ steps.version.outputs.version }}" to first check for an existing
release (using gh release view "v${{ steps.version.outputs.version }}" or
equivalent) and if it exists run gh release edit "v${{
steps.version.outputs.version }}" --title "v${{ steps.version.outputs.version
}}" --generate-notes --prerelease, otherwise run gh release create as before;
keep the step name ("Create GitHub pre-release"), the GH_TOKEN env and use
steps.version.outputs.version to locate the release.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In @.github/workflows/release.yml:
- Around line 133-142: The Create GitHub pre-release step is not idempotent
because gh release create fails if the tag/release already exists; change the
step that currently runs gh release create "v${{ steps.version.outputs.version
}}" to first check for an existing release (using gh release view "v${{
steps.version.outputs.version }}" or equivalent) and if it exists run gh release
edit "v${{ steps.version.outputs.version }}" --title "v${{
steps.version.outputs.version }}" --generate-notes --prerelease, otherwise run
gh release create as before; keep the step name ("Create GitHub pre-release"),
the GH_TOKEN env and use steps.version.outputs.version to locate the release.

ℹ️ Review info

Configuration used: Central YAML (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro

Cache: Disabled due to Reviews > Disable Cache setting

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a86fd4f and 2325316.

📒 Files selected for processing (3)
  • .github/workflows/ci.yml
  • .github/workflows/conventional-commits.yml
  • .github/workflows/release.yml

@mandarini mandarini merged commit 81e68f4 into main Mar 2, 2026
5 checks passed
@mandarini mandarini deleted the feat/release-process branch March 2, 2026 16:08
mandarini pushed a commit that referenced this pull request Mar 2, 2026
## [0.9.0](v0.8.1...v0.9.0)
(2026-03-02)


### Features

* release workflow RC versioning and publish reliability
([#164](#164))
([81e68f4](81e68f4))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: supabase-releaser[bot] <223506987+supabase-releaser[bot]@users.noreply.github.com>
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.

2 participants