ci run the definition-of-done gates from one script

Nothing enforced the three gates (type-check, tests, formatting) beyond a developer remembering to run them. scripts/ci.sh runs all three in an isolated build directory and exits non-zero on any failure, so a git hook on the deployment host, a cron job, or a hosted runner can all enforce the identical bar with one call. A GitHub Actions workflow calls the script on every push and pull request. The primary remote is a self-hosted bare repository, where the workflow is inert; it runs wherever the repository is mirrored. Ignore every isolated build directory, not only the two named before.

Commit
30bee998e343c0fcaea388c0dab1cab962c06cf4
Author
Marius Peter <dev@marius-peter.com>
Author date
Committer
Marius Peter <dev@marius-peter.com>
Committer date
Changed files
.github/workflows/ci.yml
index 00000000..87e45f05 000000..100644
@@ -0,0 +1,35 @@
1 Added: # Runs the definition-of-done gates on every push and pull request. The gates
2 Added: # themselves live in scripts/ci.sh, so this workflow and any other runner (a
3 Added: # git hook on the deployment host, a cron job) enforce the identical bar.
4 Added: #
5 Added: # The primary remote is a self-hosted bare repository, so this file is inert
6 Added: # there. It runs wherever the repository is mirrored to GitHub.
7 Added:
8 Added: name: ci
9 Added:
10 Added: on:
11 Added: push:
12 Added: pull_request:
13 Added:
14 Added: jobs:
15 Added: gates:
16 Added: runs-on: ubuntu-latest
17 Added: steps:
18 Added: - uses: actions/checkout@v4
19 Added:
20 Added: - name: Set up OCaml
21 Added: uses: ocaml/setup-ocaml@v3
22 Added: with:
23 Added: ocaml-compiler: "5.1"
24 Added: dune-cache: true
25 Added:
26 Added: - name: Install dependencies
27 Added: # --with-test brings alcotest; ocamlformat is pinned in the opam file
28 Added: # under with-dev-setup, so install it explicitly at the pinned version
29 Added: # the .ocamlformat file names.
30 Added: run: |
31 Added: opam install . --deps-only --with-test --yes
32 Added: opam install ocamlformat.0.29.0 --yes
33 Added:
34 Added: - name: Run the gates
35 Added: run: opam exec -- sh scripts/ci.sh
.gitignore
index 55ebb0f3..ae282e11 100644..100644
@@ -1,6 +1,6 @@
1 Removed: # Dune build artifacts
2 Removed: _build/
3 Removed: _build-agent/
1 Added: # Dune build artifacts, including isolated build directories (_build-agent,
2 Added: # _build-ci, ...)
3 Added: _build*/
4 4
5 5 # Local opam switch
6 6 _opam/
scripts/ci.sh
index 00000000..282e12a3 000000..100755
@@ -0,0 +1,28 @@
1 Added: #!/usr/bin/env sh
2 Added: # The definition-of-done gates, in the order the workflow steering requires:
3 Added: #
4 Added: # 1. dune build @check type-checks the libraries and the tests
5 Added: # 2. dune runtest runs every Alcotest suite
6 Added: # 3. dune build @fmt confirms ocamlformat and dune formatting are applied
7 Added: #
8 Added: # Exit status is non-zero if any gate fails, so a git hook, a cron job, or a
9 Added: # hosted CI runner can all enforce the same bar with one call. The build
10 Added: # directory is isolated so a developer's watch build is never disturbed.
11 Added: #
12 Added: # Usage: scripts/ci.sh run all gates
13 Added: # BUILD_DIR=... scripts/ci.sh override the build directory
14 Added:
15 Added: set -eu
16 Added:
17 Added: BUILD_DIR="${BUILD_DIR:-_build-ci}"
18 Added:
19 Added: run() {
20 Added: printf '==> %s\n' "$*"
21 Added: "$@"
22 Added: }
23 Added:
24 Added: run dune build @check --build-dir "$BUILD_DIR"
25 Added: run dune runtest --build-dir "$BUILD_DIR" --force
26 Added: run dune build @fmt --build-dir "$BUILD_DIR"
27 Added:
28 Added: printf '==> all gates passed\n'