Skip to content

Commit 15675ab

Browse files
authored
Merge pull request #104 from IBM/cicd-improvements
Cicd improvements (minikube, helm, argocd)
2 parents 3a64feb + 634eac2 commit 15675ab

File tree

2 files changed

+230
-91
lines changed

2 files changed

+230
-91
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
minikube-*
12
.htpasswd
23
.env.gcr
34
packages-lock.json

Makefile

Lines changed: 229 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1329,132 +1329,201 @@ ibmcloud-ce-rm:
13291329
# =============================================================================
13301330
# 🧪 MINIKUBE LOCAL CLUSTER
13311331
# =============================================================================
1332+
# A self‑contained block with sensible defaults, overridable via the CLI.
1333+
# App is accessible after: kubectl port-forward svc/mcp-context-forge 8080:80
1334+
# Examples:
1335+
# make minikube-start MINIKUBE_DRIVER=podman
1336+
# make minikube-image-load TAG=v0.1.2
1337+
#
1338+
# # Push via the internal registry (registry addon):
1339+
# # 1️⃣ Discover the randomized host‑port (docker driver only):
1340+
# REG_URL=$(shell minikube -p $(MINIKUBE_PROFILE) service registry -n kube-system --url)
1341+
# # 2️⃣ Tag & push:
1342+
# docker build -t $${REG_URL}/$(PROJECT_NAME):dev .
1343+
# docker push $${REG_URL}/$(PROJECT_NAME):dev
1344+
# # 3️⃣ Reference in manifests:
1345+
# image: $${REG_URL}/$(PROJECT_NAME):dev
1346+
#
1347+
# # If you built a prod image via:
1348+
# # make docker-prod # ⇒ mcpgateway/mcpgateway:latest
1349+
# # Tag & push it into Minikube:
1350+
# docker tag mcpgateway/mcpgateway:latest $${REG_URL}/mcpgateway:latest
1351+
# docker push $${REG_URL}/mcpgateway:latest
1352+
# # Override the Make target variable or patch your Helm values:
1353+
# make minikube-k8s-apply IMAGE=$${REG_URL}/mcpgateway:latest
1354+
# -----------------------------------------------------------------------------
1355+
1356+
# ▸ Tunables (export or pass on the command line)
1357+
MINIKUBE_PROFILE ?= mcpgw # Profile/cluster name
1358+
MINIKUBE_DRIVER ?= docker # docker | podman | hyperkit | virtualbox …
1359+
MINIKUBE_CPUS ?= 4 # vCPUs to allocate
1360+
MINIKUBE_MEMORY ?= 6g # RAM (supports m / g suffix)
1361+
# Enabled addons – tweak to suit your workflow (`minikube addons list`).
1362+
# • ingress / ingress-dns – Ingress controller + CoreDNS wildcard hostnames
1363+
# • metrics-server – HPA / kubectl top
1364+
# • dashboard – Web UI (make minikube-dashboard)
1365+
# • registry – Local Docker registry, *dynamic* host-port
1366+
# • registry-aliases – Adds handy DNS names inside the cluster
1367+
MINIKUBE_ADDONS ?= ingress ingress-dns metrics-server dashboard registry registry-aliases
1368+
# OCI image tag to preload into the cluster.
1369+
# • By default we point to the *local* image built via `make docker-prod`, e.g.
1370+
# mcpgateway/mcpgateway:latest. Override with IMAGE=<repo:tag> to use a
1371+
# remote registry (e.g. ghcr.io/ibm/mcp-context-forge:v0.1.1).
1372+
TAG ?= latest # override with TAG=<ver>
1373+
IMAGE ?= $(IMG):$(TAG) # or IMAGE=ghcr.io/ibm/mcp-context-forge:$(TAG)
1374+
1375+
# -----------------------------------------------------------------------------
1376+
# 🆘 HELP TARGETS (parsed by `make help`)
1377+
# -----------------------------------------------------------------------------
13321378
# help: 🧪 MINIKUBE LOCAL CLUSTER
1333-
# help: minikube-install - Install Minikube (macOS, Linux, or Windows via choco)
1334-
# help: helm-install - Install Helm CLI (macOS, Linux, or Windows)
1335-
# help: minikube-start - Start local Minikube cluster with Ingress + DNS + metrics-server
1336-
# help: minikube-stop - Stop the Minikube cluster
1337-
# help: minikube-delete - Delete the Minikube cluster
1338-
# help: minikube-image-load - Build and load ghcr.io/ibm/mcp-context-forge:latest into Minikube
1339-
# help: minikube-k8s-apply - Apply Kubernetes manifests from k8s/
1340-
# help: minikube-status - Show status of Minikube and ingress pods
1379+
# help: minikube-install - Install Minikube + kubectl (macOS / Linux / Windows)
1380+
# help: minikube-start - Start cluster + enable $(MINIKUBE_ADDONS)
1381+
# help: minikube-stop - Stop the cluster
1382+
# help: minikube-delete - Delete the cluster completely
1383+
# help: minikube-tunnel - Run "minikube tunnel" (LoadBalancer) in foreground
1384+
# help: minikube-dashboard - Print & (best‑effort) open the Kubernetes dashboard URL
1385+
# help: minikube-image-load - Load $(IMAGE) into Minikube container runtime
1386+
# help: minikube-k8s-apply - Apply manifests from k8s/ - access with `kubectl port-forward svc/mcp-context-forge 8080:80`
1387+
# help: minikube-status - Cluster + addon health overview
1388+
# help: minikube-context - Switch kubectl context to Minikube
1389+
# help: minikube-ssh - SSH into the Minikube VM
1390+
# help: minikube-reset - 🚨 delete ➜ start ➜ apply ➜ status (idempotent dev helper)
1391+
# help: minikube-registry-url - Echo the dynamic registry URL (e.g. http://localhost:32790)
13411392

