name: ci
permissions:
contents: read
on:
push:
branches: [main]
tags:
- "v*"
pull_request:
env:
CARGO_TERM_COLOR: always
SODIUM_USE_PKG_CONFIG: "1"
jobs:
stable:
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v6
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy
- name: Install native dependencies
run: sudo apt-get update && sudo apt-get install -y pkg-config libsodium-dev
- name: Cache Rust build artifacts
uses: Swatinem/rust-cache@v2
with:
shared-key: ${{ github.workflow }}-${{ github.job }}
- name: Check formatting
run: cargo fmt --check
- name: Run clippy
run: cargo clippy --locked --all-targets --all-features -- -D warnings
- name: Run tests
run: cargo test --locked --all-targets --all-features
- name: Build package
run: cargo package --locked --verbose --all-features
msrv:
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v6
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@1.85
- name: Install native dependencies
run: sudo apt-get update && sudo apt-get install -y pkg-config libsodium-dev
- name: Cache Rust build artifacts
uses: Swatinem/rust-cache@v2
with:
shared-key: ${{ github.workflow }}-${{ github.job }}
- name: Check MSRV
run: cargo check --locked --all-targets --all-features
release:
runs-on: ubuntu-latest
needs:
- stable
- msrv
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
permissions:
contents: write
steps:
- name: Check out repository
uses: actions/checkout@v6
- name: Validate tag format
run: |
if ! printf '%s\n' "${GITHUB_REF_NAME}" | grep -Eq '^v[0-9]+\.[0-9]+\.[0-9]+$'; then
echo "Tag '${GITHUB_REF_NAME}' must match vX.Y.Z" >&2
exit 1
fi
- name: Read crate version
run: |
version=$(sed -n 's/^version = "\(.*\)"$/\1/p' Cargo.toml | head -n1)
if [ -z "${version}" ]; then
echo "Failed to read version from Cargo.toml" >&2
exit 1
fi
if [ "v${version}" != "${GITHUB_REF_NAME}" ]; then
echo "Tag ${GITHUB_REF_NAME} does not match Cargo.toml version ${version}" >&2
exit 1
fi
- name: Extract release notes from changelog
id: changelog
run: |
version="${GITHUB_REF_NAME#v}"
release_notes=$(
awk '
BEGIN { in_section = 0 }
$0 ~ "^## Version " version " \\(" { in_section = 1; next }
in_section && $0 ~ "^## " { exit }
in_section { print }
' version="${version}" CHANGELOG.md
)
if [ -z "${release_notes}" ]; then
echo "No CHANGELOG.md section found for version ${version}" >&2
exit 1
fi
{
echo "release_notes<<EOF"
printf "%s\n" "${release_notes}"
echo "EOF"
} >> "${GITHUB_OUTPUT}"
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
- name: Install native dependencies
run: sudo apt-get update && sudo apt-get install -y pkg-config libsodium-dev
- name: Publish crate
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
run: cargo publish --locked
- name: Create GitHub release
uses: actions/github-script@v9
env:
RELEASE_NOTES: ${{ steps.changelog.outputs.release_notes }}
with:
script: |
const { owner, repo } = context.repo;
const tagName = context.ref.replace("refs/tags/", "");
await github.rest.repos.createRelease({
owner,
repo,
tag_name: tagName,
name: tagName,
body: process.env.RELEASE_NOTES,
target_commitish: context.sha,
});