file: Add more tests #26
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: Code Coverage | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| permissions: | |
| contents: read | |
| pages: write | |
| id-token: write | |
| pull-requests: write | |
| concurrency: | |
| group: coverage-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| coverage: | |
| name: Generate Coverage Report | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Install Rust toolchain | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: llvm-tools-preview | |
| - name: Setup Rust cache | |
| uses: Swatinem/rust-cache@v2 | |
| - name: Install cargo-tarpaulin | |
| uses: taiki-e/install-action@v2 | |
| with: | |
| tool: cargo-tarpaulin | |
| - name: Install system dependencies and setup D-Bus | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y libssl-dev pkg-config gnome-keyring dbus-x11 | |
| # Start D-Bus session | |
| mkdir -p ~/.local/share/keyrings | |
| eval $(dbus-launch --sh-syntax) | |
| export DBUS_SESSION_BUS_ADDRESS | |
| echo "DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS" >> $GITHUB_ENV | |
| # Initialize and unlock the default keyring | |
| printf '\n' | gnome-keyring-daemon --unlock --daemonize --login | |
| # Give the service time to start | |
| sleep 3 | |
| - name: Run coverage for native-tokio | |
| run: | | |
| mkdir -p coverage-raw | |
| cargo tarpaulin \ | |
| --package oo7 \ | |
| --lib \ | |
| --no-default-features \ | |
| --features "tracing,tokio,native_crypto" \ | |
| --ignore-panics \ | |
| --out Lcov \ | |
| --output-dir coverage-raw | |
| mv coverage-raw/lcov.info coverage-raw/native-tokio.info | |
| - name: Run coverage for openssl-async-std | |
| run: | | |
| cargo tarpaulin \ | |
| --package oo7 \ | |
| --lib \ | |
| --no-default-features \ | |
| --features "tracing,async-std,openssl_crypto" \ | |
| --ignore-panics \ | |
| --out Lcov \ | |
| --output-dir coverage-raw | |
| mv coverage-raw/lcov.info coverage-raw/openssl-async-std.info | |
| - name: Generate coverage summary for PR comparison | |
| if: github.event_name == 'pull_request' | |
| run: | | |
| # Extract PR coverage percentage using the same method as main branch | |
| PR_COVERAGE=$(cargo tarpaulin \ | |
| --package oo7 \ | |
| --lib \ | |
| --no-default-features \ | |
| --features "tracing,tokio,native_crypto" \ | |
| --ignore-panics \ | |
| --skip-clean 2>&1 | grep "% coverage" | grep -o '[0-9]\+\.[0-9]\+' | head -1 || echo "0.00") | |
| echo "PR_COVERAGE=$PR_COVERAGE" >> $GITHUB_ENV | |
| echo "PR coverage: $PR_COVERAGE%" | |
| - name: Install grcov for merging coverage | |
| uses: taiki-e/install-action@v2 | |
| with: | |
| tool: grcov | |
| - name: Merge coverage and generate HTML report | |
| run: | | |
| mkdir -p site/coverage | |
| # Merge LCOV files | |
| cat coverage-raw/*.info > coverage-raw/combined.info | |
| # Generate HTML report with grcov | |
| grcov coverage-raw/combined.info \ | |
| --binary-path target/debug/ \ | |
| --source-dir . \ | |
| --output-type html \ | |
| --output-path site/coverage \ | |
| --branch \ | |
| --ignore-not-existing \ | |
| --ignore "**/tests/*" \ | |
| --ignore "**/examples/*" \ | |
| --ignore "**/target/*" | |
| - name: Store coverage percentage for main branch | |
| if: github.ref == 'refs/heads/main' && github.event_name == 'push' | |
| run: | | |
| # Run tarpaulin and extract coverage percentage from the summary line | |
| CURRENT_COVERAGE=$(cargo tarpaulin \ | |
| --package oo7 \ | |
| --lib \ | |
| --no-default-features \ | |
| --features "tracing,tokio,native_crypto" \ | |
| --ignore-panics \ | |
| --skip-clean 2>&1 | grep "% coverage" | grep -o '[0-9]\+\.[0-9]\+' | head -1 || echo "0.00") | |
| echo "Main branch coverage: $CURRENT_COVERAGE%" | |
| # Store in a simple text file artifact for PR comparisons | |
| mkdir -p coverage-baseline | |
| echo "$CURRENT_COVERAGE" > coverage-baseline/main-coverage.txt | |
| # Generate coverage badge | |
| COVERAGE_INT=$(echo "$CURRENT_COVERAGE" | cut -d. -f1) | |
| if [ "$COVERAGE_INT" -ge 80 ]; then | |
| COLOR="brightgreen" | |
| elif [ "$COVERAGE_INT" -ge 60 ]; then | |
| COLOR="yellow" | |
| else | |
| COLOR="red" | |
| fi | |
| # Create badge SVG using shields.io format | |
| curl -s "https://img.shields.io/badge/coverage-${CURRENT_COVERAGE}%25-${COLOR}" > site/coverage/badge.svg | |
| - name: Upload baseline coverage | |
| if: github.ref == 'refs/heads/main' && github.event_name == 'push' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: coverage-baseline | |
| path: coverage-baseline/main-coverage.txt | |
| retention-days: 90 | |
| - name: Get main branch coverage for comparison | |
| if: github.event_name == 'pull_request' | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| // Find the latest successful coverage run on main that has the baseline artifact | |
| const { data: runs } = await github.rest.actions.listWorkflowRuns({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| workflow_id: 'coverage.yml', | |
| status: 'completed', | |
| conclusion: 'success', | |
| branch: 'main', | |
| per_page: 10 | |
| }); | |
| for (const run of runs.workflow_runs) { | |
| try { | |
| const { data: artifacts } = await github.rest.actions.listWorkflowRunArtifacts({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| run_id: run.id | |
| }); | |
| const baselineArtifact = artifacts.artifacts.find(a => a.name === 'coverage-baseline'); | |
| if (baselineArtifact) { | |
| core.exportVariable('BASELINE_RUN_ID', run.id.toString()); | |
| console.log(`Found baseline artifact in run ${run.id}`); | |
| return; | |
| } | |
| } catch (error) { | |
| console.log(`Error checking run ${run.id}: ${error.message}`); | |
| } | |
| } | |
| console.log('No baseline artifact found in recent main branch runs'); | |
| core.exportVariable('BASELINE_RUN_ID', ''); | |
| - name: Download baseline artifact | |
| if: github.event_name == 'pull_request' && env.BASELINE_RUN_ID != '' | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: coverage-baseline | |
| path: coverage-baseline/ | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| run-id: ${{ env.BASELINE_RUN_ID }} | |
| continue-on-error: true | |
| - name: Set main coverage for comparison | |
| if: github.event_name == 'pull_request' | |
| run: | | |
| if [ -f coverage-baseline/main-coverage.txt ]; then | |
| MAIN_COVERAGE=$(cat coverage-baseline/main-coverage.txt) | |
| echo "MAIN_COVERAGE=$MAIN_COVERAGE" >> $GITHUB_ENV | |
| echo "Using stored main branch coverage: $MAIN_COVERAGE%" | |
| else | |
| echo "MAIN_COVERAGE=0.00" >> $GITHUB_ENV | |
| echo "No baseline coverage found, using 0.00%" | |
| fi | |
| - name: Post coverage comment on PR | |
| if: github.event_name == 'pull_request' | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const prCoverage = parseFloat(process.env.PR_COVERAGE || '0.00'); | |
| const mainCoverage = parseFloat(process.env.MAIN_COVERAGE || '0.00'); | |
| const diff = prCoverage - mainCoverage; | |
| const diffText = diff > 0 ? `+${diff.toFixed(2)}%` : `${diff.toFixed(2)}%`; | |
| const emoji = diff > 0 ? '📈' : diff < 0 ? '📉' : '➡️'; | |
| const body = `## 📊 Code Coverage Report | |
| | Metric | Value | | |
| |--------|-------| | |
| | **Current PR Coverage** | ${prCoverage.toFixed(2)}% | | |
| | **Main Branch Coverage** | ${mainCoverage.toFixed(2)}% | | |
| | **Coverage Change** | ${emoji} ${diffText} | | |
| ${diff < -1 ? '⚠️ **Warning**: Coverage decreased by more than 1%' : ''} | |
| ${diff > 1 ? '🎉 **Great**: Coverage increased by more than 1%!' : ''} | |
| *Coverage report generated by [cargo-tarpaulin](https://github.com/xd009642/tarpaulin)*`; | |
| // Find existing coverage comment | |
| const { data: comments } = await github.rest.issues.listComments({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| }); | |
| const existingComment = comments.find(comment => | |
| comment.body.includes('## 📊 Code Coverage Report') | |
| ); | |
| if (existingComment) { | |
| // Update existing comment | |
| await github.rest.issues.updateComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| comment_id: existingComment.id, | |
| body: body | |
| }); | |
| } else { | |
| // Create new comment | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| body: body | |
| }); | |
| } | |
| - name: Upload coverage artifacts | |
| if: github.ref == 'refs/heads/main' && github.event_name == 'push' | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: coverage-reports | |
| path: site/coverage/html/ | |
| retention-days: 30 |