Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 101 additions & 14 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,70 @@ jobs:
- name: Checkout
uses: actions/checkout@v4

# pin-depends float on `#main`: resolve their current commits so the
# opam cache key changes when a pinned repo moves. Without this the
# restored switch is always stale (its pins predate upstream HEAD),
# `opam install` rebuilds them on every run, and the rebuilt result is
# never cached because the save step is skipped on cache hits.
- name: Resolve pinned dependency commits
id: pins
run: |
export GIT_TERMINAL_PROMPT=0
sha=$(
grep -hoE 'git\+[^"]+#[^"]+' ./*.opam | sort -u | while IFS= read -r pin; do
repo="${pin%%#*}"; ref="${pin##*#}"
git ls-remote "${repo#git+}" "$ref" || echo "unresolved $pin"
done | shasum | awk '{print $1}'
)
echo "resolved pins sha: $sha"
echo "sha=$sha" >> "$GITHUB_OUTPUT"

# setup-ocaml creates a *local* switch: the compiler and installed
# packages live in `_opam/` (~1GB+), while `~/.opam` is only the opam
# root skeleton (~40MB) — caching `~/.opam` alone never restores deps.
- name: Restore opam root
id: opam-root
uses: actions/cache/restore@v4
with:
path: ~/.opam
key: opam-root-${{ runner.os }}-ocaml-${{ matrix.ocaml-compiler }}

- name: Restore opam switch
id: opam-switch
uses: actions/cache/restore@v4
with:
path: _opam
key: opam-switch-${{ runner.os }}-ocaml-${{ matrix.ocaml-compiler }}-${{ hashFiles('*.opam') }}-${{ steps.pins.outputs.sha }}
restore-keys: |
opam-switch-${{ runner.os }}-ocaml-${{ matrix.ocaml-compiler }}-

# A restored root + local switch is already complete; only the opam
# binary is needed. This skips ocaml/setup-ocaml, whose unconditional
# `opam update` costs ~1m30s on cache hits.
- name: Check for restored opam environment
id: opam-env
run: |
if [ -f "$HOME/.opam/config" ] && [ -d "_opam" ]; then
echo "restored=true" >> "$GITHUB_OUTPUT"
else
echo "restored=false" >> "$GITHUB_OUTPUT"
fi

- name: Install opam binary
if: steps.opam-env.outputs.restored == 'true'
run: |
mkdir -p ~/.local/bin
curl -fsSL https://github.com/ocaml/opam/releases/download/2.6.0/opam-2.6.0-x86_64-linux -o ~/.local/bin/opam
chmod +x ~/.local/bin/opam
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
eval "$(opam env)"
opam --version && ocaml -version

- name: Set up OCaml
if: steps.opam-env.outputs.restored != 'true'
uses: ocaml/setup-ocaml@v3
with:
ocaml-compiler: ${{ matrix.ocaml-compiler }}
dune-cache: true

- name: Set up Java
uses: actions/setup-java@v4
Expand Down Expand Up @@ -65,24 +124,45 @@ jobs:
- name: Install system dependencies
run: sudo apt-get update && sudo apt-get install -y libsqlite3-dev pkg-config

- name: Restore opam switch cache
id: opam-cache
uses: actions/cache/restore@v4
with:
path: ~/.opam
key: ${{ runner.os }}-ocaml-${{ matrix.ocaml-compiler }}-opam-${{ hashFiles('*.opam') }}
restore-keys: |
${{ runner.os }}-ocaml-${{ matrix.ocaml-compiler }}-opam-

# On an exact switch-cache hit this only verifies and re-fetches the
# (already matching) pins; on a partial restore it rebuilds just the
# moved pins; on a miss it installs everything. The retry covers a
# stale opam-repository snapshot in a restored root failing to resolve
# newly released versions.
- name: Install OCaml dependencies
run: opam install . --deps-only --with-test -y
run: |
opam install . --deps-only --with-test -y || {
opam update -y
opam install . --deps-only --with-test -y
}

- name: Save opam switch cache
if: steps.opam-cache.outputs.cache-hit != 'true'
- name: Save opam root
if: steps.opam-root.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: ~/.opam
key: ${{ steps.opam-cache.outputs.cache-primary-key }}
key: opam-root-${{ runner.os }}-ocaml-${{ matrix.ocaml-compiler }}

- name: Save opam switch
if: steps.opam-switch.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: _opam
key: ${{ steps.opam-switch.outputs.cache-primary-key }}

- name: Restore dune build cache
uses: actions/cache/restore@v4
with:
path: ~/.cache/dune
key: dune-cache-${{ github.ref_name }}-${{ github.sha }}
restore-keys: |
dune-cache-${{ github.ref_name }}-
dune-cache-main-

- name: Enable dune shared cache
run: |
mkdir -p ~/.config/dune
printf '(lang dune 3.0)\n(cache enabled)\n' > ~/.config/dune/config

- name: Cache upstream DataScript
id: cache-upstream-datascript
Expand Down Expand Up @@ -122,3 +202,10 @@ jobs:
env:
UPSTREAM_DATASCRIPT_JS: ${{ github.workspace }}/_ci/datascript/release-js/datascript.js
run: opam exec -- script/benchmark_vs_cljs.sh

- name: Save dune build cache
if: always()
uses: actions/cache/save@v4
with:
path: ~/.cache/dune
key: dune-cache-${{ github.ref_name }}-${{ github.sha }}
Loading