Repository navigation
Expand file tree
/
Copy pathMakefile
More file actions
506 lines (458 loc) · 20.9 KB
/
Copy pathMakefile
File metadata and controls
506 lines (458 loc) · 20.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
.DEFAULT_GOAL := help
# CGO_ENABLED=0 is not FIPS compliant. large commercial vendors and FedRAMP require FIPS compliant crypto
# Use ?= so callers can override on the command line, e.g. CGO_ENABLED=0 make build for a non-FIPS static binary
CGO_ENABLED ?= 1
GOEXPERIMENT ?= boringcrypto
GOFIPS140 ?= off
GO ?= go
TOOL_MOD := tools/go.mod
gotool = "$(GO)" tool -modfile="$(TOOL_MOD)" $(1)
GOFMT ?= gofmt
# Keep promtool out of tools/go.mod: it pulls Prometheus' large server dependency graph.
PROMTOOL := github.com/prometheus/prometheus@v0.304.2
# Binary output directory and name
BIN_DIR := bin
BINARY_NAME := $(BIN_DIR)/hyperfleet-adapter
# Version information
BUILD_DATE ?= $(shell date -u +"%Y-%m-%dT%H:%M:%SZ")
GIT_SHA ?= $(shell git rev-parse --short HEAD 2>/dev/null || echo "unknown")
GIT_DIRTY ?= $(shell [ -z "$$(git status --porcelain 2>/dev/null)" ] || echo "-modified")
APP_VERSION ?= $(shell git describe --tags --always --dirty 2>/dev/null || echo "0.0.0-dev")
# Go build flags
GOFLAGS ?= -trimpath
VERSION_PKG := github.com/openshift-hyperfleet/hyperfleet-adapter/pkg/version
LDFLAGS := -s -w \
-X $(VERSION_PKG).Version=$(APP_VERSION) \
-X $(VERSION_PKG).Commit=$(GIT_SHA) \
-X $(VERSION_PKG).BuildDate=$(BUILD_DATE)
# Container tool (docker or podman)
CONTAINER_TOOL ?= $(shell command -v podman 2>/dev/null || command -v docker 2>/dev/null)
# Container build configuration
PLATFORM ?= linux/amd64
DEV_BASE_IMAGE ?= registry.access.redhat.com/ubi9/ubi-minimal:latest
# =============================================================================
# Image Configuration
# =============================================================================
IMAGE_REGISTRY ?= quay.io/openshift-hyperfleet
IMAGE_NAME ?= hyperfleet-adapter
IMAGE_TAG ?= $(APP_VERSION)
# Dev image configuration - set QUAY_USER to push to personal registry
# Usage: QUAY_USER=myuser make image-dev
QUAY_USER ?=
DEV_TAG ?= dev-$(GIT_SHA)
# Test parameters
TEST_TIMEOUT := 30m
.PHONY: help
help: ## Display this help
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z0-9_-]+:.*?##/ { printf " \033[36m%-22s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)
##@ Development
.PHONY: build
build: ## Build the adapter binary
@mkdir -p $(BIN_DIR)
CGO_ENABLED=$(CGO_ENABLED) GOEXPERIMENT=$(GOEXPERIMENT) GOFIPS140=$(GOFIPS140) $(GO) build $(GOFLAGS) -ldflags "$(LDFLAGS)" -o $(BINARY_NAME) ./cmd/adapter
.PHONY: install
install: build ## Build and install binary to GOPATH/bin
CGO_ENABLED=$(CGO_ENABLED) GOEXPERIMENT=$(GOEXPERIMENT) GOFIPS140=$(GOFIPS140) $(GO) install $(GOFLAGS) -ldflags "$(LDFLAGS)" ./cmd/adapter
.PHONY: clean
clean: ## Remove build artifacts
rm -rf $(BIN_DIR)
rm -f coverage.out coverage.html
##@ Testing
.PHONY: test
test: test-alerts ## Run unit tests with race detection
$(GO) test -v -race -coverprofile=coverage.out -timeout $(TEST_TIMEOUT) \
$$($(GO) list ./... | grep -v /test/)
.PHONY: promtool
promtool: ## Build the pinned promtool binary
@mkdir -p $(BIN_DIR)
$(GO) mod download $(PROMTOOL)
cd "$$($(GO) env GOMODCACHE)/$(PROMTOOL)" && \
$(GO) build -o "$(CURDIR)/$(BIN_DIR)/promtool" ./cmd/promtool
.PHONY: test-alerts
test-alerts: promtool ## Test Prometheus alert rules
$(BIN_DIR)/promtool test rules test/alerts/*_test.yaml
.PHONY: test-coverage
test-coverage: test ## Run tests and show coverage
$(GO) tool cover -html=coverage.out
.PHONY: test-integration
test-integration: ## Run integration tests (requires Docker/Podman)
@TEST_TIMEOUT=$(TEST_TIMEOUT) bash scripts/run-integration-tests.sh
.PHONY: image-integration-test
image-integration-test: ## Build integration test image with envtest
@bash scripts/build-integration-image.sh
.PHONY: test-all
test-all: lint test test-alerts test-integration test-helm ## Run all checks (lint, unit, alerts, integration, helm)
##@ Helm Charts
.PHONY: helm-docs
helm-docs: ## Generate Helm chart README from values.yaml annotations
$(call gotool,helm-docs) --chart-search-root=charts --sort-values-order=file
.PHONY: verify-helm-docs
verify-helm-docs: ## Verify chart README is up to date
$(call gotool,helm-docs) --chart-search-root=charts --sort-values-order=file
@git diff --exit-code charts/README.md > /dev/null 2>&1 || \
(echo "ERROR: charts/README.md is out of date. Run 'make helm-docs' and commit the result." && exit 1)
# kubeconform flags for validating rendered Helm templates against Kubernetes
# and CRD schemas. Uses the datreeio/CRDs-catalog for ServiceMonitor schemas.
KUBECONFORM_FLAGS := \
-strict \
-kubernetes-version 1.30.0 \
-schema-location default \
-schema-location 'https://raw.githubusercontent.com/datreeio/CRDs-catalog/main/{{.Group}}/{{.ResourceKind}}_{{.ResourceAPIVersion}}.json'
.PHONY: test-helm
test-helm: verify-helm-docs ## Test Helm charts (lint, template, validate, kubeconform)
@if ! command -v helm > /dev/null; then \
echo "ERROR: helm not found. Please install Helm:"; \
echo " brew install helm # macOS"; \
echo " curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash # Linux"; \
exit 1; \
fi
@echo "Linting Helm chart..."
helm lint charts/ \
--set image.registry=quay.io \
--set image.repository=openshift-hyperfleet/hyperfleet-adapter \
--set image.tag=test
@echo ""
@echo "Testing template rendering with minimal required values..."
helm template test-release charts/ \
--set image.registry=quay.io \
--set image.repository=openshift-hyperfleet/hyperfleet-adapter \
--set image.tag=test \
--set adapterConfig.yaml="apiVersion: hyperfleet.redhat.com/v1alpha1" \
--set adapterTaskConfig.yaml="apiVersion: hyperfleet.redhat.com/v1alpha1" \
--set broker.type=googlepubsub \
--set broker.googlepubsub.subscriptionId=test-sub \
--set broker.googlepubsub.topic=test-topic | $(call gotool,kubeconform) $(KUBECONFORM_FLAGS)
@echo "Minimal required values template OK"
@echo ""
@echo "Testing template with broker enabled..."
@output=$$(helm template test-release charts/ \
--set image.registry=quay.io \
--set image.repository=openshift-hyperfleet/hyperfleet-adapter \
--set image.tag=test \
--set adapterConfig.yaml="apiVersion: hyperfleet.redhat.com/v1alpha1" \
--set adapterTaskConfig.yaml="apiVersion: hyperfleet.redhat.com/v1alpha1" \
--set broker.create=true \
--set broker.googlepubsub.subscriptionId=test-sub \
--set broker.googlepubsub.topic=test-topic \
--set broker.googlepubsub.expirationTTL=1d \
--set broker.googlepubsub.messageRetentionDuration=12h \
--set broker.type=googlepubsub) \
&& echo "$$output" | grep -q 'type: googlepubsub' \
|| { echo "ERROR: expected googlepubsub broker type in rendered output"; exit 1; }; \
echo "$$output" | $(call gotool,kubeconform) $(KUBECONFORM_FLAGS)
@echo "Broker config template OK"
@echo ""
@echo "Testing template with HyperFleet API config..."
helm template test-release charts/ \
--set image.registry=quay.io \
--set image.repository=openshift-hyperfleet/hyperfleet-adapter \
--set image.tag=test \
--set adapterConfig.yaml="apiVersion: hyperfleet.redhat.com/v1alpha1" \
--set adapterTaskConfig.yaml="apiVersion: hyperfleet.redhat.com/v1alpha1" \
--set broker.type=googlepubsub \
--set broker.googlepubsub.subscriptionId=test-sub \
--set broker.googlepubsub.topic=test-topic \
--set adapterConfig.hyperfleetApi.baseUrl=http://localhost:8000 \
--set adapterConfig.hyperfleetApi.version=v1 | $(call gotool,kubeconform) $(KUBECONFORM_FLAGS)
@echo "HyperFleet API config template OK"
@echo ""
@echo "Testing template with PDB enabled..."
helm template test-release charts/ \
--set image.registry=quay.io \
--set image.repository=openshift-hyperfleet/hyperfleet-adapter \
--set image.tag=test \
--set adapterConfig.yaml="apiVersion: hyperfleet.redhat.com/v1alpha1" \
--set adapterTaskConfig.yaml="apiVersion: hyperfleet.redhat.com/v1alpha1" \
--set broker.type=googlepubsub \
--set broker.googlepubsub.subscriptionId=test-sub \
--set broker.googlepubsub.topic=test-topic \
--set podDisruptionBudget.enabled=true \
--set podDisruptionBudget.minAvailable=1 \
--set podDisruptionBudget.maxUnavailable=null | $(call gotool,kubeconform) $(KUBECONFORM_FLAGS)
@echo "PDB config template OK"
@echo ""
@echo "Testing template with autoscaling..."
helm template test-release charts/ \
--set image.registry=quay.io \
--set image.repository=openshift-hyperfleet/hyperfleet-adapter \
--set image.tag=test \
--set adapterConfig.yaml="apiVersion: hyperfleet.redhat.com/v1alpha1" \
--set adapterTaskConfig.yaml="apiVersion: hyperfleet.redhat.com/v1alpha1" \
--set broker.type=googlepubsub \
--set broker.googlepubsub.subscriptionId=test-sub \
--set broker.googlepubsub.topic=test-topic \
--set autoscaling.enabled=true \
--set autoscaling.minReplicas=2 \
--set autoscaling.maxReplicas=5 | $(call gotool,kubeconform) $(KUBECONFORM_FLAGS)
@echo "Autoscaling config template OK"
@echo ""
@echo "Testing template with probes enabled..."
helm template test-release charts/ \
--set image.registry=quay.io \
--set image.repository=openshift-hyperfleet/hyperfleet-adapter \
--set image.tag=test \
--set adapterConfig.yaml="apiVersion: hyperfleet.redhat.com/v1alpha1" \
--set adapterTaskConfig.yaml="apiVersion: hyperfleet.redhat.com/v1alpha1" \
--set broker.type=googlepubsub \
--set broker.googlepubsub.subscriptionId=test-sub \
--set broker.googlepubsub.topic=test-topic \
--set livenessProbe.enabled=true \
--set readinessProbe.enabled=true \
--set startupProbe.enabled=true | $(call gotool,kubeconform) $(KUBECONFORM_FLAGS)
@echo "Probes config template OK"
@echo ""
@echo "Testing template with ServiceMonitor enabled..."
@output=$$(helm template test-release charts/ \
--set image.registry=quay.io \
--set image.repository=openshift-hyperfleet/hyperfleet-adapter \
--set image.tag=test \
--set adapterConfig.yaml="apiVersion: hyperfleet.redhat.com/v1alpha1" \
--set adapterTaskConfig.yaml="apiVersion: hyperfleet.redhat.com/v1alpha1" \
--set broker.type=googlepubsub \
--set broker.googlepubsub.subscriptionId=test-sub \
--set broker.googlepubsub.topic=test-topic \
--set monitoring.serviceMonitor.enabled=true \
--api-versions monitoring.coreos.com/v1/ServiceMonitor) \
&& echo "$$output" | grep -q 'kind: ServiceMonitor' \
|| { echo "ERROR: ServiceMonitor not rendered"; exit 1; }; \
echo "$$output" | $(call gotool,kubeconform) $(KUBECONFORM_FLAGS)
@echo "ServiceMonitor enabled template OK"
@echo ""
@echo "Testing template with ServiceMonitor enabled but CRD unavailable..."
@output=$$(helm template test-release charts/ \
--set image.registry=quay.io \
--set image.repository=openshift-hyperfleet/hyperfleet-adapter \
--set image.tag=test \
--set adapterConfig.yaml="apiVersion: hyperfleet.redhat.com/v1alpha1" \
--set adapterTaskConfig.yaml="apiVersion: hyperfleet.redhat.com/v1alpha1" \
--set broker.type=googlepubsub \
--set broker.googlepubsub.subscriptionId=test-sub \
--set broker.googlepubsub.topic=test-topic \
--set monitoring.serviceMonitor.enabled=true) \
&& ! echo "$$output" | grep -q 'kind: ServiceMonitor' \
|| { echo "ERROR: ServiceMonitor rendered without CRD"; exit 1; }; \
echo "$$output" | $(call gotool,kubeconform) $(KUBECONFORM_FLAGS)
@echo "ServiceMonitor CRD-missing template OK"
@echo ""
@echo "Testing template with ServiceMonitor disabled..."
@output=$$(helm template test-release charts/ \
--set image.registry=quay.io \
--set image.repository=openshift-hyperfleet/hyperfleet-adapter \
--set image.tag=test \
--set adapterConfig.yaml="apiVersion: hyperfleet.redhat.com/v1alpha1" \
--set adapterTaskConfig.yaml="apiVersion: hyperfleet.redhat.com/v1alpha1" \
--set broker.type=googlepubsub \
--set broker.googlepubsub.subscriptionId=test-sub \
--set broker.googlepubsub.topic=test-topic \
--set monitoring.serviceMonitor.enabled=false \
--api-versions monitoring.coreos.com/v1/ServiceMonitor) \
&& ! echo "$$output" | grep -q 'kind: ServiceMonitor' \
|| { echo "ERROR: ServiceMonitor rendered while disabled"; exit 1; }; \
echo "$$output" | $(call gotool,kubeconform) $(KUBECONFORM_FLAGS)
@echo "ServiceMonitor disabled template OK"
@echo ""
@echo "Testing template with RabbitMQ broker..."
@output=$$(helm template test-release charts/ \
--set image.registry=quay.io \
--set image.repository=openshift-hyperfleet/hyperfleet-adapter \
--set image.tag=test \
--set adapterConfig.yaml="apiVersion: hyperfleet.redhat.com/v1alpha1" \
--set adapterTaskConfig.yaml="apiVersion: hyperfleet.redhat.com/v1alpha1" \
--set broker.create=true \
--set broker.type=rabbitmq \
--set broker.rabbitmq.url=amqp://guest:guest@rabbitmq:5672/ \
--set broker.rabbitmq.exchange=test-exchange) \
&& echo "$$output" | grep -q 'type: rabbitmq' \
|| { echo "ERROR: expected rabbitmq broker type in rendered output"; exit 1; }; \
echo "$$output" | $(call gotool,kubeconform) $(KUBECONFORM_FLAGS)
@echo "RabbitMQ broker template OK"
@echo ""
@echo "Testing that rabbitmq broker.type with both sections set selects rabbitmq..."
@output=$$(helm template test-release charts/ \
--set image.registry=quay.io \
--set image.repository=openshift-hyperfleet/hyperfleet-adapter \
--set image.tag=test \
--set adapterConfig.yaml="apiVersion: hyperfleet.redhat.com/v1alpha1" \
--set adapterTaskConfig.yaml="apiVersion: hyperfleet.redhat.com/v1alpha1" \
--set broker.create=true \
--set broker.type=rabbitmq \
--set broker.rabbitmq.url=amqp://guest:guest@rabbitmq:5672/ \
--set broker.rabbitmq.exchange=test-exchange \
--set broker.googlepubsub.projectId=my-project \
--set broker.googlepubsub.topic=my-topic \
--set broker.googlepubsub.subscriptionId=my-sub) \
&& echo "$$output" | grep -q 'type: rabbitmq' \
|| { echo "ERROR: expected rabbitmq broker type in output"; exit 1; }; \
echo "$$output" | $(call gotool,kubeconform) $(KUBECONFORM_FLAGS)
@echo "RabbitMQ broker type selection OK"
@echo ""
@echo "Testing that rabbitmq renders OK without queue (queue is optional)..."
@helm template test-release charts/ \
--set image.registry=quay.io \
--set image.repository=openshift-hyperfleet/hyperfleet-adapter \
--set image.tag=test \
--set adapterConfig.yaml="apiVersion: hyperfleet.redhat.com/v1alpha1" \
--set adapterTaskConfig.yaml="apiVersion: hyperfleet.redhat.com/v1alpha1" \
--set broker.create=true \
--set broker.type=rabbitmq \
--set broker.rabbitmq.url=amqp://guest:guest@rabbitmq:5672/ \
--set broker.rabbitmq.exchange=test-exchange > /dev/null \
|| { echo "ERROR: helm template failed when broker.rabbitmq.queue is omitted (queue should be optional)"; exit 1; }
@echo "RabbitMQ optional queue validation OK"
@echo ""
@echo "Testing that rabbitmq without exchange fails validation..."
@if helm template test-release charts/ \
--set image.registry=quay.io \
--set image.repository=openshift-hyperfleet/hyperfleet-adapter \
--set image.tag=test \
--set adapterConfig.yaml="apiVersion: hyperfleet.redhat.com/v1alpha1" \
--set adapterTaskConfig.yaml="apiVersion: hyperfleet.redhat.com/v1alpha1" \
--set broker.create=true \
--set broker.type=rabbitmq \
--set broker.rabbitmq.url=amqp://guest:guest@rabbitmq:5672/ \
--set broker.rabbitmq.queue=test-queue > /dev/null 2>&1; then \
echo "ERROR: expected helm template to fail when broker.rabbitmq.exchange is missing"; exit 1; \
fi
@echo "RabbitMQ missing exchange validation OK"
@echo ""
@echo "Testing Pub/Sub messageRetentionDuration=31d (max) is accepted..."
@helm template test-release charts/ \
--set image.registry=quay.io \
--set image.repository=openshift-hyperfleet/hyperfleet-adapter \
--set image.tag=test \
--set adapterConfig.yaml="apiVersion: hyperfleet.redhat.com/v1alpha1" \
--set adapterTaskConfig.yaml="apiVersion: hyperfleet.redhat.com/v1alpha1" \
--set broker.type=googlepubsub \
--set broker.googlepubsub.subscriptionId=test-sub \
--set broker.googlepubsub.topic=test-topic \
--set broker.googlepubsub.messageRetentionDuration=31d > /dev/null \
|| { echo "ERROR: helm template failed for messageRetentionDuration=31d"; exit 1; }
@echo "Pub/Sub 31d retention validation OK"
@echo ""
@echo "Testing Pub/Sub expirationTTL=86400s (1d) is accepted..."
@helm template test-release charts/ \
--set image.registry=quay.io \
--set image.repository=openshift-hyperfleet/hyperfleet-adapter \
--set image.tag=test \
--set adapterConfig.yaml="apiVersion: hyperfleet.redhat.com/v1alpha1" \
--set adapterTaskConfig.yaml="apiVersion: hyperfleet.redhat.com/v1alpha1" \
--set broker.type=googlepubsub \
--set broker.googlepubsub.subscriptionId=test-sub \
--set broker.googlepubsub.topic=test-topic \
--set broker.googlepubsub.expirationTTL=86400s > /dev/null \
|| { echo "ERROR: helm template failed for expirationTTL=86400s"; exit 1; }
@echo "Pub/Sub 86400s TTL validation OK"
@echo ""
@echo "Testing Pub/Sub numeric-zero messageRetentionDuration is rejected..."
@if helm template test-release charts/ \
--set image.registry=quay.io \
--set image.repository=openshift-hyperfleet/hyperfleet-adapter \
--set image.tag=test \
--set adapterConfig.yaml="apiVersion: hyperfleet.redhat.com/v1alpha1" \
--set adapterTaskConfig.yaml="apiVersion: hyperfleet.redhat.com/v1alpha1" \
--set broker.type=googlepubsub \
--set broker.googlepubsub.subscriptionId=test-sub \
--set broker.googlepubsub.topic=test-topic \
--set broker.googlepubsub.messageRetentionDuration=0 > /dev/null 2>&1; then \
echo "ERROR: expected helm template to fail when messageRetentionDuration=0"; exit 1; \
fi
@echo "Pub/Sub zero retention validation OK"
@for values in charts/examples/*/values.yaml; do \
echo "Rendering $$values example overlay..."; \
output=$$(helm template example charts/ -f "$$values" \
--set image.registry=quay.io \
--set image.repository=openshift-hyperfleet/hyperfleet-adapter \
--set image.tag=test) || exit 1; \
echo "$$output" | $(call gotool,kubeconform) $(KUBECONFORM_FLAGS) || exit 1; \
done
##@ Code Quality
.PHONY: install-hooks
install-hooks: ## Install pre-commit hooks
pre-commit install
.PHONY: fmt
fmt: ## Format code with goimports
$(call gotool,goimports) -w .
.PHONY: gofmt
gofmt: fmt ## Alias for fmt
.PHONY: fmt-check
fmt-check: ## Check if code is formatted
@diff=$$($(GOFMT) -s -d .); \
if [ -n "$$diff" ]; then \
echo "Code is not formatted. Run 'make fmt' to fix:"; \
echo "$$diff"; \
exit 1; \
fi
.PHONY: vet
vet: ## Run go vet
$(GO) vet ./...
.PHONY: go-vet
go-vet: vet ## Alias for vet
.PHONY: lint
lint: ## Run golangci-lint
$(call gotool,golangci-lint) run ./...
.PHONY: tools
tools: ## Ensure tool dependencies are up to date
cd tools && "$(GO)" mod tidy
.PHONY: verify-tools
verify-tools: tools ## Fail if tool module drifted
@git diff --exit-code HEAD -- tools/go.mod tools/go.sum || (echo "tool modules out of date; run 'make tools'" && exit 1)
.PHONY: verify
verify: fmt-check vet ## Run all verification checks
##@ Dependencies
.PHONY: tidy
tidy: ## Tidy go.mod
$(GO) mod tidy
.PHONY: download
download: ## Download dependencies
$(GO) mod download
##@ Container Images
.PHONY: check-container-tool
check-container-tool:
ifndef CONTAINER_TOOL
@echo "Error: No container tool found (podman or docker)"
@echo ""
@echo "Please install one of:"
@echo " brew install podman # macOS"
@echo " brew install docker # macOS"
@echo " dnf install podman # Fedora/RHEL"
@exit 1
endif
.PHONY: image
image: check-container-tool ## Build container image
@echo "Building image $(IMAGE_REGISTRY)/$(IMAGE_NAME):$(IMAGE_TAG) ..."
$(CONTAINER_TOOL) build \
--platform $(PLATFORM) \
--build-arg GIT_SHA=$(GIT_SHA) \
--build-arg GIT_DIRTY=$(GIT_DIRTY) \
--build-arg BUILD_DATE=$(BUILD_DATE) \
--build-arg APP_VERSION=$(APP_VERSION) \
-t $(IMAGE_REGISTRY)/$(IMAGE_NAME):$(IMAGE_TAG) .
@echo "Image built: $(IMAGE_REGISTRY)/$(IMAGE_NAME):$(IMAGE_TAG)"
.PHONY: image-push
image-push: check-container-tool image ## Build and push container image
@echo "Pushing image $(IMAGE_REGISTRY)/$(IMAGE_NAME):$(IMAGE_TAG) ..."
$(CONTAINER_TOOL) push $(IMAGE_REGISTRY)/$(IMAGE_NAME):$(IMAGE_TAG)
@echo "Image pushed: $(IMAGE_REGISTRY)/$(IMAGE_NAME):$(IMAGE_TAG)"
.PHONY: image-dev
image-dev: check-container-tool ## Build and push to personal Quay registry (requires QUAY_USER)
ifndef QUAY_USER
@echo "Error: QUAY_USER is not set"
@echo ""
@echo "Usage: QUAY_USER=myuser make image-dev"
@echo ""
@echo "This will build and push to: quay.io/$$QUAY_USER/$(IMAGE_NAME):$(DEV_TAG)"
@exit 1
endif
@echo "Building dev image quay.io/$(QUAY_USER)/$(IMAGE_NAME):$(DEV_TAG) ..."
$(CONTAINER_TOOL) build \
--platform $(PLATFORM) \
--build-arg BASE_IMAGE=$(DEV_BASE_IMAGE) \
--build-arg GIT_SHA=$(GIT_SHA) \
--build-arg GIT_DIRTY=$(GIT_DIRTY) \
--build-arg BUILD_DATE=$(BUILD_DATE) \
--build-arg APP_VERSION=0.0.0-dev \
-t quay.io/$(QUAY_USER)/$(IMAGE_NAME):$(DEV_TAG) .
@echo "Pushing dev image..."
$(CONTAINER_TOOL) push quay.io/$(QUAY_USER)/$(IMAGE_NAME):$(DEV_TAG)
@echo ""
@echo "Dev image pushed: quay.io/$(QUAY_USER)/$(IMAGE_NAME):$(DEV_TAG)"