From d72b349fd36ce1a3b336dfee85e543d19158ec79 Mon Sep 17 00:00:00 2001 From: Olivier Desenfans Date: Mon, 13 Nov 2023 12:31:50 +0100 Subject: [PATCH] CI: Cache prover Docker build Problem: building the prover from scratch takes ages. Solution: cache the generated Docker image and reuse it for subsequent builds. This caching solution makes the build closer to a local dev environment where the prover has already been built once. --- .github/workflows/tests.yml | 26 ++++++++++++++++++++++++++ stone-prover/build.rs | 19 +++++++++++++++---- 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 05d03cf..18dd0ce 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -21,6 +21,7 @@ jobs: uses: actions/checkout@v3 with: submodules: recursive + - name: Install Rust uses: actions-rs/toolchain@v1 with: @@ -28,6 +29,7 @@ jobs: toolchain: 1.73 override: true components: rustfmt, clippy + - name: Set up cargo cache uses: actions/cache@v3 continue-on-error: false @@ -40,9 +42,33 @@ jobs: target/ key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} restore-keys: ${{ runner.os }}-cargo- + + - name: Log in to Github container registry + run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin + + - name: Set cache image environment variables + run: | + # Uppercase characters are not allowed in Docker tags + cache_image=$(echo ghcr.io/${GITHUB_REPOSITORY}/build-cache | tr '[:upper:]' '[:lower:]') + echo "STONE_PROVER_DOCKER_CACHE=$(echo ${cache_image})" >> $GITHUB_ENV + + + - name: Download Docker cache image (if available) + run: docker pull ghcr.io/$GITHUB_REPOSITORY/build-cache || true + - name: Build run: cargo build --verbose + - name: Lint with Clippy run: cargo clippy -- -D warnings + - name: Run tests run: cargo test --verbose + + - name: Push the image to the cache + # It's not possible to push packages from fork PRs. + if: github.event.pull_request.head.repo.full_name == github.repository + run: | + docker tag stone-prover-build:latest ${STONE_PROVER_DOCKER_CACHE} + docker push ${STONE_PROVER_DOCKER_CACHE} + diff --git a/stone-prover/build.rs b/stone-prover/build.rs index 280cf33..47aab93 100644 --- a/stone-prover/build.rs +++ b/stone-prover/build.rs @@ -58,6 +58,20 @@ fn copy_prover_files_from_container( Ok(()) } +fn make_docker_build_command(repo_dir: &Path, image_name: &str) -> String { + let mut docker_build_command = format!( + "docker build -t {image_name} {}", + repo_dir.to_string_lossy() + ); + + // Check if a cache image exists. Used by the CI/CD pipeline. + if let Ok(build_cache) = std::env::var("STONE_PROVER_DOCKER_CACHE") { + docker_build_command.push_str(&format!(" --build-from {build_cache}")); + } + + docker_build_command +} + /// Build the Stone Prover and copy binaries to `output_dir`. /// /// The prover repository contains a Dockerfile to build the prover. This function: @@ -68,10 +82,7 @@ fn copy_prover_files_from_container( fn build_stone_prover(repo_dir: &Path, output_dir: &Path) { // Build the Stone Prover build Docker image let image_name = "stone-prover-build:latest"; - let docker_build_command = format!( - "docker build -t {image_name} {}", - repo_dir.to_string_lossy() - ); + let docker_build_command = make_docker_build_command(repo_dir, image_name); run_command(&docker_build_command).expect("Failed to build Stone Prover using Dockerfile"); // Run a container based on the Docker image