name: Release
on:
workflow_dispatch:
inputs:
version:
description: "Version to release, for example 3.1.0"
required: true
type: string
permissions:
contents: read
env:
CARGO_TERM_COLOR: always
RUST_BACKTRACE: full
jobs:
validate:
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
version: ${{ steps.version.outputs.version }}
tag: ${{ steps.version.outputs.tag }}
steps:
- name: Checkout candidate
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 with:
fetch-depth: 0
- name: Set up Rust 1.95
uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c
with:
toolchain: 1.95
components: rustfmt, clippy
- name: Resolve release version
id: version
shell: bash
env:
INPUT_VERSION: ${{ inputs.version }}
run: |
VERSION="$INPUT_VERSION"
if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+([+-][0-9A-Za-z.-]+)?$ ]]; then
echo "Invalid release version" >&2
exit 1
fi
MANIFEST_VERSION="$(cargo metadata --no-deps --format-version 1 |
python3 -c 'import json, sys; print(json.load(sys.stdin)["packages"][0]["version"])')"
if [[ "$MANIFEST_VERSION" != "$VERSION" ]]; then
echo "Cargo.toml version does not match the requested release" >&2
exit 1
fi
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "tag=v$VERSION" >> "$GITHUB_OUTPUT"
- name: Check formatting
run: cargo fmt --all -- --check
- name: Lint all targets and features
run: cargo clippy --all-targets --all-features -- -D warnings
- name: Test all features
run: cargo test --all-features
- name: Test no-default feature matrix
run: cargo test --no-default-features --features serde,bytes,simd
- name: Verify allocation contracts
run: cargo test --test allocation_contract --all-features -- --test-threads=1
- name: Verify layout contracts
run: cargo test --test layout_snapshot --all-features -- --nocapture
- name: Check packaged MSRV consumers
run: bash scripts/check-msrv-package.sh 1.95
- name: Build default documentation
run: RUSTDOCFLAGS="-D warnings" cargo doc --lib --no-deps
- name: Build all-feature documentation
run: RUSTDOCFLAGS="-D warnings" cargo doc --lib --no-deps --all-features
- name: Run repository contracts
run: python -m unittest discover -s scripts/tests -v
- name: Install dependency auditor
run: cargo install cargo-audit --version 0.22.2 --locked
- name: Audit dependencies
run: cargo audit -D warnings
- name: Package crate
run: cargo package
- name: Create candidate digest
shell: bash
env:
VERSION: ${{ steps.version.outputs.version }}
run: |
cd target/package
sha256sum "cheetah-string-$VERSION.crate" > "cheetah-string-$VERSION.crate.sha256"
- name: Upload release candidate
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 with:
name: cheetah-string-release-candidate
path: |
target/package/cheetah-string-${{ steps.version.outputs.version }}.crate
target/package/cheetah-string-${{ steps.version.outputs.version }}.crate.sha256
if-no-files-found: error
retention-days: 7
publish:
needs: [validate]
runs-on: ubuntu-latest
environment: crates-io
permissions:
contents: write
steps:
- name: Checkout validated commit
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 with:
fetch-depth: 0
ref: ${{ github.sha }}
- name: Set up Rust
uses: dtolnay/rust-toolchain@4360b52568e2003a75bf9bc1d59f33a8e3fc893c
with:
toolchain: stable
- name: Download release candidate
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 with:
name: cheetah-string-release-candidate
path: release-candidate
- name: Verify candidate digest
shell: bash
working-directory: release-candidate
env:
VERSION: ${{ needs.validate.outputs.version }}
run: sha256sum -c "cheetah-string-$VERSION.crate.sha256"
- name: Create tag for manual release
shell: bash
env:
TAG: ${{ needs.validate.outputs.tag }}
EXPECTED_SHA: ${{ github.sha }}
run: |
git fetch --force --tags origin
if git rev-parse "$TAG" >/dev/null 2>&1; then
TAG_SHA="$(git rev-list -n 1 "$TAG")"
if [[ "$TAG_SHA" != "$EXPECTED_SHA" ]]; then
echo "Release tag exists at a different commit" >&2
exit 1
fi
else
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git tag -a "$TAG" "$EXPECTED_SHA" -m "cheetah-string $TAG"
git push origin "$TAG"
fi
- name: Publish crate to crates.io
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: cargo publish --token "$CARGO_REGISTRY_TOKEN"
- name: Create GitHub release
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ needs.validate.outputs.tag }}
VERSION: ${{ needs.validate.outputs.version }}
run: |
gh release create "$TAG" \
"release-candidate/cheetah-string-$VERSION.crate#cheetah-string-$VERSION.crate" \
--verify-tag \
--title "cheetah-string $TAG" \
--generate-notes