Changeset 0.21.1.1 (#87)
This commit is contained in:
@@ -394,7 +394,7 @@ jobs:
|
||||
|
||||
# ── Determine environment ──────────────────
|
||||
- name: Determine environment
|
||||
id: env
|
||||
id: setup
|
||||
run: |
|
||||
# All environments share one host: switchboard.DOMAIN
|
||||
# Environments are separated by path prefix (BASE_PATH)
|
||||
@@ -472,20 +472,20 @@ jobs:
|
||||
PGPASSWORD: ${{ secrets.POSTGRES_ADMIN_PASSWORD }}
|
||||
APP_USER: ${{ secrets.POSTGRES_USER }}
|
||||
APP_PASSWORD: ${{ secrets.POSTGRES_PASSWORD }}
|
||||
DB_NAME: ${{ steps.env.outputs.DB_NAME }}
|
||||
DB_NAME: ${{ steps.setup.outputs.DB_NAME }}
|
||||
run: |
|
||||
chmod +x scripts/db-bootstrap.sh
|
||||
scripts/db-bootstrap.sh
|
||||
|
||||
# ── Dev: Upgrade Test (dev only) ───────────
|
||||
- name: "Dev: test migration upgrade"
|
||||
if: steps.env.outputs.DB_WIPE == 'true'
|
||||
if: steps.setup.outputs.DB_WIPE == 'true'
|
||||
env:
|
||||
PGHOST: ${{ env.POSTGRES_HOST }}
|
||||
PGPORT: ${{ env.POSTGRES_PORT }}
|
||||
PGUSER: ${{ secrets.POSTGRES_USER }}
|
||||
PGPASSWORD: ${{ secrets.POSTGRES_PASSWORD }}
|
||||
PGDATABASE: ${{ steps.env.outputs.DB_NAME }}
|
||||
PGDATABASE: ${{ steps.setup.outputs.DB_NAME }}
|
||||
run: |
|
||||
echo "━━━ Upgrade test: applying migrations to existing dev DB ━━━"
|
||||
|
||||
@@ -531,28 +531,28 @@ jobs:
|
||||
|
||||
# ── Dev: Validate Schema ───────────────────
|
||||
- name: "Dev: validate schema"
|
||||
if: steps.env.outputs.DB_WIPE == 'true'
|
||||
if: steps.setup.outputs.DB_WIPE == 'true'
|
||||
env:
|
||||
PGHOST: ${{ env.POSTGRES_HOST }}
|
||||
PGPORT: ${{ env.POSTGRES_PORT }}
|
||||
PGUSER: ${{ secrets.POSTGRES_USER }}
|
||||
PGPASSWORD: ${{ secrets.POSTGRES_PASSWORD }}
|
||||
PGDATABASE: ${{ steps.env.outputs.DB_NAME }}
|
||||
PGDATABASE: ${{ steps.setup.outputs.DB_NAME }}
|
||||
run: |
|
||||
chmod +x scripts/db-validate.sh
|
||||
scripts/db-validate.sh
|
||||
|
||||
# ── Dev Wipe (fresh install test) ──────────
|
||||
- name: "Dev: wipe for fresh install test"
|
||||
if: steps.env.outputs.DB_WIPE == 'true'
|
||||
if: steps.setup.outputs.DB_WIPE == 'true'
|
||||
env:
|
||||
PGHOST: ${{ env.POSTGRES_HOST }}
|
||||
PGPORT: ${{ env.POSTGRES_PORT }}
|
||||
PGUSER: ${{ secrets.POSTGRES_USER }}
|
||||
PGPASSWORD: ${{ secrets.POSTGRES_PASSWORD }}
|
||||
PGDATABASE: ${{ steps.env.outputs.DB_NAME }}
|
||||
PGDATABASE: ${{ steps.setup.outputs.DB_NAME }}
|
||||
run: |
|
||||
DB="${{ steps.env.outputs.DB_NAME }}"
|
||||
DB="${{ steps.setup.outputs.DB_NAME }}"
|
||||
|
||||
if [[ "${DB}" != *_dev ]]; then
|
||||
echo "❌ REFUSING to wipe '${DB}' — only *_dev databases can be wiped"
|
||||
@@ -575,46 +575,46 @@ jobs:
|
||||
- name: Build backend image
|
||||
run: |
|
||||
docker build -f server/Dockerfile \
|
||||
-t ${BE_IMAGE}:${{ steps.env.outputs.IMAGE_TAG }} \
|
||||
-t ${BE_IMAGE}:${{ steps.setup.outputs.IMAGE_TAG }} \
|
||||
.
|
||||
|
||||
# ── Build Frontend Image ─────────────────────
|
||||
- name: Build frontend image
|
||||
run: |
|
||||
docker build -f Dockerfile.frontend \
|
||||
-t ${FE_IMAGE}:${{ steps.env.outputs.IMAGE_TAG }} \
|
||||
-t ${FE_IMAGE}:${{ steps.setup.outputs.IMAGE_TAG }} \
|
||||
.
|
||||
|
||||
# ── Tag release versions ─────────────────────
|
||||
- name: Tag release versions
|
||||
if: steps.env.outputs.EXTRA_TAG != ''
|
||||
if: steps.setup.outputs.EXTRA_TAG != ''
|
||||
run: |
|
||||
docker tag ${BE_IMAGE}:${{ steps.env.outputs.IMAGE_TAG }} ${BE_IMAGE}:${{ steps.env.outputs.EXTRA_TAG }}
|
||||
docker tag ${FE_IMAGE}:${{ steps.env.outputs.IMAGE_TAG }} ${FE_IMAGE}:${{ steps.env.outputs.EXTRA_TAG }}
|
||||
docker tag ${BE_IMAGE}:${{ steps.setup.outputs.IMAGE_TAG }} ${BE_IMAGE}:${{ steps.setup.outputs.EXTRA_TAG }}
|
||||
docker tag ${FE_IMAGE}:${{ steps.setup.outputs.IMAGE_TAG }} ${FE_IMAGE}:${{ steps.setup.outputs.EXTRA_TAG }}
|
||||
|
||||
# ── Push to Internal Registry ────────────────
|
||||
- name: Push images
|
||||
run: |
|
||||
docker push ${BE_IMAGE}:${{ steps.env.outputs.IMAGE_TAG }}
|
||||
docker push ${FE_IMAGE}:${{ steps.env.outputs.IMAGE_TAG }}
|
||||
if [[ -n "${{ steps.env.outputs.EXTRA_TAG }}" ]]; then
|
||||
docker push ${BE_IMAGE}:${{ steps.env.outputs.EXTRA_TAG }}
|
||||
docker push ${FE_IMAGE}:${{ steps.env.outputs.EXTRA_TAG }}
|
||||
docker push ${BE_IMAGE}:${{ steps.setup.outputs.IMAGE_TAG }}
|
||||
docker push ${FE_IMAGE}:${{ steps.setup.outputs.IMAGE_TAG }}
|
||||
if [[ -n "${{ steps.setup.outputs.EXTRA_TAG }}" ]]; then
|
||||
docker push ${BE_IMAGE}:${{ steps.setup.outputs.EXTRA_TAG }}
|
||||
docker push ${FE_IMAGE}:${{ steps.setup.outputs.EXTRA_TAG }}
|
||||
fi
|
||||
|
||||
# ── Build + Push Unified to Docker Hub (release only) ──
|
||||
- name: Build and push unified image
|
||||
if: steps.env.outputs.is_release == 'true'
|
||||
if: steps.setup.outputs.is_release == 'true'
|
||||
run: |
|
||||
docker build -f Dockerfile \
|
||||
-t ${DOCKERHUB_IMAGE}:latest \
|
||||
-t ${DOCKERHUB_IMAGE}:${{ steps.env.outputs.EXTRA_TAG }} \
|
||||
-t ${DOCKERHUB_IMAGE}:${{ steps.setup.outputs.EXTRA_TAG }} \
|
||||
.
|
||||
if [[ -n "${{ secrets.DOCKERHUB_TOKEN }}" ]]; then
|
||||
echo "${{ secrets.DOCKERHUB_TOKEN }}" | \
|
||||
docker login -u "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin
|
||||
docker push ${DOCKERHUB_IMAGE}:latest
|
||||
docker push ${DOCKERHUB_IMAGE}:${{ steps.env.outputs.EXTRA_TAG }}
|
||||
docker push ${DOCKERHUB_IMAGE}:${{ steps.setup.outputs.EXTRA_TAG }}
|
||||
else
|
||||
echo "⚠ Docker Hub credentials not configured, skipping push"
|
||||
fi
|
||||
@@ -679,23 +679,23 @@ jobs:
|
||||
|
||||
- name: Render and apply manifests
|
||||
env:
|
||||
ENVIRONMENT: ${{ steps.env.outputs.ENVIRONMENT }}
|
||||
GIN_MODE: ${{ steps.env.outputs.GIN_MODE }}
|
||||
IMAGE_TAG: ${{ steps.env.outputs.IMAGE_TAG }}
|
||||
DEPLOY_SUFFIX: ${{ steps.env.outputs.DEPLOY_SUFFIX }}
|
||||
DEPLOY_HOST: ${{ steps.env.outputs.DEPLOY_HOST }}
|
||||
BASE_PATH: ${{ steps.env.outputs.BASE_PATH }}
|
||||
DB_NAME: ${{ steps.env.outputs.DB_NAME }}
|
||||
FE_REPLICAS: ${{ steps.env.outputs.FE_REPLICAS }}
|
||||
BE_REPLICAS: ${{ steps.env.outputs.BE_REPLICAS }}
|
||||
FE_MEMORY_REQUEST: ${{ steps.env.outputs.FE_MEMORY_REQUEST }}
|
||||
FE_MEMORY_LIMIT: ${{ steps.env.outputs.FE_MEMORY_LIMIT }}
|
||||
FE_CPU_REQUEST: ${{ steps.env.outputs.FE_CPU_REQUEST }}
|
||||
FE_CPU_LIMIT: ${{ steps.env.outputs.FE_CPU_LIMIT }}
|
||||
BE_MEMORY_REQUEST: ${{ steps.env.outputs.BE_MEMORY_REQUEST }}
|
||||
BE_MEMORY_LIMIT: ${{ steps.env.outputs.BE_MEMORY_LIMIT }}
|
||||
BE_CPU_REQUEST: ${{ steps.env.outputs.BE_CPU_REQUEST }}
|
||||
BE_CPU_LIMIT: ${{ steps.env.outputs.BE_CPU_LIMIT }}
|
||||
ENVIRONMENT: ${{ steps.setup.outputs.ENVIRONMENT }}
|
||||
GIN_MODE: ${{ steps.setup.outputs.GIN_MODE }}
|
||||
IMAGE_TAG: ${{ steps.setup.outputs.IMAGE_TAG }}
|
||||
DEPLOY_SUFFIX: ${{ steps.setup.outputs.DEPLOY_SUFFIX }}
|
||||
DEPLOY_HOST: ${{ steps.setup.outputs.DEPLOY_HOST }}
|
||||
BASE_PATH: ${{ steps.setup.outputs.BASE_PATH }}
|
||||
DB_NAME: ${{ steps.setup.outputs.DB_NAME }}
|
||||
FE_REPLICAS: ${{ steps.setup.outputs.FE_REPLICAS }}
|
||||
BE_REPLICAS: ${{ steps.setup.outputs.BE_REPLICAS }}
|
||||
FE_MEMORY_REQUEST: ${{ steps.setup.outputs.FE_MEMORY_REQUEST }}
|
||||
FE_MEMORY_LIMIT: ${{ steps.setup.outputs.FE_MEMORY_LIMIT }}
|
||||
FE_CPU_REQUEST: ${{ steps.setup.outputs.FE_CPU_REQUEST }}
|
||||
FE_CPU_LIMIT: ${{ steps.setup.outputs.FE_CPU_LIMIT }}
|
||||
BE_MEMORY_REQUEST: ${{ steps.setup.outputs.BE_MEMORY_REQUEST }}
|
||||
BE_MEMORY_LIMIT: ${{ steps.setup.outputs.BE_MEMORY_LIMIT }}
|
||||
BE_CPU_REQUEST: ${{ steps.setup.outputs.BE_CPU_REQUEST }}
|
||||
BE_CPU_LIMIT: ${{ steps.setup.outputs.BE_CPU_LIMIT }}
|
||||
# Storage (v0.12.0+)
|
||||
STORAGE_CLASS: ${{ vars.STORAGE_CLASS }}
|
||||
STORAGE_SIZE: ${{ vars.STORAGE_SIZE || '10Gi' }}
|
||||
@@ -727,8 +727,8 @@ jobs:
|
||||
|
||||
- name: Rollout and verify
|
||||
env:
|
||||
SUFFIX: ${{ steps.env.outputs.DEPLOY_SUFFIX }}
|
||||
ENV: ${{ steps.env.outputs.ENVIRONMENT }}
|
||||
SUFFIX: ${{ steps.setup.outputs.DEPLOY_SUFFIX }}
|
||||
ENV: ${{ steps.setup.outputs.ENVIRONMENT }}
|
||||
run: |
|
||||
kubectl rollout restart deployment/switchboard-be${SUFFIX} -n ${NAMESPACE}
|
||||
kubectl rollout restart deployment/switchboard-fe${SUFFIX} -n ${NAMESPACE}
|
||||
@@ -753,36 +753,46 @@ jobs:
|
||||
|
||||
# ── Post-deploy: verify schema ─────────────
|
||||
- name: Verify schema migration
|
||||
env:
|
||||
EXPECTED_DB: ${{ steps.setup.outputs.DB_NAME }}
|
||||
run: |
|
||||
sleep 5
|
||||
HOST="${{ steps.env.outputs.DEPLOY_HOST }}"
|
||||
BP="${{ steps.env.outputs.BASE_PATH }}"
|
||||
HEALTH=$(curl -sf "https://${HOST}${BP}/api/v1/health" 2>/dev/null || echo "unreachable")
|
||||
HOST="${{ steps.setup.outputs.DEPLOY_HOST }}"
|
||||
BP="${{ steps.setup.outputs.BASE_PATH }}"
|
||||
HEALTH=$(curl -sf "https://${HOST}${BP}/health" 2>/dev/null || echo "unreachable")
|
||||
echo "Health: ${HEALTH}"
|
||||
|
||||
SCHEMA=$(echo "${HEALTH}" | grep -o '"schema_version":"[^"]*"' | cut -d'"' -f4 || true)
|
||||
DB_OK=$(echo "${HEALTH}" | grep -o '"database":true' || true)
|
||||
ACTUAL_DB=$(echo "${HEALTH}" | grep -o '"database_name":"[^"]*"' | cut -d'"' -f4 || true)
|
||||
|
||||
if [[ -n "${SCHEMA}" ]] && [[ -n "${DB_OK}" ]]; then
|
||||
echo "✅ Schema: ${SCHEMA} | DB: connected"
|
||||
echo "✅ Schema: ${SCHEMA} | DB: ${ACTUAL_DB}"
|
||||
else
|
||||
echo "⚠ Could not verify schema (backend may still be starting)"
|
||||
echo " Response: ${HEALTH:0:200}"
|
||||
fi
|
||||
|
||||
# Verify the backend connected to the correct database
|
||||
if [[ -n "${ACTUAL_DB}" ]] && [[ "${ACTUAL_DB}" != "${EXPECTED_DB}" ]]; then
|
||||
echo "❌ DATABASE MISMATCH: expected=${EXPECTED_DB} actual=${ACTUAL_DB}"
|
||||
echo " The backend is connected to the WRONG database!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Summary
|
||||
run: |
|
||||
HOST="${{ steps.env.outputs.DEPLOY_HOST }}"
|
||||
BP="${{ steps.env.outputs.BASE_PATH }}"
|
||||
echo "## ✅ Deployed to ${{ steps.env.outputs.env_label }}" >> $GITHUB_STEP_SUMMARY
|
||||
HOST="${{ steps.setup.outputs.DEPLOY_HOST }}"
|
||||
BP="${{ steps.setup.outputs.BASE_PATH }}"
|
||||
echo "## ✅ Deployed to ${{ steps.setup.outputs.env_label }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| | |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "|---|---|" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| **URL** | https://${HOST}${BP}/ |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| **Backend** | \`${BE_IMAGE}:${{ steps.env.outputs.IMAGE_TAG }}\` |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| **Frontend** | \`${FE_IMAGE}:${{ steps.env.outputs.IMAGE_TAG }}\` |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| **Database** | \`${{ steps.env.outputs.DB_NAME }}\` |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| **DB Wipe** | ${{ steps.env.outputs.DB_WIPE }} |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| **Backend** | \`${BE_IMAGE}:${{ steps.setup.outputs.IMAGE_TAG }}\` |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| **Frontend** | \`${FE_IMAGE}:${{ steps.setup.outputs.IMAGE_TAG }}\` |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| **Database** | \`${{ steps.setup.outputs.DB_NAME }}\` |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| **DB Wipe** | ${{ steps.setup.outputs.DB_WIPE }} |" >> $GITHUB_STEP_SUMMARY
|
||||
if [[ -n "${{ vars.STORAGE_CLASS }}" ]]; then
|
||||
if [[ "${{ vars.STORAGE_BACKEND }}" == "s3" ]]; then
|
||||
echo "| **Storage** | S3 (bucket: ${{ vars.S3_BUCKET }}, PVC scratch: ${{ vars.STORAGE_CLASS }}) |" >> $GITHUB_STEP_SUMMARY
|
||||
@@ -792,6 +802,6 @@ jobs:
|
||||
else
|
||||
echo "| **Storage** | Disabled (STORAGE_CLASS not set) |" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
if [[ "${{ steps.env.outputs.is_release }}" == "true" ]]; then
|
||||
echo "| **Docker Hub** | \`${DOCKERHUB_IMAGE}:${{ steps.env.outputs.EXTRA_TAG }}\` (unified) |" >> $GITHUB_STEP_SUMMARY
|
||||
if [[ "${{ steps.setup.outputs.is_release }}" == "true" ]]; then
|
||||
echo "| **Docker Hub** | \`${DOCKERHUB_IMAGE}:${{ steps.setup.outputs.EXTRA_TAG }}\` (unified) |" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
Reference in New Issue
Block a user