oficina / sheets Public

Clone
git clone https://amadan.net/oficina/sheets

Plain git — no account needed to clone.

Download

Download this file

1comma := ,
2export GOPRIVATE := $(if $(GOPRIVATE),$(GOPRIVATE)$(comma))amadan.net/oficina/estilo.git
3
4.PHONY: build release test test-vet test-fmt test-build test-migrations test-go test-race test-browser
5
6# One binary, CGO_ENABLED=0, cgo-free SQLite (AGENTS.md / Deploys). Set
7# per-target below rather than exported globally, because test-race is
8# a deliberate, documented exception — see its comment.
9build:
10 CGO_ENABLED=0 go build ./...
11
12# The ONLY way a binary should be built for shipping. rastrillo's
13# BuildVersion defaults to "dev", and an unstamped binary answers
14# GET /api/version with "dev" — which is the field used to tell what is
15# actually deployed, so an unstamped release makes the fleet unreadable
16# while still looking like a successful deploy. Shipping one by hand
17# with a plain `go build` is exactly the mistake this target removes.
18#
19# A dirty tree is refused: the sha would name a commit that is not what
20# is in the binary, which is worse than no stamp at all.
21#
22# The stamp was a short sha because there were no tags to describe. Now
23# that a release IS a tag, git describe --tags --always answers with the
24# tag when the build sits on one and falls back to the same short sha
25# when it does not, so nothing is lost and a published binary reports
26# the name it was published under.
27#
28# The artifact lands in releases/ under the name the publish step
29# expects: `amadan release create` uploads a file under its basename,
30# and that basename is what appears on the release page permanently.
31APP := sheets
32RELEASE_GOOS ?= linux
33RELEASE_GOARCH ?= arm64
34RELEASE_BIN := releases/$(APP)-$(RELEASE_GOOS)-$(RELEASE_GOARCH)
35VERSION ?= $(shell git describe --tags --always 2>/dev/null)
36
37release:
38 @git diff --quiet && git diff --cached --quiet || \
39 { echo "refusing to build a release from a dirty tree"; exit 1; }
40 @test -n "$(VERSION)" || \
41 { echo "make release: no version to stamp; commit, or name it: make release VERSION=v0.1.0"; exit 1; }
42 @mkdir -p releases
43 CGO_ENABLED=0 GOOS=$(RELEASE_GOOS) GOARCH=$(RELEASE_GOARCH) go build -trimpath \
44 -ldflags "-s -w -X amadan.net/rastrillo/rastrillo.BuildVersion=$(VERSION)" \
45 -o $(RELEASE_BIN) ./cmd/$(APP)
46 @echo "built $(RELEASE_BIN) reporting version $(VERSION)"
47 @echo "publish it with:"
48 @echo " amadan release create -repo oficina/$(APP) -notes-file NOTES.md $(VERSION) $(RELEASE_BIN)"
49
50# The gate, split into named targets so CI can report them individually
51# (.amadan/ci.d calls these one at a time, each its own step). `make
52# test` runs exactly the same six things in the same order, so the
53# local gate and CI stay ONE definition rather than two lists that
54# drift apart. Debugging CI is running `make test`.
55#
56# Order is cheapest-and-fastest first: vet and gofmt are near-instant,
57# build catches compile errors before minutes are spent on tests,
58# test-migrations needs the app to compile but no database and no test
59# suite, plain `go test` (tens of seconds, dominated by the store
60# package) comes next, and -race — by far the slowest step — runs last.
61test: test-vet test-fmt test-build test-migrations test-go test-race
62
63# Also vets the browser-tagged tests: they are outside `make test`, and a
64# test behind a tag that nothing compiles rots silently.
65test-vet:
66 CGO_ENABLED=0 go vet ./...
67 CGO_ENABLED=0 go vet -tags browser ./internal/sheets/
68
69# Fails on unformatted files rather than rewriting them. CI must never
70# silently "fix" a diff out from under a branch — a red test-fmt tells
71# the author to run `gofmt -w` themselves.
72test-fmt:
73 @if [ -n "$$(gofmt -l .)" ]; then \
74 echo "gofmt needs to be run on:"; \
75 gofmt -l .; \
76 exit 1; \
77 fi
78
79test-build:
80 CGO_ENABLED=0 go build ./...
81
82# CI gate for AGENTS.md's additive-only migrations rule: models
83# (internal/sheets/migrations.go's Models) and migrations
84# (internal/sheets/migrations/*.sql, via Schema) must already agree.
85# Touches no database — it diffs structs against committed SQL, the
86# same computation `rastrillo migration generate` does before deciding
87# there is nothing to write — so it belongs this early, right after the
88# app is known to compile and well before test-go pays for real SQLite
89# files. A model changed without `rastrillo migration generate` run
90# after it fails here, not in production at the next boot.
91#
92# `go tool`, not a bare `rastrillo` on PATH: go.mod pins the CLI as a tool
93# at the same version as the module, so the check always runs the
94# migrate the app is built against — never whatever a machine happened
95# to have installed (a v0.25.0 CLI answering for a v0.23.0 app, until
96# the move to amadan.net/rastrillo/rastrillo).
97test-migrations:
98 go tool rastrillo migration check
99
100# Includes internal/guardstest: the mechanical guards for the line cap,
101# forbidden imports, excelize confinement, calc isolation and sealtest
102# containment all run here as ordinary tests, plus internal/sheets/seal
103# and internal/sheets/xlsx's plaintext-leak checks (AGENTS.md / "The one
104# rule"). -count=1 so a cached "ok" from a previous run can never stand
105# in for actually having run.
106test-go:
107 CGO_ENABLED=0 go test -count=1 ./...
108
109# The concurrency-bearing packages: store's one-connection writer pool
110# and its handle gate (AGENTS.md: "Scope tx, never the outer handle,
111# inside transactions, or the one-connection writer pool deadlocks"),
112# and live's fan-out hub, where one publisher and every open browser
113# tab meet. Scoped to those two rather than ./... because -race's
114# slowdown is worth paying where the concurrency actually lives, not
115# repeated across packages that don't touch goroutines.
116#
117# Deliberately NOT CGO_ENABLED=0: the race detector requires cgo (`go:
118# -race requires cgo`), so this one target runs with the ambient
119# CGO_ENABLED (cgo on, given a C toolchain is present). Nothing this
120# target builds is shipped — it only exercises store's own test suite —
121# so it does not violate the cgo-free binary rule, which is about what
122# gets deployed.
123test-race:
124 go test -race -count=1 ./internal/sheets/store/... ./internal/sheets/live/...
125
126# The browser checks (internal/sheets/*_browser_test.go), in a real
127# Chromium: on PATH, via RASTRILLO_CHROME, or in a Playwright cache.
128# Deliberately NOT part of `test`: the gate CI runs on every push must
129# not need a browser. Run it before shipping a change to the CSS or to
130# rastrillo's pin — TestNoZoomOnTap is the iOS zoom-on-tap check, and
131# TestDocumentStylesSurviveTheProductionCSP is the one browser check served
132# through rastrillo's production stack, so it sees the real CSP.
133test-browser:
134 CGO_ENABLED=0 go test -tags browser -count=1 -run 'OnTap|DocumentStyles' ./internal/sheets/
135