13421393
.PHONY: minikube-install helm-install minikube-start minikube-stop minikube-delete \
1343-
minikube-image-load minikube-k8s-apply minikube-status
1394+
minikube-tunnel minikube-dashboard minikube-image-load minikube-k8s-apply \
1395+
minikube-status minikube-context minikube-ssh minikube-reset minikube-registry-url
13441396

1397+
# -----------------------------------------------------------------------------
1398+
# 🚀 INSTALLATION HELPERS
1399+
# -----------------------------------------------------------------------------
13451400
minikube-install:
13461401
@echo "💻 Detecting OS and installing Minikube + kubectl…"
1347-
@if [ "$$(uname)" = "Darwin" ]; then \
1348-
echo "🍎 Installing via Homebrew…"; \
1402+
@if [ "$(shell uname)" = "Darwin" ]; then \
13491403
brew install minikube kubernetes-cli; \
1350-
elif [ "$$(uname)" = "Linux" ]; then \
1351-
echo "🐧 Installing via direct download…"; \
1352-
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 && \
1353-
sudo install minikube-linux-amd64 /usr/local/bin/minikube && \
1354-
rm minikube-linux-amd64; \
1355-
echo "🔧 Installing kubectl…"; \
1356-
curl -LO "https://dl.k8s.io/release/$$(curl -sL https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" && \
1404+
elif [ "$(shell uname)" = "Linux" ]; then \
1405+
curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 && \
1406+
chmod +x minikube && sudo mv minikube /usr/local/bin/; \
1407+
curl -Lo kubectl "https://dl.k8s.io/release/$$(curl -sL https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" && \
13571408
chmod +x kubectl && sudo mv kubectl /usr/local/bin/; \
13581409
elif command -v powershell.exe >/dev/null; then \
1359-
echo "🪟 Installing via Chocolatey…"; \
1360-
powershell.exe -Command "choco install -y minikube kubernetes-cli"; \
1410+
powershell.exe -NoProfile -Command "choco install -y minikube kubernetes-cli"; \
13611411
else \
1362-
echo "❌ Unsupported OS. Please install manually."; \
1363-
exit 1; \
1364-
fi
1365-
1366-
helm-install:
1367-
@echo "📦 Installing Helm CLI…"
1368-
@if [ "$$(uname)" = "Darwin" ]; then \
1369-
brew install helm; \
1370-
elif [ "$$(uname)" = "Linux" ]; then \
1371-
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash; \
1372-
elif command -v powershell.exe >/dev/null; then \
1373-
powershell.exe -Command "choco install -y kubernetes-helm"; \
1374-
else \
1375-
echo "❌ Unsupported OS. Please install Helm manually."; \
1376-
exit 1; \
1412+
echo "❌ Unsupported OS. Install manually ↗"; exit 1; \
13771413
fi
13781414

