10812606bf
Släppprocessen (~/.claude/skills/release) körde hittills bara riksdata och
rd-web, och vägrade den här katalogen med "not one of the release-managed
repos". Den kräver två saker: en .release.conf och ett release-vars-mål som
skriver ut IMAGE, HELM_CHART och HELM_REPO. Poängen med att fråga make i
stället för att upprepa värdena i processen är att de bara kan ha en
definition, så det som taggas, det som pushas och det som wrappern pinnar
inte kan glida isär.
Makefilen är avsiktligt inte en kopia av riksdatas. Två skillnader:
fmt, lint och test speglar .gitea/workflows/ci.yaml steg för steg, så ett
grönt "make fmt lint test" här betyder samma sak som en grön CI. gofmt-målet
är kopierat ordagrant och inte förenklat, eftersom gofmts två felsätt inte
är lika: en felformaterad fil listas på stdout med exit 0, medan en fil som
inte går att parsa ger tom stdout och exit 2 — och den naiva varianten läser
det andra som framgång (9046f6e). Undantaget är -race, som CI inte kör:
sveparen, notifieraren och deadman-svepet delar en enda databasanslutning,
och en kapplöpning där dyker upp som en flaxig incident i produktion i
stället för som ett rött bygge.
Det finns medvetet inga build-, push- eller helm-push-mål, till skillnad
från riksdata och rd-web. Här äger .gitea/workflows/release.yaml
publiceringen, och den gör två saker en lokal make inte gör: bygger
linux/amd64 och linux/arm64 genom buildx, och stämplar chartets version och
appVersion från taggen. Ett vanligt "docker build && docker push" skulle
lägga en enarkitektursbild över den multiarkitekturella taggen — lätt att
göra av misstag och osynligt efteråt, eftersom taggen fortfarande svarar,
bara inte på arm64. Publicering sker genom att pusha en tagg, inget annat.
Claude-Session: https://claude.ai/code/session_01S7R4gWTz5wh5xCY4nCSJjN
85 lines
3.9 KiB
Makefile
85 lines
3.9 KiB
Makefile
REGISTRY := git.ryuvia.com
|
|
# The personal namespace, not ryuvia — deliberately, and for one reason: Gitea
|
|
# scopes package visibility to the owner with no per-package override, so
|
|
# ryuvia/* is private because the org is. Publishing here keeps the image and
|
|
# chart anonymously pullable, so no pull secret is needed in the cluster and
|
|
# Flux needs no registry credentials. Same choice riksdata and rd-web made.
|
|
OWNER := niklas
|
|
|
|
IMAGE := $(REGISTRY)/$(OWNER)/terdut-server
|
|
HELM_CHART := charts/terdut-server
|
|
HELM_REPO := oci://$(REGISTRY)/$(OWNER)
|
|
|
|
# go.mod pins an exact patch release so nobody builds the shipped binary with a
|
|
# toolchain carrying known stdlib CVEs. Fedora's Go package overrides the
|
|
# upstream GOTOOLCHAIN default to `local`, which turns that pin into a hard
|
|
# failure on a dev box one patch behind, so restore the upstream default here.
|
|
export GOTOOLCHAIN ?= auto
|
|
|
|
.PHONY: help
|
|
help: ## Show this help
|
|
@grep -hE '^[a-zA-Z_-]+:.*?## ' $(MAKEFILE_LIST) | \
|
|
awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-22s\033[0m %s\n", $$1, $$2}'
|
|
|
|
## --- checks ---
|
|
#
|
|
# These three mirror .gitea/workflows/ci.yaml step for step, so a green `make fmt
|
|
# lint test` here means the same thing CI means. The one deliberate difference is
|
|
# -race below.
|
|
|
|
.PHONY: test
|
|
test: ## Run the test suite
|
|
go test -race ./...
|
|
|
|
# CI runs a bare `go test ./...`. This is stricter on purpose: the sweeper, the
|
|
# notifier goroutine and the deadman sweep all touch the same single-connection
|
|
# database, and a race there would surface as a flaky production incident rather
|
|
# than a failed build. It passes today; if it ever costs more than it catches,
|
|
# the honest fix is to teach CI -race too, not to quietly drop it here.
|
|
.PHONY: lint
|
|
lint: ## go vet
|
|
go vet ./...
|
|
|
|
# Copied from ci.yaml rather than simplified, because both of gofmt's failure
|
|
# modes need handling and they are not alike. A file that is merely misformatted
|
|
# is listed on stdout with exit 0 — so the failure has to be raised by hand. A
|
|
# file that does not parse is the opposite: nothing on stdout and exit 2, which a
|
|
# naive `[ -n "$$out" ]` reads as success. See 9046f6e.
|
|
.PHONY: fmt
|
|
fmt: ## Report unformatted files
|
|
@if ! unformatted=$$(gofmt -l .); then \
|
|
echo "gofmt could not parse the tree:"; gofmt -l .; exit 1; \
|
|
fi; \
|
|
if [ -n "$$unformatted" ]; then \
|
|
echo "gofmt needed:"; echo "$$unformatted"; gofmt -d .; exit 1; \
|
|
fi
|
|
|
|
.PHONY: helm-lint
|
|
helm-lint: ## Lint and render the chart
|
|
helm lint $(HELM_CHART) --set image.tag=v0.0.0
|
|
helm template terdut-server $(HELM_CHART) --namespace terdut-server \
|
|
--set image.tag=v0.0.0 >/dev/null
|
|
@# networking.listener defaults to "", which attaches the route to every
|
|
@# matching listener including plaintext HTTP. Production sets it, so the
|
|
@# default render proves nothing about the path that actually ships.
|
|
helm template terdut-server $(HELM_CHART) --namespace terdut-server \
|
|
--set image.tag=v0.0.0 --set networking.listener=https-terdut >/dev/null
|
|
|
|
## --- release ---
|
|
|
|
# The release process (~/.claude/skills/release) reads these rather than restating them.
|
|
# One definition, so the version that gets tagged, the image that gets pushed and the chart
|
|
# the wrapper pins cannot drift apart in a second copy.
|
|
.PHONY: release-vars
|
|
release-vars: ## Print the variables the release process reads
|
|
@printf 'IMAGE=%s\nHELM_CHART=%s\nHELM_REPO=%s\n' '$(IMAGE)' '$(HELM_CHART)' '$(HELM_REPO)'
|
|
|
|
# There is deliberately no build/push/helm-package/helm-push/release here, unlike
|
|
# riksdata and rd-web. .gitea/workflows/release.yaml owns publishing for this repo,
|
|
# and it does two things a local make cannot: it builds linux/amd64 and linux/arm64
|
|
# through buildx, and it stamps the chart's version and appVersion from the tag. A
|
|
# `docker build && docker push` target would push a single-architecture image over
|
|
# the multi-arch tag, which is both easy to do by accident and invisible afterwards
|
|
# — the tag would still resolve, just not on arm64. Publishing happens by pushing a
|
|
# tag; nothing else.
|