carlos / movement Public

Clone
git clone https://amadan.net/carlos/movement

Plain git — no account needed to clone.

Download

Download this file

1APP := movement
2
3# What `carlos ship -target` defaults to, and therefore what a release
4# must be built for. Building for your own machine and shipping that is a
5# silent architecture mismatch: the binary uploads fine and fails to exec
6# on the instance. Override for a one-off:
7# make release RELEASE_GOARCH=amd64
8RELEASE_GOOS ?= linux
9RELEASE_GOARCH ?= arm64
10RELEASE_BIN := releases/$(APP)-$(RELEASE_GOOS)-$(RELEASE_GOARCH)
11
12# What the running binary reports from GET /api/version. The platform's
13# deploy verification polls that endpoint on every instance socket and
14# compares what it finds against the release it believes it adopted; an
15# unstamped binary answers "dev" from every build you have ever made, so
16# those two facts can never disagree and a process that was never
17# recycled onto the new release verifies green. Stamping this is what
18# gives that check the ability to fail.
19#
20# git describe, because the tag is what you ship against. Outside a
21# repository, or before the first commit, name it yourself:
22# make release VERSION=v0.1.0
23VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null)
24
25.PHONY: build release version-check test test-browser vet fmt-check migration-check ci
26
27# build is the compile check: with more than one package matched, go
28# build discards the output, so this catches a broken package without
29# producing an artifact.
30build:
31 CGO_ENABLED=0 go build ./...
32
33# release is what ships. -s -w drops the symbol table and DWARF, which on
34# this family's apps is 23-31% off the binary and 45-53% off the
35# compressed artifact — and compressed size is what actually gets
36# transferred. carlos is built the same way (see platform's Makefile).
37#
38# What survives: panic traces keep their function names AND line numbers
39# (Go's pclntab is untouched by these flags), debug.ReadBuildInfo works,
40# and go version -m still reports module metadata. What you lose is
41# source-level debugging with delve or gdb — build without the flags for
42# that. rastrillo dev never strips, for the same reason.
43release: version-check
44 @mkdir -p releases
45 CGO_ENABLED=0 GOOS=$(RELEASE_GOOS) GOARCH=$(RELEASE_GOARCH) \
46 go build -ldflags="-s -w -X 'github.com/carlosframework/rastrillo.BuildVersion=$(VERSION)'" \
47 -o $(RELEASE_BIN) ./cmd/$(APP)
48 @echo
49 @echo "built $(RELEASE_BIN) reporting version $(VERSION)"
50 @echo "ship it with:"
51 @echo " carlos ship -app $(APP) -target $(RELEASE_GOOS)-$(RELEASE_GOARCH) $(RELEASE_BIN)"
52
53# version-check refuses rather than letting release ship a binary whose
54# version is untrue. Both refusals are about the same thing: /api/version
55# is only evidence if the answer identifies one artifact.
56#
57# An empty stamp is worse than the "dev" default, because "dev" is
58# saying something true about itself and "" looks like a value that
59# arrived from somewhere.
60#
61# A dirty tree is refused rather than suffixed. A -dirty stamp names a
62# commit plus changes nobody can name, so two different binaries can
63# carry the identical string — which does not fix the check, it makes
64# it look reliable while it is not, and that is the more expensive
65# failure. Refusing costs one `git stash`; a wrong stamp ships. If you
66# mean to ship uncommitted work, say so out loud:
67# make release VERSION=v0.1.0-wip
68version-check:
69 @if [ -z "$(VERSION)" ]; then \
70 echo "make release: no version to stamp."; \
71 echo " git describe found nothing here: no repository, or no commit yet."; \
72 echo " Commit, or name it: make release VERSION=v0.1.0"; \
73 exit 1; \
74 fi
75 @case "$(VERSION)" in *-dirty) \
76 echo "make release: the tree is dirty, so $(VERSION) does not name what you are about to ship."; \
77 echo " Commit or stash first, or name it: make release VERSION=v0.1.0-wip"; \
78 exit 1;; \
79 esac
80
81test:
82 go test ./...
83
84# The browser gate, and it is not optional decoration. The proof-of-work
85# solver is only proven by driving the real module in a real browser and
86# checking its answer against the Go verifier: a Go-only test proves the
87# verifier, not the scheme. Same for the honeypot, where the thing being
88# tested is what Chrome's autofill does to a hidden field.
89#
90# This fails rather than skips when no browser is present, which is
91# deliberate — a gate that quietly passes on a runner without Chromium is
92# not a gate. Set RASTRILLO_BROWSER_OPTIONAL=1 to relax it, and say so in
93# AGENTS.md if you ever do.
94test-browser:
95 go test -tags browser ./...
96
97vet:
98 go vet ./...
99
100fmt-check:
101 @out=$$(gofmt -l .); if [ -n "$$out" ]; then echo "gofmt needed:"; echo "$$out"; exit 1; fi
102
103# A step of its own, not folded into another target's recipe: ci.d/
104# steps each exec one make target, so migration-check needs its own
105# name to get its own reported step on a runner with step support.
106#
107# go run, not a bare "rastrillo": go.mod already requires rastrillo, so
108# this needs nothing on PATH but the Go toolchain, and works offline
109# after go mod download. A bare "rastrillo migration check" failed a
110# fresh clone's very first CI run with "make: rastrillo: Command not
111# found", and nothing in the scaffold said what to install.
112migration-check:
113 go run github.com/carlosframework/rastrillo/cmd/rastrillo migration check
114
115# ci is the one gate: what a runner executes and what you run before
116# pushing are the same definition. amadan's runner falls back to this
117# target when .amadan/ci is absent; ci.d/ carries the same targets,
118# reported one by one, for a runner with step support. migration-check
119# fails the build the moment models.go and migrations/ disagree,
120# instead of at boot on whatever machine notices next. If the app
121# declares manifest resources, also add: rastrillo generate --check
122ci: vet fmt-check test migration-check test-browser
123