1415+
# -----------------------------------------------------------------------------
1416+
# ⏯ LIFECYCLE COMMANDS
1417+
# -----------------------------------------------------------------------------
13791418
minikube-start:
1380-
@echo "🚀 Starting Minikube with profile 'mcpgw'..."
1381-
minikube start \
1382-
--driver=docker \
1383-
--cpus=4 --memory=6g \
1384-
--profile=mcpgw
1385-
@echo "🔌 (Re)enabling required addons…"
1386-
minikube addons enable ingress -p mcpgw
1387-
minikube addons enable ingress-dns -p mcpgw
1388-
minikube addons enable metrics-server -p mcpgw
1419+
@echo "🚀 Starting Minikube profile '$(MINIKUBE_PROFILE)' (driver=$(MINIKUBE_DRIVER)) …"
1420+
minikube start -p $(MINIKUBE_PROFILE) \
1421+
--driver=$(MINIKUBE_DRIVER) \
1422+
--cpus=$(MINIKUBE_CPUS) --memory=$(MINIKUBE_MEMORY)
1423+
@echo "🔌 Enabling addons: $(MINIKUBE_ADDONS)"
1424+
@for addon in $(MINIKUBE_ADDONS); do \
1425+
minikube addons enable $$addon -p $(MINIKUBE_PROFILE); \
1426+
done
13891427

13901428
minikube-stop:
1391-
@echo "🛑 Stopping Minikube cluster..."
1392-
minikube stop -p mcpgw
1429+
@echo "🛑 Stopping Minikube "
1430+
minikube stop -p $(MINIKUBE_PROFILE)
13931431

13941432
minikube-delete:
1395-
@echo "🗑 Deleting Minikube cluster..."
1396-
minikube delete -p mcpgw
1433+
@echo "🗑 Deleting Minikube profile '$(MINIKUBE_PROFILE)' …"
1434+
minikube delete -p $(MINIKUBE_PROFILE)
1435+
1436+
# -----------------------------------------------------------------------------
1437+
# 🛠 UTILITIES
1438+
# -----------------------------------------------------------------------------
1439+
minikube-tunnel:
1440+
@echo "🌐 Starting minikube tunnel (Ctrl+C to quit) …"
1441+
minikube -p $(MINIKUBE_PROFILE) tunnel
1442+
1443+
minikube-dashboard:
1444+
@echo "📊 Fetching dashboard URL …"
1445+
@minikube dashboard -p $(MINIKUBE_PROFILE) --url | { \
1446+
read url; \
1447+
echo "🔗 Dashboard: $$url"; \
1448+
( command -v xdg-open >/dev/null && xdg-open $$url >/dev/null 2>&1 ) || \
1449+
( command -v open >/dev/null && open $$url >/dev/null 2>&1 ) || true; \
1450+
}
1451+
1452+
minikube-context:
1453+
@echo "🎯 Switching kubectl context to Minikube …"
1454+
kubectl config use-context minikube
1455+
1456+
minikube-ssh:
1457+
@echo "🔧 Connecting to Minikube VM (exit with Ctrl+D) …"
1458+
minikube ssh -p $(MINIKUBE_PROFILE)
13971459

