Skip to content

chore(release): version 0.1.0 #1

chore(release): version 0.1.0

chore(release): version 0.1.0 #1

Workflow file for this run

---
name: Release
on:
push:
tags:
# The tag format cargo-release produces; see release.toml.
- "v*"
workflow_dispatch:
# Read at the top level; the two jobs that need more grant it to themselves.
# Attestation needs an OIDC token, and only the publishing job writes.
permissions:
contents: read
env:
CARGO_TERM_COLOR: always
RUST_TOOLCHAIN_VERSION: "1.95.0"
# Both pinned rather than floating. packaging/test-sbom.sh asserts the shape of
# what syft emits and how cargo-auditable's .dep-v0 section reads, so a release
# of either that changes that shape has to be adopted deliberately and
# re-verified, not picked up silently on the next tag push.
SYFT_VERSION: "v1.50.0"
CARGO_AUDITABLE_VERSION: "0.7.5"
# Every job below names a runner image rather than a `-latest` alias, so an
# image roll cannot change what a tagged release is built against. See
# build.yaml for why the label is repeated rather than named once.
jobs:
verify-version:
name: Verify tag matches Cargo.toml
runs-on: ubuntu-24.04
outputs:
version: ${{ steps.extract.outputs.version }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- id: extract
name: Compare tag and Cargo.toml version
run: |
TAG="${GITHUB_REF#refs/tags/}"
TAG_VERSION="${TAG#v}"
CARGO_VERSION=$(grep -m1 '^version = ' Cargo.toml | sed -E 's/version = "(.+)"/\1/')
if [ "$TAG_VERSION" != "$CARGO_VERSION" ]; then
echo "::error::Tag $TAG says version $TAG_VERSION but Cargo.toml has $CARGO_VERSION"
exit 1
fi
echo "version=$CARGO_VERSION" >> "$GITHUB_OUTPUT"
echo "Verified: releasing stackable-odbc-sqlite $CARGO_VERSION"
# The suite is server-free, so unlike the Trino driver's it can gate a
# release as well as a pull request.
integration-test:
name: SQLite Integration Tests
runs-on: ubuntu-24.04
needs: [verify-version]
steps:
- name: Install host dependencies
uses: awalsh128/cache-apt-pkgs-action@553a35bb8ebd9fcabcb1c9451aa4c98e1b4ca8a9 # v1.6.3
with:
packages: unixodbc-dev unixodbc sqlite3
version: ubuntu-24.04
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Install Rust ${{ env.RUST_TOOLCHAIN_VERSION }} toolchain
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b
with:
toolchain: ${{ env.RUST_TOOLCHAIN_VERSION }}
- name: Setup Rust Cache
uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
- name: Install uv
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
- name: Run SQLite integration tests
run: |
./integration-tests/setup.sh
./integration-tests/run-tests.sh
build-and-package:
name: Build and package release archives
runs-on: ubuntu-24.04
needs: [verify-version, integration-test]
# id-token and attestations are what actions/attest-* exchange for a
# Sigstore signing certificate; contents stays read, since this job
# publishes nothing.
permissions:
contents: read
id-token: write
attestations: write
steps:
- name: Install host dependencies
run: |
sudo apt-get update
sudo apt-get install -y unixodbc-dev gcc-mingw-w64-x86-64 zip
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Install Rust ${{ env.RUST_TOOLCHAIN_VERSION }} toolchain
uses: dtolnay/rust-toolchain@b3b07ba8b418998c39fb20f53e8b695cdcc8de1b
with:
toolchain: ${{ env.RUST_TOOLCHAIN_VERSION }}
targets: x86_64-pc-windows-gnu
- name: Setup Rust Cache
uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
with:
key: release
# packaging/sbom.sh reads the .dep-v0 section cargo-auditable embeds, and
# refuses an artifact without one. Both tools are therefore preconditions
# of packaging, not optional extras.
- name: Install cargo-auditable
uses: taiki-e/install-action@cb33e69fad06166ca28a42b2575e4dadabf62ee8 # v2.85.8
with:
tool: cargo-auditable@${{ env.CARGO_AUDITABLE_VERSION }}
- name: Install syft
uses: anchore/sbom-action/download-syft@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0
with:
syft-version: ${{ env.SYFT_VERSION }}
# `cargo auditable build`, not `cargo build`: the plain form links the same
# code but embeds no dependency graph, and the SBOM then lists a handful of
# components instead of the whole tree.
#
# --locked so the released binary is built from the versions Cargo.lock
# pins. The SBOM describes what was linked, so an unlocked build would
# produce an accurate document about an unintended dependency set.
- name: Build Linux release binary
run: cargo auditable build --locked --release
- name: Build Windows release binary (cross)
run: cargo auditable build --locked --release --target x86_64-pc-windows-gnu
- name: Assemble release archives
env:
VERSION: ${{ needs.verify-version.outputs.version }}
run: ./packaging/build-archives.sh
- name: Sanity-check archive contents
env:
VERSION: ${{ needs.verify-version.outputs.version }}
run: |
DIST=packaging/dist
LINUX="$DIST/stackable-odbc-sqlite-${VERSION}-linux-x64.tar.gz"
WINDOWS="$DIST/stackable-odbc-sqlite-${VERSION}-windows-x64.zip"
echo "--- Linux archive ---"
tar -tzf "$LINUX"
for f in libstackable_odbc_sqlite.so libstackable_odbc_sqlite.so.cdx.json \
install.sh uninstall.sh README.md LICENSE; do
tar -tzf "$LINUX" | grep -qx "./$f" || { echo "::error::missing $f in linux archive"; exit 1; }
done
echo "--- Windows archive ---"
unzip -l "$WINDOWS"
# configure-dsn.ps1 is load-bearing rather than an extra: install.bat
# refuses to register the driver without it.
for f in stackable_odbc_sqlite.dll stackable_odbc_sqlite.dll.cdx.json \
configure-dsn.ps1 install.bat uninstall.bat README.md LICENSE; do
unzip -l "$WINDOWS" | grep -q " $f\$" || { echo "::error::missing $f in windows archive"; exit 1; }
done
echo "--- Checksums ---"
(cd "$DIST" && sha256sum -c sha256sums.txt)
echo "Archive sanity check passed."
# TODO(@maltesander): The published binaries are unsigned. Authenticode
# for stackable_odbc_sqlite.dll needs a code-signing
# certificate, which has not been bought. Until then
# Windows SmartScreen warns on the installer. The
# attestations below are a different guarantee: they
# prove where an artifact was built, not who vouches
# for it, and no operating system consults them.
# Signs a statement that these files came out of this workflow, at this
# commit, and records it in the public transparency log. Verified with
# `gh attestation verify <file> --repo stackabletech/stackable-odbc-sqlite`.
# sha256sums.txt is included so the SBOM assets, which it covers, are
# reachable from an attested file.
- name: Attest build provenance
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1
with:
subject-path: |
packaging/dist/*.tar.gz
packaging/dist/*.zip
packaging/dist/sha256sums.txt
# One call per artifact, because each binds exactly one SBOM to one
# subject. The CycloneDX document is the one attested; the SPDX one beside
# it is a conversion of the same data for consumers that need that format.
- name: Attest SBOM for the Linux archive
uses: actions/attest-sbom@c604332985a26aa8cf1bdc465b92731239ec6b9e # v4.1.0
with:
subject-path: packaging/dist/stackable-odbc-sqlite-${{ needs.verify-version.outputs.version }}-linux-x64.tar.gz
sbom-path: packaging/dist/stackable-odbc-sqlite-${{ needs.verify-version.outputs.version }}-linux-x64.cdx.json
- name: Attest SBOM for the Windows archive
uses: actions/attest-sbom@c604332985a26aa8cf1bdc465b92731239ec6b9e # v4.1.0
with:
subject-path: packaging/dist/stackable-odbc-sqlite-${{ needs.verify-version.outputs.version }}-windows-x64.zip
sbom-path: packaging/dist/stackable-odbc-sqlite-${{ needs.verify-version.outputs.version }}-windows-x64.cdx.json
- name: Upload archives as workflow artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: release-archives
path: packaging/dist/*
retention-days: 7
publish-release:
name: Publish GitHub Release
runs-on: ubuntu-24.04
needs: [verify-version, build-and-package]
# The only job that writes, and it writes exactly one thing: the release.
permissions:
contents: write
steps:
- name: Download archives
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: release-archives
path: dist
- name: Determine prerelease flag
id: prerelease
env:
VERSION: ${{ needs.verify-version.outputs.version }}
run: |
if [[ "$VERSION" == *-* ]]; then
echo "flag=true" >> "$GITHUB_OUTPUT"
else
echo "flag=false" >> "$GITHUB_OUTPUT"
fi
- name: Create GitHub Release
uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2
with:
tag_name: ${{ github.ref_name }}
name: stackable-odbc-sqlite ${{ needs.verify-version.outputs.version }}
generate_release_notes: true
prerelease: ${{ steps.prerelease.outputs.flag }}
# Each archive already carries its own CycloneDX SBOM, so an offline
# install has one. The four standalone documents are here for whoever
# needs to read an SBOM without downloading and unpacking a release,
# and in SPDX as well as CycloneDX because tools take one or the other.
# sha256sums.txt covers every file listed above it.
files: |
dist/stackable-odbc-sqlite-${{ needs.verify-version.outputs.version }}-linux-x64.tar.gz
dist/stackable-odbc-sqlite-${{ needs.verify-version.outputs.version }}-windows-x64.zip
dist/stackable-odbc-sqlite-${{ needs.verify-version.outputs.version }}-linux-x64.cdx.json
dist/stackable-odbc-sqlite-${{ needs.verify-version.outputs.version }}-linux-x64.spdx.json
dist/stackable-odbc-sqlite-${{ needs.verify-version.outputs.version }}-windows-x64.cdx.json
dist/stackable-odbc-sqlite-${{ needs.verify-version.outputs.version }}-windows-x64.spdx.json
dist/sha256sums.txt