Improve Nix in CI (#184) #289
This file contains 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 | |
tags: | |
- '*' | |
pull_request: | |
## We specify a concurrency group with automated cancellation. This means that | |
## other pushes on the same `github.ref` (eg. other pushes to the same pull | |
## request) cancel previous occurrences of the CI. | |
concurrency: | |
group: ${{ github.workflow }}-${{ github.ref }} | |
cancel-in-progress: true | |
jobs: | |
## ========================= [ OPAM-based CI ] ========================= ## | |
opam-based: | |
strategy: | |
fail-fast: false | |
matrix: | |
include: | |
- {os: ubuntu, ocaml: 4.11.x} ## in Debian stable (as of 2023-05-11) | |
- {os: ubuntu, ocaml: 4.11.x, lower-bounds: lower-bounds, doc: no-doc} | |
- {os: ubuntu, ocaml: 4.12.x} | |
- {os: ubuntu, ocaml: 4.13.x} | |
# {os: ubuntu, ocaml: 4.14.x} ## main supported version | |
- {os: ubuntu, ocaml: 4.14.x, lower-bounds: lower-bounds, doc: no-doc} | |
- {os: ubuntu, ocaml: 4.14.x, deploy-doc: deploy-doc} | |
- {os: ubuntu, ocaml: 4.14.1, bytecode: bytecode} | |
- {os: macos, ocaml: 4.14.x} | |
- {os: windows, ocaml: 4.14.x, tests: no-tests} | |
- {os: ubuntu, ocaml: 5.0.x} | |
## NOTE: The `ocaml/setup-ocaml@v2` action does not support `4.14.x` | |
## versions for `ocaml-variants` and such, hence the detailed version. | |
## NOTE: After OCaml 5.0.0, `ocaml-option-bytecode-only` can be used | |
## directly with `ocaml-base-compiler`, probably? | |
## NOTE: Tests are written in a Unix-like way and therefore cannot | |
## run correctly on Windows. | |
## NOTE: `lower-bounds` implies to not build the documentation because | |
## `opam-0install`, the solver we use, does not support it. Therefore | |
## we don't even install those dependencies to begin with. | |
## Grant GITHUB_TOKEN the permissions required to make a pages deployment | |
permissions: | |
pages: write | |
id-token: write | |
runs-on: ${{ matrix.os }}-latest | |
steps: | |
- name: Determine OPAM flags | |
shell: bash ## for Windows | |
run: | | |
if ${{ matrix.doc != 'no-doc' }}; then | |
with_doc=--with-doc | |
fi | |
if ${{ matrix.tests != 'no-tests' }}; then | |
with_test=--with-test | |
fi | |
echo "OPAM_FLAGS=$with_doc $with_test" >> "$GITHUB_ENV" | |
- name: Checkout repository | |
uses: actions/checkout@v4 | |
- name: Use OCaml ${{ matrix.ocaml }} | |
if: matrix.bytecode != 'bytecode' | |
uses: ocaml/setup-ocaml@v2 | |
with: | |
ocaml-compiler: ${{ matrix.ocaml }} | |
- name: (Bytecode) Use OCaml ${{ matrix.ocaml }} | |
if: matrix.bytecode == 'bytecode' | |
uses: ocaml/setup-ocaml@v2 | |
with: | |
ocaml-compiler: ocaml-variants.${{ matrix.ocaml }}+options,ocaml-option-bytecode-only | |
- name: Install Dune | |
run: opam install dune --yes | |
- name: Install OPAM dependencies | |
run: opam install . --deps-only ${{ env.OPAM_FLAGS }} | |
- name: (Lower bounds) Install OPAM-0install | |
if: matrix.lower-bounds == 'lower-bounds' | |
run: | | |
opam install opam-0install | |
- name: (Lower bounds) Ask OPAM-0install for an install plan | |
if: matrix.lower-bounds == 'lower-bounds' | |
run: | | |
## Based on: https://sim642.eu/blog/2022/03/13/ocaml-dependencies-lower-bounds-ci/ | |
## Note the current version of `ocaml-base-compiler` | |
obc=ocaml-base-compiler.$(opam exec -- ocamlc --version) | |
## Ask `opam-0install` to get us the oldest possible dependencies for | |
## Morbig, while keeping the exact same version of | |
## `ocaml-base-compiler`. | |
opam exec -- \ | |
opam-0install --prefer-oldest $OPAM_FLAGS morbig.dev $obc \ | |
| sed 's|morbig.dev||' \ | |
> lower-bounds | |
## Log what we are aiming for | |
printf '\e[36m<><>\e[0m Packages to install \e[36m><><><><><><><><><><><><><><><><><><><><><><><><><><><>\e[0m\n' | |
printf '`opam-0install` suggests installing the following packages:\n' | |
cat lower-bounds | tr ' ' '\n' | sed 's|^\([^.]*\)\.|\t\1\t|' | column -t | |
- name: (Lower bounds) Downgrade OPAM dependencies | |
if: matrix.lower-bounds == 'lower-bounds' | |
run: opam install --yes $(cat lower-bounds) | |
- name: Try building | |
run: opam exec -- make | |
- name: Try building documentation | |
if: matrix.doc != 'no-doc' | |
run: opam exec -- make doc | |
- name: Run tests | |
if: matrix.tests != 'no-tests' | |
run: opam exec -- make check | |
- name: Try installing | |
run: opam exec -- make install | |
- name: Try building examples | |
## NOTE: Examples are written in a Unix-like way and cannot build on a | |
## bytecode-only infrastructure. | |
if: runner.os != 'Windows' && matrix.bytecode != 'bytecode' | |
run: opam exec -- make examples | |
- name: Try uninstalling | |
if: matrix.lower-bounds != 'lower-bounds' | |
run: opam exec -- make uninstall | |
- name: (Lower bounds) Try uninstalling | |
## NOTE: Old versions of Dune (< 3.1.0) fail when they cannot remove | |
## `bin` or `lib/morbig` in the prefix. But `bin` is very rarely empty. | |
## Until it is reasonable to require Dune >= 3.1.0, we keep this special | |
## case for the part of the CI interested in lower bounds. | |
if: matrix.lower-bounds == 'lower-bounds' | |
run: opam exec -- make uninstall || true | |
- name: Try cleaning | |
run: opam exec -- make clean | |
- name: Build documentation for auto-deployment | |
if: matrix.doc != 'no-doc' | |
run: opam exec -- make doc | |
- name: Upload documentation artifact | |
if: matrix.doc != 'no-doc' | |
uses: actions/upload-pages-artifact@v2 | |
with: | |
path: doc/ | |
- name: Deploy to GitHub pages | |
uses: actions/deploy-pages@v2 | |
if: github.event_name == 'push' | |
&& github.ref == 'refs/heads/main' | |
&& matrix.deploy-doc == 'deploy-doc' | |
## ========================= [ APT-based CI ] ========================== ## | |
apt-based: | |
runs-on: ubuntu-latest | |
steps: | |
- name: Install OCaml & dependencies | |
run: | | |
sudo apt-get install \ | |
build-essential ocaml dune menhir libmenhir-ocaml-dev \ | |
libppx-deriving-yojson-ocaml-dev libppx-visitors-ocaml-dev \ | |
libyojson-ocaml-dev | |
- name: Checkout repository | |
uses: actions/checkout@v4 | |
- name: Try building | |
run: make | |
## No odoc in Debian stable, sadly, so no documentation! | |
## REVIEW: Ubuntu 22.10 does have a package `ocaml-odoc` though. | |
# - name: Try building documentation | |
# run: make doc | |
## Ubuntu 22.10 only has Alcotest 1.6 which is not recent enough for our | |
## tests. Therefore, tests are disabled on this platform. | |
# - name: Run tests | |
# run: make check | |
- name: Try installing | |
run: sudo make install | |
- name: Try building examples | |
run: make examples | |
- name: Try uninstalling | |
run: sudo make uninstall | |
## Not working (as of 2023-03-31), `dune clean` complains about: | |
## | |
## Error: unlink: _build/default/.dune/configurator: Permission denied | |
## | |
## Maybe related to https://github.com/ocaml/dune/issues/3857. | |
# - name: Try cleaning | |
# run: make clean | |
## ======================== [ Docker-based CI ] ======================== ## | |
docker-based: | |
strategy: | |
fail-fast: false | |
matrix: | |
include: | |
- {tag: alpine, deploy-image: deploy-image} | |
- {tag: archlinux} | |
- {tag: centos, tests: no-tests} ## only has Alcotest 1.6 (as of 2023-05-11) | |
- {tag: debian} | |
- {tag: debian-testing} | |
- {tag: debian-unstable} | |
- {tag: fedora} | |
- {tag: opensuse} | |
- {tag: oraclelinux} | |
- {tag: ubuntu} | |
- {tag: ubuntu-lts} | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout repository | |
uses: actions/checkout@v4 | |
- name: Build Docker image | |
run: | | |
docker build \ | |
--tag morbig \ | |
. \ | |
--build-arg tag=${{matrix.tag}} \ | |
--build-arg doc=${{matrix.doc != 'no-doc'}} \ | |
--build-arg tests=${{matrix.tests != 'no-tests'}} | |
- name: Run tests | |
run: | | |
docker run --entrypoint /bin/sh morbig -c ' | |
set -e | |
eval $(opam env) | |
cd /home/opam/morbig | |
if ${{ matrix.tests != 'no-tests' }}; then | |
make check | |
fi | |
if ${{ matrix.doc != 'no-doc' }}; then | |
make doc | |
fi | |
make install | |
make examples | |
make uninstall | |
' | |
- name: Login to Docker Hub | |
if: github.event_name == 'push' && matrix.deploy-image == 'deploy-image' | |
uses: docker/login-action@v3 | |
with: | |
username: ${{ secrets.DOCKER_HUB_USERNAME }} | |
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} | |
- name: Rename Docker image | |
if: github.event_name == 'push' && matrix.deploy-image == 'deploy-image' | |
run: docker image tag morbig colisanr/morbig:${GITHUB_REF##*/} | |
- name: Push to Docker Hub | |
if: github.event_name == 'push' && matrix.deploy-image == 'deploy-image' | |
run: docker push colisanr/morbig:${GITHUB_REF##*/} | |
## ========================= [ Nix-based CI ] ========================== ## | |
nix-based: | |
strategy: | |
fail-fast: false | |
matrix: | |
package: | |
- with-nixpkgs | |
- with-opam-nix | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout repository | |
uses: actions/checkout@v4 | |
- name: Setup Nix | |
uses: ./.github/composites/setup-nix | |
with: | |
githubAccessToken: ${{ secrets.GITHUB_TOKEN }} | |
cachixAuthToken: ${{ secrets.CACHIX_AUTH_TOKEN }} | |
- name: Install Nix dependencies | |
run: | | |
nix develop .#${{ matrix.package }} --print-build-logs --command true | |
- name: Build in development Shell | |
run: | | |
nix develop .#${{ matrix.package }} --command make | |
- name: Build documentation in development Shell | |
run: | | |
nix develop .#${{ matrix.package }} --command make doc | |
- name: Run tests in development Shell | |
run: | | |
nix develop .#${{ matrix.package }} --command make check | |
- name: Build with Nix | |
run: | | |
nix build .#${{ matrix.package }} --print-build-logs | |
nix-flake-checks: | |
runs-on: ubuntu-latest | |
steps: | |
- name: Checkout repository | |
uses: actions/checkout@v4 | |
- name: Setup Nix | |
uses: ./.github/composites/setup-nix | |
with: | |
githubAccessToken: ${{ secrets.GITHUB_TOKEN }} | |
cachixAuthToken: ${{ secrets.CACHIX_AUTH_TOKEN }} | |
- name: Run flake checks | |
run: nix flake check . --print-build-logs |