build(deps): bump actions/deploy-pages from 4 to 5 #611
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
| name: Rust Tests & Coverage | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main] | |
| workflow_dispatch: # Allows manual trigger from GitHub UI | |
| permissions: | |
| contents: read # Default: read-only (write scoped to job level for badge push) | |
| jobs: | |
| test-and-coverage: | |
| name: Test + Tarpaulin Coverage (Ubuntu) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 45 | |
| permissions: | |
| contents: write # Required to push coverage badge (only on main) | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 | |
| with: | |
| fetch-depth: 0 # Useful if you need git history for anything | |
| - name: Install Rust stable toolchain | |
| uses: dtolnay/rust-toolchain@d0592fe69e35bc8f12e3dbaf9ad2694d976cb8e3 # stable | |
| with: | |
| toolchain: stable | |
| - name: Cache Cargo dependencies | |
| uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.7.7 | |
| with: | |
| workspaces: | | |
| rust_crypto | |
| crypto_core | |
| # If you have a workspace root Cargo.toml, it will cache the whole thing automatically | |
| - name: Install system dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y libpcsclite-dev libudev-dev pkg-config bc | |
| - name: Install cargo-tarpaulin | |
| run: cargo install cargo-tarpaulin | |
| # ββ Coverage: crypto_core ββββββββββββββββββββββββββββββββββββββββββββββ | |
| # FIX: Three issues previously caused Codecov to report 0% coverage: | |
| # 1. cdylib crate-type prevents tarpaulin ptrace instrumentation | |
| # 2. Missing --lib --tests flags (defaults to building cdylib target) | |
| # 3. lcov.info paths were "src/..." not "crypto_core/src/..." so | |
| # Codecov couldn't match them to the repo file tree | |
| - name: Run tests with coverage (crypto_core) | |
| id: tarpaulin | |
| run: | | |
| # Temporarily remove cdylib β tarpaulin cannot instrument shared libraries | |
| sed -i 's/crate-type = \["lib", "cdylib"\]/crate-type = ["lib"]/' crypto_core/Cargo.toml | |
| # Run from workspace root; tarpaulin discovers the workspace Cargo.toml | |
| # and produces workspace-relative paths (crypto_core/src/...) in lcov.info | |
| cargo tarpaulin \ | |
| -p crypto_core \ | |
| --lib --tests \ | |
| --features "pure-crypto,pq-crypto" \ | |
| --out Lcov \ | |
| --out Json \ | |
| --output-dir ./crypto_core \ | |
| --timeout 300 \ | |
| --exclude-files "src/wasm.rs" \ | |
| --exclude-files "src/hsm.rs" \ | |
| --exclude-files "src/tpm.rs" \ | |
| --exclude-files "src/yubikey_piv.rs" \ | |
| -- --test-threads=1 2>&1 | tee crypto_core/tarpaulin-output.txt | |
| # Restore Cargo.toml so the cdylib removal doesn't leak | |
| git checkout crypto_core/Cargo.toml | |
| # Fix source paths: strip absolute workspace prefix so codecov sees | |
| # repo-relative paths like "crypto_core/src/..." | |
| sed -i "s|^SF:$(pwd)/||" crypto_core/lcov.info || true | |
| # Also fix bare "src/" β "crypto_core/src/" if present | |
| sed -i 's|^SF:src/|SF:crypto_core/src/|' crypto_core/lcov.info || true | |
| # Extract coverage percentage from output | |
| COVERAGE=$(grep -oP '\d+\.\d+% coverage' crypto_core/tarpaulin-output.txt | head -1 | grep -oP '\d+\.\d+') | |
| echo "coverage=$COVERAGE" >> $GITHUB_OUTPUT | |
| echo "Rust coverage: $COVERAGE%" | |
| # ββ Coverage: rust_crypto ββββββββββββββββββββββββββββββββββββββββββββ | |
| - name: Run tests with coverage (rust_crypto) | |
| id: tarpaulin_rust_crypto | |
| run: | | |
| # Temporarily remove cdylib β tarpaulin cannot instrument shared libraries | |
| sed -i 's/crate-type = \["cdylib", "lib"\]/crate-type = ["lib"]/' rust_crypto/Cargo.toml | |
| # Run from workspace root; tarpaulin produces workspace-relative paths | |
| cargo tarpaulin \ | |
| -p meow_crypto_rs \ | |
| --lib --tests \ | |
| --features "pq,pq-signing" \ | |
| --out Lcov \ | |
| --out Json \ | |
| --output-dir ./rust_crypto \ | |
| --timeout 300 \ | |
| --exclude-files "src/lib.rs" \ | |
| -- --test-threads=1 2>&1 | tee rust_crypto/tarpaulin-output.txt | |
| # Restore Cargo.toml | |
| git checkout rust_crypto/Cargo.toml | |
| # Fix source paths: strip absolute workspace prefix so codecov sees | |
| # repo-relative paths like "rust_crypto/src/..." | |
| sed -i "s|^SF:$(pwd)/||" rust_crypto/lcov.info || true | |
| # Also fix bare "src/" β "rust_crypto/src/" if present | |
| sed -i 's|^SF:src/|SF:rust_crypto/src/|' rust_crypto/lcov.info || true | |
| COVERAGE=$(grep -oP '\d+\.\d+% coverage' rust_crypto/tarpaulin-output.txt | head -1 | grep -oP '\d+\.\d+') | |
| echo "coverage=$COVERAGE" >> $GITHUB_OUTPUT | |
| echo "rust_crypto coverage: $COVERAGE%" | |
| # ββ Coverage threshold enforcement βββββββββββββββββββββββββββββββββ | |
| - name: Enforce coverage thresholds | |
| run: | | |
| CORE="${{ steps.tarpaulin.outputs.coverage }}" | |
| RC="${{ steps.tarpaulin_rust_crypto.outputs.coverage }}" | |
| THRESHOLD=70 | |
| echo "============================================" | |
| echo "π Rust Coverage Threshold Enforcement" | |
| echo " Minimum required: ${THRESHOLD}%" | |
| echo "============================================" | |
| echo " crypto_core: ${CORE:-N/A}%" | |
| echo " rust_crypto: ${RC:-N/A}%" | |
| echo "" | |
| FAILED=0 | |
| if [ -n "$CORE" ]; then | |
| if (( $(echo "$CORE < $THRESHOLD" | bc -l) )); then | |
| echo "β crypto_core coverage ${CORE}% is below ${THRESHOLD}%" | |
| FAILED=1 | |
| fi | |
| fi | |
| if [ -n "$RC" ]; then | |
| if (( $(echo "$RC < $THRESHOLD" | bc -l) )); then | |
| echo "β rust_crypto coverage ${RC}% is below ${THRESHOLD}%" | |
| FAILED=1 | |
| fi | |
| fi | |
| if [ "$FAILED" -eq 1 ]; then | |
| echo "" | |
| echo "Coverage threshold not met. Add tests to increase coverage." | |
| exit 1 | |
| fi | |
| echo "β All Rust crates meet ${THRESHOLD}% coverage threshold" | |
| - name: Generate coverage badge | |
| if: github.ref == 'refs/heads/main' && github.event_name == 'push' | |
| run: | | |
| COVERAGE_CORE="${{ steps.tarpaulin.outputs.coverage }}" | |
| COVERAGE_RUST_CRYPTO="${{ steps.tarpaulin_rust_crypto.outputs.coverage }}" | |
| # Calculate combined coverage (simple average) | |
| # In future, could weight by lines of code | |
| if [ -n "$COVERAGE_CORE" ] && [ -n "$COVERAGE_RUST_CRYPTO" ]; then | |
| COVERAGE=$(echo "scale=2; ($COVERAGE_CORE + $COVERAGE_RUST_CRYPTO) / 2" | bc) | |
| elif [ -n "$COVERAGE_CORE" ]; then | |
| COVERAGE="$COVERAGE_CORE" | |
| else | |
| COVERAGE="0" | |
| fi | |
| echo "Combined Rust coverage: ${COVERAGE}% (crypto_core: ${COVERAGE_CORE}%, rust_crypto: ${COVERAGE_RUST_CRYPTO}%)" | |
| # Determine badge color based on coverage | |
| if (( $(echo "$COVERAGE >= 90" | bc -l) )); then | |
| COLOR="4c1" # brightgreen | |
| elif (( $(echo "$COVERAGE >= 80" | bc -l) )); then | |
| COLOR="97ca00" # green | |
| elif (( $(echo "$COVERAGE >= 70" | bc -l) )); then | |
| COLOR="a4a61d" # yellowgreen | |
| elif (( $(echo "$COVERAGE >= 60" | bc -l) )); then | |
| COLOR="dfb317" # yellow | |
| else | |
| COLOR="e05d44" # red | |
| fi | |
| # Generate SVG badge | |
| cat > assets/coverage.svg << EOF | |
| <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="168" height="20" role="img" aria-label="Rust Combined: ${COVERAGE}%"> | |
| <title>Rust Combined Coverage: ${COVERAGE}%</title> | |
| <linearGradient id="s" x2="0" y2="100%"> | |
| <stop offset="0" stop-color="#bbb" stop-opacity=".1"/> | |
| <stop offset="1" stop-opacity=".1"/> | |
| </linearGradient> | |
| <clipPath id="r"> | |
| <rect width="168" height="20" rx="3" fill="#fff"/> | |
| </clipPath> | |
| <g clip-path="url(#r)"> | |
| <rect width="120" height="20" fill="#555"/> | |
| <rect x="120" width="48" height="20" fill="#${COLOR}"/> | |
| <rect width="168" height="20" fill="url(#s)"/> | |
| </g> | |
| <g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"> | |
| <text aria-hidden="true" x="610" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="1100">Rust Combined</text> | |
| <text x="610" y="140" transform="scale(.1)" fill="#fff" textLength="1100">Rust Combined</text> | |
| <text aria-hidden="true" x="1430" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="380">${COVERAGE}%</text> | |
| <text x="1430" y="140" transform="scale(.1)" fill="#fff" textLength="380">${COVERAGE}%</text> | |
| </g> | |
| </svg> | |
| EOF | |
| echo "Generated badge with ${COVERAGE}% combined coverage (crypto_core: ${COVERAGE_CORE}%, rust_crypto: ${COVERAGE_RUST_CRYPTO}%)" | |
| - name: Commit coverage badge | |
| if: github.ref == 'refs/heads/main' && github.event_name == 'push' | |
| env: | |
| BADGE_PUSH_TOKEN: ${{ secrets.BADGE_PUSH_TOKEN }} | |
| run: | | |
| git config --local user.email "github-actions[bot]@users.noreply.github.com" | |
| git config --local user.name "github-actions[bot]" | |
| git add assets/coverage.svg | |
| if ! git diff --staged --quiet; then | |
| git commit -m "chore: update Rust coverage badge [skip ci]" | |
| if [ -n "$BADGE_PUSH_TOKEN" ]; then | |
| git push https://x-access-token:${BADGE_PUSH_TOKEN}@github.com/${{ github.repository }}.git HEAD:main | |
| else | |
| echo "::warning::BADGE_PUSH_TOKEN not set - skipping push to protected branch" | |
| fi | |
| fi | |
| - name: Upload coverage to Codecov | |
| uses: codecov/codecov-action@671740ac38dd9b0130fbe1cec585b89eea48d3de # v5.3.1 | |
| with: | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| files: ./crypto_core/lcov.info,./rust_crypto/lcov.info | |
| flags: rust | |
| name: rust-coverage | |
| fail_ci_if_error: true | |
| - name: Run regular tests (crypto_core, without coverage) | |
| if: always() | |
| run: | | |
| cd crypto_core && cargo test --features "pure-crypto,pq-crypto" | |
| - name: Run regular tests (rust_crypto, without coverage) | |
| if: always() | |
| run: | | |
| cd rust_crypto && cargo test --features "pq,pq-signing" |