Skip to content

Release

Release #8

Workflow file for this run

name: Release
on:
workflow_dispatch:
inputs:
bump:
description: Version bump to release
type: choice
required: true
options:
- patch
- minor
- major
concurrency:
group: release-${{ github.ref_name }}
cancel-in-progress: false
permissions:
contents: write
jobs:
publish:
name: Publish crate
if: ${{ github.ref == 'refs/heads/main' }}
runs-on: ubuntu-latest
environment: Production
outputs:
crate_name: ${{ steps.version.outputs.crate_name }}
next_version: ${{ steps.version.outputs.next_version }}
tag: ${{ steps.version.outputs.tag }}
tinybus_version: ${{ steps.version.outputs.tinybus_version }}
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
submodules: true
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- uses: taiki-e/install-action@cargo-llvm-cov
- uses: Swatinem/rust-cache@v2
- name: Check formatting
run: cargo fmt --all -- --check
- name: Clippy
run: cargo clippy --all-targets --all-features -- -D warnings
- name: Test
run: cargo test --all-features
- name: Require 90% line coverage in every source file
run: .github/scripts/check-file-coverage.sh 90 target/coverage.json
- name: Build documentation
env:
RUSTDOCFLAGS: -D warnings
run: cargo doc --no-deps --all-features
- name: Compute next version
id: version
shell: bash
run: |
set -euo pipefail
metadata="$(cargo metadata --format-version 1 --no-deps)"
crate_name="tinydocs"
current_version="$(jq -r '.packages[] | select(.name == "tinydocs") | .version' <<< "$metadata")"
tinybus_version="$(
cargo metadata \
--manifest-path vendor/tinybus/Cargo.toml \
--format-version 1 \
--no-deps \
| jq -r '.packages[] | select(.name == "tinybus") | .version'
)"
if [[ -z "$current_version" || "$current_version" == "null" ]]; then
echo "Could not resolve the current crate version" >&2
exit 1
fi
if [[ -z "$tinybus_version" || "$tinybus_version" == "null" ]]; then
echo "Could not resolve the TinyBus version" >&2
exit 1
fi
IFS=. read -r major minor patch <<< "$current_version"
case "${{ inputs.bump }}" in
major)
major=$((major + 1))
minor=0
patch=0
;;
minor)
minor=$((minor + 1))
patch=0
;;
patch)
patch=$((patch + 1))
;;
*)
echo "Unsupported bump: ${{ inputs.bump }}" >&2
exit 1
;;
esac
next_version="${major}.${minor}.${patch}"
tag="v${next_version}"
git fetch --tags origin
if git rev-parse --verify --quiet "refs/tags/${tag}"; then
echo "Tag ${tag} already exists" >&2
exit 1
fi
{
echo "crate_name=${crate_name}"
echo "current_version=${current_version}"
echo "next_version=${next_version}"
echo "tag=${tag}"
echo "tinybus_version=${tinybus_version}"
} >> "$GITHUB_OUTPUT"
- name: Update crate version
env:
CRATE_NAME: ${{ steps.version.outputs.crate_name }}
NEXT_VERSION: ${{ steps.version.outputs.next_version }}
run: |
set -euo pipefail
perl -0pi -e 's/(\[package\][\s\S]*?\nversion = ")[^"]+(")/$1$ENV{NEXT_VERSION}$2/' Cargo.toml
perl -0pi -e 's/(\[package\][\s\S]*?\nversion = ")[^"]+(")/$1$ENV{NEXT_VERSION}$2/' crates/tinydocs-module/Cargo.toml
cargo update -p "$CRATE_NAME" --precise "$NEXT_VERSION"
- name: Commit version bump and tag
env:
RELEASE_TAG: ${{ steps.version.outputs.tag }}
run: |
set -euo pipefail
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add Cargo.toml Cargo.lock crates/tinydocs-module/Cargo.toml
git commit -m "Release ${RELEASE_TAG}"
git tag -a "${RELEASE_TAG}" -m "Release ${RELEASE_TAG}"
- name: Package crate
run: cargo package --locked --package tinydocs
- name: Package TinyBus source and module SDK
run: |
set -euo pipefail
tinybus_revision="$(git -C vendor/tinybus rev-parse --short=12 HEAD)"
git -C vendor/tinybus archive \
--format=tar.gz \
--prefix="tinybus-${tinybus_revision}/" \
--output="$PWD/target/package/tinybus-source-${tinybus_revision}.tar.gz" \
HEAD
- name: Upload source packages
uses: actions/upload-artifact@v4
with:
name: source-packages
path: |
target/package/${{ steps.version.outputs.crate_name }}-${{ steps.version.outputs.next_version }}.crate
target/package/tinybus-source-*.tar.gz
if-no-files-found: error
- name: Push release commit and tag
env:
RELEASE_TAG: ${{ steps.version.outputs.tag }}
run: |
set -euo pipefail
git push origin "HEAD:${GITHUB_REF_NAME}"
git push origin "${RELEASE_TAG}"
native-bundles:
name: Module bundle (${{ matrix.id }})
needs: publish
strategy:
fail-fast: false
matrix:
include:
- id: ubuntu-22.04-x86_64
os: ubuntu-22.04
target: x86_64-unknown-linux-gnu
- id: ubuntu-22.04-arm64
os: ubuntu-22.04-arm
target: aarch64-unknown-linux-gnu
- id: ubuntu-24.04-x86_64
os: ubuntu-24.04
target: x86_64-unknown-linux-gnu
- id: ubuntu-24.04-arm64
os: ubuntu-24.04-arm
target: aarch64-unknown-linux-gnu
- id: macos-15-x86_64
os: macos-15-intel
target: x86_64-apple-darwin
- id: macos-15-arm64
os: macos-15
target: aarch64-apple-darwin
- id: macos-26-x86_64
os: macos-26-intel
target: x86_64-apple-darwin
- id: macos-26-arm64
os: macos-26
target: aarch64-apple-darwin
- id: windows-2022-x86_64
os: windows-2022
target: x86_64-pc-windows-msvc
- id: windows-2025-x86_64
os: windows-2025
target: x86_64-pc-windows-msvc
- id: windows-11-arm64
os: windows-11-arm
target: aarch64-pc-windows-msvc
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v7
with:
ref: ${{ needs.publish.outputs.tag }}
persist-credentials: false
submodules: true
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Verify native Rust target
shell: bash
env:
EXPECTED_TARGET: ${{ matrix.target }}
run: |
set -euo pipefail
actual_target="$(rustc -vV | sed -n 's/^host: //p')"
[[ "$actual_target" == "$EXPECTED_TARGET" ]]
- name: Build installable module
run: cargo build --locked --release --package tinydocs-module
- name: Assemble Unix module package
if: ${{ runner.os != 'Windows' }}
id: unix_package
shell: bash
env:
BUNDLE_ID: ${{ matrix.id }}
VERSION: ${{ needs.publish.outputs.next_version }}
run: |
set -euo pipefail
library_name="tinydocs_module"
case "$RUNNER_OS" in
Linux) module="target/release/lib${library_name}.so" ;;
macOS) module="target/release/lib${library_name}.dylib" ;;
*) echo "unsupported Unix runner: ${RUNNER_OS}" >&2; exit 1 ;;
esac
package_name="tinydocs-module-${VERSION}-${BUNDLE_ID}"
package_root="dist/${package_name}"
mkdir -p "$package_root"
install -m 755 "$module" "$package_root/"
install -m 644 LICENSE README.md docs/specs/tinybus-module.md "$package_root/"
module_name="$(basename "$module")"
module_hash="$(sha256sum "$package_root/$module_name" | awk '{print $1}')"
printf '"%s" = "%s"\n' "$module_name" "$module_hash" \
> "$package_root/modules.toml"
tar -C "$package_root" -czf "dist/${package_name}.tar.gz" .
echo "archive=dist/${package_name}.tar.gz" >> "$GITHUB_OUTPUT"
- name: Assemble Windows module package
if: ${{ runner.os == 'Windows' }}
id: windows_package
shell: pwsh
env:
BUNDLE_ID: ${{ matrix.id }}
VERSION: ${{ needs.publish.outputs.next_version }}
run: |
$ErrorActionPreference = 'Stop'
$libraryName = 'tinydocs_module'
$module = "target/release/$libraryName.dll"
$packageName = "tinydocs-module-$env:VERSION-$env:BUNDLE_ID"
$packageRoot = "dist/$packageName"
New-Item -ItemType Directory -Force $packageRoot | Out-Null
Copy-Item -LiteralPath $module, 'LICENSE', 'README.md' -Destination $packageRoot
$hash = (Get-FileHash -LiteralPath $module -Algorithm SHA256).Hash.ToLowerInvariant()
$moduleName = Split-Path -Leaf $module
"`"$moduleName`" = `"$hash`"`n" |
Set-Content -Path "$packageRoot/modules.toml" -Encoding utf8NoBOM
Compress-Archive -Path "$packageRoot/*" -DestinationPath "dist/$packageName.zip"
"archive=dist/$packageName.zip" >> $env:GITHUB_OUTPUT
- name: Upload Unix module package
if: ${{ runner.os != 'Windows' }}
uses: actions/upload-artifact@v4
with:
name: tinydocs-module-${{ matrix.id }}
path: ${{ steps.unix_package.outputs.archive }}
if-no-files-found: error
- name: Upload Windows module package
if: ${{ runner.os == 'Windows' }}
uses: actions/upload-artifact@v4
with:
name: tinydocs-module-${{ matrix.id }}
path: ${{ steps.windows_package.outputs.archive }}
if-no-files-found: error
github-release:
name: Create GitHub release
needs:
- publish
- native-bundles
runs-on: ubuntu-latest
steps:
- name: Download workflow artifacts
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
mkdir -p release-assets
mapfile -t artifact_ids < <(
gh api --paginate \
"/repos/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}/artifacts" \
--jq '.artifacts[] | select(.expired == false) | .id'
)
if [[ ${#artifact_ids[@]} -eq 0 ]]; then
echo "no unexpired workflow artifacts found" >&2
exit 1
fi
for artifact_id in "${artifact_ids[@]}"; do
archive="$(mktemp)"
gh api \
"/repos/${GITHUB_REPOSITORY}/actions/artifacts/${artifact_id}/zip" \
> "$archive"
unzip -q "$archive" -d release-assets
rm -f "$archive"
done
- uses: actions/checkout@v7
with:
ref: ${{ needs.publish.outputs.tag }}
persist-credentials: false
submodules: true
- uses: dtolnay/rust-toolchain@stable
- name: Create release checksum manifest with TinyBus
shell: bash
run: |
set -euo pipefail
shopt -s nullglob
mapfile -t assets < <(
find release-assets -type f \
\( -name 'tinydocs-module-*.tar.gz' -o -name 'tinydocs-module-*.zip' \) \
| sort
)
if [[ ${#assets[@]} -ne 11 ]]; then
echo "expected 11 module archives, found ${#assets[@]}" >&2
exit 1
fi
checksum_args=()
for asset in "${assets[@]}"; do checksum_args+=(--path "$asset"); done
cargo run --manifest-path vendor/tinybus/Cargo.toml --locked \
--package tinybus --all-features --bin tinybus -- \
modules checksum "${checksum_args[@]}" --output release-assets/checksum.toml
- name: Create release and upload assets
env:
GH_TOKEN: ${{ github.token }}
RELEASE_TAG: ${{ needs.publish.outputs.tag }}
REPOSITORY: ${{ github.repository }}
run: |
set -euo pipefail
mapfile -t release_files < <(find release-assets -type f | sort)
gh release create "$RELEASE_TAG" "${release_files[@]}" \
--repo "$REPOSITORY" \
--verify-tag \
--title "$RELEASE_TAG" \
--generate-notes
- name: Verify the published module through TinyBus
shell: bash
env:
RELEASE_TAG: ${{ needs.publish.outputs.tag }}
REPOSITORY: ${{ github.repository }}
VERSION: ${{ needs.publish.outputs.next_version }}
run: |
set -euo pipefail
archive="tinydocs-module-${VERSION}-ubuntu-24.04-x86_64.tar.gz"
release_url="https://github.com/${REPOSITORY}/releases/tag/${RELEASE_TAG}"
sha256="$(sed -n "s/^\"${archive}\" = \"\([0-9a-f]\{64\}\)\"$/\1/p" release-assets/checksum.toml)"
test -n "$sha256"
cargo run --manifest-path vendor/tinybus/Cargo.toml --locked \
--package tinybus --all-features --example github_module_host -- \
"$release_url" "$archive" "$sha256"