Merge branch 'staging'

This commit is contained in:
Greg
2025-07-01 14:26:21 -07:00
14 changed files with 123 additions and 119 deletions

View File

@@ -7,10 +7,15 @@ on:
- completed - completed
branches: [ develop ] branches: [ develop ]
permissions:
actions: write
contents: write
jobs: jobs:
test-and-promote-to-staging: test-and-promote-to-staging:
name: Test Dev and Auto-Promote to Staging name: Test Dev and Auto-Promote to Staging
runs-on: ubuntu-latest runs-on: ubuntu-latest
environment: development
if: ${{ github.event.workflow_run.conclusion == 'success' }} if: ${{ github.event.workflow_run.conclusion == 'success' }}
steps: steps:
@@ -28,40 +33,20 @@ jobs:
run: | run: |
echo "🧪 Running comprehensive tests on dev environment..." echo "🧪 Running comprehensive tests on dev environment..."
# Test canonical domain first (primary test) # Use the canonical Knative domain
echo "Testing canonical domain: game-2048-dev.game-2048-dev.dev.wa.darknex.us" CANONICAL_URL="https://game-2048-dev.game-2048-dev.${{ secrets.DEV_DOMAIN }}"
canonical_response=$(curl -s -o /dev/null -w "%{http_code}" -L --max-time 30 https://game-2048-dev.game-2048-dev.dev.wa.darknex.us/) echo "Testing canonical domain: $CANONICAL_URL"
canonical_response=$(curl -s -o /dev/null -w "%{http_code}" -L --max-time 30 "$CANONICAL_URL")
if [ "$canonical_response" != "200" ]; then if [ "$canonical_response" != "200" ]; then
echo "❌ Canonical domain returned HTTP $canonical_response" echo "❌ Canonical domain returned HTTP $canonical_response"
exit 1 exit 1
fi fi
echo "✅ Canonical domain accessible" echo "✅ Canonical domain accessible"
# Test SSL certificate on custom domain
echo "Testing SSL certificate on custom domain..."
cert_expiry=$(echo | openssl s_client -servername 2048-dev.wa.darknex.us -connect 2048-dev.wa.darknex.us:443 2>/dev/null | openssl x509 -noout -enddate | cut -d= -f2)
expiry_epoch=$(date -d "$cert_expiry" +%s)
current_epoch=$(date +%s)
days_until_expiry=$(( (expiry_epoch - current_epoch) / 86400 ))
if [ $days_until_expiry -lt 30 ]; then
echo "❌ SSL certificate expires in less than 30 days!"
exit 1
fi
echo "✅ SSL certificate valid for $days_until_expiry days"
# Test custom domain accessibility
echo "Testing custom domain accessibility..."
response_code=$(curl -s -o /dev/null -w "%{http_code}" -L --max-time 30 https://2048-dev.wa.darknex.us/)
if [ "$response_code" != "200" ]; then
echo "❌ Custom domain returned HTTP $response_code"
exit 1
fi
echo "✅ Custom domain accessible"
# Test content validation on canonical domain # Test content validation on canonical domain
echo "Testing content validation on canonical domain..." echo "Testing content validation on canonical domain..."
content=$(curl -s -L --max-time 30 https://game-2048-dev.game-2048-dev.dev.wa.darknex.us/) content=$(curl -s -L --max-time 30 "$CANONICAL_URL")
if ! echo "$content" | grep -q "2048"; then if ! echo "$content" | grep -q "2048"; then
echo "❌ Content missing 2048 title" echo "❌ Content missing 2048 title"
@@ -87,7 +72,7 @@ jobs:
# Test performance on canonical domain # Test performance on canonical domain
echo "Testing performance on canonical domain..." echo "Testing performance on canonical domain..."
response_time=$(curl -s -o /dev/null -w "%{time_total}" -L --max-time 30 https://game-2048-dev.game-2048-dev.dev.wa.darknex.us/) response_time=$(curl -s -o /dev/null -w "%{time_total}" -L --max-time 30 "$CANONICAL_URL")
if (( $(echo "$response_time > 10.0" | bc -l) )); then if (( $(echo "$response_time > 10.0" | bc -l) )); then
echo "❌ Response time too slow: ${response_time}s" echo "❌ Response time too slow: ${response_time}s"
exit 1 exit 1
@@ -134,8 +119,7 @@ jobs:
echo "| Staging Deploy | ⏳ Triggered | Deployment will start automatically |" >> $GITHUB_STEP_SUMMARY echo "| Staging Deploy | ⏳ Triggered | Deployment will start automatically |" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY
echo "### 📋 Tests Performed" >> $GITHUB_STEP_SUMMARY echo "### 📋 Tests Performed" >> $GITHUB_STEP_SUMMARY
echo "- SSL certificate validation" >> $GITHUB_STEP_SUMMARY echo "- Canonical domain accessibility check" >> $GITHUB_STEP_SUMMARY
echo "- Domain accessibility check" >> $GITHUB_STEP_SUMMARY
echo "- Content and functionality validation" >> $GITHUB_STEP_SUMMARY echo "- Content and functionality validation" >> $GITHUB_STEP_SUMMARY
echo "- Performance testing" >> $GITHUB_STEP_SUMMARY echo "- Performance testing" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY

View File

@@ -26,7 +26,7 @@ jobs:
with: with:
registry: ${{ env.REGISTRY }} registry: ${{ env.REGISTRY }}
username: ${{ github.actor }} username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }} password: ${{ secrets.GH_TOKEN }}
- name: Extract metadata - name: Extract metadata
id: meta id: meta

View File

@@ -2,7 +2,7 @@ name: Deploy to Development
on: on:
push: push:
branches: [ main, master ] branches: [ main, master, develop ]
paths: paths:
- 'src/**' - 'src/**'
- 'Dockerfile' - 'Dockerfile'
@@ -29,7 +29,7 @@ jobs:
with: with:
registry: ${{ env.REGISTRY }} registry: ${{ env.REGISTRY }}
username: ${{ github.actor }} username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }} password: ${{ secrets.GH_TOKEN }}
- name: Extract metadata - name: Extract metadata
id: meta id: meta
@@ -59,23 +59,11 @@ jobs:
run: | run: |
echo "🚀 Triggering webhook deployment to development..." echo "🚀 Triggering webhook deployment to development..."
# Prepare deployment payload # Prepare deployment payload (compact JSON to avoid whitespace issues)
PAYLOAD=$(cat <<EOF PAYLOAD='{"environment":"development","image":"${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }}","namespace":"game-2048-dev","service_name":"game-2048-dev","deployment_id":"${{ github.run_id }}-${{ github.run_attempt }}","commit_sha":"${{ github.sha }}","triggered_by":"${{ github.actor }}","timestamp":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"}'
{
"environment": "development",
"image": "${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }}",
"namespace": "game-2048-dev",
"service_name": "game-2048-dev",
"deployment_id": "${{ github.run_id }}-${{ github.run_attempt }}",
"commit_sha": "${{ github.sha }}",
"triggered_by": "${{ github.actor }}",
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
}
EOF
)
# Generate HMAC signature for webhook security # Generate HMAC signature for webhook security
SIGNATURE=$(echo -n "$PAYLOAD" | openssl dgst -sha256 -hmac "${{ secrets.WEBHOOK_SECRET }}" -binary | base64) SIGNATURE=$(echo -n "$PAYLOAD" | openssl dgst -sha256 -hmac "${{ secrets.WEBHOOK_SECRET }}" | sed 's/^.* //')
# Send webhook # Send webhook
HTTP_CODE=$(curl -s -o /tmp/webhook_response.json -w "%{http_code}" \ HTTP_CODE=$(curl -s -o /tmp/webhook_response.json -w "%{http_code}" \
@@ -108,9 +96,8 @@ jobs:
MAX_RETRIES=10 MAX_RETRIES=10
RETRY_COUNT=0 RETRY_COUNT=0
# Get the canonical Knative domain for health check # Use the canonical Knative domain for health check
# Format: service-name.namespace.knative-domain HEALTH_URL="https://game-2048-dev.game-2048-dev.${{ secrets.DEV_DOMAIN }}"
HEALTH_URL="https://game-2048-dev.game-2048-dev.${{ secrets.KNATIVE_DOMAIN }}"
while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
echo "Attempt $((RETRY_COUNT + 1))/$MAX_RETRIES - Checking: $HEALTH_URL" echo "Attempt $((RETRY_COUNT + 1))/$MAX_RETRIES - Checking: $HEALTH_URL"
@@ -143,7 +130,7 @@ jobs:
if [ "${{ job.status }}" = "success" ]; then if [ "${{ job.status }}" = "success" ]; then
echo "- **Status:** ✅ Success" >> $GITHUB_STEP_SUMMARY echo "- **Status:** ✅ Success" >> $GITHUB_STEP_SUMMARY
echo "- **URL:** https://game-2048-dev.game-2048-dev.${{ secrets.KNATIVE_DOMAIN }}" >> $GITHUB_STEP_SUMMARY echo "- **URL:** https://game-2048-dev.game-2048-dev.${{ secrets.DEV_DOMAIN }}" >> $GITHUB_STEP_SUMMARY
else else
echo "- **Status:** ❌ Failed" >> $GITHUB_STEP_SUMMARY echo "- **Status:** ❌ Failed" >> $GITHUB_STEP_SUMMARY
fi fi

View File

@@ -116,8 +116,8 @@ jobs:
MAX_RETRIES=10 MAX_RETRIES=10
RETRY_COUNT=0 RETRY_COUNT=0
# Get the canonical Knative domain for health check # Use the canonical Knative domain for health check
HEALTH_URL="https://game-2048-prod.game-2048-prod.${{ secrets.KNATIVE_DOMAIN }}" HEALTH_URL="https://game-2048-prod.game-2048-prod.${{ secrets.PROD_DOMAIN }}"
while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
echo "Attempt $((RETRY_COUNT + 1))/$MAX_RETRIES - Checking: $HEALTH_URL" echo "Attempt $((RETRY_COUNT + 1))/$MAX_RETRIES - Checking: $HEALTH_URL"
@@ -172,10 +172,10 @@ jobs:
if [ "${{ job.status }}" = "success" ]; then if [ "${{ job.status }}" = "success" ]; then
echo "- **Status:** ✅ **LIVE IN PRODUCTION**" >> $GITHUB_STEP_SUMMARY echo "- **Status:** ✅ **LIVE IN PRODUCTION**" >> $GITHUB_STEP_SUMMARY
echo "- **URL:** https://game-2048-prod.game-2048-prod.${{ secrets.KNATIVE_DOMAIN }}" >> $GITHUB_STEP_SUMMARY echo "- **URL:** https://game-2048-prod.game-2048-prod.${{ secrets.PROD_DOMAIN }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY
echo "### 🎉 Production is Live!" >> $GITHUB_STEP_SUMMARY echo "### 🎉 Production is Live!" >> $GITHUB_STEP_SUMMARY
echo "- 🎮 [Play the game](https://game-2048-prod.game-2048-prod.${{ secrets.KNATIVE_DOMAIN }})" >> $GITHUB_STEP_SUMMARY echo "- 🎮 [Play the game](https://game-2048-prod.game-2048-prod.${{ secrets.PROD_DOMAIN }})" >> $GITHUB_STEP_SUMMARY
echo "- 🧪 [Run smoke tests](https://github.com/${{ github.repository }}/actions/workflows/smoke-test.yml)" >> $GITHUB_STEP_SUMMARY echo "- 🧪 [Run smoke tests](https://github.com/${{ github.repository }}/actions/workflows/smoke-test.yml)" >> $GITHUB_STEP_SUMMARY
else else
echo "- **Status:** ❌ Failed" >> $GITHUB_STEP_SUMMARY echo "- **Status:** ❌ Failed" >> $GITHUB_STEP_SUMMARY

View File

@@ -93,8 +93,8 @@ jobs:
MAX_RETRIES=10 MAX_RETRIES=10
RETRY_COUNT=0 RETRY_COUNT=0
# Get the canonical Knative domain for health check # Use the canonical Knative domain for health check
HEALTH_URL="https://game-2048-staging.game-2048-staging.${{ secrets.KNATIVE_DOMAIN }}" HEALTH_URL="https://game-2048-staging.game-2048-staging.${{ secrets.STAGING_DOMAIN }}"
while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do
echo "Attempt $((RETRY_COUNT + 1))/$MAX_RETRIES - Checking: $HEALTH_URL" echo "Attempt $((RETRY_COUNT + 1))/$MAX_RETRIES - Checking: $HEALTH_URL"
@@ -133,7 +133,7 @@ jobs:
if [ "${{ job.status }}" = "success" ]; then if [ "${{ job.status }}" = "success" ]; then
echo "- **Status:** ✅ Success" >> $GITHUB_STEP_SUMMARY echo "- **Status:** ✅ Success" >> $GITHUB_STEP_SUMMARY
echo "- **URL:** https://game-2048-staging.game-2048-staging.${{ secrets.KNATIVE_DOMAIN }}" >> $GITHUB_STEP_SUMMARY echo "- **URL:** https://game-2048-staging.game-2048-staging.${{ secrets.STAGING_DOMAIN }}" >> $GITHUB_STEP_SUMMARY
else else
echo "- **Status:** ❌ Failed" >> $GITHUB_STEP_SUMMARY echo "- **Status:** ❌ Failed" >> $GITHUB_STEP_SUMMARY
fi fi

View File

@@ -11,6 +11,7 @@ jobs:
test-staging-and-promote-to-main: test-staging-and-promote-to-main:
name: Test Staging and Promote to Main name: Test Staging and Promote to Main
runs-on: ubuntu-latest runs-on: ubuntu-latest
environment: staging
if: ${{ github.event.workflow_run.conclusion == 'success' }} if: ${{ github.event.workflow_run.conclusion == 'success' }}
steps: steps:
@@ -28,27 +29,20 @@ jobs:
run: | run: |
echo "🧪 Running comprehensive tests on staging environment..." echo "🧪 Running comprehensive tests on staging environment..."
# Test canonical staging domain first (primary test) # Use the canonical Knative domain for staging
echo "Testing canonical staging domain: game-2048-staging.game-2048-staging.staging.wa.darknex.us" CANONICAL_URL="https://game-2048-staging.game-2048-staging.${{ secrets.STAGING_DOMAIN }}"
canonical_response=$(curl -s -o /dev/null -w "%{http_code}" -L --max-time 30 https://game-2048-staging.game-2048-staging.staging.wa.darknex.us/) echo "Testing canonical staging domain: $CANONICAL_URL"
canonical_response=$(curl -s -o /dev/null -w "%{http_code}" -L --max-time 30 "$CANONICAL_URL")
if [ "$canonical_response" != "200" ]; then if [ "$canonical_response" != "200" ]; then
echo "❌ Staging canonical domain returned HTTP $canonical_response" echo "❌ Staging canonical domain returned HTTP $canonical_response"
exit 1 exit 1
fi fi
echo "✅ Staging canonical domain accessible" echo "✅ Staging canonical domain accessible"
# Test custom staging domain
echo "Testing custom staging domain: 2048-staging.wa.darknex.us"
response_code=$(curl -s -o /dev/null -w "%{http_code}" -L --max-time 30 https://2048-staging.wa.darknex.us/)
if [ "$response_code" != "200" ]; then
echo "❌ Staging custom domain returned HTTP $response_code"
exit 1
fi
echo "✅ Staging custom domain accessible"
# Test staging content validation on canonical domain # Test staging content validation on canonical domain
echo "Testing staging content validation..." echo "Testing staging content validation..."
content=$(curl -s -L --max-time 30 https://game-2048-staging.game-2048-staging.staging.wa.darknex.us/) content=$(curl -s -L --max-time 30 "$CANONICAL_URL")
if ! echo "$content" | grep -q "2048"; then if ! echo "$content" | grep -q "2048"; then
echo "❌ Content missing 2048 title" echo "❌ Content missing 2048 title"
@@ -74,7 +68,7 @@ jobs:
# Test staging performance on canonical domain # Test staging performance on canonical domain
echo "Testing staging performance..." echo "Testing staging performance..."
response_time=$(curl -s -o /dev/null -w "%{time_total}" -L --max-time 30 https://game-2048-staging.game-2048-staging.staging.wa.darknex.us/) response_time=$(curl -s -o /dev/null -w "%{time_total}" -L --max-time 30 "$CANONICAL_URL")
if (( $(echo "$response_time > 10.0" | bc -l) )); then if (( $(echo "$response_time > 10.0" | bc -l) )); then
echo "❌ Response time too slow: ${response_time}s" echo "❌ Response time too slow: ${response_time}s"
exit 1 exit 1
@@ -127,9 +121,15 @@ jobs:
echo "- Performance testing" >> $GITHUB_STEP_SUMMARY echo "- Performance testing" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY
echo "### 🎮 Deployment Status" >> $GITHUB_STEP_SUMMARY echo "### 🎮 Deployment Status" >> $GITHUB_STEP_SUMMARY
echo "- **Development**: ✅ Live at https://game-2048-dev.game-2048-dev.dev.wa.darknex.us" >> $GITHUB_STEP_SUMMARY
echo "- **Staging**: ✅ Live at https://game-2048-staging.game-2048-staging.staging.wa.darknex.us" >> $GITHUB_STEP_SUMMARY # Use canonical domain format (these are the Knative domains)
echo "- **Production**: 🚀 Deploying to https://game-2048-prod.game-2048-prod.wa.darknex.us" >> $GITHUB_STEP_SUMMARY DEV_URL="https://game-2048-dev.game-2048-dev.dev.wa.darknex.us"
STAGING_URL="https://game-2048-staging.game-2048-staging.staging.wa.darknex.us"
PROD_URL="https://game-2048-prod.game-2048-prod.wa.darknex.us"
echo "- **Development**: ✅ Live at $DEV_URL" >> $GITHUB_STEP_SUMMARY
echo "- **Staging**: ✅ Live at $STAGING_URL" >> $GITHUB_STEP_SUMMARY
echo "- **Production**: 🚀 Deploying to $PROD_URL" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY
echo "### 🔗 Next Steps" >> $GITHUB_STEP_SUMMARY echo "### 🔗 Next Steps" >> $GITHUB_STEP_SUMMARY
echo "- Production deployment will start automatically" >> $GITHUB_STEP_SUMMARY echo "- Production deployment will start automatically" >> $GITHUB_STEP_SUMMARY

View File

@@ -43,15 +43,15 @@ jobs:
run: | run: |
case "${{ matrix.environment }}" in case "${{ matrix.environment }}" in
dev) dev)
echo "CANONICAL_DOMAIN=game-2048-dev.game-2048-dev.dev.wa.darknex.us" >> $GITHUB_ENV echo "CANONICAL_DOMAIN=https://game-2048-dev.game-2048-dev.dev.wa.darknex.us" >> $GITHUB_ENV
echo "ENV_NAME=development" >> $GITHUB_ENV echo "ENV_NAME=development" >> $GITHUB_ENV
;; ;;
staging) staging)
echo "CANONICAL_DOMAIN=game-2048-staging.game-2048-staging.staging.wa.darknex.us" >> $GITHUB_ENV echo "CANONICAL_DOMAIN=https://game-2048-staging.game-2048-staging.staging.wa.darknex.us" >> $GITHUB_ENV
echo "ENV_NAME=staging" >> $GITHUB_ENV echo "ENV_NAME=staging" >> $GITHUB_ENV
;; ;;
prod) prod)
echo "CANONICAL_DOMAIN=game-2048-prod.game-2048-prod.wa.darknex.us" >> $GITHUB_ENV echo "CANONICAL_DOMAIN=https://game-2048-prod.game-2048-prod.wa.darknex.us" >> $GITHUB_ENV
echo "ENV_NAME=production" >> $GITHUB_ENV echo "ENV_NAME=production" >> $GITHUB_ENV
;; ;;
esac esac
@@ -61,7 +61,7 @@ jobs:
echo "🎯 Testing canonical Knative domain: ${{ env.CANONICAL_DOMAIN }}" echo "🎯 Testing canonical Knative domain: ${{ env.CANONICAL_DOMAIN }}"
# Test HTTPS access to canonical domain # Test HTTPS access to canonical domain
response_code=$(curl -s -o /dev/null -w "%{http_code}" -L --max-time 30 https://${{ env.CANONICAL_DOMAIN }}/) response_code=$(curl -s -o /dev/null -w "%{http_code}" -L --max-time 30 "${{ env.CANONICAL_DOMAIN }}")
echo "Canonical domain HTTP response code: $response_code" echo "Canonical domain HTTP response code: $response_code"
if [ "$response_code" != "200" ]; then if [ "$response_code" != "200" ]; then
@@ -76,7 +76,7 @@ jobs:
echo "📄 Testing content validation on canonical domain: ${{ env.CANONICAL_DOMAIN }}" echo "📄 Testing content validation on canonical domain: ${{ env.CANONICAL_DOMAIN }}"
# Download the page content from canonical domain # Download the page content from canonical domain
content=$(curl -s -L --max-time 30 https://${{ env.CANONICAL_DOMAIN }}/) content=$(curl -s -L --max-time 30 "${{ env.CANONICAL_DOMAIN }}")
# Check if it contains expected 2048 game elements # Check if it contains expected 2048 game elements
if echo "$content" | grep -q "2048"; then if echo "$content" | grep -q "2048"; then
@@ -120,7 +120,7 @@ jobs:
echo "⚡ Testing performance for canonical domain: ${{ env.CANONICAL_DOMAIN }}" echo "⚡ Testing performance for canonical domain: ${{ env.CANONICAL_DOMAIN }}"
# Measure response time on canonical domain # Measure response time on canonical domain
response_time=$(curl -s -o /dev/null -w "%{time_total}" -L --max-time 30 https://${{ env.CANONICAL_DOMAIN }}/) response_time=$(curl -s -o /dev/null -w "%{time_total}" -L --max-time 30 "${{ env.CANONICAL_DOMAIN }}")
echo "Canonical domain response time: ${response_time}s" echo "Canonical domain response time: ${response_time}s"
# Check if response time is reasonable (under 10 seconds) # Check if response time is reasonable (under 10 seconds)
@@ -131,7 +131,7 @@ jobs:
fi fi
# Check content size # Check content size
content_size=$(curl -s -L --max-time 30 https://${{ env.CANONICAL_DOMAIN }}/ | wc -c) content_size=$(curl -s -L --max-time 30 "${{ env.CANONICAL_DOMAIN }}" | wc -c)
echo "Content size: $content_size bytes" echo "Content size: $content_size bytes"
if [ $content_size -gt 1000 ]; then if [ $content_size -gt 1000 ]; then
@@ -154,6 +154,7 @@ jobs:
run: | run: |
echo "🌐 Testing canonical domain DNS resolution" echo "🌐 Testing canonical domain DNS resolution"
# Canonical domains (Knative domains only)
canonical_domains=( canonical_domains=(
"game-2048-dev.game-2048-dev.dev.wa.darknex.us" "game-2048-dev.game-2048-dev.dev.wa.darknex.us"
"game-2048-staging.game-2048-staging.staging.wa.darknex.us" "game-2048-staging.game-2048-staging.staging.wa.darknex.us"
@@ -175,6 +176,7 @@ jobs:
run: | run: |
echo "🔐 Testing SSL certificate chains for canonical domains" echo "🔐 Testing SSL certificate chains for canonical domains"
# Canonical domains (Knative domains only)
canonical_domains=( canonical_domains=(
"game-2048-dev.game-2048-dev.dev.wa.darknex.us" "game-2048-dev.game-2048-dev.dev.wa.darknex.us"
"game-2048-staging.game-2048-staging.staging.wa.darknex.us" "game-2048-staging.game-2048-staging.staging.wa.darknex.us"
@@ -226,6 +228,12 @@ jobs:
echo "| Canonical Domain Tests | ${{ needs.test-canonical-domains.result == 'success' && '✅ Passed' || '❌ Failed' }} |" >> $GITHUB_STEP_SUMMARY echo "| Canonical Domain Tests | ${{ needs.test-canonical-domains.result == 'success' && '✅ Passed' || '❌ Failed' }} |" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY
echo "### Tested Canonical Domains" >> $GITHUB_STEP_SUMMARY echo "### Tested Canonical Domains" >> $GITHUB_STEP_SUMMARY
echo "- 🧪 Development: https://game-2048-dev.game-2048-dev.dev.wa.darknex.us" >> $GITHUB_STEP_SUMMARY
echo "- 🎭 Staging: https://game-2048-staging.game-2048-staging.staging.wa.darknex.us" >> $GITHUB_STEP_SUMMARY # Use canonical domain format
echo "- 🚀 Production: https://game-2048-prod.game-2048-prod.wa.darknex.us" >> $GITHUB_STEP_SUMMARY DEV_URL="https://game-2048-dev.game-2048-dev.dev.wa.darknex.us"
STAGING_URL="https://game-2048-staging.game-2048-staging.staging.wa.darknex.us"
PROD_URL="https://game-2048-prod.game-2048-prod.wa.darknex.us"
echo "- 🧪 Development: $DEV_URL" >> $GITHUB_STEP_SUMMARY
echo "- 🎭 Staging: $STAGING_URL" >> $GITHUB_STEP_SUMMARY
echo "- 🚀 Production: $PROD_URL" >> $GITHUB_STEP_SUMMARY

4
.gitignore vendored
View File

@@ -33,6 +33,10 @@ Thumbs.db
.env.production .env.production
webhook_secret.txt webhook_secret.txt
# Test files with PII
test-signature.py
test-webhook.sh
# Personal deployment files # Personal deployment files
manifests/personal/ manifests/personal/
config/personal/ config/personal/

View File

@@ -108,12 +108,7 @@ spec:
cp /shared/kubectl /usr/local/bin/ 2>/dev/null || echo "kubectl already available" cp /shared/kubectl /usr/local/bin/ 2>/dev/null || echo "kubectl already available"
chmod +x /usr/local/bin/kubectl 2>/dev/null || true chmod +x /usr/local/bin/kubectl 2>/dev/null || true
# Set up kubeconfig # Test connectivity (using in-cluster service account)
mkdir -p /root/.kube
cp /etc/kubeconfig/config /root/.kube/config
chmod 600 /root/.kube/config
# Test connectivity
echo "🔍 Testing Kubernetes connectivity..." echo "🔍 Testing Kubernetes connectivity..."
kubectl version --client || echo "⚠️ kubectl client test failed" kubectl version --client || echo "⚠️ kubectl client test failed"
kubectl cluster-info || echo "⚠️ cluster connectivity test failed, but continuing..." kubectl cluster-info || echo "⚠️ cluster connectivity test failed, but continuing..."
@@ -128,10 +123,6 @@ spec:
subPath: webhook-handler.py subPath: webhook-handler.py
- name: manifests - name: manifests
mountPath: /app/manifests mountPath: /app/manifests
- name: docker-socket
mountPath: /var/run/docker.sock
- name: kubeconfig
mountPath: /etc/kubeconfig
- name: shared-tools - name: shared-tools
mountPath: /shared mountPath: /shared
livenessProbe: livenessProbe:
@@ -166,14 +157,6 @@ spec:
hostPath: hostPath:
path: /home/administrator/k8s-game-2048/manifests path: /home/administrator/k8s-game-2048/manifests
type: Directory type: Directory
- name: docker-socket
hostPath:
path: /var/run/docker.sock
type: Socket
- name: kubeconfig
secret:
secretName: webhook-kubeconfig
defaultMode: 0600
- name: shared-tools - name: shared-tools
emptyDir: {} emptyDir: {}
--- ---

View File

@@ -25,6 +25,7 @@ metadata:
nginx.ingress.kubernetes.io/force-ssl-redirect: "true" nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
cert-manager.io/cluster-issuer: "letsencrypt-prod" # Adjust to your cert issuer cert-manager.io/cluster-issuer: "letsencrypt-prod" # Adjust to your cert issuer
spec: spec:
ingressClassName: nginx
tls: tls:
- hosts: - hosts:
- webhook.wa.darknex.us - webhook.wa.darknex.us

View File

@@ -38,8 +38,13 @@ def verify_signature(payload, signature):
def run_command(cmd, **kwargs): def run_command(cmd, **kwargs):
"""Run shell command with logging""" """Run shell command with logging"""
logger.info(f"Running command: {' '.join(cmd)}") logger.info(f"Running command: {' '.join(cmd)}")
# Set up environment for kubectl to use in-cluster config
env = os.environ.copy()
env['KUBECONFIG'] = '' # Force kubectl to use in-cluster config
try: try:
result = subprocess.run(cmd, check=True, capture_output=True, text=True, **kwargs) result = subprocess.run(cmd, check=True, capture_output=True, text=True, env=env, **kwargs)
logger.info(f"Command output: {result.stdout}") logger.info(f"Command output: {result.stdout}")
return result return result
except subprocess.CalledProcessError as e: except subprocess.CalledProcessError as e:
@@ -53,8 +58,16 @@ def pull_image(image):
def apply_manifests(environment): def apply_manifests(environment):
"""Apply Kubernetes manifests for environment""" """Apply Kubernetes manifests for environment"""
manifest_dir = f"{MANIFESTS_PATH}/{environment}" # Map environment names to manifest directories
logger.info(f"Applying manifests from: {manifest_dir}") env_mapping = {
'development': 'dev',
'staging': 'staging',
'production': 'prod'
}
manifest_env = env_mapping.get(environment, environment)
manifest_dir = f"{MANIFESTS_PATH}/{manifest_env}"
logger.info(f"Applying manifests from: {manifest_dir} (environment: {environment})")
if not os.path.exists(manifest_dir): if not os.path.exists(manifest_dir):
raise FileNotFoundError(f"Manifest directory not found: {manifest_dir}") raise FileNotFoundError(f"Manifest directory not found: {manifest_dir}")
@@ -167,9 +180,33 @@ def deploy():
try: try:
# Verify signature # Verify signature
signature = request.headers.get('X-Signature-SHA256') signature = request.headers.get('X-Signature-SHA256')
if not verify_signature(request.data, signature): payload = request.data
logger.info(f"Received webhook request")
logger.info(f"Signature header: {signature}")
logger.info(f"Payload length: {len(payload)} bytes")
logger.info(f"Payload: {payload.decode('utf-8')[:200]}...")
# Test signature verification with debug
if signature:
expected = hmac.new(
WEBHOOK_SECRET.encode('utf-8'),
payload,
hashlib.sha256
).hexdigest()
expected_full = f"sha256={expected}"
logger.info(f"Expected signature: {expected_full}")
logger.info(f"Received signature: {signature}")
logger.info(f"Signatures match: {hmac.compare_digest(expected_full, signature)}")
if not verify_signature(payload, signature):
logger.warning("Invalid webhook signature") logger.warning("Invalid webhook signature")
return jsonify({"error": "Invalid signature"}), 401 return jsonify({"error": "Invalid signature"}), 401
else:
logger.warning("No signature header found")
return jsonify({"error": "No signature provided"}), 401
logger.info(f"Signature verification passed")
# Parse payload # Parse payload
data = request.json data = request.json
@@ -198,8 +235,8 @@ def deploy():
logger.info(f"Service: {service_name}") logger.info(f"Service: {service_name}")
logger.info(f"Strategy: {deployment_strategy}") logger.info(f"Strategy: {deployment_strategy}")
# Step 1: Pull the Docker image # Step 1: Skip Docker pull for Knative (Knative handles image pulling)
pull_image(image) logger.info("Skipping Docker pull step (Knative handles image pulling)")
# Step 2: Apply manifests # Step 2: Apply manifests
apply_manifests(environment) apply_manifests(environment)

View File

@@ -3,7 +3,7 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>2048 Game - Knative Edition v2.0</title> <title>Knative 2048 v2.0.3 - Auto-Promotion Fixed <20></title>
<link rel="stylesheet" href="style.css"> <link rel="stylesheet" href="style.css">
<link rel="icon" type="image/png" href="favicon.png"> <link rel="icon" type="image/png" href="favicon.png">
</head> </head>

View File

@@ -246,8 +246,8 @@ class Game2048 {
const tile = document.createElement('div'); const tile = document.createElement('div');
tile.className = `tile tile-${this.grid[row][col]}`; tile.className = `tile tile-${this.grid[row][col]}`;
tile.textContent = this.grid[row][col]; tile.textContent = this.grid[row][col];
tile.style.left = `${col * 121.25}px`; tile.style.left = `${col * 124.25}px`;
tile.style.top = `${row * 121.25}px`; tile.style.top = `${row * 124.25}px`;
if (this.grid[row][col] > 2048) { if (this.grid[row][col] > 2048) {
tile.className = 'tile tile-super'; tile.className = 'tile tile-super';

View File

@@ -25,7 +25,7 @@ h1.title {
} }
.container { .container {
width: 500px; width: 512px;
margin: 0 auto; margin: 0 auto;
} }
@@ -141,8 +141,8 @@ h1.title {
touch-action: none; touch-action: none;
background: #bbada0; background: #bbada0;
border-radius: 10px; border-radius: 10px;
width: 500px; width: 512px;
height: 500px; height: 512px;
box-sizing: border-box; box-sizing: border-box;
} }
@@ -208,7 +208,7 @@ h1.title {
} }
.grid-row { .grid-row {
margin-bottom: 15px; margin-bottom: 18px;
} }
.grid-row:last-child { .grid-row:last-child {
@@ -220,7 +220,7 @@ h1.title {
height: 106.25px; height: 106.25px;
background: rgba(238, 228, 218, 0.35); background: rgba(238, 228, 218, 0.35);
border-radius: 6px; border-radius: 6px;
margin-right: 15px; margin-right: 18px;
float: left; float: left;
} }