migration and deployment aligned
This commit is contained in:
parent
69d9613e22
commit
042deb0f6c
3 changed files with 120 additions and 116 deletions
92
.github/workflows/deploy-postgres-env.yml
vendored
92
.github/workflows/deploy-postgres-env.yml
vendored
|
|
@ -1,92 +0,0 @@
|
|||
name: Deploy Postgres (dev & prod, .env MVP)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- "feature/*"
|
||||
tags:
|
||||
- "*"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: mealcraft-runners
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
# -----------------------------
|
||||
# kubectl
|
||||
# -----------------------------
|
||||
- name: Install kubectl
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y curl ca-certificates gettext
|
||||
curl -LO "https://dl.k8s.io/release/$(curl -sL https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
|
||||
sudo install -m 0755 kubectl /usr/local/bin/kubectl
|
||||
|
||||
- name: Configure kubeconfig (in-cluster)
|
||||
run: |
|
||||
KUBE_HOST="https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT"
|
||||
SA_TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
|
||||
CA_CERT=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
|
||||
|
||||
kubectl config set-cluster microk8s \
|
||||
--server="$KUBE_HOST" \
|
||||
--certificate-authority="$CA_CERT"
|
||||
|
||||
kubectl config set-credentials runner --token="$SA_TOKEN"
|
||||
|
||||
kubectl config set-context runner-context \
|
||||
--cluster=microk8s \
|
||||
--user=runner
|
||||
|
||||
kubectl config use-context runner-context
|
||||
|
||||
# -----------------------------
|
||||
# Decide env
|
||||
# -----------------------------
|
||||
- name: Set environment
|
||||
run: |
|
||||
if [[ "$GITHUB_REF" == refs/heads/main || "$GITHUB_REF" == refs/tags/* ]]; then
|
||||
echo "ENV=prod" >> $GITHUB_ENV
|
||||
echo "NAMESPACE=default" >> $GITHUB_ENV
|
||||
echo "RUNTIME_SECRET=postgres-prod" >> $GITHUB_ENV
|
||||
echo "POSTGRES_HOST=postgres-prod.default.svc.cluster.local" >> $GITHUB_ENV
|
||||
echo "POSTGRES_DB=stripe_invoice" >> $GITHUB_ENV
|
||||
else
|
||||
echo "ENV=dev" >> $GITHUB_ENV
|
||||
echo "NAMESPACE=dev" >> $GITHUB_ENV
|
||||
echo "RUNTIME_SECRET=postgres-dev" >> $GITHUB_ENV
|
||||
echo "POSTGRES_HOST=postgres-dev.dev.svc.cluster.local" >> $GITHUB_ENV
|
||||
echo "POSTGRES_DB=stripe_invoice_dev" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Load DB creds from db/.env
|
||||
run: |
|
||||
set -a
|
||||
source db/.env
|
||||
set +a
|
||||
|
||||
if [[ "$ENV" == "prod" ]]; then
|
||||
USER="$PROD_POSTGRES_USER"
|
||||
PASS="$PROD_POSTGRES_PASSWORD"
|
||||
else
|
||||
USER="$DEV_POSTGRES_USER"
|
||||
PASS="$DEV_POSTGRES_PASSWORD"
|
||||
fi
|
||||
|
||||
DATABASE_URL="postgres://${USER}:${PASS}@${POSTGRES_HOST}:5432/${POSTGRES_DB}?sslmode=disable"
|
||||
|
||||
echo "DATABASE_URL=$DATABASE_URL" >> $GITHUB_ENV
|
||||
|
||||
# -----------------------------
|
||||
# Create runtime secret
|
||||
# -----------------------------
|
||||
- name: Apply runtime DATABASE_URL secret
|
||||
run: |
|
||||
kubectl create secret generic $RUNTIME_SECRET \
|
||||
--namespace $NAMESPACE \
|
||||
--from-literal=DATABASE_URL="$DATABASE_URL" \
|
||||
--dry-run=client -o yaml | kubectl apply -f -
|
||||
96
.github/workflows/stripe-to-invoice.yml
vendored
96
.github/workflows/stripe-to-invoice.yml
vendored
|
|
@ -1,4 +1,4 @@
|
|||
name: Build & Deploy stripe-to-invoice
|
||||
name: Build & Deploy stripe-to-invoice (with DB secrets)
|
||||
|
||||
on:
|
||||
push:
|
||||
|
|
@ -8,10 +8,15 @@ on:
|
|||
- release/**
|
||||
tags:
|
||||
- "*"
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
# --------------------------------------------------
|
||||
# BUILD IMAGE
|
||||
# --------------------------------------------------
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
|
|
@ -35,7 +40,11 @@ jobs:
|
|||
run: |
|
||||
docker push docker.io/kimjunte/stripe_to_invoice:$GITHUB_REF_SLUG
|
||||
|
||||
deploy:
|
||||
# --------------------------------------------------
|
||||
# APPLY DB SECRETS
|
||||
# --------------------------------------------------
|
||||
secrets:
|
||||
name: Apply runtime DB secret
|
||||
runs-on: mealcraft-runners
|
||||
needs: build
|
||||
|
||||
|
|
@ -49,7 +58,81 @@ jobs:
|
|||
curl -LO "https://dl.k8s.io/release/$(curl -sL https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
|
||||
sudo install -m 0755 kubectl /usr/local/bin/kubectl
|
||||
|
||||
- name: Configure kubeconfig
|
||||
- name: Configure kubeconfig (in-cluster)
|
||||
run: |
|
||||
KUBE_HOST="https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT"
|
||||
SA_TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
|
||||
CA_CERT=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt
|
||||
|
||||
kubectl config set-cluster microk8s \
|
||||
--server="$KUBE_HOST" \
|
||||
--certificate-authority="$CA_CERT"
|
||||
|
||||
kubectl config set-credentials runner --token="$SA_TOKEN"
|
||||
|
||||
kubectl config set-context runner-context \
|
||||
--cluster=microk8s \
|
||||
--user=runner
|
||||
|
||||
kubectl config use-context runner-context
|
||||
|
||||
- name: Decide environment
|
||||
run: |
|
||||
if [[ "$GITHUB_REF" == refs/heads/main || "$GITHUB_REF" == refs/tags/* || "$GITHUB_REF" == refs/heads/release/* ]]; then
|
||||
echo "ENV=prod" >> $GITHUB_ENV
|
||||
echo "NAMESPACE=default" >> $GITHUB_ENV
|
||||
echo "RUNTIME_SECRET=postgres-prod" >> $GITHUB_ENV
|
||||
echo "POSTGRES_HOST=postgres-prod.default.svc.cluster.local" >> $GITHUB_ENV
|
||||
echo "POSTGRES_DB=stripe_invoice" >> $GITHUB_ENV
|
||||
else
|
||||
echo "ENV=dev" >> $GITHUB_ENV
|
||||
echo "NAMESPACE=dev" >> $GITHUB_ENV
|
||||
echo "RUNTIME_SECRET=postgres-dev" >> $GITHUB_ENV
|
||||
echo "POSTGRES_HOST=postgres-dev.dev.svc.cluster.local" >> $GITHUB_ENV
|
||||
echo "POSTGRES_DB=stripe_invoice_dev" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Load DB creds from db/.env and apply secret
|
||||
run: |
|
||||
set -a
|
||||
source db/.env
|
||||
set +a
|
||||
|
||||
if [[ "$ENV" == "prod" ]]; then
|
||||
USER="$PROD_POSTGRES_USER"
|
||||
PASS="$PROD_POSTGRES_PASSWORD"
|
||||
else
|
||||
USER="$DEV_POSTGRES_USER"
|
||||
PASS="$DEV_POSTGRES_PASSWORD"
|
||||
fi
|
||||
|
||||
DATABASE_URL="postgres://${USER}:${PASS}@${POSTGRES_HOST}:5432/${POSTGRES_DB}?sslmode=disable"
|
||||
|
||||
kubectl create secret generic $RUNTIME_SECRET \
|
||||
--namespace $NAMESPACE \
|
||||
--from-literal=DATABASE_URL="$DATABASE_URL" \
|
||||
--dry-run=client -o yaml | kubectl apply -f -
|
||||
|
||||
# --------------------------------------------------
|
||||
# DEPLOY APP
|
||||
# --------------------------------------------------
|
||||
deploy:
|
||||
runs-on: mealcraft-runners
|
||||
needs:
|
||||
- build
|
||||
- secrets
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install kubectl
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y curl ca-certificates gettext
|
||||
curl -LO "https://dl.k8s.io/release/$(curl -sL https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
|
||||
sudo install -m 0755 kubectl /usr/local/bin/kubectl
|
||||
|
||||
- name: Configure kubeconfig (in-cluster)
|
||||
run: |
|
||||
KUBE_HOST="https://$KUBERNETES_SERVICE_HOST:$KUBERNETES_SERVICE_PORT"
|
||||
SA_TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)
|
||||
|
|
@ -64,7 +147,7 @@ jobs:
|
|||
- name: Inject slug variables
|
||||
uses: rlespinasse/github-slug-action@v4
|
||||
|
||||
- name: Set environment
|
||||
- name: Decide environment
|
||||
run: |
|
||||
if [[ "$GITHUB_REF" == refs/heads/release/* || "$GITHUB_REF" == refs/tags/* ]]; then
|
||||
echo "NAMESPACE=default" >> $GITHUB_ENV
|
||||
|
|
@ -75,8 +158,9 @@ jobs:
|
|||
echo "DB_ENV=dev" >> $GITHUB_ENV
|
||||
echo "HOSTNAME=stripe-to-invoice.dev.juntekim.com" >> $GITHUB_ENV
|
||||
fi
|
||||
- name: Deploy
|
||||
|
||||
- name: Deploy application
|
||||
run: |
|
||||
export IMAGE="docker.io/kimjunte/stripe_to_invoice:$GITHUB_REF_SLUG"
|
||||
export NAMESPACE DB_ENV
|
||||
export NAMESPACE DB_ENV HOSTNAME
|
||||
envsubst < stripe_to_invoice/deployment/deployment.yaml | kubectl apply -f -
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ mkdir -p "$BACKUP_DIR"
|
|||
# NEVER touch raw Postgres data
|
||||
TAR_EXCLUDES=(
|
||||
"$K8S_STORAGE_ROOT/postgres"
|
||||
"$K8S_STORAGE_ROOT/lost+found"
|
||||
)
|
||||
|
||||
# ==================================================
|
||||
|
|
@ -31,7 +32,7 @@ TAR_EXCLUDES=(
|
|||
# ==================================================
|
||||
case "$ENVIRONMENT" in
|
||||
dev)
|
||||
PG_SECRET_NAME="postgres-secret"
|
||||
PG_SECRET_NAME="postgres-dev"
|
||||
PG_POD_SELECTOR="app=postgres-dev"
|
||||
S3_PREFIX="dev"
|
||||
NAMESPACE="dev"
|
||||
|
|
@ -43,7 +44,7 @@ case "$ENVIRONMENT" in
|
|||
exit 1
|
||||
fi
|
||||
|
||||
PG_SECRET_NAME="postgres-prod-secret"
|
||||
PG_SECRET_NAME="postgres-prod"
|
||||
PG_POD_SELECTOR="app=postgres-prod"
|
||||
S3_PREFIX="prod"
|
||||
NAMESPACE="default"
|
||||
|
|
@ -56,14 +57,15 @@ esac
|
|||
|
||||
echo "=== Backup started ($(date -u)) ==="
|
||||
echo "Environment: $ENVIRONMENT"
|
||||
echo "Namespace: $NAMESPACE"
|
||||
|
||||
# ==================================================
|
||||
# POSTGRES DUMP (SAFE)
|
||||
# LOCATE POSTGRES POD
|
||||
# ==================================================
|
||||
POSTGRES_POD=$(kubectl get pods \
|
||||
-n "$NAMESPACE" \
|
||||
-l "$PG_POD_SELECTOR" \
|
||||
-o jsonpath='{.items[*].metadata.name}' | awk '{print $1}')
|
||||
-o jsonpath='{.items[0].metadata.name}')
|
||||
|
||||
if [[ -z "$POSTGRES_POD" ]]; then
|
||||
echo "❌ No Postgres pod found for selector: $PG_POD_SELECTOR"
|
||||
|
|
@ -71,26 +73,36 @@ if [[ -z "$POSTGRES_POD" ]]; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
POSTGRES_USER=$(kubectl get secret "$PG_SECRET_NAME" \
|
||||
-n "$NAMESPACE" \
|
||||
-o jsonpath='{.data.POSTGRES_USER}' | base64 -d)
|
||||
echo "Using Postgres pod: $POSTGRES_POD"
|
||||
|
||||
POSTGRES_DB=$(kubectl get secret "$PG_SECRET_NAME" \
|
||||
# ==================================================
|
||||
# READ DATABASE_URL FROM SECRET
|
||||
# ==================================================
|
||||
DATABASE_URL=$(kubectl get secret "$PG_SECRET_NAME" \
|
||||
-n "$NAMESPACE" \
|
||||
-o jsonpath='{.data.POSTGRES_DB}' 2>/dev/null | base64 -d || true)
|
||||
-o jsonpath='{.data.DATABASE_URL}' | base64 -d)
|
||||
|
||||
if [[ -z "$POSTGRES_DB" ]]; then
|
||||
echo "❌ POSTGRES_DB missing in secret $PG_SECRET_NAME"
|
||||
if [[ -z "$DATABASE_URL" ]]; then
|
||||
echo "❌ DATABASE_URL missing in secret $PG_SECRET_NAME"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Dumping database: $POSTGRES_DB"
|
||||
# Parse DATABASE_URL
|
||||
POSTGRES_USER="$(echo "$DATABASE_URL" | sed -E 's|.*://([^:]+):.*|\1|')"
|
||||
POSTGRES_DB="$(echo "$DATABASE_URL" | sed -E 's|.*/([^?]+).*|\1|')"
|
||||
|
||||
if [[ -z "$POSTGRES_USER" || -z "$POSTGRES_DB" ]]; then
|
||||
echo "❌ Failed to parse DATABASE_URL"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Dumping database: $POSTGRES_DB (user: $POSTGRES_USER)"
|
||||
|
||||
# ==================================================
|
||||
# POSTGRES LOGICAL DUMP (SAFE)
|
||||
# ==================================================
|
||||
kubectl exec -n "$NAMESPACE" "$POSTGRES_POD" -- \
|
||||
pg_dump \
|
||||
-h localhost \
|
||||
-U "$POSTGRES_USER" \
|
||||
"$POSTGRES_DB" \
|
||||
pg_dump "$POSTGRES_DB" \
|
||||
> "$BACKUP_DIR/postgres.sql"
|
||||
|
||||
echo "✔ pg_dump complete ($(du -h "$BACKUP_DIR/postgres.sql" | cut -f1))"
|
||||
|
|
@ -145,6 +157,6 @@ echo " sudo tar -xzf k8s_storage_$DATE.tar.gz -C /"
|
|||
echo ""
|
||||
echo "Restore Postgres:"
|
||||
echo " kubectl exec -n $NAMESPACE -i $POSTGRES_POD -- \\"
|
||||
echo " psql -U $POSTGRES_USER $POSTGRES_DB < postgres.sql"
|
||||
echo " psql $POSTGRES_DB < postgres.sql"
|
||||
echo ""
|
||||
echo "=== Backup completed successfully ==="
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue