name: CI on: push: branches: [main] pull_request: env: # Test the module alone, with the versions in go.mod (never a go.work). GOWORK: "off" GOPRIVATE: bnema.dev/ermite* jobs: lint: name: Lint runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 # Job containers reach Forgejo through the Gordon edge on the host loopback, # in plain HTTP on :8088 (see vps-infra homelab/igor/ci-runner). - name: Fetch bnema.dev/ermite* modules through the runner's Forgejo route run: git config --global url."http://git.bnema.dev:8088/".insteadOf "https://git.bnema.dev/" - uses: actions/setup-go@v5 with: go-version-file: go.mod cache: true - uses: golangci/golangci-lint-action@v9 with: version: v2.14.0 test: name: Test # ermite needs git >= 2.45; the ubuntu-latest image (Debian bookworm) has 2.39. # The arch label runs archlinux:latest as root, with a current git. runs-on: arch steps: # openssh provides ssh-keygen, which the tests use to check that the squash # commits verify (git verify-commit, ADR 0022). The tests fail without it when CI is set. # nodejs runs the tests of the file finder (internal/adapters/web/jstest). - name: System packages run: pacman -Syu --noconfirm --needed git gcc openssh nodejs - uses: actions/checkout@v6 # Job containers reach Forgejo through the Gordon edge on the host loopback, # in plain HTTP on :8088 (see vps-infra homelab/igor/ci-runner). - name: Fetch bnema.dev/ermite* modules through the runner's Forgejo route run: git config --global url."http://git.bnema.dev:8088/".insteadOf "https://git.bnema.dev/" - uses: actions/setup-go@v5 with: go-version-file: go.mod cache: true - name: Git is at least 2.45 run: | git --version v=$(git --version | sed -E 's/^git version ([0-9]+)\.([0-9]+).*/\1 \2/') set -- $v if [ "$1" -lt 2 ] || { [ "$1" -eq 2 ] && [ "$2" -lt 45 ]; }; then echo "git 2.45 or newer is required" >&2 exit 1 fi - name: Verify tidy run: | go mod tidy git diff --exit-code -- go.mod go.sum - name: Generated templ code is up to date run: scripts/templ-drift.sh - run: go vet ./... # The end-to-end tests (internal/app, a real server per test) run before a # PR is opened (README, Build) and here on main only: they are most of the # time of a PR run. - name: Tests run: go test -race $(go list ./... | grep -vx 'bnema.dev/ermite/internal/app') - name: End-to-end tests if: github.event_name == 'push' run: go test -race ./internal/app/ - name: Architecture run: go tool hexcheck -fail-on warn ./... # The core of the file finder (static/js/files.js) runs in Node. - name: JavaScript tests run: node --test 'internal/adapters/web/jstest/*.test.mjs' proto: name: Protobuf and generated code runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 with: # buf breaking compares with the base branch. fetch-depth: 0 # Job containers reach Forgejo through the Gordon edge on the host loopback, # in plain HTTP on :8088 (see vps-infra homelab/igor/ci-runner). - name: Fetch bnema.dev/ermite* modules through the runner's Forgejo route run: git config --global url."http://git.bnema.dev:8088/".insteadOf "https://git.bnema.dev/" - uses: actions/setup-go@v5 with: go-version-file: go.mod cache: true - run: go tool buf lint - name: Breaking changes if: github.event_name == 'pull_request' # Skipped by the script while the base branch has no proto/ directory. run: scripts/buf-breaking.sh "origin/${{ github.base_ref }}" - name: Generated protobuf code is up to date run: | go tool buf generate git diff --exit-code -- gen/ test -z "$(git status --porcelain -- gen/)" - name: Generated mocks are up to date run: | go generate ./internal/ports git diff --exit-code -- internal/ports/mocks/ test -z "$(git status --porcelain -- internal/ports/mocks/)" image: name: Image # Build only, nothing is pushed. The arch job container gets the runner's rootless # Podman socket as /var/run/docker.sock (docker_host in ci-runner/config.yml), so the # docker CLI builds through Podman. runs-on: arch steps: - name: System packages run: pacman -Syu --noconfirm --needed git docker - uses: actions/checkout@v6 with: # git describe needs the tags for the image version. fetch-depth: 0 # The build runs in Podman on the runner host. With the host network it resolves # git.bnema.dev through the host's /etc/hosts (127.0.0.1, see vps-infra # homelab/igor/ci-runner) and reaches Forgejo on :8088. Podman's Docker API rejects # the classic builder's --add-host encoding, so host networking is used instead. # Acceptable because only trusted branches of this repo trigger CI (no fork PRs). - name: Build the image run: | docker build \ --network host \ --build-arg GIT_REWRITE_BASE=http://git.bnema.dev:8088/ \ --build-arg VERSION="$(git describe --tags --always --dirty)" \ -t ermite:ci . - name: Smoke test run: | docker run --rm ermite:ci version | tee /dev/stderr | grep -qF "ermite $(git describe --tags --always --dirty)" docker run --rm --entrypoint git ermite:ci --version