1460+
# -----------------------------------------------------------------------------
1461+
# 📦 IMAGE & MANIFEST HANDLING
1462+
# -----------------------------------------------------------------------------
13981463
minikube-image-load:
1399-
@echo "📦 Loading image into Minikube (must be pre-built)..."
1400-
@if ! docker image inspect ghcr.io/ibm/mcp-context-forge:latest >/dev/null 2>&1; then \
1401-
echo "❌ Image ghcr.io/ibm/mcp-context-forge:latest not found. Download or build it first."; \
1402-
exit 1; \
1464+
@echo "📦 Loading $(IMAGE) into Minikube …"
1465+
@if ! docker image inspect $(IMAGE) >/dev/null 2>&1; then \
1466+
echo "$(IMAGE) not found locally. Build or pull it first."; exit 1; \
14031467
fi
1404-
minikube image load ghcr.io/ibm/mcp-context-forge:latest -p mcpgw
1405-
@echo "🔍 Verifying image presence inside Minikube..."
1406-
minikube ssh -p mcpgw "sudo crictl images | grep ghcr.io/ibm/mcp-context-forge || echo '❌ Image not found in Minikube runtime'"
1468+
minikube image load $(IMAGE) -p $(MINIKUBE_PROFILE)
14071469

14081470
minikube-k8s-apply:
1409-
@echo "🧩 Applying Kubernetes manifests..."
1410-
kubectl apply -f k8s/postgres-config.yaml || true
1411-
kubectl apply -f k8s/postgres-pv.yaml || true
1412-
kubectl apply -f k8s/postgres-pvc.yaml || true
1413-
kubectl apply -f k8s/postgres-deployment.yaml
1414-
kubectl apply -f k8s/postgres-service.yaml
1415-
kubectl apply -f k8s/redis-deployment.yaml
1416-
kubectl apply -f k8s/redis-service.yaml
1417-
kubectl apply -f k8s/mcp-context-forge-deployment.yaml
1418-
kubectl apply -f k8s/mcp-context-forge-service.yaml
1419-
kubectl apply -f k8s/mcp-context-forge-ingress.yaml
1420-
minikube status -p mcpgw
1421-
1422-
minikube-status:
1423-
@echo "📊 Minikube cluster status:"
1424-
minikube status -p mcpgw
1471+
@echo "🧩 Applying k8s manifests in ./k8s …"
1472+
@kubectl apply -f k8s/ --recursive
14251473

1426-
@echo "\n📦 Addon status (ingress, ingress-dns, metrics-server):"
1427-
minikube addons list | grep -E 'ingress|ingress-dns|metrics-server'
1428-
1429-
@echo "\n🚦 Ingress controller pods:"
1430-
kubectl get pods -n ingress-nginx -o wide || true
1431-
1432-
@echo "\n🧭 Ingress-DNS pods (coredns):"
1433-
kubectl get pods -n kube-system -l k8s-app=kube-dns -o wide || true
1474+
# -----------------------------------------------------------------------------
1475+
# 🔍 Utility: print the current registry URL (host‑port) – works after cluster
1476+
# + registry addon are up.
1477+
# -----------------------------------------------------------------------------
1478+
minikube-registry-url:
1479+
@echo "📦 Internal registry URL:" && \
1480+
minikube -p $(MINIKUBE_PROFILE) service registry -n kube-system --url || \
1481+
echo "⚠️ Registry addon not ready – run make minikube-start first."
14341482

1435-
@echo "\n🧩 Application services:"
1436-
kubectl get svc || true
1483+
# -----------------------------------------------------------------------------
1484+
# 📊 INSPECTION & RESET
1485+
# -----------------------------------------------------------------------------
1486+
minikube-status:
1487+
@echo "📊 Minikube cluster status:" && minikube status -p $(MINIKUBE_PROFILE)
1488+
@echo "\n📦 Addon status:" && minikube addons list | grep -E "$(subst $(space),|,$(MINIKUBE_ADDONS))"
1489+
@echo "\n🚦 Ingress controller:" && kubectl get pods -n ingress-nginx -o wide || true
1490+
@echo "\n🔍 Dashboard:" && kubectl get pods -n kubernetes-dashboard -o wide || true
1491+
@echo "\n🧩 Services:" && kubectl get svc || true
1492+
@echo "\n🌐 Ingress:" && kubectl get ingress || true
14371493

