Skip to content

chore: release

chore: release #332

Workflow file for this run

# SPDX-FileCopyrightText: 2025 RAprogramm <andrey.rozanov.vl@gmail.com>
#
# SPDX-License-Identifier: MIT
name: CI
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
inputs:
force_publish:
description: "Force publish (ignores version check)"
type: boolean
default: false
skip_tests:
description: "Skip test stage (for emergency releases)"
type: boolean
default: false
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
permissions:
contents: write
pull-requests: write
id-token: write
attestations: write
env:
CARGO_TERM_COLOR: always
CARGO_INCREMENTAL: 0
RUST_BACKTRACE: short
RUSTFLAGS: -D warnings
jobs:
# ════════════════════════════════════════════════════════════════════════════
# STAGE 0: PREPARE (single source of truth for MSRV)
# ════════════════════════════════════════════════════════════════════════════
prepare:
name: Prepare
runs-on: ubuntu-latest
outputs:
msrv: ${{ steps.msrv.outputs.msrv }}
steps:
- uses: actions/checkout@v7
- name: Read MSRV from workspace Cargo.toml
id: msrv
run: |
MSRV=$(grep -m1 -E '^rust-version' Cargo.toml | sed 's/.*"\(.*\)".*/\1/')
if [[ -z "$MSRV" ]]; then
echo "::error::Failed to read rust-version from Cargo.toml"
exit 1
fi
echo "msrv=$MSRV" >> "$GITHUB_OUTPUT"
echo "Detected MSRV: $MSRV"
# ════════════════════════════════════════════════════════════════════════════
# STAGE 1: CHECKS (parallel)
# ════════════════════════════════════════════════════════════════════════════
check:
name: Check (${{ matrix.rust }} / ${{ matrix.os }})
needs: prepare
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
# MSRV (from workspace Cargo.toml)
- rust: ${{ needs.prepare.outputs.msrv }}
os: ubuntu-latest
msrv: true
# Stable (primary)
- rust: stable
os: ubuntu-latest
# Stable on macOS
- rust: stable
os: macos-latest
# Stable on Windows
- rust: stable
os: windows-latest
# Nightly (for future compat)
- rust: nightly
os: ubuntu-latest
allow_fail: true
continue-on-error: ${{ matrix.allow_fail || false }}
steps:
- uses: actions/checkout@v7
- name: Install Rust ${{ matrix.rust }}
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.rust }}
components: clippy
- name: Cache
uses: Swatinem/rust-cache@v2
with:
shared-key: ${{ matrix.rust }}-${{ matrix.os }}
save-if: ${{ github.ref == 'refs/heads/main' }}
- name: Clippy
run: cargo clippy --all-targets --all-features -- -D warnings
- name: Check (all features)
run: cargo check --all-features
- name: Check (no default features)
run: cargo check --no-default-features
fmt:
name: Format
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Install Rust nightly
uses: dtolnay/rust-toolchain@nightly
with:
components: rustfmt
- name: Check formatting
run: cargo +nightly fmt --all -- --check
docs:
name: Documentation
runs-on: ubuntu-latest
env:
RUSTDOCFLAGS: -D warnings
steps:
- uses: actions/checkout@v7
- name: Install Rust stable
uses: dtolnay/rust-toolchain@stable
- name: Cache
uses: Swatinem/rust-cache@v2
- name: Build docs
run: cargo doc --all-features --no-deps
security:
name: Security Audit
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Install Rust stable
uses: dtolnay/rust-toolchain@stable
- name: Install cargo-deny
uses: taiki-e/install-action@v2
with:
tool: cargo-deny
- name: Security audit
run: cargo deny check advisories
reuse:
name: REUSE Compliance
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Install reuse
run: pip install --user reuse
- name: Check REUSE compliance
run: reuse lint
# ════════════════════════════════════════════════════════════════════════════
# STAGE 2: TEST (after checks pass)
# ════════════════════════════════════════════════════════════════════════════
test:
name: Test Suite
needs: [check, fmt, security, reuse]
if: ${{ !inputs.skip_tests }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Install Rust stable
uses: dtolnay/rust-toolchain@stable
- name: Cache
uses: Swatinem/rust-cache@v2
continue-on-error: true
with:
shared-key: test
save-if: ${{ github.ref == 'refs/heads/main' }}
- name: Install nextest
uses: taiki-e/install-action@v2
with:
tool: cargo-nextest
- name: Run tests
run: cargo nextest run --all-features --profile ci --no-tests=pass
- name: Run doctests
run: cargo test --doc --all-features || true
- name: Test garde backend (garde without validate)
run: |
cargo nextest run -p entity-derive-impl --no-default-features --features garde --profile ci --no-tests=pass
cargo nextest run -p entity-derive --no-default-features --features postgres,garde --test garde --profile ci --no-tests=pass
- name: Upload test results
if: always()
uses: actions/upload-artifact@v7
with:
name: test-results
path: target/nextest/ci/junit.xml
if-no-files-found: ignore
retention-days: 30
- name: Upload test results to Codecov
if: ${{ !cancelled() }}
uses: codecov/codecov-action@v7
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: target/nextest/ci/junit.xml
report_type: test_results
fail_ci_if_error: false
coverage:
name: Coverage
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Install Rust stable
uses: dtolnay/rust-toolchain@stable
with:
components: llvm-tools-preview
- name: Cache
uses: Swatinem/rust-cache@v2
continue-on-error: true
with:
shared-key: coverage
save-if: ${{ github.ref == 'refs/heads/main' }}
- name: Install tools
uses: taiki-e/install-action@v2
with:
tool: cargo-llvm-cov,cargo-nextest
- name: Generate coverage
run: |
cargo llvm-cov nextest --all-features --profile ci --lcov --output-path lcov.info
cargo llvm-cov report --html
- name: Upload to Codecov
uses: codecov/codecov-action@v7
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: lcov.info
fail_ci_if_error: false
- name: Upload coverage report
uses: actions/upload-artifact@v7
with:
name: coverage-report
path: target/llvm-cov/html/
retention-days: 30
- name: Coverage summary
run: |
COVERAGE=$(cargo llvm-cov report 2>/dev/null | grep TOTAL | awk '{print $NF}' || echo "N/A")
echo "## Coverage: $COVERAGE" >> $GITHUB_STEP_SUMMARY
# ════════════════════════════════════════════════════════════════════════════
# STAGE 3: RELEASE (after tests pass, main branch only)