Repository navigation
Expand file tree
/
Copy pathMakefile
More file actions
188 lines (161 loc) · 8.99 KB
/
Copy pathMakefile
File metadata and controls
188 lines (161 loc) · 8.99 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
# k8s_stack_base — Validation & linting tooling
# ==============================================
# Run `make help` to see available targets.
SHELL := /bin/bash
.SHELLFLAGS := -eu -o pipefail -c
# --- Tool discovery ---
HELM := $(shell command -v helm 2>/dev/null || echo "")
KUSTOMIZE := $(shell command -v kustomize 2>/dev/null || echo "")
KUBECONFORM := $(shell command -v kubeconform 2>/dev/null || echo "")
KUBELINTER := $(shell command -v kube-linter 2>/dev/null || echo "")
PRECOMMIT := $(shell command -v pre-commit 2>/dev/null || echo "")
PYTHON3 := $(shell command -v python3 2>/dev/null || echo "")
UV := $(shell command -v uv 2>/dev/null || echo "")
LUA := $(shell command -v lua 2>/dev/null || echo "")
# --- Paths ---
CHART_DIRS := $(sort $(shell find charts -type f -name Chart.yaml -print | xargs -n1 dirname))
KUSTOMIZE_DIRS := $(sort $(shell find releases -type f -name kustomization.yaml -print | xargs -n1 dirname))
# Charts with committed dependency locks. Validation never updates these files.
HAS_DEPS := $(sort $(shell find charts -type f -name Chart.lock -print | xargs -n1 dirname))
HELM_LINT_VALUES := $(CURDIR)/tests/validation/helm-lint-values.yaml
# --- Colors ---
RED := \033[31m
GREEN := \033[32m
YELLOW := \033[33m
CYAN := \033[36m
RESET := \033[0m
.PHONY: help tools helm-lint helm-lint-only helm-validate rendered-check kustomize-validate kube-linter chart-check security-check platform-check release-manifest release-check release-notes check streaming-acceptance live-acceptance live-postgres-acceptance pre-commit-install helm-deps deps-verify
help: ## Show this help
@printf "$(CYAN)Available targets:$(RESET)\n"
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) \
| awk 'BEGIN {FS = ":.*?## "}; {printf " $(GREEN)%-22s$(RESET) %s\n", $$1, $$2}'
tools: ## Check that required CLIs are installed
@printf "$(CYAN)Checking required tools...$(RESET)\n"
@errors=0; \
for tool in "helm" "kustomize" "kubeconform" "kube-linter" "python3" "uv" "lua"; do \
path=$$(command -v "$$tool" 2>/dev/null || true); \
if [ -z "$$path" ]; then \
printf " $(RED)✗$(RESET) $$tool — not found\n"; \
errors=$$((errors + 1)); \
else \
case "$$tool" in \
helm) version=$$("$$tool" version --short 2>/dev/null) ;; \
kustomize) version=$$("$$tool" version 2>/dev/null) ;; \
kubeconform) version=$$("$$tool" -v 2>/dev/null) ;; \
kube-linter) version=$$("$$tool" version 2>/dev/null) ;; \
python3) version=$$("$$tool" --version 2>/dev/null) ;; \
uv) version=$$("$$tool" --version 2>/dev/null) ;; \
lua) version=$$("$$tool" -v 2>&1) ;; \
esac; \
printf " $(GREEN)✓$(RESET) $$tool — $$version\n"; \
fi \
done; \
if [ "$$errors" -gt 0 ]; then \
printf "\n$(RED)❌ $$errors tool(s) missing. Install them before running checks.$(RESET)\n"; \
exit 1; \
fi; \
printf "$(GREEN)All required tools are installed.$(RESET)\n"
helm-deps: ## Rebuild Helm chart dependencies from committed lock files
@printf "$(CYAN)Rebuilding Helm dependencies...$(RESET)\n"
@for dir in $(HAS_DEPS); do \
printf " helm dep build %s\n" "$$dir"; \
cd "$(CURDIR)/$$dir" && $(HELM) dependency build --skip-refresh 2>&1 | tail -1; \
done
@printf "$(GREEN)Done.$(RESET)\n"
helm-lint: deps-verify helm-lint-only ## Verify deps then lint all charts
helm-lint-only: ## Lint all charts (without updating deps)
@printf "$(CYAN)Linting all charts...$(RESET)\n"
@errors=0; \
for dir in $(CHART_DIRS); do \
if [ ! -d "$(CURDIR)/$$dir/templates" ]; then printf " $(GREEN)✓$(RESET) %s — no local templates\\n" "$$dir"; continue; fi; \
output=$$(cd "$(CURDIR)/$$dir" && $(HELM) lint --strict . --values "$(HELM_LINT_VALUES)" 2>&1) || { printf " $(RED)✗$(RESET) %s — FAILED\\n" "$$dir"; echo "$$output"; errors=$$((errors + 1)); continue; }; \
printf " $(GREEN)✓$(RESET) %s — PASSED\n" "$$dir"; \
done; \
if [ "$$errors" -gt 0 ]; then \
printf "\n$(RED)❌ $$errors chart(s) failed linting.$(RESET)\n"; \
exit 1; \
fi; \
printf "$(GREEN)All charts passed linting.$(RESET)\n"
helm-validate: rendered-check ## Validate schemas and lint rendered charts
kube-linter: rendered-check ## Validate schemas and lint rendered charts
rendered-check: deps-verify
@printf "$(CYAN)Rendering charts for schema validation and kube-linter...$(RESET)\n"
@tmpdir=$$(mktemp -d); \
trap 'rm -rf "$$tmpdir"' EXIT; \
errors=0; \
for dir in $(CHART_DIRS); do \
tmpfile="$$tmpdir/rendered.yaml"; \
if ! $(HELM) template "$$(basename "$$dir")" "$(CURDIR)/$$dir" --skip-tests --values "$(HELM_LINT_VALUES)" > "$$tmpfile"; then \
printf " $(RED)✗$(RESET) %s — render failed\n" "$$dir"; \
errors=$$((errors + 1)); \
elif ! grep -Eq '^kind:[[:space:]]+' "$$tmpfile"; then \
if [ "$$dir" = "charts/keycloak/addon-oidc" ] || [ "$$dir" = "charts/postgres/documentdb-addon" ]; then \
printf " $(GREEN)✓$(RESET) %s — opt-in chart disabled; enabled resources checked by chart-check\n" "$$dir"; \
continue; \
fi; \
printf " $(RED)✗$(RESET) %s — rendered zero resources\n" "$$dir"; \
errors=$$((errors + 1)); \
else \
$(KUBECONFORM) -strict -summary -ignore-missing-schemas "$$tmpfile" || errors=$$((errors + 1)); \
$(KUBELINTER) lint --config "$(CURDIR)/.kube-linter.yaml" "$$tmpfile" || errors=$$((errors + 1)); \
fi; \
done; \
if [ "$$errors" -gt 0 ]; then \
printf "\n$(RED)❌ $$errors render, schema or lint check(s) failed.$(RESET)\n"; \
exit 1; \
fi; \
printf "$(GREEN)All charts passed validation.$(RESET)\n"
kustomize-validate: deps-verify ## Build and validate root Kustomizations
@printf "$(CYAN)Building and validating root Kustomizations...$(RESET)\n"
@if [ -z "$(KUSTOMIZE)" ]; then printf "$(RED)kustomize is required$(RESET)\n"; exit 1; fi
@for dir in releases/namespaces releases/infrastructure releases/applications releases/keycloak/active-directory releases/namespaces/contextforge releases/contextforge/configuration releases/contextforge/secret-sync releases/contextforge/secret-sync/database releases/contextforge/oauth-apps releases/contextforge/certificates releases/contextforge/postgres releases/contextforge/app releases/namespaces/tailscale releases/tailscale/secret-sync releases/tailscale/operator releases/tailscale/access; do \
$(KUSTOMIZE) build --load-restrictor LoadRestrictionsNone "$(CURDIR)/$$dir" | $(KUBECONFORM) -strict -summary -ignore-missing-schemas; \
done
deps-verify: ## Verify committed dependency archives without changing them
@for dir in $(HAS_DEPS); do \
if ! $(HELM) dependency list "$(CURDIR)/$$dir" >/dev/null; then \
printf "$(RED)Dependency verification failed: %s$(RESET)\n" "$$dir"; exit 1; \
fi; \
done
security-check: ## Run offline acceptance-runner safety tests
@if [ -z "$(PYTHON3)" ]; then \
printf "$(RED)python3 not found. Install it before running security checks.$(RESET)\n"; \
exit 1; \
fi
@$(PYTHON3) -m unittest discover -s tests/security/static -p 'test_*.py' -v
chart-check: ## Run chart-specific rendered contract tests
@$(UV) run --frozen python -m unittest discover -s tests/charts -p 'test_*.py' -v
platform-check: ## Verify the generated platform release contract
@if [ -z "$(UV)" ]; then printf "$(RED)uv is required$(RESET)\n"; exit 1; fi
@PLATFORM_RELEASE_TEST_TAG="$(TAG)" $(UV) run --frozen python -m unittest discover -s tests/platform -p 'test_*.py' -v
release-manifest: ## Regenerate the platform release manifest
@if [ -z "$(UV)" ]; then printf "$(RED)uv is required$(RESET)\n"; exit 1; fi
@$(UV) run --frozen python scripts/platform_release.py generate
release-check: platform-check ## Verify release evidence; pass TAG=vX.Y.Z for tag consistency
@$(UV) run --frozen python scripts/platform_release.py check $(if $(TAG),--tag "$(TAG)",)
release-notes: ## Write release notes; pass OUTPUT=<path>
@if [ -z "$(OUTPUT)" ]; then printf "$(RED)OUTPUT is required$(RESET)\n"; exit 1; fi
@$(UV) run --frozen python scripts/platform_release.py notes --output "$(OUTPUT)"
check: tools helm-lint rendered-check kustomize-validate chart-check security-check platform-check ## Run full local validation suite
streaming-acceptance: ## Run opt-in local streaming regression; see tests/live/agentgateway/README.md
@$(PYTHON3) tests/live/agentgateway/test_streaming.py
live-acceptance: ## Run explicitly opted-in live AgentGateway acceptance (not part of check)
@if [ -z "$(PYTHON3)" ]; then \
printf "$(RED)python3 not found. Install it before running live acceptance.$(RESET)\n"; \
exit 1; \
fi
@$(PYTHON3) tests/live/agentgateway/acceptance.py
live-postgres-acceptance: ## Run explicitly opted-in disposable PostgreSQL acceptance (not part of check)
@if [ -z "$(PYTHON3)" ]; then \
printf "$(RED)python3 not found. Install it before running live acceptance.$(RESET)\n"; \
exit 1; \
fi
@$(PYTHON3) -u tests/live/postgres/acceptance.py
pre-commit-install: ## Install pre-commit hooks
@if [ -n "$(PRECOMMIT)" ]; then \
$(PRECOMMIT) install; \
printf "$(GREEN)pre-commit hooks installed.$(RESET)\n"; \
else \
printf "$(RED)pre-commit not found. Install it first.$(RESET)\n"; \
exit 1; \
fi