fix!: harden geometry, rollback, and public API contracts #1868
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: Codecov | |
| concurrency: | |
| # This concurrency group ensures that only one Codecov analysis runs at a time | |
| group: codecov-${{ github.ref_name }} | |
| cancel-in-progress: true | |
| on: | |
| push: | |
| branches: ["main"] | |
| pull_request: | |
| branches: ["main"] | |
| # Least-privilege permissions | |
| permissions: | |
| contents: read | |
| checks: write | |
| pull-requests: write | |
| jobs: | |
| coverage: | |
| name: Code Coverage | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| fetch-depth: 0 # Needed for codecov to analyze diff | |
| persist-credentials: false | |
| - name: Install Rust toolchain | |
| uses: actions-rust-lang/setup-rust-toolchain@166cdcfd11aee3cb47222f9ddb555ce30ddb9659 # v1.17.0 | |
| with: | |
| cache: true | |
| cache-bin: false | |
| # toolchain, components, etc. are specified in rust-toolchain.toml | |
| - name: Set up just | |
| id: setup_just | |
| uses: $/.github/actions/setup-just | |
| - name: Export coverage tool versions | |
| id: tool_versions | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| resolve_version() { | |
| local name="$1" | |
| local value | |
| if ! value="$(just --evaluate "$name")"; then | |
| echo "::error::Failed to resolve $name from justfile" >&2 | |
| return 1 | |
| fi | |
| if [[ -z "$value" ]]; then | |
| echo "::error::Resolved empty $name from justfile" >&2 | |
| return 1 | |
| fi | |
| printf '%s\n' "$value" | |
| } | |
| cargo_llvm_cov_version="$(resolve_version cargo_llvm_cov_version)" | |
| cargo_nextest_version="$(resolve_version nextest_version)" | |
| { | |
| echo "CARGO_LLVM_COV_VERSION=$cargo_llvm_cov_version" | |
| echo "CARGO_NEXTEST_VERSION=$cargo_nextest_version" | |
| } >> "$GITHUB_OUTPUT" | |
| - name: Install LLVM coverage tools | |
| run: rustup component add llvm-tools-preview | |
| - name: Install cargo-llvm-cov | |
| uses: taiki-e/cache-cargo-install-action@9ee83daaa7b96a6fab930949ecf1122bba04a389 # v3.0.8 | |
| with: | |
| tool: cargo-llvm-cov@${{ steps.tool_versions.outputs.CARGO_LLVM_COV_VERSION }} | |
| - name: Install cargo-nextest | |
| uses: taiki-e/cache-cargo-install-action@9ee83daaa7b96a6fab930949ecf1122bba04a389 # v3.0.8 | |
| with: | |
| tool: cargo-nextest@${{ steps.tool_versions.outputs.CARGO_NEXTEST_VERSION }} | |
| - name: Verify cargo-nextest | |
| run: cargo nextest --version | |
| - name: Run coverage and test results | |
| run: | | |
| # Create coverage directory with proper permissions | |
| mkdir -p coverage | |
| chmod 755 coverage | |
| echo "::group::Running coverage" | |
| # Use just coverage-ci for single source of truth. The recipe runs | |
| # cargo-llvm-cov through nextest so one instrumented test pass | |
| # produces both Cobertura coverage and nextest JUnit XML. | |
| just coverage-ci | |
| echo "::endgroup::" | |
| # Detailed sanity check: verify coverage report was generated | |
| echo "::group::Coverage verification" | |
| echo "Directory listing:" | |
| ls -la coverage/ || echo "Coverage directory not found" | |
| printf "\nSearching for XML files:\n" | |
| find . -name "*.xml" -type f -ls 2>/dev/null || echo "No XML files found" | |
| printf "\nSearching for cobertura files:\n" | |
| find . -name "*cobertura*" -type f -ls 2>/dev/null || echo "No cobertura files found" | |
| if [ ! -f coverage/cobertura.xml ]; then | |
| echo "::error::coverage/cobertura.xml not found. cargo-llvm-cov failed to generate XML output." | |
| echo "::error::Check cargo-llvm-cov logs above for errors." | |
| exit 2 | |
| else | |
| coverage_bytes=$(wc -c < coverage/cobertura.xml) | |
| coverage_newlines=$(wc -l < coverage/cobertura.xml) | |
| coverage_lines_covered=$( | |
| grep -oE 'lines-covered="[0-9]+"' coverage/cobertura.xml \ | |
| | head -n1 \ | |
| | cut -d'"' -f2 || true | |
| ) | |
| coverage_lines_valid=$( | |
| grep -oE 'lines-valid="[0-9]+"' coverage/cobertura.xml \ | |
| | head -n1 \ | |
| | cut -d'"' -f2 || true | |
| ) | |
| coverage_line_rate=$( | |
| grep -oE 'line-rate="[0-9.]+"' coverage/cobertura.xml \ | |
| | head -n1 \ | |
| | cut -d'"' -f2 || true | |
| ) | |
| if [ -n "${coverage_lines_covered}" ] \ | |
| && [ -n "${coverage_lines_valid}" ] \ | |
| && [ -n "${coverage_line_rate}" ]; then | |
| echo "::notice::Coverage report generated successfully:" | |
| echo "::notice:: bytes=${coverage_bytes}, xml_newlines=${coverage_newlines}" | |
| echo "::notice:: covered=${coverage_lines_covered}, valid=${coverage_lines_valid}" | |
| echo "::notice:: rate=${coverage_line_rate}" | |
| else | |
| echo "::warning::Coverage report generated (${coverage_bytes} bytes)," | |
| echo "::warning:: could not parse Cobertura metrics; XML newlines=${coverage_newlines}" | |
| fi | |
| fi | |
| # Sanity: ensure benches/examples aren't present (defense-in-depth with .codecov.yml) | |
| if command -v rg >/dev/null 2>&1; then | |
| if rg -n '(^|/)(benches|examples)/' coverage/cobertura.xml; then | |
| echo "::warning::benches/ or examples/ paths detected in coverage report" | |
| fi | |
| else | |
| if grep -nE '(^|/)(benches|examples)/' coverage/cobertura.xml; then | |
| echo "::warning::benches/ or examples/ paths detected in coverage report" | |
| fi | |
| fi | |
| echo "::endgroup::" | |
| echo "::group::Test result verification" | |
| # Nextest outputs to target/nextest/<profile>/<path-from-config>. | |
| if [ ! -f target/nextest/coverage/test-results/junit.xml ]; then | |
| echo "::error::target/nextest/coverage/test-results/junit.xml not found" | |
| exit 2 | |
| else | |
| echo "::notice::Test results generated: $(wc -l < target/nextest/coverage/test-results/junit.xml) lines" | |
| fi | |
| echo "::endgroup::" | |
| env: | |
| RUST_BACKTRACE: 1 | |
| DELAUNAY_PROPTEST_COVERAGE_LOGS: 1 | |
| - name: Upload coverage to Codecov | |
| if: ${{ success() && hashFiles('coverage/cobertura.xml') != '' }} | |
| uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 | |
| with: | |
| files: coverage/cobertura.xml | |
| flags: unittests | |
| name: codecov-umbrella | |
| fail_ci_if_error: false | |
| env: | |
| CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} | |
| - name: Upload test results to Codecov | |
| if: ${{ success() && hashFiles('target/nextest/coverage/test-results/junit.xml') != '' }} | |
| uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 | |
| with: | |
| files: target/nextest/coverage/test-results/junit.xml | |
| flags: unittests | |
| name: test-results | |
| report_type: test_results | |
| fail_ci_if_error: false | |
| env: | |
| CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} | |
| - name: Upload coverage to Codacy | |
| if: ${{ success() && hashFiles('coverage/cobertura.xml') != '' }} | |
| uses: codacy/codacy-coverage-reporter-action@89d6c85cfafaec52c72b6c5e8b2878d33104c699 # v1.3.0 | |
| with: | |
| project-token: ${{ secrets.CODACY_PROJECT_TOKEN }} | |
| coverage-reports: coverage/cobertura.xml | |
| language: rust | |
| continue-on-error: true | |
| - name: Archive coverage results | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| if: always() | |
| with: | |
| name: coverage-report | |
| path: coverage/ | |
| - name: Archive test results | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| if: always() | |
| with: | |
| name: test-results | |
| path: target/nextest/coverage/test-results/ |