name: Release PR
on:
workflow_dispatch:
inputs:
version:
description: 'Semver to bump everything to (e.g., 0.2.0 or 1.0.0-rc.1)'
required: true
type: string
permissions:
contents: write
pull-requests: write
concurrency:
group: release-pr-${{ inputs.version }}
cancel-in-progress: false
jobs:
open-release-pr:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: main
fetch-depth: 0
- name: Validate version input
id: validate
run: |
VERSION="${{ inputs.version }}"
# Same semver regex as scripts/bump-version.sh — keep them
# in sync. Copy-pasted rather than shared to avoid adding
# a Python / awk dependency here.
if ! [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$ ]]; then
echo "::error::'$VERSION' is not a valid semver (X.Y.Z[-pre][+build])"
exit 1
fi
CURRENT=$(grep '^version = ' Cargo.toml | head -1 | cut -d'"' -f2)
if [ "$VERSION" = "$CURRENT" ]; then
echo "::error::version is already $CURRENT — pick a new one"
exit 1
fi
# Reject re-using an existing tag. The policy is "never
# reuse, always bump past" — see release-plan.md.
if git rev-parse "v$VERSION" >/dev/null 2>&1; then
echo "::error::tag v$VERSION already exists — pick a higher version"
exit 1
fi
echo "current=$CURRENT" >> "$GITHUB_OUTPUT"
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Cache cargo
uses: Swatinem/rust-cache@v2
with:
shared-key: release-pr
- name: Run bump-version.sh
run: ./scripts/bump-version.sh "${{ inputs.version }}"
- name: Refresh Cargo.lock
run: cargo build --workspace --exclude sqlrite-desktop --quiet
- name: Configure git identity
run: |
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
- name: Create branch + commit
run: |
BRANCH="release/v${{ inputs.version }}"
git checkout -b "$BRANCH"
git add -A
git commit -m "release: v${{ inputs.version }}"
git push -u origin "$BRANCH"
- name: Open PR
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh pr create \
--title "Release v${{ inputs.version }}" \
--head "release/v${{ inputs.version }}" \
--base main \
--body "Bumps every product to \`v${{ inputs.version }}\` (previously \`${{ steps.validate.outputs.current }}\`).
The diff should be exactly:
- 10 manifests with a new \`version\` string (root Cargo.toml, sqlrite-ffi, sdk/python × 2, sdk/nodejs × 2, sdk/wasm, desktop × 3).
- \`Cargo.lock\` refreshed with the new workspace versions.
**Once this PR merges**, the \`release.yml\` workflow automatically:
1. Tags \`sqlrite-v${{ inputs.version }}\`, \`sqlrite-ffi-v${{ inputs.version }}\`, and umbrella \`v${{ inputs.version }}\` against the merge commit.
2. Publishes the Rust engine to crates.io (gated by maintainer approval in the \`release\` environment).
3. Builds \`libsqlrite_c\` for Linux x86_64/aarch64 + macOS aarch64 + Windows x86_64 and uploads them to the \`sqlrite-ffi\` GitHub Release.
4. Creates the umbrella \`v${{ inputs.version }}\` GitHub Release with auto-generated notes linking to the per-product ones.
Python / Node.js / WASM / Go / desktop SDKs land as their publish jobs come online (Phases 6e–6i).
See [docs/release-plan.md](../blob/main/docs/release-plan.md) for the full flow."