diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 31cd9e6..04fcf19 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,12 +16,12 @@ jobs: - uses: actions/checkout@v6 with: persist-credentials: false + # `docker build` streams the context to the daemon. A compose bind-mount of + # `.` mounts an empty host dir instead, because the job is itself a container. - name: Latest supported Go - run: docker compose run --rm ci + run: docker build . # Runs even when the step above failed, so a red build says whether the # failure is version-specific. - name: Lowest supported Go if: ${{ !cancelled() }} - env: - GO_VERSION: 1.22.12 - run: docker compose run --rm ci + run: docker build --build-arg GO_VERSION=1.22.12 . diff --git a/Dockerfile b/Dockerfile index 51d7df9..63be7a8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ -# Reproducible test/build image. `docker build .` fails if vet or tests fail, -# so it doubles as CI. Day-to-day, prefer `docker compose run` (bind-mounts -# source, no rebuilds). GO_VERSION defaults to the latest stable Go; override it -# to test the lowest supported version: docker build --build-arg GO_VERSION=1.22 . +# The merge gate: `docker build .` fails if vet, formatting or tests fail, and CI +# runs exactly this. Day-to-day, prefer `docker compose run` (bind-mounts source, +# no rebuilds). GO_VERSION defaults to the latest stable Go; override it to test +# the lowest supported version: docker build --build-arg GO_VERSION=1.22.12 . ARG GO_VERSION=1.26.4 FROM golang:${GO_VERSION} @@ -12,4 +12,7 @@ COPY go.mod ./ RUN go mod download COPY . . -RUN go vet ./... && go test ./... +RUN go vet ./... && \ + { unformatted="$(gofmt -l .)"; test -z "$unformatted" || \ + { echo "unformatted files:"; echo "$unformatted"; exit 1; }; } && \ + go test ./... diff --git a/README.md b/README.md index 61ddfa4..77a1baf 100644 --- a/README.md +++ b/README.md @@ -482,7 +482,6 @@ Source is bind-mounted; build caches persist in the `gocache` volume. ```sh docker compose run --rm test # run tests -docker compose run --rm ci # vet + format check + tests docker compose run --rm cover # tests with coverage docker compose run --rm bench # benchmarks docker compose run --rm build # compile the library @@ -497,9 +496,14 @@ docker compose run --rm --user "$(id -u):$(id -g)" fmt # gofmt -w . docker compose run --rm --user "$(id -u):$(id -g)" tidy # go mod tidy ``` -Every pull request runs `docker compose run --rm ci` against both the latest and -the lowest supported Go, and must pass before it can be merged. `docker build .` -runs the same vet and tests locally. +Every pull request runs `docker build .` against both the latest and the lowest +supported Go, and must pass before it can be merged. That build is the whole +gate — vet, format check and tests — so run it locally before pushing: + +```sh +docker build . # latest +docker build --build-arg GO_VERSION=1.22.12 . # lowest supported +``` Tests run against the latest Go by default. Set `GO_VERSION` to check the lowest supported version too: diff --git a/cmd/fejkdata/main_test.go b/cmd/fejkdata/main_test.go index 95b187f..1ced7b8 100644 --- a/cmd/fejkdata/main_test.go +++ b/cmd/fejkdata/main_test.go @@ -176,8 +176,9 @@ func TestRunVersion(t *testing.T) { if code != 0 { t.Fatalf("-version = %d, stderr=%q", code, errb) } - if strings.TrimSpace(out) == "" { - t.Error("-version: want a version on stdout") + version, ok := strings.CutPrefix(out, "fejkdata ") + if !ok || strings.TrimSpace(version) == "" { + t.Errorf("-version = %q, want the command name and a version on stdout", out) } } diff --git a/compose.yaml b/compose.yaml index 3a1d997..18f706c 100644 --- a/compose.yaml +++ b/compose.yaml @@ -1,10 +1,12 @@ # Docker-based dev workflow — no local tooling beyond Docker is required. # # docker compose run --rm test -# docker compose run --rm ci # docker compose run --rm vet # docker compose run --rm build # +# The full gate — vet, formatting and tests — is `docker build .`, which is what +# CI runs. +# # Build caches persist in the `gocache` volume, so re-runs are fast and the # host tree stays clean. Commands that rewrite source (fmt, tidy) keep your # ownership when run with `--user "$(id -u):$(id -g)"`. @@ -52,15 +54,6 @@ services: <<: *go command: go mod tidy - # vet + format check + tests, in one container. - ci: - <<: *go - command: > - sh -c 'go vet ./... && - { unformatted=$$(gofmt -l .); test -z "$$unformatted" || - { echo "unformatted files:"; echo "$$unformatted"; exit 1; }; } && - go test ./...' - # Interactive shell for ad-hoc work: docker compose run --rm dev dev: <<: *go