The live tests reached one shared bus and assert, read and remove the mesh's own objects by their fixed names, so packages run in parallel deleted what each other read and the suite passed only one package at a time; a red suite read as noise. internal/testbus starts a server per test, linked in at the nats-server release go.mod pins, and a test holds that pin to the catalogue's bus image and to the facts snapshot's bus when there is one, so the tests never run a bus the mesh does not. The waiter test read a timing (the most connections held at one look) and now reads the state it means (the fewest held across the wait). make check runs the packages in parallel under the race detector, with a timeout.
142 lines
6.7 KiB
Makefile
142 lines
6.7 KiB
Makefile
# novox/hq ADR 0006 — the control plane, in Go.
|
|
#
|
|
# The image the bundle pins holds the program and nothing else, so the build is static and the
|
|
# container is built FROM scratch. That is not a size optimisation: this image is fetched by
|
|
# digest and run on a machine where no mesh exists to check anything, and everything in it is
|
|
# something a person would have to audit.
|
|
|
|
VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null || echo development)
|
|
LDFLAGS := -s -w -X main.version=$(VERSION)
|
|
|
|
# Where `make check` raises PostgreSQL. A high port and a throwaway container: nothing here
|
|
# touches a database anybody else is using. Override PG_PORT if this one is taken -- the first
|
|
# port chosen was already serving something that had been up for six days.
|
|
PG_PORT ?= 55532
|
|
PG_CONTAINER ?= mesh-controller-check
|
|
PG_IMAGE ?= postgres:17-alpine
|
|
export MESH_TEST_POSTGRES ?= postgres://postgres:check@127.0.0.1:$(PG_PORT)/postgres?sslmode=disable
|
|
|
|
.PHONY: build image check test vet fmt postgres postgres-stop clean
|
|
|
|
build:
|
|
CGO_ENABLED=0 go build -trimpath -ldflags '$(LDFLAGS)' -o build/mesh-controller ./cmd/mesh-controller
|
|
|
|
# Tagged 'development' as well as by version, because the lab places images by name and a
|
|
# scenario naming a version would have to be edited on every build. The version tag is what a
|
|
# real bundle pins.
|
|
IMAGE ?= mesh-controller:$(VERSION)
|
|
DEV_TAG ?= mesh-controller:development
|
|
|
|
# The Go base the image is built on.
|
|
#
|
|
# **`make image` was broken and stayed broken**, because the Dockerfile's fallback base was a Go
|
|
# older than go.mod asks for: every build died at `go mod download` with "go.mod requires go >=
|
|
# 1.26.0", and the pipeline never saw it because the pipeline passes the declared base in. Anybody
|
|
# building the image by hand hit it and had to find the digest themselves (novox/hq 04-ISSUES/146,
|
|
# what it cost).
|
|
#
|
|
# **Pinned here since the manifest stopped building an image** (novox/hq issue 213): the mesh builds
|
|
# the controller as a Go bundle with its own toolchain, and only `make image` — genesis and the lab —
|
|
# still needs a Go base. The digest is the one the manifest declared until then.
|
|
GO_BASE ?= golang@sha256:8ac98ca534ac3f51e1f420a1dd2c15e74c75cfa0f23f3ad27eb5d7236c349a0c
|
|
|
|
image:
|
|
@test -n "$(GO_BASE)" || { echo "no GO_BASE; pass GO_BASE=<image>"; exit 1; }
|
|
docker build --build-arg GO_BASE=$(GO_BASE) --build-arg VERSION=$(VERSION) -t $(IMAGE) -t $(DEV_TAG) .
|
|
@echo
|
|
@docker image inspect $(IMAGE) --format 'built {{.RepoTags}} {{.Size}} bytes'
|
|
|
|
# The builder ships as an image too, because it is a module the mesh assigns rather than a program
|
|
# somebody starts on a machine by hand.
|
|
BUILDER_IMAGE ?= mesh-builder:$(VERSION)
|
|
BUILDER_DEV_TAG ?= mesh-builder:development
|
|
|
|
builder-image:
|
|
@test -n "$(GO_BASE)" || { echo "no GO_BASE; pass GO_BASE=<image>"; exit 1; }
|
|
docker build --build-arg GO_BASE=$(GO_BASE) -f cmd/mesh-builder/Dockerfile -t $(BUILDER_IMAGE) -t $(BUILDER_DEV_TAG) .
|
|
@echo
|
|
@docker image inspect $(BUILDER_IMAGE) --format 'built {{.RepoTags}} {{.Size}} bytes'
|
|
|
|
# The provisioner ships as an image too, because it is the thing that makes a sealed credential
|
|
# true on a machine -- and the mesh cannot, having discarded the plaintext.
|
|
PROVISIONER_IMAGE ?= mesh-provision-postgres:$(VERSION)
|
|
PROVISIONER_DEV_TAG ?= mesh-provision-postgres:development
|
|
|
|
provisioner-image:
|
|
docker build --build-arg GO_BASE=$(GO_BASE) -f examples/postgres-provisioner/Dockerfile \
|
|
-t $(PROVISIONER_IMAGE) -t $(PROVISIONER_DEV_TAG) .
|
|
@echo
|
|
@docker image inspect $(PROVISIONER_IMAGE) --format 'built {{.RepoTags}} {{.Size}} bytes'
|
|
|
|
# The object store's provisioner, for the same reason: a bucket and a policy are not files, and
|
|
# the mesh cannot make them -- it discarded the credential it would have to use.
|
|
OBJECTSTORE_IMAGE ?= mesh-provision-objectstore:$(VERSION)
|
|
OBJECTSTORE_DEV_TAG ?= mesh-provision-objectstore:development
|
|
|
|
objectstore-image:
|
|
docker build --build-arg GO_BASE=$(GO_BASE) -f examples/objectstore-provisioner/Dockerfile \
|
|
-t $(OBJECTSTORE_IMAGE) -t $(OBJECTSTORE_DEV_TAG) .
|
|
@echo
|
|
@docker image inspect $(OBJECTSTORE_IMAGE) --format 'built {{.RepoTags}} {{.Size}} bytes'
|
|
|
|
# The cache's provisioner, for the same reason as the database's: an ACL user is not a file,
|
|
# and the mesh cannot make one -- it discarded the credential it would have to use.
|
|
REDIS_PROVISIONER_IMAGE ?= mesh-provision-redis:$(VERSION)
|
|
REDIS_PROVISIONER_DEV_TAG ?= mesh-provision-redis:development
|
|
|
|
redis-provisioner-image:
|
|
docker build --build-arg GO_BASE=$(GO_BASE) -f examples/redis-provisioner/Dockerfile \
|
|
-t $(REDIS_PROVISIONER_IMAGE) -t $(REDIS_PROVISIONER_DEV_TAG) .
|
|
@echo
|
|
@docker image inspect $(REDIS_PROVISIONER_IMAGE) --format 'built {{.RepoTags}} {{.Size}} bytes'
|
|
|
|
# The proxy that turns a route grant into traffic reaching a workload.
|
|
PROXY_IMAGE ?= mesh-route-proxy:$(VERSION)
|
|
PROXY_DEV_TAG ?= mesh-route-proxy:development
|
|
|
|
proxy-image:
|
|
docker build --build-arg GO_BASE=$(GO_BASE) -f examples/route-proxy/Dockerfile -t $(PROXY_IMAGE) -t $(PROXY_DEV_TAG) .
|
|
@echo
|
|
@docker image inspect $(PROXY_IMAGE) --format 'built {{.RepoTags}} {{.Size}} bytes'
|
|
|
|
# The whole gate. Raises a database, runs everything against it, and takes it down again --
|
|
# including when the tests fail, which is why the teardown is not conditional.
|
|
#
|
|
# **Packages in parallel, under the race detector, each test on a bus of its own** (internal/testbus).
|
|
# It was one package at a time against one shared bus, because the live tests assert, read and remove
|
|
# the mesh's own objects by their fixed names, and two packages at once deleted what the other read; the
|
|
# suite was red run as Go runs it and read as noise. A bus per test, of the release the mesh runs, made
|
|
# it the same in any order. The timeout bounds a hang to a failure with a stack, never a stalled gate.
|
|
check: fmt vet postgres
|
|
@go test -race -timeout 15m ./... ; status=$$? ; $(MAKE) postgres-stop ; exit $$status
|
|
|
|
# Without a database the store's tests skip rather than fail, so this is the honest subset and not
|
|
# the gate.
|
|
test:
|
|
go test -timeout 15m ./...
|
|
|
|
vet:
|
|
go vet ./...
|
|
|
|
fmt:
|
|
@unformatted=$$(gofmt -l . 2>/dev/null) ; \
|
|
if [ -n "$$unformatted" ] ; then echo "not gofmt'd:" ; echo "$$unformatted" ; exit 1 ; fi
|
|
|
|
postgres:
|
|
@docker rm -f $(PG_CONTAINER) >/dev/null 2>&1 || true
|
|
@docker run -d --name $(PG_CONTAINER) -e POSTGRES_PASSWORD=check \
|
|
-p 127.0.0.1:$(PG_PORT):5432 $(PG_IMAGE) >/dev/null
|
|
@printf 'waiting for postgres'
|
|
@for i in $$(seq 1 60) ; do \
|
|
if docker exec $(PG_CONTAINER) pg_isready -U postgres >/dev/null 2>&1 ; then \
|
|
echo ' — ready' ; exit 0 ; fi ; \
|
|
printf '.' ; sleep 1 ; \
|
|
done ; \
|
|
echo ' — never came up' ; docker logs $(PG_CONTAINER) | tail -20 ; exit 1
|
|
|
|
postgres-stop:
|
|
@docker rm -f $(PG_CONTAINER) >/dev/null 2>&1 || true
|
|
|
|
clean:
|
|
rm -rf build/
|