perf(ci): optimize caching for Rust builds and Docker images #98
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: CI | |
| on: | |
| push: | |
| branches: [main, master] | |
| tags: ['v*'] | |
| pull_request: | |
| branches: [main, master] | |
| env: | |
| CARGO_TERM_COLOR: always | |
| CARGO_INCREMENTAL: 0 | |
| RUST_BACKTRACE: short | |
| CARGO_NET_RETRY: 10 | |
| RUSTUP_MAX_RETRIES: 10 | |
| REGISTRY: ghcr.io | |
| IMAGE_NAME: ${{ github.repository }} | |
| # Cancel in-progress runs for the same branch | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| # Build job - creates shared cache for other jobs (only this job saves cache) | |
| build: | |
| name: Build | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Free disk space | |
| run: | | |
| sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache/CodeQL | |
| sudo docker image prune --all --force | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - name: Cache cargo | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| cache-on-failure: true | |
| shared-key: "platform-ci" | |
| save-if: ${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) }} | |
| - name: Build | |
| run: cargo build --release | |
| # Clippy runs in parallel with build (reads cache only) | |
| clippy: | |
| name: Clippy | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Free disk space | |
| run: | | |
| sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache/CodeQL | |
| sudo docker image prune --all --force | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: clippy | |
| - name: Cache cargo | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| cache-on-failure: true | |
| shared-key: "platform-ci" | |
| save-if: false | |
| - name: Run clippy | |
| run: cargo clippy --all-targets --workspace -- -W clippy::all | |
| # Test job - runs faster with nextest (reads cache only) | |
| test: | |
| name: Test | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Free disk space | |
| run: | | |
| sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache/CodeQL | |
| sudo docker image prune --all --force | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| with: | |
| components: llvm-tools-preview | |
| - name: Install cargo-nextest and cargo-llvm-cov | |
| uses: taiki-e/install-action@v2 | |
| with: | |
| tool: cargo-nextest,cargo-llvm-cov | |
| - name: Cache cargo | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| cache-on-failure: true | |
| shared-key: "platform-ci" | |
| save-if: false | |
| # Run tests with nextest (faster) - coverage only on main | |
| - name: Run tests | |
| if: github.ref != format('refs/heads/{0}', github.event.repository.default_branch) | |
| run: cargo nextest run --workspace -E 'not (test(/live/) | test(/integration/))' | |
| - name: Run tests with coverage | |
| if: github.ref == format('refs/heads/{0}', github.event.repository.default_branch) | |
| run: | | |
| cargo llvm-cov nextest --workspace --json --output-path coverage.json -E 'not (test(/live/) | test(/integration/))' | |
| - name: Generate coverage badge | |
| if: github.ref == format('refs/heads/{0}', github.event.repository.default_branch) | |
| run: | | |
| COVERAGE=$(jq '.data[0].totals.lines.percent // 0 | round' coverage.json) | |
| echo "Coverage: $COVERAGE%" | |
| mkdir -p badges | |
| if (( COVERAGE >= 80 )); then COLOR="brightgreen" | |
| elif (( COVERAGE >= 60 )); then COLOR="green" | |
| elif (( COVERAGE >= 40 )); then COLOR="yellow" | |
| else COLOR="red"; fi | |
| curl -s "https://img.shields.io/badge/coverage-${COVERAGE}%25-${COLOR}" > badges/coverage.svg | |
| - name: Deploy coverage badge | |
| if: github.ref == format('refs/heads/{0}', github.event.repository.default_branch) | |
| uses: peaceiris/actions-gh-pages@v4 | |
| with: | |
| github_token: ${{ secrets.GITHUB_TOKEN }} | |
| publish_dir: ./badges | |
| destination_dir: badges | |
| keep_files: true | |
| # Docker build - only after tests pass | |
| docker: | |
| name: Build & Push Docker | |
| runs-on: ubuntu-latest | |
| needs: [build, test] | |
| permissions: | |
| contents: read | |
| packages: write | |
| steps: | |
| - name: Free disk space | |
| run: | | |
| sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache/CodeQL | |
| sudo docker image prune --all --force | |
| - uses: actions/checkout@v4 | |
| - uses: docker/setup-buildx-action@v3 | |
| - name: Log in to Container Registry | |
| if: github.event_name != 'pull_request' | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Extract metadata | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | |
| tags: | | |
| type=ref,event=branch | |
| type=ref,event=pr | |
| type=semver,pattern={{version}} | |
| type=semver,pattern={{major}}.{{minor}} | |
| type=sha,prefix= | |
| type=raw,value=latest,enable={{is_default_branch}} | |
| - name: Build and push Docker image | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| platforms: linux/amd64 | |
| push: ${{ github.event_name != 'pull_request' }} | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| # Release - only on tags | |
| release: | |
| name: Release | |
| runs-on: ubuntu-latest | |
| needs: [build, test, docker] | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Free disk space | |
| run: | | |
| sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /opt/hostedtoolcache/CodeQL | |
| sudo docker image prune --all --force | |
| - uses: actions/checkout@v4 | |
| - uses: dtolnay/rust-toolchain@stable | |
| - name: Cache cargo | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: "platform-ci" | |
| save-if: false | |
| - name: Build release binaries | |
| run: cargo build --release | |
| - name: Create release archive | |
| run: | | |
| mkdir -p release | |
| cp target/release/validator-node release/ | |
| cp target/release/csudo release/ | |
| tar -czvf platform-${{ github.ref_name }}-linux-x86_64.tar.gz -C release . | |
| - name: Upload release assets | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| files: | | |
| platform-${{ github.ref_name }}-linux-x86_64.tar.gz | |
| generate_release_notes: true |