name: Coverage # Using a single file workflow is the preferred solution for our CI over workflow_runs. # 1. It generates only 1 action item in the list making it more readable # 2. It includes the PR/Commit text in the action item # 3. Artifacts are not available between workflows. on: pull_request: push: branches: - master env: NODE_OPTIONS: "--max-old-space-size=12288" GRCOV_VERSION: 0.8.18 jobs: ####### Check files and formatting ####### set-tags: runs-on: ubuntu-latest permissions: contents: read outputs: git_branch: ${{ steps.check-git-ref.outputs.git_branch }} git_target_branch: ${{ steps.check-git-ref.outputs.git_target_branch }} git_ref: ${{ steps.check-git-ref.outputs.git_ref }} sha: ${{ steps.get-sha.outputs.sha }} sha8: ${{ steps.get-sha.outputs.sha8 }} polkadot_repo: ${{ steps.get-sha.outputs.polkadot_repo }} polkadot_commit: ${{ steps.get-sha.outputs.polkadot_commit }} latest_rt: ${{ steps.get-sha.outputs.latest_rt }} latest_rt_sha8: ${{ steps.get-sha.outputs.latest_rt_sha8 }} coverage_dir: ${{ steps.check-git-ref.outputs.coverage_dir }} coverage_report: ${{ steps.check-git-ref.outputs.coverage_report }} steps: - name: Check git ref id: check-git-ref # if PR # else if manual PR # else (push) run: | if [[ -n "${{ github.event.pull_request.head.sha }}" ]]; then echo "git_branch=$(echo ${GITHUB_HEAD_REF})" >> $GITHUB_OUTPUT echo "git_target_branch=$(echo ${GITHUB_BASE_REF})" >> $GITHUB_OUTPUT echo "git_ref=${{ github.event.pull_request.head.sha }}" >> $GITHUB_OUTPUT echo "coverage_dir=pulls/${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT echo "coverage_report=true" >> $GITHUB_OUTPUT else echo "git_branch=$(echo ${GITHUB_REF#refs/heads/})" >> $GITHUB_OUTPUT echo "git_target_branch=$(echo ${GITHUB_REF#refs/heads/})" >> $GITHUB_OUTPUT echo "git_ref=$GITHUB_REF" >> $GITHUB_OUTPUT echo "coverage_dir=branches/master" >> $GITHUB_OUTPUT echo "coverage_report=false" >> $GITHUB_OUTPUT fi - uses: actions/checkout@v4 with: ref: ${{ steps.check-git-ref.outputs.git_ref }} - name: Get Latest RT Release id: get-latest-rt run: | LATEST_RUNTIME_RELEASE=$(curl -s https://api.github.com/repos/moonbeam-foundation/moonbeam/releases | jq -r '.[] | select(.name | test("runtime";"i")) | .tag_name' | sort -rs | head -n 1 | tr -d '[:blank:]') echo $LATEST_RUNTIME_RELEASE echo "latest_rt=$LATEST_RUNTIME_RELEASE" >> $GITHUB_OUTPUT - name: Get Sha id: get-sha run: | echo "sha=$(git log -1 --format='%H')" >> $GITHUB_OUTPUT echo "sha8=$(git log -1 --format='%H' | cut -c1-8)" >> $GITHUB_OUTPUT echo "polkadot_repo=$(egrep -o 'https.*/polkadot' Cargo.lock | head -1)" >> $GITHUB_OUTPUT echo "polkadot_commit=$(egrep -o '/polkadot.*#([^\"]*)' Cargo.lock | \ head -1 | sed 's/.*#//' | cut -c1-8)" >> $GITHUB_OUTPUT echo "$(curl -s "https://api.github.com/repos/moonbeam-foundation/moonbeam/git/refs/tags/${{ steps.get-latest-rt.outputs.latest_rt }}" | jq -r '.object.sha' | cut -c 1-8)" echo "latest_rt_sha8=$(curl -s 'https://api.github.com/repos/moonbeam-foundation/moonbeam/git/refs/tags/${{steps.get-latest-rt.outputs.latest_rt }}' | jq -r '.object.sha' | cut -c 1-8 )" >> $GITHUB_OUTPUT - name: Check existing docker image id: check-docker-image run: | TAG=sha-${{ steps.get-sha.outputs.sha8 }} - name: Display variables run: | echo git_ref: ${{ steps.check-git-ref.outputs.git_ref }} echo sha: ${{ steps.get-sha.outputs.sha }} echo sha8: ${{ steps.get-sha.outputs.sha8 }} echo latest_rt: ${{ steps.get-latest-rt.outputs.latest_rt }} echo latest_rt_sha8: ${{ steps.get-sha.outputs.latest_rt_sha8 }} build-and-coverage: runs-on: labels: bare-metal permissions: contents: read pull-requests: write needs: ["set-tags"] if: ${{ !github.event.pull_request.head.repo.fork }} timeout-minutes: 90 env: RUSTC_WRAPPER: "sccache" CARGO_INCREMENTAL: "0" SCCACHE_CACHE_SIZE: "100GB" CARGO_TERM_COLOR: always steps: - name: Checkout uses: actions/checkout@v4 with: ref: ${{ needs.set-tags.outputs.git_ref }} - name: Setup Variables shell: bash run: | echo "RUSTFLAGS=-C opt-level=3 -D warnings -C instrument-coverage -C linker=clang -C link-arg=-fuse-ld=$(pwd)/mold/bin/mold" >> $GITHUB_ENV # Disable coverage when building echo "LLVM_PROFILE_FILE=/dev/null" >> $GITHUB_ENV - name: Setup grcov run: | wget https://github.com/mozilla/grcov/releases/download/v${{ env.GRCOV_VERSION }}/grcov-x86_64-unknown-linux-gnu.tar.bz2 tar xvf grcov-x86_64-unknown-linux-gnu.tar.bz2 chmod +x grcov - name: Install llvm tools run: rustup component add llvm-tools-preview - name: Cargo build uses: ./.github/workflow-templates/cargo-build with: features: metadata-hash - name: Enable coverage gathering run: | # Enable coverage when running tests echo "LLVM_PROFILE_FILE=$(pwd)/proffiles/default_%m_%p.profraw" >> $GITHUB_ENV - name: Unit tests run: | # curl -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash curl -LsSf https://get.nexte.st/latest/linux | tar zxf - -C ${CARGO_HOME:-~/.cargo}/bin # echo $PATH cargo nextest run --release --workspace --features=evm-tracing - name: "Run Moonwall Dev Tests" uses: ./.github/workflow-templates/dev-tests with: moonwall_environment: dev_moonbase force-pass: true - name: Retrieve coverage id: coverage run: | du -sh proffiles echo "Executing grcov" mkdir -p coverage ./grcov proffiles/ -s ./ --binary-path ./target/release/ \ -t html,covdir --branch --ignore-not-existing --ignore "target/release/build/*" \ --ignore "$HOME/.cargo/**" -o coverage/ --llvm 2>&1 \ | tee grcov.log INVALID="$(grep invalid grcov.log | \ grep -o '[^\ /]*raw' | \ sed 's/_1\.profraw/\.profraw/g' || echo '')" echo "Invalid files: $INVALID" if [ -n "$INVALID" ]; then echo "Removing invalid files: $INVALID" cd proffiles/ rm $INVALID cd .. echo "Executing grcov again" rm -rf coverage mkdir -p coverage ./grcov proffiles/ -s ./ --binary-path ./target/release/ \ -t html,covdir --branch --ignore-not-existing --ignore "target/release/build/*" \ --ignore "$HOME/.cargo/**" -o coverage/ --llvm fi if [ "${{ needs.set-tags.outputs.coverage_report }}" == "true" ]; then echo "Generating coverage report" wget ${{ vars.S3_COVERAGE_URL }}/branches/master/covdir \ -O base_covdir || true python3 .github/scripts/coverage-report.py \ --base-covdir ./base_covdir \ --incoming-covdir ./coverage/covdir \ --base-branch ${{ needs.set-tags.outputs.git_target_branch }} \ --incoming-branch ${{ needs.set-tags.outputs.git_branch }} \ --base-html-url ${{ vars.S3_COVERAGE_URL }}/${{ needs.set-tags.outputs.coverage_dir }} \ > coverage_report.md echo "coverage_date=\"$(date)\"" >> $GITHUB_OUTPUT fi rm -rf proffiles/ - name: Upload coverage to gha uses: actions/upload-artifact@v4 with: name: coverage path: coverage - name: Upload coverage s3 uses: mario-sangar/upload-s3-action@master id: S3 with: aws_key_id: ${{ secrets.S3_COVERAGE_ID }} aws_secret_access_key: ${{ secrets.S3_COVERAGE_KEY }} aws_bucket: ${{ vars.S3_COVERAGE_BUCKET }} destination_dir: "${{ needs.set-tags.outputs.coverage_dir }}" source_dir: "coverage" acl: "none" - name: Link To Report run: echo "${{ vars.S3_COVERAGE_URL }}/${{steps.S3.outputs.object_key}}/html/index.html" - name: Create coverage report comment if: ${{ needs.set-tags.outputs.coverage_report == 'true' }} run: | mv coverage_report.md temp_coverage_report.md echo "## [Coverage Report](${{ vars.S3_COVERAGE_URL }}/${{steps.S3.outputs.object_key}}/html/index.html)" > coverage_report.md cat temp_coverage_report.md >> coverage_report.md rm temp_coverage_report.md echo "> Coverage generated ${{ steps.coverage.outputs.coverage_date }}" >> coverage_report.md echo "Generated coverage report comment" cat coverage_report.md - name: Find Comment if: ${{ needs.set-tags.outputs.coverage_report == 'true' }} uses: peter-evans/find-comment@v3 id: fc with: issue-number: ${{ github.event.pull_request.number }} comment-author: "github-actions[bot]" body-includes: Coverage generated - name: Create or update comment if: ${{ needs.set-tags.outputs.coverage_report == 'true' }} uses: peter-evans/create-or-update-comment@v4 with: comment-id: ${{ steps.fc.outputs.comment-id }} issue-number: ${{ github.event.pull_request.number }} body-path: coverage_report.md edit-mode: replace