1438-
@echo "\n🌐 Application ingress:"
1439-
kubectl get ingress || true
1494+
minikube-reset: minikube-delete minikube-start minikube-image-load minikube-k8s-apply minikube-status
1495+
@echo "✅ Minikube reset complete!"
14401496

14411497
# -----------------------------------------------------------------------------
14421498
# 🛠️ HELM CHART TASKS
14431499
# -----------------------------------------------------------------------------
14441500
# help: 🛠️ HELM CHART TASKS
1501+
# help: helm-install - Install Helm 3 CLI
14451502
# help: helm-lint - Lint the Helm chart (static analysis)
14461503
# help: helm-package - Package the chart into dist/ as mcp-stack-<ver>.tgz
14471504
# help: helm-deploy - Upgrade/Install chart into Minikube (profile mcpgw)
14481505
# help: helm-delete - Uninstall the chart release from Minikube
14491506
# -----------------------------------------------------------------------------
14501507

1451-
.PHONY: helm-lint helm-package helm-deploy helm-delete
1508+
.PHONY: helm-install helm-lint helm-package helm-deploy helm-delete
14521509

14531510
CHART_DIR ?= charts/mcp-stack
14541511
RELEASE_NAME ?= mcp-stack
14551512
NAMESPACE ?= mcp
14561513
VALUES ?= $(CHART_DIR)/values.yaml
14571514

1515+
helm-install:
1516+
@echo "📦 Installing Helm CLI…"
1517+
@if [ "$(shell uname)" = "Darwin" ]; then \
1518+
brew install helm; \
1519+
elif [ "$(shell uname)" = "Linux" ]; then \
1520+
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash; \
1521+
elif command -v powershell.exe >/dev/null; then \
1522+
powershell.exe -NoProfile -Command "choco install -y kubernetes-helm"; \
1523+
else \
1524+
echo "❌ Unsupported OS. Install Helm manually ↗"; exit 1; \
1525+
fi
1526+
14581527
helm-lint:
14591528
@echo "🔍 Helm lint..."
14601529
helm lint $(CHART_DIR)
@@ -1480,19 +1549,88 @@ helm-delete:
14801549
@echo "🗑 Deleting $(RELEASE_NAME) release..."
14811550
helm uninstall $(RELEASE_NAME) -n $(NAMESPACE) || true
14821551

