name: Rust CI & Release
on:
push:
branches: [main]
tags: ["v*"]
pull_request:
branches: [main]
schedule:
- cron: "0 6 * * 1"
workflow_dispatch:
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
env:
CARGO_TERM_COLOR: always
RUSTFLAGS: -D warnings
RUSTDOCFLAGS: -D warnings
jobs:
build:
name: Build & Test (${{ matrix.rust }})
runs-on: ubuntu-latest
timeout-minutes: 25
permissions:
contents: read
strategy:
fail-fast: false
matrix:
rust: [stable, beta, nightly]
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
persist-credentials: false
- name: Setup Rust toolchain
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: ${{ matrix.rust }}
components: rustfmt, clippy
cache: false
- name: Setup Rust cache
uses: Swatinem/rust-cache@v2
with:
cache-on-failure: false
- name: Check code formatting
run: cargo fmt --all -- --check
- name: Run Clippy lints (lib/bin)
continue-on-error: ${{ matrix.rust == 'nightly' }}
run: cargo clippy --all-features -- -D clippy::expect_used -D clippy::panic -D clippy::unwrap_used -D warnings
- name: Run Clippy lints (tests)
continue-on-error: ${{ matrix.rust == 'nightly' }}
run: cargo clippy --tests --all-features -- -D warnings
- name: Build project
continue-on-error: ${{ matrix.rust == 'nightly' }}
run: cargo build --all --locked --verbose
- name: Run tests
continue-on-error: ${{ matrix.rust == 'nightly' }}
run: cargo test --all --locked --verbose
- name: Check documentation
continue-on-error: ${{ matrix.rust == 'nightly' }}
run: cargo doc --no-deps --all-features --locked
- name: Install tarpaulin
if: matrix.rust == 'stable'
uses: taiki-e/install-action@v2
with:
tool: cargo-tarpaulin
- name: Generate coverage report
if: matrix.rust == 'stable'
run: cargo tarpaulin --all-features --workspace --timeout 120 --out xml --output-dir ./coverage
- name: Upload coverage to Codecov
if: matrix.rust == 'stable' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository)
uses: codecov/codecov-action@v6
with:
files: ./coverage/cobertura.xml
fail_ci_if_error: false
token: ${{ secrets.CODECOV_TOKEN }}
verbose: true
security:
name: Security Audit
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
persist-credentials: false
- name: Setup Rust toolchain
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: stable
cache: false
- name: Setup Rust cache
uses: Swatinem/rust-cache@v2
with:
cache-on-failure: false
- name: Install cargo-audit
uses: taiki-e/install-action@v2
with:
tool: cargo-audit
- name: Run security audit
run: cargo audit
release:
name: Release to crates.io
needs: [build, security]
runs-on: ubuntu-latest
timeout-minutes: 15
if: startsWith(github.ref, 'refs/tags/v') && github.repository == 'GuoMonth/range_date'
environment:
name: crates-io
url: https://crates.io/crates/range_date
permissions:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v6
with:
persist-credentials: false
- name: Setup Rust toolchain
uses: actions-rust-lang/setup-rust-toolchain@v1
with:
toolchain: stable
cache: false
- name: Setup Rust cache
uses: Swatinem/rust-cache@v2
with:
cache-on-failure: false
- name: Verify package
run: cargo package --locked --verbose
- name: Publish to crates.io
run: cargo publish --locked --verbose
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}