Skip to content

Commit

Permalink
Make better use of the GHA cache (#4489)
Browse files Browse the repository at this point in the history
* Make better use of the GHA cache
  • Loading branch information
jorisdral committed Jul 22, 2024
1 parent 3c1b576 commit 8972703
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 20 deletions.
80 changes: 60 additions & 20 deletions .github/workflows/haskell.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,28 +80,60 @@ jobs:
- name: Cabal update
run: cabal update

- name: Cabal configure
run: cabal configure --enable-tests --enable-benchmarks --write-ghc-environment-files=always

- uses: actions/cache@v4
if: matrix.os != 'macos-latest'
name: Cache cabal store
# We create a dependencies.txt file that can be used to index the cabal
# store cache.
#
# We do not use plan.json directly because adding a dependency to our
# Cabal files which was already present somewhere else would result in a
# diferent plan, even though the set of dependencies is the same.
- name: Record dependencies to be used as cache keys
id: record-deps
run: |
cabal build all --enable-tests --dry-run --minimize-conflict-set
cat dist-newstyle/cache/plan.json \
| jq '.["install-plan"][].id' \
| sort \
| uniq \
| tee dependencies.txt
- name: Restore cache
uses: actions/cache/restore@v4
id: restore-cabal-cache
env:
cache-name: cache-cabal-build
with:
path: |
${{ steps.install-haskell.outputs.cabal-store }}
# cache is invalidated upon a change to cabal.project (and/or cabal.project.local), a bump to
# CABAL_CACHE_VERSION or after a week of inactivity
key: cache-${{ runner.os }}-${{ matrix.ghc }}-${{ env.CABAL_CACHE_VERSION }}-${{ hashFiles('cabal.project*') }}
# Restoring attempts are from current branch then master
# A new cache is created upon a change to the cabal build plan,
# cabal.project (and/or cabal.project.local), or a bump to
# CABAL_CACHE_VERSION.
key: ${{ env.cache-name }}-${{ runner.os }}-${{ matrix.ghc }}-${{ env.CABAL_CACHE_VERSION }}-${{ hashFiles('dependencies.txt') }}-${{ hashFiles('cabal.project*') }}
# Restoring attempts are from current branch then master. The key above
# is by default already a restore-key.
restore-keys: |
cache-${{ runner.os }}-${{ matrix.ghc }}-${{ env.CABAL_CACHE_VERSION }}-${{ hashFiles('cabal.project*') }}
${{ env.cache-name }}-${{ runner.os }}-${{ matrix.ghc }}-${{ env.CABAL_CACHE_VERSION }}-${{ hashFiles('dependencies.txt') }}
${{ env.cache-name }}-${{ runner.os }}-${{ matrix.ghc }}-${{ env.CABAL_CACHE_VERSION }}-
- name: Check workflow test matrix
run: cabal build all --dry-run && scripts/check-workflow-test-matrix.hs

- name: Build dependencies
id: build-dependencies
run: cabal build all --only-dependencies

# Save the cache of built dependencies early, so that it is available for
# the next GHA run if the Build step fails.
- name: Save cache
uses: actions/cache/save@v4
id: save-cabal-cache
# Note: cache-hit will be set to true only when cache hit occurs for the
# exact key match. For a partial key match via restore-keys or a cache
# miss, it will be set to false.
if: steps.build-dependencies.outcome == 'success' && steps.restore-cabal-cache.outputs.cache-hit != 'true'
with:
path: ${{ steps.install-haskell.outputs.cabal-store }}
key: ${{ steps.restore-cabal-cache.outputs.cache-primary-key }}

- name: Build
run: cabal build all

Expand Down Expand Up @@ -228,18 +260,26 @@ jobs:
- name: Unarchive working directory
run: tar -xf state.tar && rm state.tar

- uses: actions/cache@v4
if: matrix.os != 'macos-latest'
name: Cache cabal store
# A dependencies.txt file should have been created by the build job, so we
# check if it exists and is not empty.
- name: Check dependencies to be used as cache keys
id: check-deps
run: |
./scripts/file-not-null.sh dependencies.txt
- name: Restore cache
uses: actions/cache/restore@v4
id: restore-cabal-cache
env:
cache-name: cache-cabal-build
with:
path: |
${{ steps.install-haskell.outputs.cabal-store }}
# cache is invalidated upon a change to cabal.project (and/or cabal.project.local), a bump to
# CABAL_CACHE_VERSION or after a week of inactivity
key: cache-${{ runner.os }}-${{ matrix.ghc }}-${{ env.CABAL_CACHE_VERSION }}-${{ hashFiles('cabal.project*') }}
# Restoring attempts are from current branch then master
restore-keys: |
cache-${{ runner.os }}-${{ matrix.ghc }}-${{ env.CABAL_CACHE_VERSION }}-${{ hashFiles('cabal.project*') }}
key: ${{ env.cache-name }}-${{ runner.os }}-${{ matrix.ghc }}-${{ env.CABAL_CACHE_VERSION }}-${{ hashFiles('dependencies.txt') }}-${{ hashFiles('cabal.project*') }}
# The cache with this specific key should have been created by the build
# job. If the cache is missing, something is terribly wrong! We fail the
# test job, or otherwise we would start rebuilding all the dependencies.
fail-on-cache-miss: true

- name: Cabal update
run: cabal update
Expand Down
16 changes: 16 additions & 0 deletions scripts/file-not-null.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/usr/bin/env bash

set -euo pipefail

if [ ! -f "$1" ]; then
echo "Error: $1 does not exist!"
exit 1
fi

if [ ! -s "$1" ]; then
echo "Error: $1 is empty!"
exit 1
fi

echo "$1 exists and is non-empty. Printing..."
cat "$1"

0 comments on commit 8972703

Please sign in to comment.