#!/usr/bin/env bash set -euo pipefail # ── helpers ────────────────────────────────────────────────────────── RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m' log() { echo -e "${GREEN}[OK]${NC} $*"; } warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } err() { echo -e "${RED}[ERR]${NC} $*"; exit 1; } command_exists() { command -v "$1" &>/dev/null; } # ── defaults ───────────────────────────────────────────────────────── NAMESPACE="${NAMESPACE:-app}" RELEASE="${RELEASE:-deploy}" CHART_DIR="${CHART_DIR:-./deploy}" REGISTRY="${REGISTRY:-harbor.gitdata.me/gtateam}" TAG="${TAG:-$(git rev-parse --short HEAD)}" CONFIG_MAP="${CONFIG_MAP:-app-env}" PVC_NAME="${PVC_NAME:-shared-data}" # ── prerequisites ──────────────────────────────────────────────────── command_exists helm || err "helm not found — install via https://helm.sh/docs/intro/install/" command_exists kubectl || err "kubectl not found — install via https://kubernetes.io/docs/tasks/tools/" log "helm $(helm version --short)" log "kubectl $(kubectl version --client --short 2>/dev/null || kubectl version -o json 2>/dev/null | grep gitVersion)" # ── 1. Ensure namespace (not managed by Helm — preserved on uninstall) ── log "Ensuring namespace $NAMESPACE exists..." kubectl create namespace "$NAMESPACE" --dry-run=client -o yaml | kubectl apply -f - # ── 2. Ensure prerequisites ───────────────────────────────────────── if ! kubectl get namespace "$NAMESPACE" &>/dev/null; then err "Namespace '$NAMESPACE' not found — create it first: kubectl create namespace $NAMESPACE" fi if ! kubectl get configmap "$CONFIG_MAP" -n "$NAMESPACE" &>/dev/null; then err "ConfigMap '$CONFIG_MAP' not found in namespace '$NAMESPACE' — create it first" fi if ! kubectl get pvc "$PVC_NAME" -n "$NAMESPACE" &>/dev/null; then err "PVC '$PVC_NAME' not found in namespace '$NAMESPACE' — create it first" fi # Protect ConfigMap and PVC from accidental Helm deletion kubectl annotate configmap "$CONFIG_MAP" -n "$NAMESPACE" helm.sh/resource-policy=keep --overwrite kubectl annotate pvc "$PVC_NAME" -n "$NAMESPACE" helm.sh/resource-policy=keep --overwrite # cert-manager ClusterIssuer if ! kubectl get clusterissuer cloudflare-acme-cluster-issuer &>/dev/null; then warn "ClusterIssuer 'cloudflare-acme-cluster-issuer' not found — TLS certificate issuance will fail" fi log "Prerequisites verified" # ── 3. Lint chart ──────────────────────────────────────────────────── log "Linting Helm chart..." helm lint "$CHART_DIR" || err "Helm lint failed" # ── 4. Deploy ──────────────────────────────────────────────────────── log "Deploying release $RELEASE with tag $TAG..." if ! helm upgrade --install "$RELEASE" "$CHART_DIR" \ --namespace "$NAMESPACE" \ --set imageRegistry="$REGISTRY" \ --set imageTag="$TAG" \ --set configMapName="$CONFIG_MAP" \ --set pvcName="$PVC_NAME" \ --timeout 5m; then echo "" err "Deployment FAILED — release preserved for debugging. Debug commands: helm status $RELEASE -n $NAMESPACE kubectl get pods -n $NAMESPACE kubectl logs -n app --previous helm rollback $RELEASE -n $NAMESPACE (rollback to previous release) helm uninstall $RELEASE -n $NAMESPACE (remove failed release)" fi log "Release $RELEASE deployed successfully" # ── 5. Verify ──────────────────────────────────────────────────────── log "Checking deployment status..." kubectl get deployments -n "$NAMESPACE" -l app.kubernetes.io/instance="$RELEASE" kubectl get pods -n "$NAMESPACE" -l app.kubernetes.io/instance="$RELEASE" kubectl get services -n "$NAMESPACE" -l app.kubernetes.io/instance="$RELEASE" kubectl get ingress -n "$NAMESPACE" log "Deployment complete"