From aa3cfef2b3bf0b235dcb5a28508d0f59bcaaeacf Mon Sep 17 00:00:00 2001 From: ajet Date: Sat, 19 Sep 2026 05:54:32 -0900 Subject: [PATCH] remove clojure dep for CI --- .gitea/workflows/ci.yml | 56 ++++++++++------------------------- README.md | 7 +++-- script/docker-coverage-report | 18 +++++++++++ script/docker-unit-coverage | 23 ++++++++++++++ script/docker-unit-test | 8 +++++ script/integration-test | 11 ++----- script/lib/docker.sh | 20 +++++++++++++ 7 files changed, 91 insertions(+), 52 deletions(-) create mode 100755 script/docker-coverage-report create mode 100755 script/docker-unit-coverage create mode 100755 script/docker-unit-test create mode 100644 script/lib/docker.sh diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index d32733b..24f1c30 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -5,6 +5,11 @@ on: branches: [main] pull_request: +# Everything runs in Docker (script/docker-*, script/integration-*), so the runner needs +# no JDK, Clojure or Babashka; only a Docker daemon. That means /var/run/docker.sock +# mounted into job containers, or a host-mode runner. Scripts move files with `docker cp` +# rather than bind mounts so they work from inside a job container. + jobs: unit: name: Unit tests @@ -12,24 +17,13 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: actions/setup-java@v4 - with: - distribution: temurin - java-version: "11" + # Fail fast with a clear message if the runner has no usable Docker. + - name: Check Docker + run: | + docker version + docker buildx version - - uses: DeLaGuardo/setup-clojure@13.4.0 - with: - cli: latest - - - uses: actions/cache@v4 - with: - path: | - ~/.m2/repository - ~/.gitlibs - key: deps-${{ runner.os }}-${{ hashFiles('deps.edn') }} - restore-keys: deps-${{ runner.os }}- - - - run: script/unit-test + - run: script/docker-unit-test integration: name: Integration tests + coverage @@ -38,35 +32,17 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: actions/setup-java@v4 - with: - distribution: temurin - java-version: "11" - - - uses: DeLaGuardo/setup-clojure@13.4.0 - with: - cli: latest - bb: latest - - - uses: actions/cache@v4 - with: - path: | - ~/.m2/repository - ~/.gitlibs - key: deps-${{ runner.os }}-${{ hashFiles('deps.edn') }} - restore-keys: deps-${{ runner.os }}- - - # The integration suite drives `docker compose` and `docker buildx`, so the - # runner must expose a Docker daemon (e.g. /var/run/docker.sock mounted into - # job containers, or a host-mode runner). Fail fast with a clear message. - name: Check Docker run: | docker version docker compose version docker buildx version - # Unit + integration under Cloverage, then the merged report. - - run: script/coverage + # Unit + integration under Cloverage, then the merged report + # (the dockerized equivalent of script/coverage). + - run: script/docker-unit-coverage + - run: script/integration-coverage + - run: script/docker-coverage-report # Gitea Actions only supports upload-artifact v3 (v4+ needs GitHub's artifact backend). - uses: actions/upload-artifact@v3 diff --git a/README.md b/README.md index bf1807b..34b993d 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,8 @@ integration tests, and joint line coverage. ## Requirements -- [Clojure CLI](https://clojure.org/guides/install_clojure) (tools.deps) and JDK 11+ -- [Babashka](https://babashka.org/) for merging coverage reports (`script/coverage-report`) -- Docker, for the integration tests only +- Docker, for the integration tests and the `script/docker-*` tasks (all CI needs) +- For running tasks natively (optional): [Clojure CLI](https://clojure.org/guides/install_clojure) (tools.deps) with JDK 11+, and [Babashka](https://babashka.org/) for `script/coverage-report` ## Running @@ -60,6 +59,7 @@ script/repl | `script/unit-test` | Runs the Clojure tests in `test/` | | `script/integration-test` | Builds the app image, starts it on a random port, runs the [integration suite](integration-test/README.md) against it, then tears it down | | `script/test` | Unit tests, then integration tests (stops at the first failure) | +| `script/docker-unit-test` | Same as `script/unit-test`, but inside the app image (Docker only) | ### Coverage @@ -70,6 +70,7 @@ Line coverage via [Cloverage](https://github.com/cloverage/cloverage): | `script/unit-coverage` | `target/coverage/unit/` | | `script/integration-coverage` | `target/coverage/integration/` | | `script/coverage` | Runs both, then writes the merged report to `target/coverage/merged/` | +| `script/docker-unit-coverage`, `script/docker-coverage-report` | Dockerized versions of the unit run and the merge step, so `script/docker-unit-coverage`, `script/integration-coverage`, `script/docker-coverage-report` is `script/coverage` with no local Clojure or Babashka (this is what CI runs) | Each report directory has an `index.html` and an `lcov.info`. See [integration-test/README.md](integration-test/README.md) for how integration coverage is diff --git a/script/docker-coverage-report b/script/docker-coverage-report new file mode 100755 index 0000000..96be42c --- /dev/null +++ b/script/docker-coverage-report @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +# Merge the unit and integration coverage results inside a Babashka container; needs only +# Docker. Inputs and outputs travel via `docker cp` rather than a bind mount. Extra args go +# to script/coverage_report.clj. Output: target/coverage/merged. +set -euo pipefail +cd "$(dirname "$0")/.." + +id=$(docker create --security-opt apparmor=unconfined -w / --entrypoint bb \ + babashka/babashka:latest script/coverage_report.clj "$@") +trap 'docker rm -f "$id" >/dev/null' EXIT + +# The report reads target/coverage/*/lcov.info and, for the HTML, the sources. +tar -c script/coverage_report.clj src integration-test test target/coverage | docker cp - "$id:/" + +docker start -a "$id" + +rm -rf target/coverage/merged +docker cp "$id:/target/coverage/merged" target/coverage/ diff --git a/script/docker-unit-coverage b/script/docker-unit-coverage new file mode 100755 index 0000000..024a2cc --- /dev/null +++ b/script/docker-unit-coverage @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +# Run the unit tests under Cloverage inside the app image; needs only Docker. The report is +# copied out with `docker cp` (not a bind mount) so it works when this itself runs in a +# job container. Output: target/coverage/unit. +set -euo pipefail +cd "$(dirname "$0")/.." +source script/lib/docker.sh + +build_unit_image + +id=$(docker create --security-opt apparmor=unconfined vibe-unit \ + clojure -M:cov -m cloverage.coverage \ + --src-ns-path src --test-ns-path test \ + --lcov --html --output target/coverage/unit) +trap 'docker rm -f "$id" >/dev/null' EXIT + +status=0 +docker start -a "$id" || status=$? + +rm -rf target/coverage/unit +mkdir -p target/coverage +docker cp "$id:/app/target/coverage/unit" target/coverage/ || echo "[test] WARNING: no unit coverage report was produced" +exit "$status" diff --git a/script/docker-unit-test b/script/docker-unit-test new file mode 100755 index 0000000..29e1a4d --- /dev/null +++ b/script/docker-unit-test @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +# Run the Clojure unit tests inside the app image; needs only Docker. Extra args go to the test runner. +set -euo pipefail +cd "$(dirname "$0")/.." +source script/lib/docker.sh + +build_unit_image +exec docker run --rm --security-opt apparmor=unconfined vibe-unit clojure -M:test "$@" diff --git a/script/integration-test b/script/integration-test index 98a39e8..8c8741f 100755 --- a/script/integration-test +++ b/script/integration-test @@ -9,6 +9,7 @@ set -euo pipefail cd "$(dirname "$0")/.." root=$PWD +source script/lib/docker.sh # Picks a random port in [lo, hi] that's currently free on this host; retries on # collision since another process could grab it first. @@ -34,15 +35,7 @@ if [[ -n "${COVERAGE:-}" ]]; then compose+=(-f docker-compose.yml -f docker-compose.coverage.yml) fi -# Works around an LXC/AppArmor bug in runc (opencontainers/runc#5007) that fails RUN steps -# during image build; a docker-container builder with apparmor disabled sidesteps it. -builder=vibe-builder -if ! docker buildx inspect "$builder" >/dev/null 2>&1; then - docker buildx create --name "$builder" \ - --driver docker-container \ - --buildkitd-config buildkitd.toml -fi -docker buildx use "$builder" +use_builder cd integration-test export VIBE_PORT=$port diff --git a/script/lib/docker.sh b/script/lib/docker.sh new file mode 100644 index 0000000..c85d0d0 --- /dev/null +++ b/script/lib/docker.sh @@ -0,0 +1,20 @@ +# Shared helpers for the script/docker-* entry points and script/integration-test. Source, don't run. +# +# The docker-container buildx builder works around an LXC/AppArmor bug in runc +# (opencontainers/runc#5007) that fails RUN steps during image build. + +use_builder() { + local builder=vibe-builder + if ! docker buildx inspect "$builder" >/dev/null 2>&1; then + docker buildx create --name "$builder" \ + --driver docker-container \ + --buildkitd-config buildkitd.toml + fi + docker buildx use "$builder" +} + +# Builds the app image with the test and coverage deps pre-fetched, tagged vibe-unit. +build_unit_image() { + use_builder + docker buildx build --load --build-arg DEPS_ALIASES=test:cov -t vibe-unit . +}