oficina / calendar Public

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

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
4APP := calendar
5
6# What `carlos ship -target` defaults to, and therefore what a release
7# must be built for. Building for your own machine and shipping that is a
8# silent architecture mismatch: the binary uploads fine and fails to exec
9# on the instance. Override for a one-off:
10# make release RELEASE_GOARCH=amd64
11RELEASE_GOOS ?= linux
12RELEASE_GOARCH ?= arm64
13RELEASE_BIN := releases/$(APP)-$(RELEASE_GOOS)-$(RELEASE_GOARCH)
14
15# What the running binary reports from GET /api/version. The platform's
16# deploy verification polls that endpoint on every instance socket and
17# compares what it finds against the release it believes it adopted; an
18# unstamped binary answers "dev" from every build you have ever made, so
19# those two facts can never disagree and a process that was never
20# recycled onto the new release verifies green. Stamping this is what
21# gives that check the ability to fail.
22#
23# git describe, because the tag is what you ship against. Outside a
24# repository, or before the first commit, name it yourself:
25# make release VERSION=v0.1.0
26VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null)
27
28.PHONY: build release version-check deps test vet fmt-check migration-check ci browser
29
30# build is the compile check: with more than one package matched, go
31# build discards the output, so this catches a broken package without
32# producing an artifact.
33build:
34 CGO_ENABLED=0 go build ./...
35
36# release is what ships. -s -w drops the symbol table and DWARF, which on
37# this family's apps is 23-31% off the binary and 45-53% off the
38# compressed artifact — and compressed size is what actually gets
39# transferred. carlos is built the same way (see platform's Makefile).
40#
41# What survives: panic traces keep their function names AND line numbers
42# (Go's pclntab is untouched by these flags), debug.ReadBuildInfo works,
43# and go version -m still reports module metadata. What you lose is
44# source-level debugging with delve or gdb — build without the flags for
45# that. rastrillo dev never strips, for the same reason.
46release: version-check
47 @mkdir -p releases
48 CGO_ENABLED=0 GOOS=$(RELEASE_GOOS) GOARCH=$(RELEASE_GOARCH) \
49 go build -ldflags="-s -w -X 'amadan.net/rastrillo/rastrillo.BuildVersion=$(VERSION)'" \
50 -o $(RELEASE_BIN) ./cmd/$(APP)
51 @echo
52 @echo "built $(RELEASE_BIN) reporting version $(VERSION)"
53 @echo "ship it with:"
54 @echo " carlos ship -app $(APP) -target $(RELEASE_GOOS)-$(RELEASE_GOARCH) $(RELEASE_BIN)"
55
56# version-check refuses rather than letting release ship a binary whose
57# version is untrue. Both refusals are about the same thing: /api/version
58# is only evidence if the answer identifies one artifact.
59#
60# An empty stamp is worse than the "dev" default, because "dev" is
61# saying something true about itself and "" looks like a value that
62# arrived from somewhere.
63#
64# A dirty tree is refused rather than suffixed. A -dirty stamp names a
65# commit plus changes nobody can name, so two different binaries can
66# carry the identical string — which does not fix the check, it makes
67# it look reliable while it is not, and that is the more expensive
68# failure. Refusing costs one `git stash`; a wrong stamp ships. If you
69# mean to ship uncommitted work, say so out loud:
70# make release VERSION=v0.1.0-wip
71version-check:
72 @if [ -z "$(VERSION)" ]; then \
73 echo "make release: no version to stamp."; \
74 echo " git describe found nothing here: no repository, or no commit yet."; \
75 echo " Commit, or name it: make release VERSION=v0.1.0"; \
76 exit 1; \
77 fi
78 @case "$(VERSION)" in *-dirty) \
79 echo "make release: the tree is dirty, so $(VERSION) does not name what you are about to ship."; \
80 echo " Commit or stash first, or name it: make release VERSION=v0.1.0-wip"; \
81 exit 1;; \
82 esac
83
84test:
85 go test ./...
86
87# deps makes sure the module cache holds what go.sum says, and repairs it
88# when it does not. A CI runner's cache once held an extracted
89# amadan.net/rastrillo/rastrillo whose embedded files (locales/*.toml,
90# migrations/*.sql, ui/calendar.js) were missing, so vet failed with
91# "pattern ...: no matching files found" on every run, while the same
92# commit passed here. `go mod verify` names such a directory as "dir has
93# been modified"; deleting it lets `go mod download` extract it again
94# from the checksummed zip.
95deps:
96 @go mod download
97 @out=$$(go mod verify 2>&1) || { \
98 echo "$$out"; \
99 echo "$$out" | sed -n 's/.*: dir has been modified (\(.*\))$$/\1/p' | while read -r dir; do \
100 echo "deps: re-extracting $$dir"; chmod -R u+w "$$dir" && rm -rf "$$dir"; \
101 done; \
102 go mod download && go mod verify; \
103 }
104
105# Also vets the browser-tagged tests: they are outside `make ci`, and a
106# test behind a tag that nothing compiles rots silently.
107vet: deps
108 go vet ./...
109 go vet -tags browser ./internal/calendartest/
110
111fmt-check:
112 @out=$$(gofmt -l .); if [ -n "$$out" ]; then echo "gofmt needed:"; echo "$$out"; exit 1; fi
113
114# A step of its own, not folded into another target's recipe: ci.d/
115# steps each exec one make target, so migration-check needs its own
116# name to get its own reported step on a runner with step support.
117#
118# go tool, not a bare "rastrillo": go.mod pins the CLI as a tool at the
119# module's own version, so this needs nothing on PATH but the Go
120# toolchain, works offline after go mod download, and always runs the
121# migrate the app is built against. A bare "rastrillo migration check"
122# failed a fresh clone's very first CI run with "make: rastrillo:
123# Command not found", and nothing in the scaffold said what to install.
124migration-check:
125 go tool rastrillo migration check
126
127# ci is the one gate: what a runner executes and what you run before
128# pushing are the same definition. amadan's runner falls back to this
129# target when .amadan/ci is absent; ci.d/ carries the same targets,
130# reported one by one, for a runner with step support. migration-check
131# fails the build the moment models.go and migrations/ disagree,
132# instead of at boot on whatever machine notices next. If the app
133# declares manifest resources, also add: rastrillo generate --check
134ci: vet fmt-check test migration-check
135
136# The browser gate: the quick-add box driven in a real Chromium, with
137# script and then with JavaScript disabled.
138#
139# Deliberately NOT part of `ci`. It needs node and `npm install`, and
140# the one gate the team runs on every push must not depend on a
141# toolchain the app itself does not use. Run it before shipping a
142# change to the box.
143#
144# TestNoZoomOnTap (the iOS zoom-on-tap check),
145# TestFormFootOnANarrowScreen and TestPlacedChipsSurviveTheProductionCSP
146# drive Chromium through chromedp instead, and find it through
147# RASTRILLO_CHROME; on a Mac the Playwright cache's Chromium is used when
148# that is unset. The CSP check is the one served through rastrillo's
149# production stack, so it is the one that sees the real policy.
150browser:
151 npm install --no-save playwright
152 RASTRILLO_CHROME="$(RASTRILLO_CHROME)" go test -tags browser -run 'InARealBrowser|OnTap|OnANarrowScreen|SurviveTheProductionCSP' ./internal/calendartest/
153
154RASTRILLO_CHROME ?= $(firstword $(wildcard $(HOME)/Library/Caches/ms-playwright/chromium-*/chrome-mac*/Chromium.app/Contents/MacOS/Chromium))
155
156.PHONY: credits
157credits:
158 @set -eu; notices_tmp=$$(mktemp -d); trap 'rm -rf "$$notices_tmp"' EXIT; \
159 GOOS=$$(go env GOHOSTOS) GOARCH=$$(go env GOHOSTARCH) CGO_ENABLED=0 \
160 go build -o "$$notices_tmp/notices" amadan.net/oficina/estilo.git/cmd/oficina-notices; \
161 GOOS=linux GOARCH=arm64 CGO_ENABLED=0 "$$notices_tmp/notices" \
162 -package ./cmd/calendar -lucide -onest \
163 -exclude amadan.net/oficina/estilo.git,amadan.net/oficina/home/connect,amadan.net/oficina/home/handoff,amadan.net/rastrillo/native/server \
164 > "$$notices_tmp/notices.json"; \
165 mv "$$notices_tmp/notices.json" internal/calendar/credits/notices.json
166