Skip to content

ci: gate go vet and gofmt -s, and fix the vet findings (MAPCO-11498) - #36

Merged
NivGreenstein merged 7 commits into
developmentfrom
ci/gate-vet-and-gofmt
Sep 23, 2026
Merged

NivGreenstein merged 7 commits into
developmentfrom
ci/gate-vet-and-gofmt

Conversation

@NivGreenstein

Copy link
Copy Markdown
Collaborator

Jira: MAPCO-11498

What and why

Formatting and vet were enforced by convention only. The formatting convention held, but vet did not: go vet -mod vendor ./... reported findings in five places. That is why nothing could gate on it. This PR fixes all five, then makes CI fail on either kind of violation.

The vet findings. Each fix is its own commit:

  • cmd/shigola/cmd/tile_name_format_test.go (unreachable code). A successful parse hit continue before the coordinate assertion. TestFormatParse only ever checked errors and never checked the parsed z/x/y. It now checks them. I confirmed the assertion runs by breaking an expected value, which made the test fail.
  • internal/cmd/main.go (unbuffered signal.Notify channel). This one is a real bug, not just noise. signal.Notify never blocks on a send, so a SIGTERM that arrives before the handler goroutine is receiving is dropped. The channel is now buffered.
  • observability/prometheus/prometheus.go (copylocks). Handler was the only method with a value receiver, and it copied the sync.Once fields on every call. It now uses *observer like every other method.
  • cmd/internal/register/maps_test.go (copylocks). tcase carried an atlas.Atlas, which holds a mutex, and no case ever set it. The test now creates a fresh atlas per case.
  • internal/env/dict.go (composites). The dict.ErrKeyType literals now name their fields.

The gate. A new Static checks job, separate from the test job, so a failure is named in the checks list and shows up in seconds:

  • Formatting: runs gofmt -s -l over every tracked Go file outside vendor/. vendor/ is not gofmt -s clean. Listing the files with git ls-files avoids piping through grep -v, which exits 1 on a clean run under the runner's pipefail.
  • Vet: runs go vet -mod vendor ./... twice. The first run uses the default build. The second sets every opt-out tag plus pprof, so the stub files for compiled-out backends are vetted too.

CONTRIBUTING.md now lists both as required checks next to govulncheck, using the same gofmt command CI runs.

Base branch

The base is development, not master. development is where current work is integrated, and this branch was cut from it.

Verification

All runs used a golang:1.26.6-bookworm container.

  • Vet: clean with cgo on, with CGO_ENABLED=0, and with the full tag set.
  • Formatting: the CI gofmt script passes on the tree and fails on a deliberately misformatted tile.go.
  • Tests: ran go test -race ./... with RUN_POSTGIS_TESTS=yes. Everything passes except TestValidateTileInGrid and server/ogc TestTile, which are known to fail on arm64 only. Both packages pass on amd64.
  • Redis tests: not run locally, because the only Redis available is a live one.

Left out

  • Extra analyzers: no staticcheck and no analyzers beyond vet's defaults. The ticket asks for vet.
  • Test style: TestFormatParse still uses a plain loop rather than the repo's fn := func(tc tcase) subtest pattern. Converting it would widen a vet-fix commit.
  • Docs repo: no shigola-docs change. None of the files touched here are sources for docs pages.

🤖 Generated with Claude Code

NivGreenstein and others added 7 commits September 23, 2026 18:00
A successful parse hit `continue` before the coordinate assertion, so
the test only ever checked errors. go vet reports the assertion as
unreachable (MAPCO-11498).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tcase carried an atlas.Atlas, which holds a mutex, and every case copied
it by value. No case ever set it. go vet reports the copies (MAPCO-11498).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
signal.Notify never blocks on a send, so with an unbuffered channel a
SIGTERM that arrives before signalHandler is receiving is dropped and
the process does not shut down. Flagged by go vet (MAPCO-11498).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A value receiver copied the whole observer, sync.Once fields included,
on every call. Every other method already takes *observer, and only
*observer satisfies the observer interfaces. Flagged by go vet
(MAPCO-11498).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An unkeyed literal of a type from another package breaks silently if
its fields are reordered. go vet's composites check flags it
(MAPCO-11498).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A static checks job runs gofmt -s over every tracked Go file outside
vendor/ and go vet over the tree. Both were clean only by convention,
and vet was not: four kinds of finding had accumulated (MAPCO-11498).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both now fail CI, so say so where contributors look, next to
govulncheck (MAPCO-11498).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@NivGreenstein
NivGreenstein merged commit 5de9681 into development Sep 23, 2026
17 checks passed
@NivGreenstein
NivGreenstein deleted the ci/gate-vet-and-gofmt branch September 23, 2026 15:10
@coveralls

Copy link
Copy Markdown

Coverage Report for CI Build 5

Coverage decreased (-0.01%) to 56.74%

Details

  • Coverage decreased (-0.01%) from the base build.
  • Patch coverage: 9 uncovered changes across 3 files (0 of 9 lines covered, 0.0%).
  • No coverage regressions found.

Uncovered Changes

File Changed Covered %
internal/env/dict.go 4 0 0.0%
internal/cmd/main.go 3 0 0.0%
observability/prometheus/prometheus.go 2 0 0.0%

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 10608
Covered Lines: 6019
Line Coverage: 56.74%
Coverage Strength: 121.33 hits per line

💛 - Coveralls

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants