name: Release
on:
push:
tags:
- "v*"
workflow_dispatch:
inputs:
version:
description: "Version tag (e.g., v0.5.0)"
required: true
permissions:
contents: read
env:
CARGO_TERM_COLOR: always
jobs:
validate:
name: Pre-release Validation
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: stable
components: rustfmt, clippy
- name: Cache dependencies
uses: Swatinem/rust-cache@v2
- name: Verify version matches tag
run: |
# Extract version from tag or workflow_dispatch input
if [[ "$GITHUB_REF" == refs/tags/* ]]; then
TAG_VERSION=${GITHUB_REF#refs/tags/v}
else
# For workflow_dispatch, use the input version (strip 'v' prefix if present)
INPUT_VERSION="${{ github.event.inputs.version }}"
TAG_VERSION=${INPUT_VERSION#v}
fi
CARGO_VERSION=$(cargo metadata --no-deps --format-version 1 | jq -r '.packages[0].version')
if [ "$TAG_VERSION" != "$CARGO_VERSION" ]; then
echo "Version mismatch: expected $TAG_VERSION vs Cargo.toml $CARGO_VERSION"
exit 1
fi
echo "Version verification passed: $TAG_VERSION"
- name: Check formatting
run: cargo fmt --all -- --check
- name: Run clippy (strict)
run: cargo clippy --all-targets --all-features -- -D warnings -D clippy::all
- name: Run tests (all features)
run: cargo test --all-features --verbose
- name: Run integration tests
run: cargo test --test integration_test --all-features --verbose
- name: Test documentation
run: cargo test --doc --all-features
- name: Build release mode
run: cargo build --release --all-features
- name: Verify package can be built
run: cargo package --allow-dirty --no-verify
build-matrix:
name: Build Matrix
needs: validate
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
rust: [stable]
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.rust }}
- name: Cache dependencies
uses: Swatinem/rust-cache@v2
- name: Build
run: cargo build --release
- name: Test
run: cargo test --release
security-audit:
name: Security Audit
needs: validate
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: stable
- name: Install cargo-audit
run: cargo install cargo-audit
- name: Security audit
run: cargo audit
publish:
name: Publish to Crates.io
needs: [validate, build-matrix, security-audit]
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: stable
- name: Cache dependencies
uses: Swatinem/rust-cache@v2
- name: Login to crates.io
run: cargo login ${{ secrets.CRATES_IO_TOKEN }}
- name: Publish to crates.io
run: cargo publish --allow-dirty
github-release:
name: Create GitHub Release
needs: publish
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: stable
- name: Cache dependencies
uses: Swatinem/rust-cache@v2
- name: Extract version from tag
id: get_version
run: |
if [[ "$GITHUB_REF" == refs/tags/* ]]; then
VERSION=${GITHUB_REF#refs/tags/v}
else
# For workflow_dispatch, use the input version (strip 'v' prefix if present)
INPUT_VERSION="${{ github.event.inputs.version }}"
VERSION=${INPUT_VERSION#v}
fi
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "Extracted version: $VERSION"
- name: Generate crate package
run: |
VERSION="${{ steps.get_version.outputs.version }}"
echo "Generating crate package for version $VERSION"
cargo package --allow-dirty
ls -la target/package/
- name: Verify crate file exists
run: |
VERSION="${{ steps.get_version.outputs.version }}"
CRATE_FILE="target/package/rainy-sdk-$VERSION.crate"
if [ ! -f "$CRATE_FILE" ]; then
echo "Error: Crate file $CRATE_FILE not found!"
ls -la target/package/
exit 1
fi
echo "Crate file found: $CRATE_FILE"
ls -lh "$CRATE_FILE"
- name: Extract changelog for this version
id: extract_changelog
run: |
VERSION="${{ steps.get_version.outputs.version }}"
# Extract changelog section for this version
sed -n "/^## \[$VERSION\]/,/^## \[/p" CHANGELOG.md | sed '$d' > release_notes.md
# If the changelog section is empty, create a default one
if [ ! -s release_notes.md ]; then
echo "## Changes in Release $VERSION" > release_notes.md
echo "" >> release_notes.md
echo "See [CHANGELOG.md](https://github.com/enosislabs/rainy-sdk/blob/main/CHANGELOG.md) for full details." >> release_notes.md
fi
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
name: "Release v${{ steps.get_version.outputs.version }}"
body_path: release_notes.md
draft: false
prerelease: false
generate_release_notes: true
append_body: true
files: |
target/package/rainy-sdk-${{ steps.get_version.outputs.version }}.crate
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}