oficina / home Public

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

Plain git — no account needed to clone.

Download

Download this file

1export GOTOOLCHAIN := go1.26.5
2export GOPRIVATE := $(GOPRIVATE),amadan.net/oficina/estilo.git
3
4private_comma := ,
5export GOPRIVATE := $(if $(GOPRIVATE),$(GOPRIVATE)$(private_comma))amadan.net/oficina/estilo.git,amadan.net/carlos/platform.git
6
7.PHONY: build release deps test test-vet test-fmt test-build test-go test-race test-browser
8
9# One binary, CGO_ENABLED=0, cgo-free SQLite (AGENTS.md / Deploys). Set
10# per-target rather than exported globally, because test-race is a
11# deliberate, documented exception — see its comment.
12build:
13 CGO_ENABLED=0 go build ./...
14
15# release is what ships, and it is the ONLY way a binary should be built
16# for shipping. rastrillo's BuildVersion defaults to "dev", so an
17# unstamped binary answers GET /api/version with "dev" from every build
18# ever made — and that is the field the deploy check compares, so an
19# unstamped release makes the check structurally incapable of failing
20# while still reporting green. A plain `go build` sent to an instance is
21# exactly the mistake this target removes.
22#
23# linux/arm64 because that is what the instances run; building for this
24# Mac and shipping it is a silent architecture mismatch that uploads
25# fine and fails to exec. Override for a one-off:
26# make release RELEASE_GOARCH=amd64
27#
28# -s -w drops the symbol table and DWARF. Panic traces keep their
29# function names and line numbers either way (pclntab is untouched);
30# what you lose is delve and gdb, so build without them for that.
31#
32# git describe --tags, because the tag is what gets published. A dirty
33# tree is refused rather than suffixed: a -dirty stamp names a commit
34# plus changes nobody can name, so two different binaries can carry the
35# identical string, which makes the check look reliable while it is not.
36# If you mean to ship uncommitted work, say so out loud:
37# make release VERSION=v0.1.0-wip
38APP := home
39RELEASE_GOOS ?= linux
40RELEASE_GOARCH ?= arm64
41RELEASE_BIN := releases/$(APP)-$(RELEASE_GOOS)-$(RELEASE_GOARCH)
42VERSION ?= $(shell git describe --tags --always 2>/dev/null)
43
44release:
45 @git diff --quiet && git diff --cached --quiet || \
46 { echo "refusing to build a release from a dirty tree"; exit 1; }
47 @test -n "$(VERSION)" || \
48 { echo "make release: no version to stamp; commit, or name it: make release VERSION=v0.1.0"; exit 1; }
49 @mkdir -p releases
50 CGO_ENABLED=0 GOOS=$(RELEASE_GOOS) GOARCH=$(RELEASE_GOARCH) go build -trimpath \
51 -ldflags "-s -w -X amadan.net/rastrillo/rastrillo.BuildVersion=$(VERSION)" \
52 -o $(RELEASE_BIN) ./cmd/$(APP)
53 @echo "built $(RELEASE_BIN) reporting version $(VERSION)"
54 @echo "publish it with:"
55 @echo " amadan release create -repo oficina/$(APP) -notes-file NOTES.md $(VERSION) $(RELEASE_BIN)"
56
57# The gate, split into named targets so CI can report them individually
58# (.amadan/ci.d calls these one at a time, each its own step). `make
59# test` runs exactly the same things in the same order, so the local
60# gate and CI stay ONE definition rather than two lists that drift
61# apart. Debugging CI is running `make test`.
62#
63# Order is cheapest-and-fastest first: vet and gofmt are near-instant,
64# build catches compile errors before time is spent on tests, plain
65# `go test` next, and -race — by far the slowest step — last.
66test: test-vet test-fmt test-build test-go test-race
67
68# The modules first, one directory at a time and retried. The hub
69# rate-limits public git reads per address (5 a second, a burst of 10),
70# and a cold module cache fetches estilo, rastrillo, the platform and
71# this repo at once — more than the burst — so vet failed every run
72# with HTTP 429 however long the runner waited between runs. What one
73# attempt fetched stays cached, so each retry asks for less.
74deps:
75 @for dir in . handoff roster connect; do \
76 n=0; until (cd $$dir && go mod download); do \
77 n=$$((n+1)); [ $$n -lt 6 ] || exit 1; \
78 echo "go mod download in $$dir failed (the hub's git rate limit?); retrying in $$((n*5))s"; \
79 sleep $$((n*5)); \
80 done; \
81 done
82
83test-vet: deps
84 CGO_ENABLED=0 go vet ./...
85 CGO_ENABLED=0 go vet -tags browser ./internal/home/
86 cd handoff && CGO_ENABLED=0 go vet ./...
87 cd roster && CGO_ENABLED=0 go vet ./...
88 cd connect && CGO_ENABLED=0 go vet ./...
89
90# Fails on unformatted files rather than rewriting them. CI must never
91# silently "fix" a diff out from under a branch — a red test-fmt tells
92# the author to run `gofmt -w` themselves.
93test-fmt:
94 @if [ -n "$$(gofmt -l .)" ]; then \
95 echo "gofmt needs to be run on:"; \
96 gofmt -l .; \
97 exit 1; \
98 fi
99
100test-build:
101 CGO_ENABLED=0 go build ./...
102 CGO_ENABLED=0 GOOS=linux GOARCH=arm64 go build ./cmd/home ./cmd/oficina ./internal/operatorlaunch
103 cd handoff && CGO_ENABLED=0 go build ./...
104 cd roster && CGO_ENABLED=0 go build ./...
105 cd connect && CGO_ENABLED=0 go build ./...
106
107test-go:
108 CGO_ENABLED=0 go test -count=1 ./...
109 cd handoff && CGO_ENABLED=0 go test -count=1 ./...
110 cd roster && CGO_ENABLED=0 go test -count=1 ./...
111 cd connect && CGO_ENABLED=0 go test -count=1 ./...
112
113# The one concurrency-bearing package. internal/home's link store is
114# taken by a single DELETE ... RETURNING precisely so that two clicks on
115# one magic link mint one session, and its test races sixteen goroutines
116# at the same row to prove it. A race the detector would catch there is
117# a session minted twice.
118#
119# Deliberately NOT CGO_ENABLED=0: the race detector requires cgo (`go:
120# -race requires cgo`), so this one target runs with the ambient
121# CGO_ENABLED. Nothing it builds is shipped, so it does not violate the
122# cgo-free binary rule, which is about what gets deployed.
123test-race:
124 go test -race -count=1 ./internal/home/ ./internal/operator/ ./internal/operatorlaunch/ ./internal/provisioner/ ./internal/home/directorydata/
125 cd handoff && CGO_ENABLED=1 go test -race -count=1 ./...
126 cd roster && CGO_ENABLED=1 go test -race -count=1 ./...
127 cd connect && CGO_ENABLED=1 go test -race -count=1 ./...
128
129# The browser checks, in a real Chromium (RASTRILLO_CHROME, on PATH, or
130# the newest in a Playwright cache: Linux's ~/.cache or macOS's
131# ~/Library/Caches). Deliberately NOT part of `test`: the gate CI runs on
132# every push must not need a browser. Run it before shipping a change to
133# the CSS or to rastrillo's pin — TestNoZoomOnTap is the iOS zoom-on-tap
134# check. Every test in the package runs, the browser ones (the `browser`
135# tag) with them, so none is left out by a -run filter that predates it.
136# test-vet vets these files with the tag, so they keep compiling.
137test-browser:
138 CGO_ENABLED=0 go test -tags browser -count=1 ./internal/home/
139
140.PHONY: credits
141credits:
142 @set -eu; notices_tmp=$$(mktemp -d); trap 'rm -rf "$$notices_tmp"' EXIT; \
143 GOOS=$$(go env GOHOSTOS) GOARCH=$$(go env GOHOSTARCH) CGO_ENABLED=0 \
144 go build -o "$$notices_tmp/notices" amadan.net/oficina/estilo.git/cmd/oficina-notices; \
145 GOOS=linux GOARCH=arm64 CGO_ENABLED=0 "$$notices_tmp/notices" \
146 -package ./cmd/home -lucide -onest \
147 -exclude amadan.net/oficina/estilo.git,amadan.net/oficina/home/handoff,amadan.net/oficina/home/roster \
148 > "$$notices_tmp/notices.json"; \
149 mv "$$notices_tmp/notices.json" internal/home/credits/notices.json
150