diff --git a/examples.md b/examples.md index 15da4e3..8ef0520 100644 --- a/examples.md +++ b/examples.md @@ -252,7 +252,7 @@ Esy allows you to export built dependencies and import pre-built dependencies. ...(Build job)... # Re-export dependencies if anything has changed or if it is the first time - - name: Setting dependency cache + - name: Setting dependency cache run: | esy export-dependencies if: steps.restore-cache.outputs.cache-hit != 'true' @@ -428,14 +428,214 @@ When dependencies are installed later in the workflow, we must specify the same ## Rust - Cargo +### Simple end product build + +If `Cargo.lock` is checked into git, its hash can be used as a key +to cache filesystem state suitable for the build. Use the `--locked` option +with cargo build and test commands to ensure that the state cached at the +post step corresponds to the contents of `Cargo.lock` that were hashed for +the key. + ```yaml -- uses: actions/cache@v2 +- name: Cache cargo dependencies + uses: actions/cache@v2 with: path: | - ~/.cargo/registry - ~/.cargo/git - target - key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} + ~/.cargo/registry/index + ~/.cargo/registry/cache + ~/.cargo/git/db + key: cargo-deps-${{ hashFiles('**/Cargo.lock') }} +- name: Cache cargo build + uses: actions/cache@v2 + with: + path: target + key: ${{ runner.os }}-cargo-build-${{ hashFiles('**/Cargo.lock') }} +``` + +### A separate job to fetch and cache the dependencies + +The files cached from `$CARGO_HOME` are platform-independent. +If cargo build/test jobs are run on a matrix and `Cargo.lock` changes often, +it might make sense to populate the cache with the matching state in one job, +then reuse it in the matrix jobs. + +This example also uses a separate cache to avoid expensive syncs with the +`crates.io-index` repository. + +```yaml +jobs: + update-deps: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - id: cargo-deps + name: Cache cargo dependencies + uses: actions/cache@v2 + with: + path: | + ~/.cargo/registry/index + ~/.cargo/registry/cache + ~/.cargo/git/db + key: cargo-deps-${{ hashFiles('**/Cargo.lock') }} + + - if: ${{ steps.cargo-deps.outputs.cache-hit != 'true' }} + id: ls-crates-io-index + name: Get head commit hash of crates.io registry index + shell: bash + run: | + commit=$( + git ls-remote --heads https://github.com/rust-lang/crates.io-index.git master | + cut -f 1 + ) + echo "::set-output name=head::$commit" + - if: ${{ steps.cargo-deps.outputs.cache-hit != 'true' }} + name: Cache cargo registry index + uses: actions/cache@v2 + with: + path: ~/.cargo/registry/index + key: cargo-index-${{ steps.ls-crates-io-index.outputs.head }} + restore-keys: cargo-index- + + - if: ${{ steps.cargo-deps.outputs.cache-hit != 'true' }} + name: Fetch dependencies and update registry index + run: cargo fetch --locked + + test: + needs: update-deps + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v2 + + # https://github.com/actions/runner/issues/498 + - if: ${{ runner.os == 'Windows' }} + name: Fix up Cargo.lock hash + shell: powershell + run: | + Get-ChildItem . -Recurse -Filter Cargo.lock | + Foreach-Object { + ((Get-Content $_.FullName) -join "`n") + "`n" | + Set-Content -NoNewline $_.FullName + } + + - name: Restore cargo dependencies + uses: actions/cache@v2 + with: + path: | + ~/.cargo/registry/index + ~/.cargo/registry/cache + ~/.cargo/git/db + key: cargo-deps-${{ hashFiles('**/Cargo.lock') }} + + - name: Build and test + uses: actions-rs/cargo@v1 + env: + CARGO_INCREMENTAL: 0 + with: + command: test + args: --locked +``` + +### Testing a library + +Rust library projects typically [do not put][cargo-faq] `Cargo.lock` under +version control. It can be generated with the `cargo generate-lockfile` command +assisted by the registry index cache that is used and possibly updated +for every workflow run. The same index cache is reused by the test jobs. + +[cargo-faq]: https://doc.rust-lang.org/cargo/faq.html#why-do-binaries-have-cargolock-in-version-control-but-not-libraries + +```yaml +jobs: + update-deps: + runs-on: ubuntu-latest + outputs: + crates-io-index-head: ${{ steps.ls-crates-io-index.outputs.head }} + steps: + - uses: actions/checkout@v2 + + - id: ls-crates-io-index + name: Get head commit hash of crates.io registry index + shell: bash + run: | + commit=$( + git ls-remote --heads https://github.com/rust-lang/crates.io-index.git master | + cut -f 1 + ) + echo "::set-output name=head::$commit" + + - name: Cache cargo registry index + uses: actions/cache@v2 + with: + path: ~/.cargo/registry/index + key: cargo-index-${{ steps.ls-crates-io-index.outputs.head }} + restore-keys: cargo-index- + + - name: Generate Cargo.lock + run: cargo generate-lockfile + + - id: cargo-deps + name: Cache dependency crates + uses: actions/cache@v2 + with: + path: ~/.cargo/registry/cache + key: cargo-deps-${{ hashFiles('Cargo.lock') }} + + - if: ${{ steps.cargo-deps.outputs.cache-hit != 'true' }} + name: Fetch dependencies + run: cargo fetch --locked + + - name: Upload Cargo.lock + uses: actions/upload-artifact@v2 + with: + name: lockfile + path: Cargo.lock + + test: + needs: update-deps + strategy: + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + runs-on: ${{ matrix.os }} + env: + CARGO_INCREMENTAL: 0 + steps: + - uses: actions/checkout@v2 + + - name: Download Cargo.lock + uses: actions/download-artifact@v2 + with: + name: lockfile + + - name: Restore cargo registry index + uses: actions/cache@v2 + with: + path: ~/.cargo/registry/index + key: cargo-index-${{ needs.update-deps.outputs.crates-io-index-head }} + # May miss on Windows: + # https://github.com/actions/cache/issues/330#issuecomment-637701649 + restore-keys: cargo-index- + + - name: Restore dependency crates + uses: actions/cache@v2 + with: + path: ~/.cargo/registry/cache + key: cargo-deps-${{ hashFiles('Cargo.lock') }} + + - name: Build + uses: actions-rs/cargo@v1 + with: + command: build + args: --all-targets --locked + + - name: Test + uses: actions-rs/cargo@v1 + with: + command: test + args: --locked ``` ## Scala - SBT