name: Release
on:
push:
branches: [main]
workflow_dispatch:
inputs:
version:
description: 'Version to (re-)publish. Use only when the auto-trigger needs a manual kick.'
required: true
type: string
permissions:
contents: write
concurrency:
group: release
cancel-in-progress: false
jobs:
detect:
name: Detect release commit
runs-on: ubuntu-latest
outputs:
version: ${{ steps.parse.outputs.version }}
should_release: ${{ steps.parse.outputs.should_release }}
steps:
- uses: actions/checkout@v4
- id: parse
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
VERSION="${{ inputs.version }}"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "should_release=true" >> "$GITHUB_OUTPUT"
echo "::notice::Manually dispatched release for v$VERSION"
exit 0
fi
MSG=$(git log -1 --pretty=%s)
if [[ "$MSG" =~ ^release:\ v([0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?)$ ]]; then
VERSION="${BASH_REMATCH[1]}"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "should_release=true" >> "$GITHUB_OUTPUT"
echo "::notice::Release commit detected: v$VERSION"
else
echo "should_release=false" >> "$GITHUB_OUTPUT"
echo "::notice::Not a release commit — skipping"
fi
tag-all:
name: Tag all products
needs: detect
if: needs.detect.outputs.should_release == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- 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 + push tags
run: |
V="${{ needs.detect.outputs.version }}"
TAGS=(
"sqlrite-v$V"
"sqlrite-ffi-v$V"
"v$V"
)
for tag in "${TAGS[@]}"; do
if git rev-parse "$tag" >/dev/null 2>&1; then
echo "::notice::Tag $tag already exists — skipping (re-run scenario)"
else
git tag "$tag"
echo "Created tag $tag"
fi
done
git push --tags
publish-crate:
name: Publish sqlrite crate to crates.io
needs: [detect, tag-all]
if: needs.detect.outputs.should_release == 'true'
runs-on: ubuntu-latest
environment: release
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
shared-key: publish-crate
- name: cargo publish
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CRATES_IO_TOKEN }}
run: |
# `--no-verify` skips the rebuild+test that publish does
# by default — CI already ran on the same commit on the
# Release PR, so re-running here is duplicate work.
#
# Package name on crates.io is `sqlrite-engine`, not
# `sqlrite` — the latter was taken by an unrelated project
# (see root Cargo.toml for context). The [lib] name is
# still `sqlrite`, so downstream code writes `use sqlrite::…`.
cargo publish -p sqlrite-engine --no-verify
- name: GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: sqlrite-v${{ needs.detect.outputs.version }}
name: Rust engine v${{ needs.detect.outputs.version }}
body: |
Published to crates.io: https://crates.io/crates/sqlrite-engine/${{ needs.detect.outputs.version }}
```toml
[dependencies]
sqlrite-engine = "${{ needs.detect.outputs.version }}"
```
```rust
// The [lib] name stays `sqlrite`, so the import alias is
// the short one even though the package name is longer.
use sqlrite::{Database, ExecutionResult};
```
See the umbrella release [v${{ needs.detect.outputs.version }}](../../releases/tag/v${{ needs.detect.outputs.version }}) for the full changelog.
generate_release_notes: true
publish-ffi:
name: Publish C FFI (${{ matrix.platform }})
needs: [detect, tag-all]
if: needs.detect.outputs.should_release == 'true'
runs-on: ${{ matrix.os }}
environment: release
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
platform: linux-x86_64
shared_lib: libsqlrite_c.so
static_lib: libsqlrite_c.a
- os: ubuntu-24.04-arm
platform: linux-aarch64
shared_lib: libsqlrite_c.so
static_lib: libsqlrite_c.a
- os: macos-latest
platform: macos-aarch64
shared_lib: libsqlrite_c.dylib
static_lib: libsqlrite_c.a
- os: windows-latest
platform: windows-x86_64
shared_lib: sqlrite_c.dll
static_lib: sqlrite_c.lib
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
shared-key: publish-ffi-${{ matrix.platform }}
- name: Build libsqlrite_c
run: cargo build --release -p sqlrite-ffi
- name: Package tarball
shell: bash
run: |
V="${{ needs.detect.outputs.version }}"
STAGE="sqlrite-ffi-v$V-${{ matrix.platform }}"
mkdir -p "$STAGE/lib" "$STAGE/include"
cp "target/release/${{ matrix.shared_lib }}" "$STAGE/lib/"
cp "target/release/${{ matrix.static_lib }}" "$STAGE/lib/" 2>/dev/null || \
echo "::warning::static lib ${{ matrix.static_lib }} not found on ${{ matrix.platform }} — shipping shared lib only"
cp "sqlrite-ffi/include/sqlrite.h" "$STAGE/include/"
# README pointer so end users know what they're looking at
# when they untar the download.
cat > "$STAGE/README" <<EOF
SQLRite C FFI v$V — ${{ matrix.platform }}
Contents:
lib/ ${{ matrix.shared_lib }} — dynamic library to link against
lib/ ${{ matrix.static_lib }} — static library (if present)
include/ sqlrite.h — C header
Full docs: https://github.com/joaoh82/rust_sqlite/blob/main/sqlrite-ffi/README.md
EOF
tar czf "$STAGE.tar.gz" "$STAGE"
# Emit the path for the upload step below.
echo "ASSET=$STAGE.tar.gz" >> "$GITHUB_ENV"
- name: Upload to GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: sqlrite-ffi-v${{ needs.detect.outputs.version }}
name: C FFI v${{ needs.detect.outputs.version }}
body: |
Prebuilt `libsqlrite_c` for every supported platform, plus the `sqlrite.h` header.
Download the tarball for your platform, extract, and link:
```
tar xzf sqlrite-ffi-v${{ needs.detect.outputs.version }}-<platform>.tar.gz
# lib/ — dynamic + static libraries
# include/sqlrite.h — header to #include
```
See the umbrella release [v${{ needs.detect.outputs.version }}](../../releases/tag/v${{ needs.detect.outputs.version }}) for the full changelog.
files: ${{ env.ASSET }}
generate_release_notes: true
finalize:
name: Finalize umbrella release
needs: [detect, publish-crate, publish-ffi]
if: needs.detect.outputs.should_release == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Umbrella GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: v${{ needs.detect.outputs.version }}
name: v${{ needs.detect.outputs.version }}
body: |
**SQLRite v${{ needs.detect.outputs.version }}**
Per-product releases in this wave:
- 🦀 [Rust engine](../../releases/tag/sqlrite-v${{ needs.detect.outputs.version }}) → [crates.io](https://crates.io/crates/sqlrite-engine/${{ needs.detect.outputs.version }})
- 🔧 [C FFI](../../releases/tag/sqlrite-ffi-v${{ needs.detect.outputs.version }}) — prebuilt `libsqlrite_c` for Linux x86_64/aarch64, macOS aarch64, Windows x86_64
_Python / Node.js / WASM / Go / desktop SDKs land as their publish jobs come online (Phases 6e–6i)._
---
Auto-generated changelog below ↓
generate_release_notes: true