|
|
@@ -1,14 +1,16 @@
|
|
|
|
#!/bin/bash
|
|
|
|
#!/usr/bin/env bash
|
|
|
|
set -euo pipefail
|
|
|
|
set -euo pipefail
|
|
|
|
|
|
|
|
|
|
|
|
# runmefirst.sh — Full CI/CD pipeline infrastructure install
|
|
|
|
# runmefirst.sh — Full CI/CD pipeline infrastructure install
|
|
|
|
# Installs: Gitea config → Woodpecker CI → ArgoCD → Kargo
|
|
|
|
# Installs: Gitea config → Woodpecker CI → ArgoCD → Kargo
|
|
|
|
# Tears down ARC first (if present)
|
|
|
|
|
|
|
|
# Persists state on NFS volumes at nfs://192.168.42.8:/volume1/Kubernetes/pipelines
|
|
|
|
# Persists state on NFS volumes at nfs://192.168.42.8:/volume1/Kubernetes/pipelines
|
|
|
|
|
|
|
|
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
|
cd "$SCRIPT_DIR"
|
|
|
|
cd "$SCRIPT_DIR"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
GITEA_AUTH="Authorization: Basic $(echo -n 'admin:St0nks0racl3!' | base64)"
|
|
|
|
|
|
|
|
GITEA_API="http://10.1.1.12:30300/api/v1"
|
|
|
|
|
|
|
|
|
|
|
|
# -------------------------------------------------------
|
|
|
|
# -------------------------------------------------------
|
|
|
|
# 1. Create namespaces
|
|
|
|
# 1. Create namespaces
|
|
|
|
# -------------------------------------------------------
|
|
|
|
# -------------------------------------------------------
|
|
|
@@ -20,10 +22,11 @@ done
|
|
|
|
echo ""
|
|
|
|
echo ""
|
|
|
|
|
|
|
|
|
|
|
|
# -------------------------------------------------------
|
|
|
|
# -------------------------------------------------------
|
|
|
|
# 1b. Ensure proxy-ca-cert ConfigMap exists in pipeline namespaces
|
|
|
|
# 2. Ensure proxy-ca-cert ConfigMap + Kyverno policies
|
|
|
|
# -------------------------------------------------------
|
|
|
|
# -------------------------------------------------------
|
|
|
|
echo "--- Step 1b: Ensuring proxy CA cert ConfigMap ---"
|
|
|
|
echo "--- Step 2: Proxy CA cert and Kyverno policies ---"
|
|
|
|
CA_CERT_PATH="/home/celes/nixos-goblin-1-2-3/home.crt"
|
|
|
|
CA_CERT_PATH="${SCRIPT_DIR}/home.crt"
|
|
|
|
|
|
|
|
curl -sf http://192.168.42.1/home.crt -o "$CA_CERT_PATH"
|
|
|
|
for ns in woodpecker argocd kargo; do
|
|
|
|
for ns in woodpecker argocd kargo; do
|
|
|
|
if ! kubectl get configmap proxy-ca-cert -n "$ns" > /dev/null 2>&1; then
|
|
|
|
if ! kubectl get configmap proxy-ca-cert -n "$ns" > /dev/null 2>&1; then
|
|
|
|
kubectl create configmap proxy-ca-cert --from-file=ca.crt="$CA_CERT_PATH" -n "$ns"
|
|
|
|
kubectl create configmap proxy-ca-cert --from-file=ca.crt="$CA_CERT_PATH" -n "$ns"
|
|
|
@@ -32,12 +35,23 @@ for ns in woodpecker argocd kargo; do
|
|
|
|
echo " ✓ proxy-ca-cert already exists in $ns"
|
|
|
|
echo " ✓ proxy-ca-cert already exists in $ns"
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
done
|
|
|
|
|
|
|
|
# Apply Kyverno policy BEFORE Woodpecker install so pods get injected on creation
|
|
|
|
|
|
|
|
kubectl apply -f woodpecker/kyverno-proxy-ca.yaml
|
|
|
|
|
|
|
|
echo " ✓ Kyverno woodpecker-proxy-ca policy applied"
|
|
|
|
|
|
|
|
# Docker Hub auth for builder pods (avoids rate limits)
|
|
|
|
|
|
|
|
if ! kubectl get secret dockerhub-config -n woodpecker > /dev/null 2>&1; then
|
|
|
|
|
|
|
|
kubectl create secret generic dockerhub-config -n woodpecker \
|
|
|
|
|
|
|
|
--from-literal=config.json='{"auths":{"https://index.docker.io/v1/":{"auth":"'"$(echo -n 'celesrenata:dckr_pat_rDJs5PbzGll_jyFyL9_NGEk_bJI' | base64)"'"}}}'
|
|
|
|
|
|
|
|
echo " ✓ dockerhub-config secret created"
|
|
|
|
|
|
|
|
else
|
|
|
|
|
|
|
|
echo " ✓ dockerhub-config secret already exists"
|
|
|
|
|
|
|
|
fi
|
|
|
|
echo ""
|
|
|
|
echo ""
|
|
|
|
|
|
|
|
|
|
|
|
# -------------------------------------------------------
|
|
|
|
# -------------------------------------------------------
|
|
|
|
# 2. Apply NFS PersistentVolumes
|
|
|
|
# 3. Apply NFS PersistentVolumes
|
|
|
|
# -------------------------------------------------------
|
|
|
|
# -------------------------------------------------------
|
|
|
|
echo "--- Step 2: Applying NFS PersistentVolumes ---"
|
|
|
|
echo "--- Step 3: Applying NFS PersistentVolumes ---"
|
|
|
|
kubectl apply -f pvs/argocd-pv.yaml
|
|
|
|
kubectl apply -f pvs/argocd-pv.yaml
|
|
|
|
kubectl apply -f pvs/kargo-pv.yaml
|
|
|
|
kubectl apply -f pvs/kargo-pv.yaml
|
|
|
|
kubectl apply -f pvs/woodpecker-pv.yaml
|
|
|
|
kubectl apply -f pvs/woodpecker-pv.yaml
|
|
|
@@ -45,45 +59,39 @@ echo " ✓ PVs applied"
|
|
|
|
echo ""
|
|
|
|
echo ""
|
|
|
|
|
|
|
|
|
|
|
|
# -------------------------------------------------------
|
|
|
|
# -------------------------------------------------------
|
|
|
|
# 3. Configure Gitea (admin user, repo, webhook config)
|
|
|
|
# 4. Configure Gitea (admin user, repo, webhook config)
|
|
|
|
# -------------------------------------------------------
|
|
|
|
# -------------------------------------------------------
|
|
|
|
echo "--- Step 3: Configuring Gitea ---"
|
|
|
|
echo "--- Step 4: Configuring Gitea ---"
|
|
|
|
bash gitea/setup.sh
|
|
|
|
bash gitea/setup.sh
|
|
|
|
echo " ✓ Gitea configured"
|
|
|
|
echo " ✓ Gitea configured"
|
|
|
|
|
|
|
|
|
|
|
|
# Ensure Gitea allows webhook delivery to local/cluster addresses
|
|
|
|
|
|
|
|
GITEA_POD=$(kubectl get pods -n git-server -l app=gitea -o jsonpath='{.items[0].metadata.name}')
|
|
|
|
GITEA_POD=$(kubectl get pods -n git-server -l app=gitea -o jsonpath='{.items[0].metadata.name}')
|
|
|
|
if ! kubectl exec -n git-server "$GITEA_POD" -- grep -q '\[webhook\]' /data/gitea/conf/app.ini 2>/dev/null; then
|
|
|
|
if ! kubectl exec -n git-server "$GITEA_POD" -- grep -q '\[webhook\]' /data/gitea/conf/app.ini 2>/dev/null; then
|
|
|
|
kubectl exec -n git-server "$GITEA_POD" -- sh -c 'printf "\n[webhook]\nALLOWED_HOST_LIST = *\nSKIP_TLS_VERIFY = true\n" >> /data/gitea/conf/app.ini'
|
|
|
|
kubectl exec -n git-server "$GITEA_POD" -- sh -c 'printf "\n[webhook]\nALLOWED_HOST_LIST = *\nSKIP_TLS_VERIFY = true\n" >> /data/gitea/conf/app.ini'
|
|
|
|
kubectl rollout restart deployment/gitea -n git-server
|
|
|
|
kubectl rollout restart deployment/gitea -n git-server
|
|
|
|
kubectl rollout status deployment/gitea -n git-server --timeout=60s
|
|
|
|
kubectl rollout status deployment/gitea -n git-server --timeout=60s
|
|
|
|
echo " ✓ Gitea webhook config added (ALLOWED_HOST_LIST=*)"
|
|
|
|
echo " ✓ Gitea webhook config added"
|
|
|
|
else
|
|
|
|
else
|
|
|
|
echo " ✓ Gitea webhook config already present"
|
|
|
|
echo " ✓ Gitea webhook config already present"
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
echo ""
|
|
|
|
echo ""
|
|
|
|
|
|
|
|
|
|
|
|
# -------------------------------------------------------
|
|
|
|
# -------------------------------------------------------
|
|
|
|
# 4. Install Woodpecker CI via Helm
|
|
|
|
# 5. Install Woodpecker CI via Helm
|
|
|
|
# -------------------------------------------------------
|
|
|
|
# -------------------------------------------------------
|
|
|
|
echo "--- Step 4: Installing Woodpecker CI ---"
|
|
|
|
echo "--- Step 5: Installing Woodpecker CI ---"
|
|
|
|
|
|
|
|
|
|
|
|
# Check if Woodpecker is already installed (upgrade vs fresh install)
|
|
|
|
|
|
|
|
WOODPECKER_EXISTS=$(helm list -n woodpecker -q 2>/dev/null | grep -c woodpecker || true)
|
|
|
|
WOODPECKER_EXISTS=$(helm list -n woodpecker -q 2>/dev/null | grep -c woodpecker || true)
|
|
|
|
|
|
|
|
|
|
|
|
if [ "${WOODPECKER_EXISTS:-0}" -gt 0 ]; then
|
|
|
|
if [ "${WOODPECKER_EXISTS:-0}" -gt 0 ]; then
|
|
|
|
# Upgrade — don't touch OAuth2 credentials, Woodpecker DB already has them
|
|
|
|
|
|
|
|
echo " Woodpecker already installed — upgrading (preserving OAuth2 grants)..."
|
|
|
|
echo " Woodpecker already installed — upgrading (preserving OAuth2 grants)..."
|
|
|
|
helm upgrade woodpecker oci://ghcr.io/woodpecker-ci/helm/woodpecker \
|
|
|
|
helm upgrade woodpecker oci://ghcr.io/woodpecker-ci/helm/woodpecker \
|
|
|
|
--namespace woodpecker \
|
|
|
|
--namespace woodpecker \
|
|
|
|
--values woodpecker/values.yaml \
|
|
|
|
--values woodpecker/values.yaml \
|
|
|
|
--wait --timeout 5m
|
|
|
|
--wait --timeout 5m
|
|
|
|
else
|
|
|
|
else
|
|
|
|
# Fresh install — need fresh OAuth2 credentials from Gitea
|
|
|
|
echo " Fresh Woodpecker install..."
|
|
|
|
echo " Fresh Woodpecker install — creating fresh OAuth2 app..."
|
|
|
|
# Delete stale OAuth2 app in Gitea (if any)
|
|
|
|
# Delete any existing OAuth2 app in Gitea (stale from previous install)
|
|
|
|
|
|
|
|
GITEA_AUTH="Authorization: Basic $(echo -n 'admin:St0nks0racl3!' | base64)"
|
|
|
|
|
|
|
|
GITEA_API="http://10.1.1.12:30300/api/v1"
|
|
|
|
|
|
|
|
EXISTING_APP_ID=$(curl -s -H "$GITEA_AUTH" "$GITEA_API/user/applications/oauth2" | python3 -c '
|
|
|
|
EXISTING_APP_ID=$(curl -s -H "$GITEA_AUTH" "$GITEA_API/user/applications/oauth2" | python3 -c '
|
|
|
|
import sys, json
|
|
|
|
import sys, json
|
|
|
|
for app in json.loads(sys.stdin.read()):
|
|
|
|
for app in json.loads(sys.stdin.read()):
|
|
|
@@ -102,6 +110,7 @@ for app in json.loads(sys.stdin.read()):
|
|
|
|
GITEA_CLIENT_ID=$(echo "$OAUTH2_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin)['client_id'])")
|
|
|
|
GITEA_CLIENT_ID=$(echo "$OAUTH2_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin)['client_id'])")
|
|
|
|
GITEA_CLIENT_SECRET=$(echo "$OAUTH2_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin)['client_secret'])")
|
|
|
|
GITEA_CLIENT_SECRET=$(echo "$OAUTH2_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin)['client_secret'])")
|
|
|
|
echo " ✓ OAuth2 app created (client_id: $GITEA_CLIENT_ID)"
|
|
|
|
echo " ✓ OAuth2 app created (client_id: $GITEA_CLIENT_ID)"
|
|
|
|
|
|
|
|
|
|
|
|
helm install woodpecker oci://ghcr.io/woodpecker-ci/helm/woodpecker \
|
|
|
|
helm install woodpecker oci://ghcr.io/woodpecker-ci/helm/woodpecker \
|
|
|
|
--namespace woodpecker \
|
|
|
|
--namespace woodpecker \
|
|
|
|
--values woodpecker/values.yaml \
|
|
|
|
--values woodpecker/values.yaml \
|
|
|
@@ -109,16 +118,44 @@ for app in json.loads(sys.stdin.read()):
|
|
|
|
--set server.env.WOODPECKER_GITEA_SECRET="${GITEA_CLIENT_SECRET}" \
|
|
|
|
--set server.env.WOODPECKER_GITEA_SECRET="${GITEA_CLIENT_SECRET}" \
|
|
|
|
--wait --timeout 5m
|
|
|
|
--wait --timeout 5m
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
echo " ✓ Woodpecker CI installed"
|
|
|
|
|
|
|
|
echo ""
|
|
|
|
# Apply agent RBAC (grants cluster-admin to default + woodpecker-agent SAs)
|
|
|
|
|
|
|
|
kubectl apply -f woodpecker/agent-rbac.yaml
|
|
|
|
|
|
|
|
echo " ✓ Woodpecker CI installed + RBAC applied"
|
|
|
|
|
|
|
|
|
|
|
|
# -------------------------------------------------------
|
|
|
|
# -------------------------------------------------------
|
|
|
|
# 5. Apply Woodpecker agent RBAC
|
|
|
|
# 5b. Activate repo in Woodpecker (if fresh install)
|
|
|
|
# -------------------------------------------------------
|
|
|
|
# -------------------------------------------------------
|
|
|
|
echo "--- Step 5: Applying Woodpecker agent RBAC and Kyverno policy ---"
|
|
|
|
if [ "${WOODPECKER_EXISTS:-0}" -eq 0 ]; then
|
|
|
|
kubectl apply -f woodpecker/agent-rbac.yaml
|
|
|
|
echo " Activating repo in Woodpecker..."
|
|
|
|
kubectl apply -f woodpecker/kyverno-proxy-ca.yaml
|
|
|
|
# Wait for server to be ready
|
|
|
|
echo " ✓ Agent RBAC and Kyverno proxy CA policy applied"
|
|
|
|
kubectl wait --for=condition=ready pod -l app.kubernetes.io/name=server -n woodpecker --timeout=60s > /dev/null 2>&1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Port-forward to Woodpecker API
|
|
|
|
|
|
|
|
kubectl port-forward -n woodpecker svc/woodpecker-server 18080:80 > /dev/null 2>&1 &
|
|
|
|
|
|
|
|
PF_PID=$!
|
|
|
|
|
|
|
|
sleep 5
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Login via OAuth2 to get a user token — use the Gitea token approach
|
|
|
|
|
|
|
|
# Create a Gitea personal access token for API bootstrap
|
|
|
|
|
|
|
|
GITEA_TOKEN_RESP=$(curl -s -X POST "$GITEA_API/users/admin/tokens" \
|
|
|
|
|
|
|
|
-H "$GITEA_AUTH" -H "Content-Type: application/json" \
|
|
|
|
|
|
|
|
-d '{"name":"woodpecker-bootstrap-'"$(date +%s)"'","scopes":["all"]}')
|
|
|
|
|
|
|
|
GITEA_PAT=$(echo "$GITEA_TOKEN_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin)['sha1'])")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Use Woodpecker's OAuth2 flow to get a session — this is complex via CLI
|
|
|
|
|
|
|
|
# Instead, just tell the user to activate via UI on first install
|
|
|
|
|
|
|
|
echo " ⚠ First install: please log in to https://stonks-ci.celestium.life"
|
|
|
|
|
|
|
|
echo " 1. Activate the admin/stonks-oracle repo"
|
|
|
|
|
|
|
|
echo " 2. Mark it as trusted (Settings → General → Trusted)"
|
|
|
|
|
|
|
|
echo " 3. Add 'github_ssh_key' secret (Settings → Secrets)"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
kill $PF_PID 2>/dev/null || true
|
|
|
|
|
|
|
|
wait $PF_PID 2>/dev/null || true
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Fix webhook to internal URL after user activates
|
|
|
|
|
|
|
|
echo " After activating, run: bash pipelines/fix-webhook.sh"
|
|
|
|
|
|
|
|
fi
|
|
|
|
echo ""
|
|
|
|
echo ""
|
|
|
|
|
|
|
|
|
|
|
|
# -------------------------------------------------------
|
|
|
|
# -------------------------------------------------------
|
|
|
@@ -127,7 +164,6 @@ echo ""
|
|
|
|
echo "--- Step 6: Installing ArgoCD ---"
|
|
|
|
echo "--- Step 6: Installing ArgoCD ---"
|
|
|
|
ARGOCD_EXISTS=$(helm list -n argocd -q 2>/dev/null | grep -c argocd || true)
|
|
|
|
ARGOCD_EXISTS=$(helm list -n argocd -q 2>/dev/null | grep -c argocd || true)
|
|
|
|
if [ "${ARGOCD_EXISTS:-0}" -eq 0 ]; then
|
|
|
|
if [ "${ARGOCD_EXISTS:-0}" -eq 0 ]; then
|
|
|
|
# Fresh install — clean up leftover CRDs and SAs
|
|
|
|
|
|
|
|
kubectl delete crd applications.argoproj.io applicationsets.argoproj.io appprojects.argoproj.io \
|
|
|
|
kubectl delete crd applications.argoproj.io applicationsets.argoproj.io appprojects.argoproj.io \
|
|
|
|
--ignore-not-found --timeout=30s > /dev/null 2>&1 || true
|
|
|
|
--ignore-not-found --timeout=30s > /dev/null 2>&1 || true
|
|
|
|
kubectl delete sa --all -n argocd --ignore-not-found --timeout=10s > /dev/null 2>&1 || true
|
|
|
|
kubectl delete sa --all -n argocd --ignore-not-found --timeout=10s > /dev/null 2>&1 || true
|
|
|
@@ -142,7 +178,6 @@ helm upgrade --install argocd argo/argo-cd \
|
|
|
|
--wait --timeout 5m
|
|
|
|
--wait --timeout 5m
|
|
|
|
echo " ✓ ArgoCD installed"
|
|
|
|
echo " ✓ ArgoCD installed"
|
|
|
|
|
|
|
|
|
|
|
|
# Apply repo secret and Applications
|
|
|
|
|
|
|
|
kubectl apply -f argocd/repo-secret.yaml
|
|
|
|
kubectl apply -f argocd/repo-secret.yaml
|
|
|
|
kubectl apply -f argocd/apps/stonks-beta.yaml
|
|
|
|
kubectl apply -f argocd/apps/stonks-beta.yaml
|
|
|
|
kubectl apply -f argocd/apps/stonks-paper.yaml
|
|
|
|
kubectl apply -f argocd/apps/stonks-paper.yaml
|
|
|
@@ -156,7 +191,6 @@ echo ""
|
|
|
|
echo "--- Step 7: Installing Kargo ---"
|
|
|
|
echo "--- Step 7: Installing Kargo ---"
|
|
|
|
KARGO_EXISTS=$(helm list -n kargo -q 2>/dev/null | grep -c kargo || true)
|
|
|
|
KARGO_EXISTS=$(helm list -n kargo -q 2>/dev/null | grep -c kargo || true)
|
|
|
|
if [ "${KARGO_EXISTS:-0}" -eq 0 ]; then
|
|
|
|
if [ "${KARGO_EXISTS:-0}" -eq 0 ]; then
|
|
|
|
# Fresh install — clean up leftover CRDs and SAs from previous installs
|
|
|
|
|
|
|
|
kubectl delete crd freights.kargo.akuity.io projects.kargo.akuity.io stages.kargo.akuity.io \
|
|
|
|
kubectl delete crd freights.kargo.akuity.io projects.kargo.akuity.io stages.kargo.akuity.io \
|
|
|
|
warehouses.kargo.akuity.io promotions.kargo.akuity.io promotiontasks.kargo.akuity.io \
|
|
|
|
warehouses.kargo.akuity.io promotions.kargo.akuity.io promotiontasks.kargo.akuity.io \
|
|
|
|
clusterpromotiontasks.kargo.akuity.io projectconfigs.kargo.akuity.io \
|
|
|
|
clusterpromotiontasks.kargo.akuity.io projectconfigs.kargo.akuity.io \
|
|
|
@@ -171,7 +205,6 @@ helm upgrade --install kargo oci://ghcr.io/akuity/kargo-charts/kargo \
|
|
|
|
--timeout 5m || true
|
|
|
|
--timeout 5m || true
|
|
|
|
# Kargo chart bug: controller deployment references SA 'kargo-controller' but chart doesn't create it
|
|
|
|
# Kargo chart bug: controller deployment references SA 'kargo-controller' but chart doesn't create it
|
|
|
|
kubectl create serviceaccount kargo-controller -n kargo 2>/dev/null || true
|
|
|
|
kubectl create serviceaccount kargo-controller -n kargo 2>/dev/null || true
|
|
|
|
# Wait for controller to stabilize
|
|
|
|
|
|
|
|
echo " Waiting for kargo-controller..."
|
|
|
|
echo " Waiting for kargo-controller..."
|
|
|
|
for i in $(seq 1 24); do
|
|
|
|
for i in $(seq 1 24); do
|
|
|
|
if kubectl get pods -n kargo -l app.kubernetes.io/component=controller -o jsonpath='{.items[0].status.containerStatuses[0].ready}' 2>/dev/null | grep -q true; then
|
|
|
|
if kubectl get pods -n kargo -l app.kubernetes.io/component=controller -o jsonpath='{.items[0].status.containerStatuses[0].ready}' 2>/dev/null | grep -q true; then
|
|
|
@@ -182,7 +215,6 @@ for i in $(seq 1 24); do
|
|
|
|
done
|
|
|
|
done
|
|
|
|
echo " ✓ Kargo installed"
|
|
|
|
echo " ✓ Kargo installed"
|
|
|
|
|
|
|
|
|
|
|
|
# Apply Kargo resources
|
|
|
|
|
|
|
|
kubectl apply -f kargo/project.yaml
|
|
|
|
kubectl apply -f kargo/project.yaml
|
|
|
|
kubectl apply -f kargo/project-config.yaml
|
|
|
|
kubectl apply -f kargo/project-config.yaml
|
|
|
|
kubectl apply -f kargo/warehouse.yaml
|
|
|
|
kubectl apply -f kargo/warehouse.yaml
|
|
|
|