It was broken and stayed broken: the Dockerfile's fallback base is a Go older than go.mod asks for, so every hand build died at 'go mod download' with 'go.mod requires go >= 1.26.0'. The pipeline never saw it because the pipeline passes the declared base in, so the cost fell entirely on whoever built the image themselves and had to find the digest by hand (novox/hq 04-ISSUES/146). Read from module.json rather than written here as well, so the two cannot disagree, and refused outright if the manifest declares none.
138 lines
6.5 KiB
Makefile
138 lines
6.5 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 base the module declares, read from the manifest rather than written here twice.
|
|
#
|
|
# **`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).
|
|
GO_BASE ?= $(shell python3 -c "import json;print(next(o['image'] for o in json.load(open('module.json'))['build']['on'] if o['arg']=='GO_BASE'))" 2>/dev/null)
|
|
|
|
image:
|
|
@test -n "$(GO_BASE)" || { echo "module.json declares no GO_BASE; pass GO_BASE=<image> or fix the manifest"; 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 "module.json declares no GO_BASE; pass GO_BASE=<image> or fix the manifest"; 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 -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 -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 -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 -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.
|
|
#
|
|
# **One package at a time (-p 1), and it is not about speed.** The live tests reach one bus, and on
|
|
# it they assert, read and remove the mesh's own objects -- streams and consumers with fixed names,
|
|
# because those names are the mesh's and a test cannot choose others. Two packages doing that at once
|
|
# is one deleting a consumer the other is reading through, and the failure lands in whichever test
|
|
# was reading, as "no response from stream". That reads as a bug in the code under test.
|
|
check: fmt vet postgres
|
|
@go test -p 1 ./... ; status=$$? ; $(MAKE) postgres-stop ; exit $$status
|
|
|
|
# Without a database the live tests skip rather than fail, so this is the honest subset and not
|
|
# the gate. Serialised for the same reason check is: a bus may be configured even when a store is not.
|
|
test:
|
|
go test -p 1 ./...
|
|
|
|
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/
|