#!/usr/bin/env -S make -f
# ==============================================================================
# MCP Stack Helm Chart Makefile
# ==============================================================================
# Chart configuration
CHART_NAME := mcp-stack
CHART_VERSION := $(shell grep '^version:' Chart.yaml | cut -d' ' -f2)
APP_VERSION := $(shell grep '^appVersion:' Chart.yaml | cut -d' ' -f2 | tr -d '"')
# Registry configuration
REGISTRY := ghcr.io
REPO := ibm/mcp-context-forge
CHART_REGISTRY := oci://$(REGISTRY)/$(REPO)
# Directories
DIST_DIR := dist
DOCS_DIR := docs
TEMP_DIR := tmp
TEST_DIR := tests
# Kubernetes configuration
KUBECONFIG ?= ~/.kube/config
NAMESPACE ?= mcp-test
RELEASE_NAME ?= mcp-stack-test
# Colors for output
RED := \033[0;31m
GREEN := \033[0;32m
YELLOW := \033[0;33m
BLUE := \033[0;34m
PURPLE := \033[0;35m
CYAN := \033[0;36m
WHITE := \033[0;37m
NC := \033[0m # No Color
# Default target
.DEFAULT_GOAL := help
# ==============================================================================
# HELP & INFORMATION
# ==============================================================================
.PHONY: help
help: ## ๐ฏ Show this help message
@echo "$(CYAN)MCP Stack Helm Chart$(NC) - Available targets:"
@echo ""
@awk 'BEGIN {FS = ":.*##"; printf "Usage: make $(CYAN)<target>$(NC)\n\nTargets:\n"} \
/^[a-zA-Z_-]+:.*?##/ { \
printf " $(CYAN)%-20s$(NC) %s\n", $$1, $$2 \
} \
/^##@/ { \
printf "\n$(YELLOW)%s$(NC)\n", substr($$0, 5) \
}' $(MAKEFILE_LIST)
@echo ""
.PHONY: info
info: ## ๐ Show chart information
@echo "$(CYAN)Chart Information:$(NC)"
@echo " Name: $(CHART_NAME)"
@echo " Version: $(CHART_VERSION)"
@echo " App Version: $(APP_VERSION)"
@echo " Registry: $(CHART_REGISTRY)"
@echo " Namespace: $(NAMESPACE)"
@echo " Release: $(RELEASE_NAME)"
@echo ""
.PHONY: version
version: ## ๐ท๏ธ Show chart version
@echo "$(CHART_VERSION)"
##@ ๐ Validation & Linting
.PHONY: lint
lint: ## ๐ง Run Helm lint on the chart
@echo "$(BLUE)Running Helm lint...$(NC)"
@helm lint . --strict
@echo "$(GREEN)โ Lint completed successfully$(NC)"
.PHONY: lint-values
lint-values: ## ๐ Validate values.yaml against schema
@echo "$(BLUE)Validating values.yaml against schema...$(NC)"
@if [ -f values.schema.json ]; then \
helm lint . --strict > /dev/null && \
echo "$(GREEN)โ Values validation passed$(NC)"; \
else \
echo "$(YELLOW)โ No values.schema.json found$(NC)"; \
fi
.PHONY: lint-yaml
lint-yaml: ## ๐ Lint YAML files with yamllint
@echo "$(BLUE)Running yamllint...$(NC)"
@if command -v yamllint >/dev/null 2>&1; then \
yamllint . -c .yamllint.yml || yamllint .; \
echo "$(GREEN)โ YAML lint completed$(NC)"; \
else \
echo "$(YELLOW)โ yamllint not found, skipping$(NC)"; \
fi
.PHONY: validate-all
validate-all: lint lint-values lint-yaml ## โ
Run all validation checks
##@ ๐งช Testing
.PHONY: test-template
test-template: ## ๐ Test template rendering with default values
@echo "$(BLUE)Testing template rendering...$(NC)"
@helm template $(CHART_NAME) . --debug --dry-run > $(TEMP_DIR)/rendered.yaml
@echo "$(GREEN)โ Template rendering successful$(NC)"
.PHONY: test-template-values
test-template-values: ## ๐ Test template rendering with custom values
@echo "$(BLUE)Testing template rendering with custom values...$(NC)"
@if [ -f my-values.yaml ]; then \
helm template $(CHART_NAME) . -f my-values.yaml --debug --dry-run > $(TEMP_DIR)/rendered-custom.yaml; \
echo "$(GREEN)โ Template rendering with custom values successful$(NC)"; \
else \
echo "$(YELLOW)โ my-values.yaml not found, using default values$(NC)"; \
$(MAKE) test-template; \
fi
.PHONY: test-dry-run
test-dry-run: ## ๐ญ Test installation with dry-run
@echo "$(BLUE)Testing installation (dry-run)...$(NC)"
@helm install $(RELEASE_NAME) . --namespace $(NAMESPACE) --create-namespace --dry-run --debug
@echo "$(GREEN)โ Dry-run installation successful$(NC)"
.PHONY: test-upgrade-dry-run
test-upgrade-dry-run: ## ๐ Test upgrade with dry-run
@echo "$(BLUE)Testing upgrade (dry-run)...$(NC)"
@helm upgrade $(RELEASE_NAME) . --namespace $(NAMESPACE) --dry-run --debug
@echo "$(GREEN)โ Dry-run upgrade successful$(NC)"
.PHONY: test-kubeval
test-kubeval: ## ๐ Validate Kubernetes manifests with kubeval
@echo "$(BLUE)Validating Kubernetes manifests...$(NC)"
@if command -v kubeval >/dev/null 2>&1; then \
helm template $(CHART_NAME) . | kubeval --strict --ignore-missing-schemas; \
echo "$(GREEN)โ Kubeval validation passed$(NC)"; \
else \
echo "$(YELLOW)โ kubeval not found, skipping$(NC)"; \
fi
.PHONY: test-all
test-all: test-template test-dry-run test-kubeval ## ๐งช Run all tests
##@ ๐ฆ Packaging & Publishing
.PHONY: clean
clean: ## ๐งน Clean build artifacts
@echo "$(BLUE)Cleaning build artifacts...$(NC)"
@rm -rf $(DIST_DIR) $(TEMP_DIR) *.tgz values.schema.generated.json
@echo "$(GREEN)โ Clean completed$(NC)"
.PHONY: package
package: clean validate-all ## ๐ฆ Package the Helm chart
@echo "$(BLUE)Packaging Helm chart...$(NC)"
@mkdir -p $(DIST_DIR)
@helm package . --destination $(DIST_DIR) --dependency-update
@echo "$(GREEN)โ Chart packaged: $(DIST_DIR)/$(CHART_NAME)-$(CHART_VERSION).tgz$(NC)"
.PHONY: package-dev
package-dev: clean ## ๐ฆ Package chart for development (skip validation)
@echo "$(BLUE)Packaging Helm chart (development)...$(NC)"
@mkdir -p $(DIST_DIR)
@helm package . --destination $(DIST_DIR)
@echo "$(GREEN)โ Chart packaged: $(DIST_DIR)/$(CHART_NAME)-$(CHART_VERSION).tgz$(NC)"
.PHONY: push
push: package ## ๐ Push chart to OCI registry
@echo "$(BLUE)Pushing chart to registry...$(NC)"
@helm push $(DIST_DIR)/$(CHART_NAME)-$(CHART_VERSION).tgz $(CHART_REGISTRY)
@echo "$(GREEN)โ Chart pushed to $(CHART_REGISTRY)$(NC)"
.PHONY: sign
sign: package ## ๐ Sign the chart package
@echo "$(BLUE)Signing chart package...$(NC)"
@if command -v cosign >/dev/null 2>&1; then \
cosign sign-blob --yes $(DIST_DIR)/$(CHART_NAME)-$(CHART_VERSION).tgz \
--output-signature $(DIST_DIR)/$(CHART_NAME)-$(CHART_VERSION).tgz.sig \
--output-certificate $(DIST_DIR)/$(CHART_NAME)-$(CHART_VERSION).tgz.pem; \
echo "$(GREEN)โ Chart signed$(NC)"; \
else \
echo "$(YELLOW)โ cosign not found, skipping signing$(NC)"; \
fi
##@ ๐ Deployment & Management
.PHONY: install
install: ## ๐ Install the chart
@echo "$(BLUE)Installing chart...$(NC)"
@helm install $(RELEASE_NAME) . --namespace $(NAMESPACE) --create-namespace --wait --timeout 10m
@echo "$(GREEN)โ Chart installed successfully$(NC)"
.PHONY: install-dev
install-dev: ## ๐ Install chart with development values
@echo "$(BLUE)Installing chart (development)...$(NC)"
@if [ -f my-values.yaml ]; then \
helm install $(RELEASE_NAME) . --namespace $(NAMESPACE) --create-namespace -f my-values.yaml --wait --timeout 10m; \
else \
echo "$(YELLOW)โ my-values.yaml not found, using default values$(NC)"; \
$(MAKE) install; \
fi
@echo "$(GREEN)โ Chart installed successfully$(NC)"
.PHONY: upgrade
upgrade: ## ๐ Upgrade the chart
@echo "$(BLUE)Upgrading chart...$(NC)"
@helm upgrade $(RELEASE_NAME) . --namespace $(NAMESPACE) --wait --timeout 10m
@echo "$(GREEN)โ Chart upgraded successfully$(NC)"
.PHONY: upgrade-dev
upgrade-dev: ## ๐ Upgrade chart with development values
@echo "$(BLUE)Upgrading chart (development)...$(NC)"
@if [ -f my-values.yaml ]; then \
helm upgrade $(RELEASE_NAME) . --namespace $(NAMESPACE) -f my-values.yaml --wait --timeout 10m; \
else \
echo "$(YELLOW)โ my-values.yaml not found, using default values$(NC)"; \
$(MAKE) upgrade; \
fi
@echo "$(GREEN)โ Chart upgraded successfully$(NC)"
.PHONY: uninstall
uninstall: ## ๐๏ธ Uninstall the chart
@echo "$(BLUE)Uninstalling chart...$(NC)"
@helm uninstall $(RELEASE_NAME) --namespace $(NAMESPACE) --wait --timeout 5m
@echo "$(GREEN)โ Chart uninstalled successfully$(NC)"
.PHONY: status
status: ## ๐ Show chart status
@echo "$(BLUE)Chart status:$(NC)"
@helm status $(RELEASE_NAME) --namespace $(NAMESPACE)
.PHONY: history
history: ## ๐ Show chart history
@echo "$(BLUE)Chart history:$(NC)"
@helm history $(RELEASE_NAME) --namespace $(NAMESPACE)
.PHONY: rollback
rollback: ## โช Rollback to previous version
@echo "$(BLUE)Rolling back chart...$(NC)"
@helm rollback $(RELEASE_NAME) --namespace $(NAMESPACE) --wait --timeout 5m
@echo "$(GREEN)โ Chart rolled back successfully$(NC)"
##@ ๐ Debugging & Inspection
.PHONY: debug
debug: ## ๐ Show debug information
@echo "$(BLUE)Debug information:$(NC)"
@echo "Kubernetes context: $$(kubectl config current-context)"
@echo "Namespace: $(NAMESPACE)"
@echo "Release name: $(RELEASE_NAME)"
@echo ""
@echo "$(BLUE)Helm releases:$(NC)"
@helm list --namespace $(NAMESPACE) || echo "No releases found"
@echo ""
@echo "$(BLUE)Kubernetes resources:$(NC)"
@kubectl get all --namespace $(NAMESPACE) || echo "No resources found"
.PHONY: describe
describe: ## ๐ Describe all chart resources
@echo "$(BLUE)Describing chart resources...$(NC)"
@kubectl describe all --namespace $(NAMESPACE) -l app.kubernetes.io/instance=$(RELEASE_NAME)
.PHONY: logs
logs: ## ๐ Show logs for all pods
@echo "$(BLUE)Showing logs for all pods...$(NC)"
@kubectl logs --namespace $(NAMESPACE) -l app.kubernetes.io/instance=$(RELEASE_NAME) --all-containers=true --tail=100
.PHONY: logs-follow
logs-follow: ## ๐ Follow logs for all pods
@echo "$(BLUE)Following logs for all pods...$(NC)"
@kubectl logs --namespace $(NAMESPACE) -l app.kubernetes.io/instance=$(RELEASE_NAME) --all-containers=true --follow
.PHONY: port-forward
port-forward: ## ๐ Port-forward to gateway service
@echo "$(BLUE)Port-forwarding to gateway service...$(NC)"
@kubectl port-forward --namespace $(NAMESPACE) service/$(RELEASE_NAME)-mcpgateway 4444:80
.PHONY: shell
shell: ## ๐ Open shell in gateway pod
@echo "$(BLUE)Opening shell in gateway pod...$(NC)"
@kubectl exec --namespace $(NAMESPACE) -it deployment/$(RELEASE_NAME)-mcpgateway -- /bin/bash
##@ ๐ Documentation
.PHONY: docs
docs: ## ๐ Generate chart documentation
@echo "$(BLUE)Generating chart documentation...$(NC)"
@if command -v helm-docs >/dev/null 2>&1; then \
helm-docs --chart-search-root=. --template-files=README.md.gotmpl --output-file=README.md; \
echo "$(GREEN)โ Documentation generated$(NC)"; \
else \
echo "$(YELLOW)โ helm-docs not found, skipping documentation generation$(NC)"; \
fi
.PHONY: schema
schema: ## ๐ Generate values schema (preserves existing schema)
@echo "$(BLUE)Generating values schema...$(NC)"
@if command -v helm schema >/dev/null 2>&1; then \
helm schema --input values.yaml --output values.schema.generated.json; \
echo "$(GREEN)โ Values schema generated: values.schema.generated.json$(NC)"; \
echo "$(YELLOW)โ Review and manually merge with values.schema.json if needed$(NC)"; \
if [ -f values.schema.json ]; then \
echo "$(BLUE)๐ก Compare schemas with: make schema-diff$(NC)"; \
fi; \
else \
echo "$(YELLOW)โ helm schema plugin not found$(NC)"; \
echo "Install with: make install-deps or helm plugin install https://github.com/karuppiah7890/helm-schema-gen"; \
fi
.PHONY: schema-diff
schema-diff: ## ๐ Compare existing and generated schemas
@echo "$(BLUE)Comparing schemas...$(NC)"
@if [ -f values.schema.json ] && [ -f values.schema.generated.json ]; then \
if command -v diff >/dev/null 2>&1; then \
diff -u values.schema.json values.schema.generated.json || echo "$(YELLOW)โ Schemas differ$(NC)"; \
elif command -v jq >/dev/null 2>&1; then \
echo "$(BLUE)Existing schema keys:$(NC)"; \
jq -r 'paths(scalars) as $p | $p | join(".")' values.schema.json | sort; \
echo "$(BLUE)Generated schema keys:$(NC)"; \
jq -r 'paths(scalars) as $p | $p | join(".")' values.schema.generated.json | sort; \
else \
echo "$(YELLOW)โ diff or jq not found for comparison$(NC)"; \
fi; \
else \
echo "$(YELLOW)โ Both schemas must exist for comparison$(NC)"; \
echo "Run 'make schema' to generate values.schema.generated.json"; \
fi
.PHONY: schema-validate
schema-validate: ## โ
Validate values.yaml against existing schema
@echo "$(BLUE)Validating values.yaml against schema...$(NC)"
@if [ -f values.schema.json ]; then \
if command -v ajv >/dev/null 2>&1; then \
ajv validate -s values.schema.json -d values.yaml && echo "$(GREEN)โ Values validation passed$(NC)" || \
(echo "$(YELLOW)โ ajv failed, trying without meta-schema validation$(NC)" && \
ajv validate -s values.schema.json -d values.yaml && echo "$(GREEN)โ Values validation passed$(NC)"); \
elif command -v ajv-cli >/dev/null 2>&1; then \
ajv-cli validate -s values.schema.json -d values.yaml && echo "$(GREEN)โ Values validation passed$(NC)" || \
(echo "$(YELLOW)โ ajv-cli failed, trying helm lint validation$(NC)" && \
helm lint . --strict > /dev/null && echo "$(GREEN)โ Helm lint validation passed$(NC)"); \
elif command -v python3 >/dev/null 2>&1; then \
echo "$(YELLOW)โ ajv not found, trying Python jsonschema validation$(NC)"; \
python3 -c "import jsonschema, yaml, json; jsonschema.validate(yaml.safe_load(open('values.yaml')), json.load(open('values.schema.json')))" 2>/dev/null && \
echo "$(GREEN)โ Python jsonschema validation passed$(NC)" || \
(echo "$(YELLOW)โ Python validation failed, using helm lint$(NC)" && \
helm lint . --strict > /dev/null && echo "$(GREEN)โ Helm lint validation passed$(NC)"); \
else \
echo "$(YELLOW)โ No schema validators found, using helm lint for basic validation$(NC)"; \
echo "$(YELLOW)๐ก For proper schema validation, install ajv: npm install -g ajv-cli$(NC)"; \
helm lint . --strict > /dev/null && echo "$(GREEN)โ Helm lint validation passed$(NC)"; \
fi; \
else \
echo "$(YELLOW)โ values.schema.json not found$(NC)"; \
fi
.PHONY: schema-validate-simple
schema-validate-simple: ## โ
Simple schema validation using Python
@echo "$(BLUE)Validating values.yaml against schema (Python method)...$(NC)"
@if [ -f values.schema.json ]; then \
if command -v python3 >/dev/null 2>&1; then \
python3 -c "import jsonschema, yaml, json; jsonschema.validate(yaml.safe_load(open('values.yaml')), json.load(open('values.schema.json'))); print('โ Schema validation passed')" || \
echo "$(YELLOW)โ Install required Python packages: pip install jsonschema pyyaml$(NC)"; \
else \
echo "$(YELLOW)โ Python3 not found$(NC)"; \
fi; \
else \
echo "$(YELLOW)โ values.schema.json not found$(NC)"; \
fi
.PHONY: readme
readme: ## ๐ Update README with chart values
@echo "$(BLUE)Updating README with chart values...$(NC)"
@if command -v helm-docs >/dev/null 2>&1; then \
helm-docs --sort-values-order=file; \
echo "$(GREEN)โ README updated$(NC)"; \
else \
echo "$(YELLOW)โ helm-docs not found$(NC)"; \
fi
##@ ๐ Dependencies
.PHONY: deps-update
deps-update: ## ๐ฅ Update chart dependencies
@echo "$(BLUE)Updating chart dependencies...$(NC)"
@helm dependency update
@echo "$(GREEN)โ Dependencies updated$(NC)"
.PHONY: deps-build
deps-build: ## ๐จ Build chart dependencies
@echo "$(BLUE)Building chart dependencies...$(NC)"
@helm dependency build
@echo "$(GREEN)โ Dependencies built$(NC)"
.PHONY: deps-clean
deps-clean: ## ๐งน Clean chart dependencies
@echo "$(BLUE)Cleaning chart dependencies...$(NC)"
@rm -rf charts/ Chart.lock
@echo "$(GREEN)โ Dependencies cleaned$(NC)"
##@ ๐ ๏ธ Development Tools
.PHONY: install-deps
install-deps: ## ๐ฅ Install missing development dependencies
@echo "$(BLUE)Installing development dependencies...$(NC)"
@echo "$(BLUE)Detecting package manager...$(NC)"
@if command -v brew >/dev/null 2>&1; then \
echo "$(GREEN)โ Using Homebrew$(NC)"; \
$(MAKE) install-deps-brew; \
elif command -v apt-get >/dev/null 2>&1; then \
echo "$(GREEN)โ Using APT$(NC)"; \
$(MAKE) install-deps-apt; \
elif command -v yum >/dev/null 2>&1; then \
echo "$(GREEN)โ Using YUM$(NC)"; \
$(MAKE) install-deps-yum; \
elif command -v npm >/dev/null 2>&1; then \
echo "$(GREEN)โ Using NPM for Node.js tools$(NC)"; \
$(MAKE) install-deps-npm; \
else \
echo "$(YELLOW)โ No supported package manager found$(NC)"; \
echo "Please install tools manually:"; \
echo " - yamllint: pip install yamllint"; \
echo " - kubeval: https://github.com/instrumenta/kubeval/releases"; \
echo " - helm-docs: https://github.com/norwoodj/helm-docs/releases"; \
echo " - cosign: https://github.com/sigstore/cosign/releases"; \
echo " - prettier: npm install -g prettier"; \
echo " - ajv-cli: npm install -g ajv-cli (for JSON schema validation)"; \
echo " - fswatch: https://github.com/emcrisostomo/fswatch/releases"; \
fi
@$(MAKE) install-helm-plugins
.PHONY: install-deps-brew
install-deps-brew: ## ๐ฅ Install dependencies using Homebrew
@echo "$(BLUE)Installing dependencies with Homebrew...$(NC)"
@tools="yamllint kubeval helm-docs cosign prettier fswatch"; \
for tool in $tools; do \
if ! command -v $tool >/dev/null 2>&1; then \
echo "$(BLUE)Installing $tool...$(NC)"; \
brew install $tool || echo "$(YELLOW)โ Failed to install $tool$(NC)"; \
else \
echo "$(GREEN)โ $tool already installed$(NC)"; \
fi; \
done
.PHONY: install-deps-apt
install-deps-apt: ## ๐ฅ Install dependencies using APT
@echo "$(BLUE)Installing dependencies with APT...$(NC)"
@sudo apt-get update
@if ! command -v yamllint >/dev/null 2>&1; then \
echo "$(BLUE)Installing yamllint...$(NC)"; \
sudo apt-get install -y yamllint || pip3 install yamllint; \
fi
@if ! command -v kubeval >/dev/null 2>&1; then \
echo "$(BLUE)Installing kubeval...$(NC)"; \
wget -O /tmp/kubeval.tar.gz https://github.com/instrumenta/kubeval/releases/latest/download/kubeval-linux-amd64.tar.gz; \
tar -xzf /tmp/kubeval.tar.gz -C /tmp/; \
sudo mv /tmp/kubeval /usr/local/bin/; \
fi
@if ! command -v helm-docs >/dev/null 2>&1; then \
echo "$(BLUE)Installing helm-docs...$(NC)"; \
wget -O /tmp/helm-docs.tar.gz https://github.com/norwoodj/helm-docs/releases/latest/download/helm-docs_$(shell uname -s)_$(shell uname -m).tar.gz; \
tar -xzf /tmp/helm-docs.tar.gz -C /tmp/; \
sudo mv /tmp/helm-docs /usr/local/bin/; \
fi
@if ! command -v prettier >/dev/null 2>&1; then \
echo "$(BLUE)Installing prettier via npm...$(NC)"; \
sudo npm install -g prettier || echo "$(YELLOW)โ npm not found, skipping prettier$(NC)"; \
fi
@if ! command -v ajv-cli >/dev/null 2>&1; then \
echo "$(BLUE)Installing ajv-cli for JSON schema validation...$(NC)"; \
sudo npm install -g ajv-cli || echo "$(YELLOW)โ npm not found, skipping ajv-cli$(NC)"; \
fi
.PHONY: install-deps-yum
install-deps-yum: ## ๐ฅ Install dependencies using YUM
@echo "$(BLUE)Installing dependencies with YUM...$(NC)"
@if ! command -v yamllint >/dev/null 2>&1; then \
echo "$(BLUE)Installing yamllint...$(NC)"; \
sudo yum install -y yamllint || pip3 install yamllint; \
fi
@echo "$(YELLOW)โ Please install remaining tools manually:$(NC)"
@echo " - kubeval: https://github.com/instrumenta/kubeval/releases"
@echo " - helm-docs: https://github.com/norwoodj/helm-docs/releases"
@echo " - cosign: https://github.com/sigstore/cosign/releases"
.PHONY: install-deps-npm
install-deps-npm: ## ๐ฅ Install Node.js dependencies using NPM
@echo "$(BLUE)Installing Node.js dependencies with NPM...$(NC)"
@if ! command -v prettier >/dev/null 2>&1; then \
echo "$(BLUE)Installing prettier...$(NC)"; \
npm install -g prettier; \
fi
@if ! command -v ajv-cli >/dev/null 2>&1; then \
echo "$(BLUE)Installing ajv-cli for JSON schema validation...$(NC)"; \
npm install -g ajv-cli; \
fi
.PHONY: install-helm-plugins
install-helm-plugins: ## ๐ฅ Install required Helm plugins
@echo "$(BLUE)Installing Helm plugins...$(NC)"
@if ! helm plugin list | grep -q "schema"; then \
echo "$(BLUE)Installing helm-schema plugin...$(NC)"; \
helm plugin install https://github.com/karuppiah7890/helm-schema-gen || echo "$(YELLOW)โ Failed to install helm-schema$(NC)"; \
else \
echo "$(GREEN)โ helm-schema plugin already installed$(NC)"; \
fi
@if ! helm plugin list | grep -q "diff"; then \
echo "$(BLUE)Installing helm-diff plugin...$(NC)"; \
helm plugin install https://github.com/databus23/helm-diff || echo "$(YELLOW)โ Failed to install helm-diff$(NC)"; \
else \
echo "$(GREEN)โ helm-diff plugin already installed$(NC)"; \
fi
.PHONY: setup-dev
setup-dev: ## ๐ง Set up development environment
@echo "$(BLUE)Setting up development environment...$(NC)"
@mkdir -p $(TEMP_DIR) $(DIST_DIR)
@if [ ! -f my-values.yaml ]; then \
cp values.yaml my-values.yaml; \
echo "$(GREEN)โ Created my-values.yaml$(NC)"; \
fi
@echo "$(GREEN)โ Development environment ready$(NC)"
@echo "$(YELLOW)๐ก Run 'make install-deps' to install optional development tools$(NC)"
.PHONY: watch
watch: ## ๐ Watch for changes and re-lint
@echo "$(BLUE)Watching for changes...$(NC)"
@if command -v fswatch >/dev/null 2>&1; then \
fswatch -o . -e "$(DIST_DIR)" -e "$(TEMP_DIR)" -e "*.tgz" | xargs -n1 -I{} make lint; \
else \
echo "$(YELLOW)โ fswatch not found, install with: brew install fswatch$(NC)"; \
fi
.PHONY: format
format: ## ๐จ Format YAML files
@echo "$(BLUE)Formatting YAML files...$(NC)"
@if command -v prettier >/dev/null 2>&1; then \
prettier --write "**/*.{yaml,yml}" --ignore-path .helmignore; \
echo "$(GREEN)โ YAML files formatted$(NC)"; \
else \
echo "$(YELLOW)โ prettier not found, skipping formatting$(NC)"; \
fi
.PHONY: check-tools
check-tools: ## ๐ Check for required tools
@echo "$(BLUE)Checking for required tools...$(NC)"
@tools="helm kubectl"; \
missing_required=""; \
for tool in $tools; do \
if command -v $tool >/dev/null 2>&1; then \
echo "$(GREEN)โ $tool$(NC)"; \
else \
echo "$(RED)โ $tool (required)$(NC)"; \
missing_required="$missing_required $tool"; \
fi; \
done
@if [ -n "$missing_required" ]; then \
echo "$(RED)Missing required tools:$missing_required$(NC)"; \
echo "Please install them manually."; \
exit 1; \
fi
@echo ""
@echo "$(BLUE)Checking for optional tools...$(NC)"
@tools="yamllint kubeval helm-docs cosign prettier fswatch"; \
missing_optional=""; \
for tool in $tools; do \
if command -v $tool >/dev/null 2>&1; then \
echo "$(GREEN)โ $tool$(NC)"; \
else \
echo "$(YELLOW)- $tool (optional)$(NC)"; \
missing_optional="$missing_optional $tool"; \
fi; \
done
@echo ""
@echo "$(BLUE)Checking for Helm plugins...$(NC)"
@plugins="schema diff"; \
for plugin in $plugins; do \
if helm plugin list | grep -q "$plugin"; then \
echo "$(GREEN)โ helm-$plugin$(NC)"; \
else \
echo "$(YELLOW)- helm-$plugin (optional)$(NC)"; \
fi; \
done
@if [ -n "$missing_optional" ]; then \
echo ""; \
echo "$(YELLOW)๐ก Install missing tools with: make install-deps$(NC)"; \
fi
##@ ๐งช Integration Testing
.PHONY: test-integration
test-integration: install ## ๐งช Run integration tests
@echo "$(BLUE)Running integration tests...$(NC)"
@echo "Waiting for pods to be ready..."
@kubectl wait --for=condition=ready pod --namespace $(NAMESPACE) -l app.kubernetes.io/instance=$(RELEASE_NAME) --timeout=300s
@echo "$(GREEN)โ Integration tests passed$(NC)"
.PHONY: test-e2e
test-e2e: install ## ๐ Run end-to-end tests
@echo "$(BLUE)Running end-to-end tests...$(NC)"
@kubectl wait --for=condition=ready pod --namespace $(NAMESPACE) -l app.kubernetes.io/instance=$(RELEASE_NAME) --timeout=300s
@kubectl port-forward --namespace $(NAMESPACE) service/$(RELEASE_NAME)-mcpgateway 4444:80 &
@sleep 5
@curl -f http://localhost:4444/health || (echo "$(RED)โ Health check failed$(NC)" && exit 1)
@pkill -f "kubectl port-forward" || true
@echo "$(GREEN)โ End-to-end tests passed$(NC)"
.PHONY: test-cleanup
test-cleanup: ## ๐งน Clean up test resources
@echo "$(BLUE)Cleaning up test resources...$(NC)"
@helm uninstall $(RELEASE_NAME) --namespace $(NAMESPACE) --ignore-not-found --wait --timeout 5m
@kubectl delete namespace $(NAMESPACE) --ignore-not-found --wait --timeout 5m
@echo "$(GREEN)โ Test cleanup completed$(NC)"
##@ ๐ฏ CI/CD Targets
.PHONY: ci-setup
ci-setup: check-tools ## ๐ CI: Set up CI environment
@echo "$(BLUE)Setting up CI environment...$(NC)"
@$(MAKE) setup-dirs
@echo "$(GREEN)โ CI setup completed$(NC)"
.PHONY: ci-lint
ci-lint: validate-all ## ๐ CI: Run linting and validation
@echo "$(GREEN)โ CI linting completed$(NC)"
.PHONY: ci-test
ci-test: test-all ## ๐ CI: Run all tests
@echo "$(GREEN)โ CI testing completed$(NC)"
.PHONY: ci-package
ci-package: package ## ๐ CI: Package chart
@echo "$(GREEN)โ CI packaging completed$(NC)"
.PHONY: ci-publish
ci-publish: push ## ๐ CI: Publish chart
@echo "$(GREEN)โ CI publishing completed$(NC)"
.PHONY: ci-all
ci-all: ci-setup ci-lint ci-test ci-package ## ๐ CI: Run all CI tasks
# ==============================================================================
# UTILITY FUNCTIONS
# ==============================================================================
# Ensure temp directory exists
$(TEMP_DIR):
@mkdir -p $(TEMP_DIR)
# Ensure dist directory exists
$(DIST_DIR):
@mkdir -p $(DIST_DIR)
# Set up directories
.PHONY: setup-dirs
setup-dirs: $(TEMP_DIR) $(DIST_DIR)
# Include setup-dirs as a dependency for targets that need it
test-template: setup-dirs
package: setup-dirs
package-dev: setup-dirs
# ==============================================================================
# PHONY TARGETS
# ==============================================================================
.PHONY: all
all: validate-all test-all package ## ๐ฏ Run full build pipeline
# Mark all targets as phony
.PHONY: $(MAKECMDGOALS)