name: Release
on:
push:
tags:
- 'v*.*.*'
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: 1
permissions:
contents: write
packages: write
jobs:
validate:
name: Validate Release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Extract version from tag
id: extract_version
run: |
TAG=${GITHUB_REF#refs/tags/}
VERSION=${TAG#v}
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "tag=$TAG" >> $GITHUB_OUTPUT
- name: Verify Cargo.toml version matches tag
run: |
CARGO_VERSION=$(grep -m1 '^version = ' Cargo.toml | cut -d'"' -f2)
if [ "$CARGO_VERSION" != "${{ steps.extract_version.outputs.version }}" ]; then
echo "ERROR: Cargo.toml version ($CARGO_VERSION) does not match tag (${{ steps.extract_version.outputs.version }})"
exit 1
fi
- name: Run tests
run: cargo test --all-features
- name: Run clippy
run: cargo clippy --all-features -- -D warnings -A unused-imports -A unused-variables -A unused-doc-comments -A clippy::unwrap-or-default -A unexpected_cfgs
- name: Check documentation
run: cargo doc --all-features --no-deps
env:
RUSTDOCFLAGS: -D warnings --cfg docsrs -A unexpected_cfgs -A rustdoc::broken_intra_doc_links
build:
name: Build Release
needs: validate
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Build release
run: cargo build --release --all-features
- name: Package crate
run: cargo package --allow-dirty
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: crate-package
path: target/package/fusabi-stdlib-ext-*.crate
changelog:
name: Generate Changelog
needs: validate
runs-on: ubuntu-latest
outputs:
changelog: ${{ steps.changelog.outputs.changelog }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Extract version from tag
id: extract_version
run: |
TAG=${GITHUB_REF#refs/tags/}
VERSION=${TAG#v}
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "tag=$TAG" >> $GITHUB_OUTPUT
- name: Extract changelog for this version
id: changelog
run: |
# Extract changelog section for current version
VERSION="${{ steps.extract_version.outputs.version }}"
# Check if CHANGELOG.md exists and has content for this version
if grep -q "\[$VERSION\]" CHANGELOG.md; then
# Extract content between version headers
CHANGELOG=$(sed -n "/\[$VERSION\]/,/^## \[/p" CHANGELOG.md | sed '$d' | tail -n +2)
echo "Found changelog for version $VERSION"
else
CHANGELOG="Release $VERSION"
echo "No changelog found for version $VERSION, using default"
fi
# Save to file for multiline content
echo "$CHANGELOG" > changelog.txt
# Also set as output (escaped)
{
echo 'changelog<<EOF'
cat changelog.txt
echo EOF
} >> $GITHUB_OUTPUT
- name: Upload changelog
uses: actions/upload-artifact@v4
with:
name: changelog
path: changelog.txt
publish-crates-io:
name: Publish to crates.io
needs: [validate, build, changelog]
runs-on: ubuntu-latest
if: github.repository == 'fusabi-lang/fusabi-stdlib-ext'
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Publish to crates.io
run: cargo publish --allow-dirty
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_TOKEN }}
continue-on-error: true
github-release:
name: Create GitHub Release
needs: [validate, build, changelog, publish-crates-io]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Extract version from tag
id: extract_version
run: |
TAG=${GITHUB_REF#refs/tags/}
VERSION=${TAG#v}
echo "version=$VERSION" >> $GITHUB_OUTPUT
echo "tag=$TAG" >> $GITHUB_OUTPUT
- name: Download changelog
uses: actions/download-artifact@v4
with:
name: changelog
- name: Download crate package
uses: actions/download-artifact@v4
with:
name: crate-package
- name: Create Release
uses: softprops/action-gh-release@v1
with:
name: Release ${{ steps.extract_version.outputs.tag }}
body_path: changelog.txt
files: |
fusabi-stdlib-ext-*.crate
draft: false
prerelease: ${{ contains(steps.extract_version.outputs.version, 'alpha') || contains(steps.extract_version.outputs.version, 'beta') || contains(steps.extract_version.outputs.version, 'rc') }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Post-release notification
run: |
echo "::notice::Release ${{ steps.extract_version.outputs.tag }} created successfully"
echo "::notice::crates.io: https://crates.io/crates/fusabi-stdlib-ext/${{ steps.extract_version.outputs.version }}"
echo "::notice::docs.rs: https://docs.rs/fusabi-stdlib-ext/${{ steps.extract_version.outputs.version }}"
benchmark:
name: Performance Benchmarks
needs: validate
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
- name: Run benchmarks
run: |
if [ -d "benches" ]; then
cargo bench --all-features || echo "No benchmarks found or benchmarks failed"
else
echo "No benchmark directory found, skipping"
fi
- name: Upload benchmark results
uses: actions/upload-artifact@v4
if: always()
with:
name: benchmark-results
path: target/criterion/
if-no-files-found: ignore