ci(go): verify committed sqlc output matches its .sql sources — #2380
internal/db/dbq is 39 files and ~12k lines of generated Go covering 307 queries, and nothing checked that it still matched internal/db/queries. test-go.yml referenced sqlc.yaml only as a path trigger; sqlc never ran. So a hand-edit, a half-applied regen, or a migration changed without a regen would all pass CI while the typed layer quietly lied about the SQL underneath it — which is the single thing adopting sqlc is supposed to buy. This session's slice-1 change is an instance: its SQL const was verified byte-identical against its own .sql source by script, but never against what sqlc would actually emit. Nothing in the repo could have told the difference. make verify-generate runs ahead of vet/lint/test, because if the typed layer disagrees with its sources then everything downstream is testing a lie. generate-go runs sqlc as a Go tool rather than a container: the ci-go image already has Go, so this avoids docker-in-docker on the runner. It's pinned to the same SQLC_VERSION as the existing containerised `generate`, so both routes emit identical output and there is one version to bump — now annotated for Renovate per rule #44. The diff prints BEFORE the exit-code check on purpose. On failure the log then holds sqlc's exact expected output, so correcting it is a copy rather than a guess. That is also what makes new queries workable without installing anything: this workstation has neither Go nor sqlc. Makefile joins the workflow's paths:. Without it a Makefile-only change — including this one — would not trigger the workflow that now depends on it. Same class as #2204, where CI never ran on plugin/** changes. Landing this on its own, ahead of slice 3, so that if it fails it is unambiguous whether the drift came from slice 1 or from new code. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -27,6 +27,7 @@ on:
|
||||
- 'go.mod'
|
||||
- 'go.sum'
|
||||
- 'sqlc.yaml'
|
||||
- 'Makefile'
|
||||
- 'internal/**'
|
||||
- 'cmd/**'
|
||||
- '.golangci.yml'
|
||||
@@ -53,6 +54,9 @@ jobs:
|
||||
go version
|
||||
golangci-lint --version
|
||||
|
||||
- name: Generated code matches queries (sqlc)
|
||||
run: make verify-generate
|
||||
|
||||
- name: go vet
|
||||
run: go vet ./...
|
||||
|
||||
|
||||
@@ -1,10 +1,30 @@
|
||||
.PHONY: generate test test-short test-integration lint build
|
||||
.PHONY: generate generate-go verify-generate test test-short test-integration lint build
|
||||
|
||||
# renovate: datasource=docker depName=sqlc/sqlc
|
||||
SQLC_VERSION := 1.31.1
|
||||
|
||||
# Local codegen. Containerised so a dev needs no sqlc install.
|
||||
generate:
|
||||
docker run --rm -v "$(CURDIR):/src" -w /src sqlc/sqlc:$(SQLC_VERSION) generate
|
||||
|
||||
# Same codegen, run as a Go tool instead of a container. This is the CI path:
|
||||
# the ci-go image already has Go, so it avoids docker-in-docker. Pinned to the
|
||||
# SAME version as `generate` above so both routes emit identical output.
|
||||
generate-go:
|
||||
go run github.com/sqlc-dev/sqlc/cmd/sqlc@v$(SQLC_VERSION) generate
|
||||
|
||||
# Fail if the committed generated code no longer matches the .sql sources.
|
||||
#
|
||||
# Nothing verified this before, so internal/db/dbq could silently drift from
|
||||
# internal/db/queries — a hand-edit, a half-applied regen, or a schema change
|
||||
# without a regen would all pass CI while the typed layer lied about the SQL.
|
||||
#
|
||||
# The diff is printed BEFORE the exit-code check on purpose: when this fails,
|
||||
# the log then contains sqlc's exact expected output, which is what you commit.
|
||||
verify-generate: generate-go
|
||||
git --no-pager diff -- internal/db/dbq
|
||||
git diff --quiet -- internal/db/dbq
|
||||
|
||||
test:
|
||||
go test -race ./...
|
||||
|
||||
|
||||
Reference in New Issue
Block a user