chore: release #332
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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) |