name: CI
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
permissions:
contents: write
pull-requests: read
env:
CARGO_TERM_COLOR: always
CARGO_INCREMENTAL: 0
CARGO_NET_RETRY: 10
RUST_BACKTRACE: short
RUSTUP_MAX_RETRIES: 10
jobs:
test:
name: Test Suite
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [windows-latest, ubuntu-latest, macos-latest]
rust: [stable, beta]
steps:
- uses: actions/checkout@v4
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
toolchain: ${{ matrix.rust }}
- name: Cache dependencies
uses: actions/cache@v3
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
- name: Build
run: cargo build --verbose
- name: Run tests
run: cargo test --all-features --verbose
- name: Run doc tests
run: cargo test --doc --verbose
cross_compile:
name: Cross-compilation Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: Check Windows target compilation
run: |
rustup target add x86_64-pc-windows-gnu
cargo check --target x86_64-pc-windows-gnu
- name: Check macOS target compilation
run: |
rustup target add x86_64-apple-darwin
cargo check --target x86_64-apple-darwin
fmt:
name: Rustfmt
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt
- name: Check formatting
run: cargo fmt --all -- --check
clippy:
name: Clippy
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
components: clippy
- name: Run clippy
run: cargo clippy --all-targets --all-features -- -D warnings
security_audit:
name: Security Audit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: Cache cargo-audit
uses: actions/cache@v3
with:
path: |
~/.cargo/bin/cargo-audit
~/.cargo/.crates.toml
~/.cargo/.crates2.json
key: ${{ runner.os }}-cargo-audit-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-audit-
- name: Install cargo-audit
run: |
if ! command -v cargo-audit &> /dev/null; then
echo "Installing cargo-audit..."
cargo install cargo-audit
else
echo "cargo-audit already available"
fi
- name: Run security audit
run: cargo audit
coverage:
name: Coverage
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: Cache cargo-tarpaulin
uses: actions/cache@v3
with:
path: |
~/.cargo/bin/cargo-tarpaulin
~/.cargo/.crates.toml
~/.cargo/.crates2.json
key: ${{ runner.os }}-cargo-tarpaulin-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
${{ runner.os }}-cargo-tarpaulin-
- name: Install cargo-tarpaulin
run: |
if ! command -v cargo-tarpaulin &> /dev/null; then
echo "Installing cargo-tarpaulin..."
cargo install cargo-tarpaulin
else
echo "cargo-tarpaulin already available"
fi
- name: Generate coverage report
run: cargo tarpaulin --verbose --all-features --workspace --timeout 120 --out xml
- name: Upload to codecov.io
uses: codecov/codecov-action@v3
with:
fail_ci_if_error: false
docs:
name: Documentation
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: Check documentation
run: cargo doc --no-deps --document-private-items --all-features
env:
RUSTDOCFLAGS: "-D warnings"
publish_check:
name: Publish Check
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: Check if publishable
run: cargo publish --dry-run --allow-dirty
publish:
name: Publish to crates.io
runs-on: ubuntu-latest
needs: [test, cross_compile, fmt, clippy, security_audit, coverage, docs, publish_check]
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
- name: Check if version already published
id: check_version
run: |
CRATE_VERSION=$(cargo metadata --no-deps --format-version 1 | jq -r '.packages[0].version')
echo "version=$CRATE_VERSION" >> $GITHUB_OUTPUT
# Check if this version already exists on crates.io
if curl -s "https://crates.io/api/v1/crates/maple-rs" | jq -e ".versions[] | select(.num == \"$CRATE_VERSION\")" > /dev/null; then
echo "Version $CRATE_VERSION already exists on crates.io"
echo "should_publish=false" >> $GITHUB_OUTPUT
else
echo "Version $CRATE_VERSION not found on crates.io, proceeding with publish"
echo "should_publish=true" >> $GITHUB_OUTPUT
fi
- name: Login to crates.io
if: steps.check_version.outputs.should_publish == 'true'
run: cargo login ${{ secrets.CRATES_IO_TOKEN }}
- name: Publish to crates.io
if: steps.check_version.outputs.should_publish == 'true'
run: cargo publish
- name: Create GitHub Release
if: steps.check_version.outputs.should_publish == 'true'
uses: softprops/action-gh-release@v1
with:
tag_name: v${{ steps.check_version.outputs.version }}
name: Release v${{ steps.check_version.outputs.version }}
body: |
## Changes
Automated release of maple-rs v${{ steps.check_version.outputs.version }}
This release passed all CI checks:
- ✅ Tests (Windows, Linux, macOS)
- ✅ Code formatting
- ✅ Clippy linting
- ✅ Security audit
- ✅ Code coverage
- ✅ Documentation
- ✅ Cross-compilation
Published to [crates.io](https://crates.io/crates/maple-rs)
draft: false
prerelease: false
generate_release_notes: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}