1552+
1553+
# =============================================================================
1554+
# 🚢 ARGO CD – GITOPS
1555+
# TODO: change default to custom namespace (e.g. mcp-gitops)
1556+
# =============================================================================
1557+
# help: 🚢 ARGO CD – GITOPS
1558+
# help: argocd-cli-install - Install Argo CD CLI locally
1559+
# help: argocd-install - Install Argo CD into Minikube (ns=$(ARGOCD_NS))
1560+
# help: argocd-password - Echo initial admin password
1561+
# help: argocd-forward - Port-forward API/UI to http://localhost:$(ARGOCD_PORT)
1562+
# help: argocd-login - Log in to Argo CD CLI (requires argocd-forward)
1563+
# help: argocd-app-bootstrap - Create & auto-sync $(ARGOCD_APP) from $(GIT_REPO)/$(GIT_PATH)
1564+
# help: argocd-app-sync - Manual re-sync of the application
1565+
# -----------------------------------------------------------------------------
1566+
1567+
ARGOCD_NS ?= argocd
1568+
ARGOCD_PORT ?= 8083
1569+
ARGOCD_APP ?= mcp-gateway
1570+
GIT_REPO ?= https://github.com/ibm/mcp-context-forge.git
1571+
GIT_PATH ?= k8s
1572+
1573+
.PHONY: argocd-cli-install argocd-install argocd-password argocd-forward \
1574+
argocd-login argocd-app-bootstrap argocd-app-sync
1575+
1576+
argocd-cli-install:
1577+
@echo "🔧 Installing Argo CD CLI…"
1578+
@if command -v argocd >/dev/null 2>&1; then echo "✅ argocd already present"; \
1579+
elif [ "$$(uname)" = "Darwin" ]; then brew install argocd; \
1580+
elif [ "$$(uname)" = "Linux" ]; then curl -sSL -o /tmp/argocd \
1581+
https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64 && \
1582+
sudo install -m 555 /tmp/argocd /usr/local/bin/argocd; \
1583+
else echo "❌ Unsupported OS – install argocd manually"; exit 1; fi
1584+
1585+
argocd-install:
1586+
@echo "🚀 Installing Argo CD into Minikube…"
1587+
kubectl create namespace $(ARGOCD_NS) --dry-run=client -o yaml | kubectl apply -f -
1588+
kubectl apply -n $(ARGOCD_NS) \
1589+
-f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
1590+
@echo "⏳ Waiting for Argo CD server pod…"
1591+
kubectl -n $(ARGOCD_NS) rollout status deploy/argocd-server
1592+
1593+
argocd-password:
1594+
@kubectl -n $(ARGOCD_NS) get secret argocd-initial-admin-secret \
1595+
-o jsonpath='{.data.password}' | base64 -d ; echo
1596+
1597+
argocd-forward:
1598+
@echo "🌐 Port-forward http://localhost:$(ARGOCD_PORT) → svc/argocd-server:443 (Ctrl-C to stop)…"
1599+
kubectl -n $(ARGOCD_NS) port-forward svc/argocd-server $(ARGOCD_PORT):443
1600+
1601+
argocd-login: argocd-cli-install
1602+
@echo "🔐 Logging into Argo CD CLI…"
1603+
@PASS=$$(kubectl -n $(ARGOCD_NS) get secret argocd-initial-admin-secret -o jsonpath='{.data.password}' | base64 -d); \
1604+
argocd login localhost:$(ARGOCD_PORT) --username admin --password $$PASS --insecure
1605+
1606+
argocd-app-bootstrap:
1607+
@echo "🚀 Creating Argo CD application $(ARGOCD_APP)"
1608+
-argocd app create $(ARGOCD_APP) \
1609+
--repo $(GIT_REPO) \
1610+
--path $(GIT_PATH) \
1611+
--dest-server https://kubernetes.default.svc \
1612+
--dest-namespace default \
1613+
--sync-policy automated \
1614+
--revision HEAD || true
1615+
argocd app sync $(ARGOCD_APP)
1616+
1617+
argocd-app-sync:
1618+
@echo "🔄 Syncing Argo CD application $(ARGOCD_APP)"
1619+
argocd app sync $(ARGOCD_APP)
1620+
14831621
# =============================================================================
14841622
# 🏠 LOCAL PYPI SERVER
14851623
# Currently blocked by: https://github.com/pypiserver/pypiserver/issues/630
14861624
# =============================================================================
14871625
# help: 🏠 LOCAL PYPI SERVER
1488-
# help: local-pypi-install - Install pypiserver for local testing
1489-
# help: local-pypi-start - Start local PyPI server on :8084 (no auth)
1490-
# help: local-pypi-start-auth - Start local PyPI server with basic auth (admin/admin)
1491-
# help: local-pypi-stop - Stop local PyPI server
1492-
# help: local-pypi-upload - Upload existing package to local PyPI (no auth)
1626+
# help: local-pypi-install - Install pypiserver for local testing
1627+
# help: local-pypi-start - Start local PyPI server on :8084 (no auth)
1628+
# help: local-pypi-start-auth - Start local PyPI server with basic auth (admin/admin)
1629+
# help: local-pypi-stop - Stop local PyPI server
1630+
# help: local-pypi-upload - Upload existing package to local PyPI (no auth)
14931631
# help: local-pypi-upload-auth - Upload existing package to local PyPI (with auth)
1494-
# help: local-pypi-test - Install package from local PyPI
1495-
# help: local-pypi-clean - Full cycle: build → upload → install locally
1632+
# help: local-pypi-test - Install package from local PyPI
1633+
# help: local-pypi-clean - Full cycle: build → upload → install locally
14961634

14971635
.PHONY: local-pypi-install local-pypi-start local-pypi-start-auth local-pypi-stop local-pypi-upload \
14981636
local-pypi-upload-auth local-pypi-test local-pypi-clean

0 commit comments

Comments
 (0)