ci.yml RawHistoryFolder
1name: CI
2
3# A change that only touches these files skips the whole run: none of them
4# affects the build, the tests or the generated code.
5on:
6 push:
7 branches: [main]
8 paths-ignore: &docs-only
9 - '**.md'
10 - '**.png'
11 - 'docs/**'
12 - 'LICENSE'
13 pull_request:
14 paths-ignore: *docs-only
15
16env:
17 # Test the module alone, with the versions in go.mod (never a go.work).
18 GOWORK: "off"
19
20jobs:
21 lint:
22 name: Lint
23 runs-on: ubuntu-latest
24 steps:
25 - uses: actions/checkout@v6
26 - uses: actions/setup-go@v7
27 with:
28 go-version-file: go.mod
29 cache: true
30 - uses: golangci/golangci-lint-action@v9
31 with:
32 version: v2.14.0
33
34 test:
35 name: Test
36 # ermite needs git >= 2.45; the ubuntu-latest image (Debian bookworm) has 2.39.
37 # The job runs in archlinux:latest as root, with a current git.
38 runs-on: ubuntu-latest
39 container: archlinux:latest
40 steps:
41 # openssh provides ssh-keygen, which the tests use to check that the squash
42 # commits verify (git verify-commit, ADR 0022). The tests fail without it when CI is set.
43 # nodejs runs the tests of the file finder (internal/adapters/web/jstest).
44 - name: System packages
45 run: pacman -Syu --noconfirm --needed git gcc openssh nodejs
46 - uses: actions/checkout@v6
47 # The workspace belongs to the runner user, not root: without this, git does not
48 # treat it as a repository and `git diff a b` compares the two files instead.
49 - name: Trust the workspace
50 run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
51 - uses: actions/setup-go@v7
52 with:
53 go-version-file: go.mod
54 cache: true
55 - name: Git is at least 2.45
56 run: |
57 git --version
58 v=$(git --version | sed -E 's/^git version ([0-9]+)\.([0-9]+).*/\1 \2/')
59 set -- $v
60 if [ "$1" -lt 2 ] || { [ "$1" -eq 2 ] && [ "$2" -lt 45 ]; }; then
61 echo "git 2.45 or newer is required" >&2
62 exit 1
63 fi
64 - name: Verify tidy
65 run: |
66 go mod tidy
67 git diff --exit-code -- go.mod go.sum
68 - name: Generated templ code is up to date
69 run: scripts/templ-drift.sh
70 - run: go vet ./...
71 # The end-to-end tests (internal/app, a real server per test) run before a
72 # PR is opened (README, Build) and here on main only: they are most of the
73 # time of a PR run.
74 - name: Tests
75 run: go test -race $(go list ./... | grep -vx 'bnema.dev/ermite/internal/app')
76 - name: End-to-end tests
77 if: github.event_name == 'push'
78 run: go test -race ./internal/app/
79 - name: Architecture
80 run: go tool hexcheck -fail-on warn ./...
81 # The core of the file finder (static/js/files.js) runs in Node.
82 - name: JavaScript tests
83 run: node --test 'internal/adapters/web/jstest/*.test.mjs'
84
85 proto:
86 name: Protobuf and generated code
87 runs-on: ubuntu-latest
88 steps:
89 - uses: actions/checkout@v6
90 with:
91 # buf breaking compares with the base branch.
92 fetch-depth: 0
93 - uses: actions/setup-go@v7
94 with:
95 go-version-file: go.mod
96 cache: true
97 - run: go tool buf lint
98 - name: Breaking changes
99 if: github.event_name == 'pull_request'
100 # Skipped by the script while the base branch has no proto/ directory.
101 run: scripts/buf-breaking.sh "origin/${{ github.base_ref }}"
102 - name: Generated protobuf code is up to date
103 run: |
104 go tool buf generate
105 git diff --exit-code -- gen/
106 test -z "$(git status --porcelain -- gen/)"
107 - name: Generated mocks are up to date
108 run: |
109 go generate ./internal/ports
110 git diff --exit-code -- internal/ports/mocks/
111 test -z "$(git status --porcelain -- internal/ports/mocks/)"
112
113 image:
114 name: Image
115 # Build only, nothing is pushed. A plain ubuntu-latest job (not a container):
116 # the runner image provides the docker CLI and daemon.
117 runs-on: ubuntu-latest
118 steps:
119 - uses: actions/checkout@v6
120 with:
121 # git describe needs the tags for the image version.
122 fetch-depth: 0
123 - name: Build the image
124 run: |
125 docker build \
126 --build-arg VERSION="$(git describe --tags --always --dirty)" \
127 -t ermite:ci .
128 - name: Smoke test
129 run: |
130 docker run --rm ermite:ci version | tee /dev/stderr | grep -qF "ermite $(git describe --tags --always --dirty)"
131 docker run --rm --entrypoint git ermite:ci --version