11TOPDIR =$(PWD )
2- GH_ORG_LC =" robertkielty"
2+ GH_ORG_LC =robertkielty
33REGISTRY ?= ghcr.io
44IMAGE ?= $(REGISTRY ) /$(GH_ORG_LC ) /maintainerd:latest
5+ SYNC_IMAGE ?= $(REGISTRY ) /$(GH_ORG_LC ) /maintainerd-sync:latest
56WHOAMI =$(shell whoami)
67
78# Helpful context string for logs
89CTX_STR := $(if $(KUBECONTEXT ) ,$(KUBECONTEXT ) ,$(shell kubectl config current-context 2>/dev/null || echo current) )
910
11+ # kcp release download settings
12+ KCP_VERSION ?= 0.28.3
13+ KCP_TAG ?= v$(KCP_VERSION )
14+ KCP_OS ?= $(shell uname | tr '[:upper:]' '[:lower:]')
15+ KCP_ARCH ?= $(shell uname -m | sed -e 's/x86_64/amd64/' -e 's/aarch64/arm64/')
16+ KCP_TAR ?= kcp_$(KCP_VERSION ) _$(KCP_OS ) _$(KCP_ARCH ) .tar.gz
17+ APIGEN_TAR ?= apigen_$(KCP_VERSION ) _$(KCP_OS ) _$(KCP_ARCH ) .tar.gz
18+ KCP_CHECKSUMS ?= kcp_$(KCP_VERSION ) _checksums.txt
19+ KCP_RELEASE_URL ?= https://github.com/kcp-dev/kcp/releases/download/$(KCP_TAG )
20+ BIN_DIR ?= $(TOPDIR ) /bin
21+ KCP_BIN := $(BIN_DIR ) /kcp
22+ APIGEN_BIN := $(BIN_DIR ) /apigen
23+ CONTROLLER_GEN ?= $(BIN_DIR ) /controller-gen
24+ APIGEN ?= $(APIGEN_BIN )
25+ GOCACHE_DIR ?= $(TOPDIR ) /.gocache
26+ KCP_CRD_DIR ?= $(TOPDIR ) /config/crd/bases
27+ KCP_SCHEMA_DIR ?= $(TOPDIR ) /config/kcp
28+ KCP_RESOURCES := $(shell ls $(KCP_CRD_DIR ) /maintainer-d.cncf.io_* .yaml 2>/dev/null | sed -E 's@.* /maintainer-d\.cncf\.io_([^.]* ) \.yaml@\1@')
29+ GOFMT_PATHS ?= $(shell go list -f '{{.Dir}}' ./...)
30+
1031# GHCR auth (optional for push). If set, we will docker login before push.
1132GHCR_USER ?= $(DOCKER_REGISTRY_USERNAME )
1233GHCR_TOKEN ?= $(GITHUB_GHCR_TOKEN )
1334
1435
1536
1637# ---- Image ----
17- .PHONY : image
18- image :
38+ .PHONY : image-build
39+ image-build :
1940 @echo " Building container image: $( IMAGE) "
2041 @docker buildx build -t $(IMAGE ) -f Dockerfile .
42+
43+ .PHONY : sync-image-build
44+ sync-image-build :
45+ @echo " Building sync image: $( SYNC_IMAGE) "
46+ @docker buildx build -t $(SYNC_IMAGE ) -f deploy/sync/Dockerfile .
47+
48+ .PHONY : image-push
49+ image-push : image-build
2150 @echo " Ensuring docker is logged in to $( REGISTRY) (uses GHCR_TOKEN if set)"
2251 @if [ -n " $( GHCR_TOKEN) " ]; then \
2352 echo " Logging into $( REGISTRY) as $( GHCR_USER) using token from GHCR_TOKEN" ; \
2756 fi
2857 @echo " Pushing image: $( IMAGE) "
2958 @docker push $(IMAGE )
59+
60+ .PHONY : image-deploy
61+ image-deploy : image-push
3062 @echo " Image pushed. Attempting rollout on context $( CTX_STR) ."
3163 @CTX_FLAG=" $( if $( KUBECONTEXT) ,--context $( KUBECONTEXT) ) " ; \
3264 if kubectl $$ CTX_FLAG config current-context > /dev/null 2>&1 ; then \
@@ -40,8 +72,41 @@ image:
4072 echo " kubectl context $( CTX_STR) unavailable; skipping rollout" ; \
4173 fi
4274
43- .PHONY : image-push
44- image-push : image
75+ .PHONY : sync-image-push
76+ sync-image-push : sync-image-build
77+ @echo " Ensuring docker is logged in to $( REGISTRY) (uses GHCR_TOKEN if set)"
78+ @if [ -n " $( GHCR_TOKEN) " ]; then \
79+ echo " Logging into $( REGISTRY) as $( GHCR_USER) using token from GHCR_TOKEN" ; \
80+ echo " $( GHCR_TOKEN) " | docker login $(REGISTRY ) -u " $( GHCR_USER) " --password-stdin; \
81+ else \
82+ echo " GHCR_TOKEN not set; attempting push with existing docker auth" ; \
83+ fi
84+ @echo " Pushing image: $( SYNC_IMAGE) "
85+ @docker push $(SYNC_IMAGE )
86+
87+ .PHONY : sync-image-deploy
88+ sync-image-deploy : sync-image-push
89+ @echo " Image pushed. Updating CronJob/maintainer-sync in $( NAMESPACE) [ctx=$( CTX_STR) ]"
90+ @CTX_FLAG=" $( if $( KUBECONTEXT) ,--context $( KUBECONTEXT) ) " ; \
91+ if ! kubectl $$ CTX_FLAG config current-context > /dev/null 2>&1 ; then \
92+ echo " kubectl context $( CTX_STR) unavailable; skipping rollout" ; exit 0; \
93+ fi ; \
94+ if ! kubectl -n $( NAMESPACE) $$ CTX_FLAG get cronjob/maintainer-sync > /dev/null 2>&1 ; then \
95+ echo " CronJob/maintainer-sync not found in namespace $( NAMESPACE) ." ; \
96+ echo " Hint: apply deploy/manifests/sync.yaml or run 'make sync-apply' (or 'make manifests-apply')." ; \
97+ exit 1; \
98+ fi ; \
99+ kubectl -n $(NAMESPACE ) $$ CTX_FLAG set image cronjob/maintainer-sync ' *=$(SYNC_IMAGE)' ; \
100+ kubectl -n $(NAMESPACE ) $$ CTX_FLAG delete job -l job-name=maintainer-sync --ignore-not-found; \
101+ echo " Next scheduled run will pull $( SYNC_IMAGE) ."
102+
103+ .PHONY : sync-apply
104+ sync-apply :
105+ @echo " Applying sync resources in namespace $( NAMESPACE) [ctx=$( CTX_STR) ]"
106+ @kubectl -n $(NAMESPACE ) $(if $(KUBECONTEXT ) ,--context $(KUBECONTEXT ) ) apply -f deploy/manifests/sync.yaml
107+
108+ .PHONY : image
109+ image : image-build
45110 @true
46111
47112.PHONY : image-run
@@ -52,7 +117,7 @@ image-run: image
52117NAMESPACE ?= maintainerd
53118ENVSRC ?= .envrc
54119ENVOUT ?= bootstrap.env
55- KUBECONTEXT ?=context-cdv2c4jfn5q
120+ KUBECONTEXT ?=
56121
57122
58123# Secret names (keep these stable across clusters)
87152 @echo " make apply-creds -> create/update $( CREDS_SECRET_NAME) from $( CREDS_FILE) "
88153 @echo " make clean-env -> remove $( ENVOUT) "
89154 @echo " make print -> show which keys would be loaded (without values)"
90- @echo " make image -> build+push $( IMAGE) , then restart Deployment in $( NAMESPACE) "
91- @echo " (uses GHCR_TOKEN/GITHUB_GHCR_TOKEN + GHCR_USER/DOCKER_REGISTRY_USERNAME for ghcr login)"
155+ @echo " make image-build -> build container image $( IMAGE) locally"
156+ @echo " make image-push -> build and push $( IMAGE) (uses GHCR_TOKEN/GITHUB_GHCR_TOKEN + GHCR_USER/DOCKER_REGISTRY_USERNAME for ghcr login)"
157+ @echo " make image-deploy -> build, push, and restart Deployment in $( NAMESPACE) "
92158 @echo " make ensure-ns -> ensure namespace $( NAMESPACE) exists"
93159 @echo " make apply-ghcr-secret -> create/update docker-registry Secret 'ghcr-secret'"
94160 @echo " make manifests-apply -> kubectl apply -f deploy/manifests (prod-only)"
99165 @echo " make maintainerd-drain -> scale Deployment/maintainerd to 0 and wait for pods to exit"
100166 @echo " make maintainerd-port-forward -> forward :2525 -> svc/maintainerd:2525"
101167 @echo " make cluster-down -> delete manifests applied via deploy/manifests"
168+ @echo " make kcp-install -> download kcp $( KCP_VERSION) binaries into $( BIN_DIR) "
102169
103170# Convert .envrc (export FOO=bar) to KEY=VALUE lines
104171# - drops comments/blank lines
@@ -208,6 +275,47 @@ maintainerd-port-forward:
208275 @echo " Port-forwarding localhost:2525 -> service/maintainerd:2525 [ctx=$( CTX_STR) ]"
209276 @kubectl -n $(NAMESPACE ) $(if $(KUBECONTEXT ) ,--context $(KUBECONTEXT ) ) port-forward svc/maintainerd 2525:2525
210277
278+ .PHONY : kcp-install
279+ kcp-install :
280+ @mkdir -p $(BIN_DIR )
281+ @echo " Fetching kcp $( KCP_VERSION) for $( KCP_OS) /$( KCP_ARCH) "
282+ @TMP_DIR=$$(mktemp -d ) ; \
283+ set -euo pipefail; \
284+ echo " + curl -sSL $( KCP_RELEASE_URL) /$( KCP_CHECKSUMS) " ; \
285+ curl -sSL -o $$ TMP_DIR/$(KCP_CHECKSUMS ) $(KCP_RELEASE_URL ) /$(KCP_CHECKSUMS ) ; \
286+ for tarball in $( KCP_TAR) $( APIGEN_TAR) ; do \
287+ echo " + curl -sSL $( KCP_RELEASE_URL) /$$ tarball -o $$ TMP_DIR/$$ tarball" ; \
288+ curl -sSL -o $$ TMP_DIR/$$ tarball $(KCP_RELEASE_URL ) /$$ tarball; \
289+ grep " $$ tarball$$ " $$ TMP_DIR/$(KCP_CHECKSUMS ) > $$ TMP_DIR/$$ tarball.sha256; \
290+ SUM=$$(cut -d' ' -f1 $$TMP_DIR/$$tarball.sha256 ) ; \
291+ ( cd $$ TMP_DIR && sha256sum --check $$ tarball.sha256 ); \
292+ echo " Verified $$ tarball (sha256=$$ SUM)" ; \
293+ done ; \
294+ tar -xzf $$ TMP_DIR/$(KCP_TAR ) -C $(BIN_DIR ) --strip-components=1 bin/kcp; \
295+ tar -xzf $$ TMP_DIR/$(APIGEN_TAR ) -C $(BIN_DIR ) --strip-components=1 bin/apigen; \
296+ chmod +x $(KCP_BIN ) $(APIGEN_BIN ) ; \
297+ rm -rf $$ TMP_DIR; \
298+ echo " Installed kcp and apigen into $( BIN_DIR) "
299+
300+ .PHONY : kcp-generate
301+ kcp-generate :
302+ @[ -x " $( CONTROLLER_GEN) " ] || { echo " Missing controller-gen binary at $( CONTROLLER_GEN) . Install it or set CONTROLLER_GEN to the binary path." ; exit 1; }
303+ @[ -x " $( APIGEN) " ] || { echo " Missing apigen binary at $( APIGEN) . Run 'make kcp-install' or download it manually." ; exit 1; }
304+ @mkdir -p $(GOCACHE_DIR ) $(KCP_CRD_DIR ) $(KCP_SCHEMA_DIR )
305+ @echo " Generating CustomResourceDefinitions in $( KCP_CRD_DIR) "
306+ @GOCACHE=$(GOCACHE_DIR ) $(CONTROLLER_GEN ) crd paths=./apis/... output:crd:dir=$(KCP_CRD_DIR )
307+ @rm -f $(KCP_CRD_DIR ) /_.yaml
308+ @TMP_DIR=$$(mktemp -d ) ; \
309+ set -euo pipefail; \
310+ echo " Rendering APIResourceSchemas with apigen" ; \
311+ $(APIGEN ) --input-dir $(KCP_CRD_DIR ) --output-dir $$ TMP_DIR; \
312+ for resource in $( KCP_RESOURCES) ; do \
313+ cp $$ TMP_DIR/apiresourceschema-$$ resource.maintainer-d.cncf.io.yaml $(KCP_SCHEMA_DIR ) /schema-$$ resource.yaml; \
314+ done ; \
315+ cp $$ TMP_DIR/apiexport-maintainer-d.cncf.io.yaml $(KCP_SCHEMA_DIR ) /api-export.yaml; \
316+ rm -rf $$ TMP_DIR; \
317+ echo " Updated APIExport and APIResourceSchemas in $( KCP_SCHEMA_DIR) "
318+
211319# ---- Testing and CI ----
212320.PHONY : test
213321test :
@@ -247,25 +355,20 @@ ci-local:
247355 @echo " → Verifying dependencies..."
248356 @go mod verify
249357 @echo " → Running go fmt..."
250- @if [ " $$ (gofmt -s -l . | wc -l)" -gt 0 ]; then \
251- echo " ❌ Code needs formatting. Run: go fmt ./..." ; \
252- gofmt -s -l . ; \
358+ @GOFILES=" $$ (find . -path './.modcache' -prune -o -path './.gocache' -prune -o -path './.git' -prune -o -name '*.go' -print)" ; \
359+ if [ " $$ (gofmt -s -l $$ GOFILES | wc -l)" -gt 0 ]; then \
360+ echo " ❌ Code needs formatting. Run: gofmt -w $$ (echo $$ GOFILES)" ; \
361+ gofmt -s -l $$ GOFILES; \
253362 exit 1; \
254363 fi
255364 @echo " → Running go vet..."
256- @go vet ./...
365+ @go vet # ./...
257366 @echo " → Running staticcheck..."
258- @if command -v staticcheck > /dev/null 2>&1 ; then \
259- staticcheck ./...; \
260- else \
261- echo " ⚠️ staticcheck not installed. Run: go install honnef.co/go/tools/cmd/staticcheck@latest" ; \
262- fi
367+ @command -v staticcheck > /dev/null 2>&1 || { echo " staticcheck not installed. Run: go install honnef.co/go/tools/cmd/staticcheck@latest" ; exit 1; }
368+ @staticcheck # ./...
263369 @echo " → Running golangci-lint..."
264- @if command -v golangci-lint > /dev/null 2>&1 ; then \
265- golangci-lint run ./...; \
266- else \
267- echo " ⚠️ golangci-lint not installed. Run: go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest" ; \
268- fi
370+ @command -v golangci-lint > /dev/null 2>&1 || { echo " golangci-lint not installed. Run: go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest" ; exit 1; }
371+ @golangci-lint run ./...
269372 @echo " → Running tests with race detector..."
270373 @go test -race -coverprofile=coverage.out -covermode=atomic ./...
271374 @echo " → Coverage report:"
0 commit comments