From 9fdcc9574a58c1984ac8f58cdf806f8c0cae8f8d Mon Sep 17 00:00:00 2001 From: Greg Date: Mon, 30 Jun 2025 23:04:01 -0700 Subject: [PATCH] =?UTF-8?q?=F0=9F=8E=AF=20Update=20all=20workflows=20to=20?= =?UTF-8?q?test=20canonical=20Knative=20domains?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit โœจ Improvements: - Prioritize canonical domain testing over custom domains - Add fallback testing for both canonical and custom domains - More reliable smoke tests using direct Knative service URLs - Separate performance testing for canonical vs custom domains - Enhanced auto-promotion pipeline with canonical domain validation ๐Ÿงช Testing Strategy: - Primary: Test canonical domains (game-2048-*.*.wa.darknex.us) - Secondary: Verify custom domains work via redirects - Fallback: Test both domains in smoke tests for reliability ๐Ÿ”— Canonical Domains: - Dev: game-2048-dev.game-2048-dev.dev.wa.darknex.us - Staging: game-2048-staging.game-2048-staging.staging.wa.darknex.us - Prod: game-2048-prod.game-2048-prod.wa.darknex.us This ensures tests are more reliable since canonical domains are always accessible while custom domains may have redirect complexity. --- .github/workflows/auto-promote.yml | 216 +++++++++++++++++++++++++++ .github/workflows/deploy-dev.yml | 11 +- .github/workflows/deploy-prod.yml | 9 +- .github/workflows/deploy-staging.yml | 9 +- .github/workflows/smoke-test.yml | 84 ++++++++--- scripts/setup-environments.sh | 24 +++ 6 files changed, 328 insertions(+), 25 deletions(-) create mode 100644 .github/workflows/auto-promote.yml create mode 100644 scripts/setup-environments.sh diff --git a/.github/workflows/auto-promote.yml b/.github/workflows/auto-promote.yml new file mode 100644 index 0000000..96e8747 --- /dev/null +++ b/.github/workflows/auto-promote.yml @@ -0,0 +1,216 @@ +name: Auto-Promote Pipeline + +on: + workflow_run: + workflows: ["Deploy to Development"] + types: + - completed + branches: [ main ] + +jobs: + test-and-promote: + name: Test Dev and Auto-Promote + runs-on: ubuntu-latest + if: ${{ github.event.workflow_run.conclusion == 'success' }} + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Wait for dev deployment to settle + run: | + echo "โณ Waiting for dev deployment to fully settle..." + sleep 60 + + - name: Run comprehensive dev tests + run: | + echo "๐Ÿงช Running comprehensive tests on dev environment..." + + # Test canonical domain first (primary test) + echo "Testing canonical domain: game-2048-dev.game-2048-dev.dev.wa.darknex.us" + 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/) + if [ "$canonical_response" != "200" ]; then + echo "โŒ Canonical domain returned HTTP $canonical_response" + exit 1 + fi + 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 + 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/) + + if ! echo "$content" | grep -q "2048"; then + echo "โŒ Content missing 2048 title" + exit 1 + fi + + if ! echo "$content" | grep -q "HOW TO PLAY"; then + echo "โŒ Content missing game instructions" + exit 1 + fi + + if ! echo "$content" | grep -q "style.css"; then + echo "โŒ CSS file not referenced" + exit 1 + fi + + if ! echo "$content" | grep -q "script.js"; then + echo "โŒ JavaScript file not referenced" + exit 1 + fi + + echo "โœ… All content validation tests passed" + + # Test 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/) + if (( $(echo "$response_time > 10.0" | bc -l) )); then + echo "โŒ Response time too slow: ${response_time}s" + exit 1 + fi + echo "โœ… Performance test passed: ${response_time}s" + + - name: Auto-promote to staging + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + console.log('๐Ÿš€ All dev tests passed! Auto-promoting to staging...'); + + const response = await github.rest.actions.createWorkflowDispatch({ + owner: context.repo.owner, + repo: context.repo.repo, + workflow_id: 'deploy-staging.yml', + ref: 'main', + inputs: { + image_tag: 'latest' + } + }); + + console.log('โœ… Staging deployment triggered'); + + return response; + + - name: Create promotion summary + run: | + echo "## ๐ŸŽฏ Auto-Promotion Summary" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "| Stage | Status | Action |" >> $GITHUB_STEP_SUMMARY + echo "|-------|--------|--------|" >> $GITHUB_STEP_SUMMARY + echo "| Dev Tests | โœ… Passed | Comprehensive validation completed |" >> $GITHUB_STEP_SUMMARY + echo "| Staging | ๐Ÿš€ Triggered | Auto-promotion initiated |" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "### ๐Ÿ“‹ Tests Performed" >> $GITHUB_STEP_SUMMARY + echo "- SSL certificate validation" >> $GITHUB_STEP_SUMMARY + echo "- Domain accessibility check" >> $GITHUB_STEP_SUMMARY + echo "- Content and functionality validation" >> $GITHUB_STEP_SUMMARY + echo "- Performance testing" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "### ๐Ÿ”— Next Steps" >> $GITHUB_STEP_SUMMARY + echo "- Monitor staging deployment progress" >> $GITHUB_STEP_SUMMARY + echo "- Staging tests will run automatically" >> $GITHUB_STEP_SUMMARY + echo "- Production promotion requires manual approval" >> $GITHUB_STEP_SUMMARY + + promote-to-production: + name: Test Staging and Promote to Production + runs-on: ubuntu-latest + needs: test-and-promote + if: success() + environment: production-approval # This requires manual approval + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Wait for staging deployment + run: | + echo "โณ Waiting for staging deployment to complete..." + sleep 120 # Give staging time to deploy + + - name: Test staging environment + run: | + echo "๐Ÿงช Running staging tests..." + + # Test canonical staging domain first + echo "Testing canonical staging domain: game-2048-staging.game-2048-staging.staging.wa.darknex.us" + 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/) + if [ "$canonical_response" != "200" ]; then + echo "โŒ Staging canonical domain returned HTTP $canonical_response" + exit 1 + fi + 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 on canonical domain + echo "Testing staging content..." + content=$(curl -s -L --max-time 30 https://game-2048-staging.game-2048-staging.staging.wa.darknex.us/) + if ! echo "$content" | grep -q "2048"; then + echo "โŒ Staging content validation failed" + exit 1 + fi + echo "โœ… Staging content validation passed" + + - name: Auto-promote to production + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + console.log('๐ŸŽฏ Staging tests passed! Promoting to production...'); + + const response = await github.rest.actions.createWorkflowDispatch({ + owner: context.repo.owner, + repo: context.repo.repo, + workflow_id: 'deploy-prod.yml', + ref: 'main', + inputs: { + image_tag: 'latest', + confirmation: 'DEPLOY' + } + }); + + console.log('๐Ÿš€ Production deployment triggered'); + + return response; + + - name: Create final summary + run: | + echo "## ๐ŸŽ‰ Full Pipeline Completion" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "| Environment | Status | URL |" >> $GITHUB_STEP_SUMMARY + echo "|-------------|--------|-----|" >> $GITHUB_STEP_SUMMARY + echo "| Development | โœ… Tested & Live | https://2048-dev.wa.darknex.us |" >> $GITHUB_STEP_SUMMARY + echo "| Staging | โœ… Tested & Live | https://2048-staging.wa.darknex.us |" >> $GITHUB_STEP_SUMMARY + echo "| Production | ๐Ÿš€ Deploying | https://2048.wa.darknex.us |" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "### ๐ŸŽฎ Your 2048 Game is Live!" >> $GITHUB_STEP_SUMMARY + echo "All environments have been automatically tested and promoted successfully." >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/deploy-dev.yml b/.github/workflows/deploy-dev.yml index baf3f8a..db8e3c6 100644 --- a/.github/workflows/deploy-dev.yml +++ b/.github/workflows/deploy-dev.yml @@ -6,6 +6,8 @@ on: types: - completed branches: [ main ] + push: + branches: [ main ] workflow_dispatch: inputs: image_tag: @@ -85,8 +87,13 @@ jobs: for i in {1..5}; do echo "Attempt $i/5..." - if curl -s --max-time 30 https://2048-dev.wa.darknex.us/ | grep -q "2048"; then - echo "โœ… Smoke test passed!" + # Test canonical domain first + if curl -s --max-time 30 https://game-2048-dev.game-2048-dev.dev.wa.darknex.us/ | grep -q "2048"; then + echo "โœ… Canonical domain smoke test passed!" + break + # Fallback to custom domain + elif curl -s --max-time 30 https://2048-dev.wa.darknex.us/ | grep -q "2048"; then + echo "โœ… Custom domain smoke test passed!" break elif [ $i -eq 5 ]; then echo "โš ๏ธ Smoke test failed after 5 attempts" diff --git a/.github/workflows/deploy-prod.yml b/.github/workflows/deploy-prod.yml index 2f8e4b9..814a352 100644 --- a/.github/workflows/deploy-prod.yml +++ b/.github/workflows/deploy-prod.yml @@ -83,8 +83,13 @@ jobs: for i in {1..5}; do echo "Attempt $i/5..." - if curl -s --max-time 30 https://2048.wa.darknex.us/ | grep -q "2048"; then - echo "โœ… Smoke test passed!" + # Test canonical domain first + if curl -s --max-time 30 https://game-2048-prod.game-2048-prod.wa.darknex.us/ | grep -q "2048"; then + echo "โœ… Canonical domain smoke test passed!" + break + # Fallback to custom domain + elif curl -s --max-time 30 https://2048.wa.darknex.us/ | grep -q "2048"; then + echo "โœ… Custom domain smoke test passed!" break elif [ $i -eq 5 ]; then echo "โš ๏ธ Smoke test failed after 5 attempts" diff --git a/.github/workflows/deploy-staging.yml b/.github/workflows/deploy-staging.yml index b987ae8..c0cd265 100644 --- a/.github/workflows/deploy-staging.yml +++ b/.github/workflows/deploy-staging.yml @@ -79,8 +79,13 @@ jobs: for i in {1..5}; do echo "Attempt $i/5..." - if curl -s --max-time 30 https://2048-staging.wa.darknex.us/ | grep -q "2048"; then - echo "โœ… Smoke test passed!" + # Test canonical domain first + if curl -s --max-time 30 https://game-2048-staging.game-2048-staging.staging.wa.darknex.us/ | grep -q "2048"; then + echo "โœ… Canonical domain smoke test passed!" + break + # Fallback to custom domain + elif curl -s --max-time 30 https://2048-staging.wa.darknex.us/ | grep -q "2048"; then + echo "โœ… Custom domain smoke test passed!" break elif [ $i -eq 5 ]; then echo "โš ๏ธ Smoke test failed after 5 attempts" diff --git a/.github/workflows/smoke-test.yml b/.github/workflows/smoke-test.yml index b8e2098..535ea27 100644 --- a/.github/workflows/smoke-test.yml +++ b/.github/workflows/smoke-test.yml @@ -82,27 +82,42 @@ jobs: echo "โœ… Certificate is valid for $days_until_expiry days" fi - - name: Test Domain Accessibility + - name: Test Canonical Domain (Primary Test) run: | - echo "๐ŸŒ Testing domain accessibility for ${{ env.DOMAIN }}" + echo "๐ŸŽฏ Testing canonical Knative domain: ${{ env.CANONICAL_DOMAIN }}" - # Test HTTPS access - response_code=$(curl -s -o /dev/null -w "%{http_code}" -L --max-time 30 https://${{ env.DOMAIN }}/) - echo "HTTP response code: $response_code" + # Test HTTPS access to canonical domain + response_code=$(curl -s -o /dev/null -w "%{http_code}" -L --max-time 30 https://${{ env.CANONICAL_DOMAIN }}/) + echo "Canonical domain HTTP response code: $response_code" if [ "$response_code" != "200" ]; then - echo "โŒ Domain ${{ env.DOMAIN }} returned HTTP $response_code" + echo "โŒ Canonical domain ${{ env.CANONICAL_DOMAIN }} returned HTTP $response_code" exit 1 else - echo "โœ… Domain ${{ env.DOMAIN }} is accessible" + echo "โœ… Canonical domain ${{ env.CANONICAL_DOMAIN }} is accessible" fi - - name: Test Content Validation + - name: Test Custom Domain Accessibility run: | - echo "๐Ÿ“„ Testing content validation for ${{ env.DOMAIN }}" + echo "๐ŸŒ Testing custom domain accessibility for ${{ env.DOMAIN }}" - # Download the page content - content=$(curl -s -L --max-time 30 https://${{ env.DOMAIN }}/) + # Test HTTPS access (allow redirects) + response_code=$(curl -s -o /dev/null -w "%{http_code}" -L --max-time 30 https://${{ env.DOMAIN }}/) + echo "Custom domain HTTP response code: $response_code" + + if [ "$response_code" != "200" ]; then + echo "โŒ Custom domain ${{ env.DOMAIN }} returned HTTP $response_code" + exit 1 + else + echo "โœ… Custom domain ${{ env.DOMAIN }} is accessible" + fi + + - name: Test Content Validation (Canonical Domain) + run: | + echo "๐Ÿ“„ Testing content validation on canonical domain: ${{ env.CANONICAL_DOMAIN }}" + + # Download the page content from canonical domain + content=$(curl -s -L --max-time 30 https://${{ env.CANONICAL_DOMAIN }}/) # Check if it contains expected 2048 game elements if echo "$content" | grep -q "2048"; then @@ -123,6 +138,7 @@ jobs: echo "โœ… Page shows correct environment: ${{ env.ENV_NAME }}" else echo "โš ๏ธ Environment indicator not found or incorrect" + # Don't fail on this, just warn fi # Check if CSS and JS files are referenced @@ -140,6 +156,21 @@ jobs: exit 1 fi + - name: Test Content Validation (Custom Domain) + run: | + echo "๐Ÿ“„ Testing content validation on custom domain: ${{ env.DOMAIN }}" + + # Download the page content from custom domain + content=$(curl -s -L --max-time 30 https://${{ env.DOMAIN }}/) + + # Basic content check to ensure redirect worked + if echo "$content" | grep -q "2048"; then + echo "โœ… Custom domain serves correct content" + else + echo "โŒ Custom domain does not serve correct content" + exit 1 + fi + - name: Test Redirect Behavior run: | echo "๐Ÿ”„ Testing redirect behavior for ${{ env.DOMAIN }}" @@ -162,23 +193,23 @@ jobs: exit 1 fi - - name: Test Performance + - name: Test Performance (Canonical Domain) run: | - echo "โšก Testing performance for ${{ env.DOMAIN }}" + echo "โšก Testing performance for canonical domain: ${{ env.CANONICAL_DOMAIN }}" - # Measure response time - response_time=$(curl -s -o /dev/null -w "%{time_total}" -L --max-time 30 https://${{ env.DOMAIN }}/) - echo "Response time: ${response_time}s" + # Measure response time on canonical domain + response_time=$(curl -s -o /dev/null -w "%{time_total}" -L --max-time 30 https://${{ env.CANONICAL_DOMAIN }}/) + echo "Canonical domain response time: ${response_time}s" # Check if response time is reasonable (under 10 seconds) if (( $(echo "$response_time < 10.0" | bc -l) )); then - echo "โœ… Response time is acceptable" + echo "โœ… Canonical domain response time is acceptable" else - echo "โš ๏ธ Response time is slow: ${response_time}s" + echo "โš ๏ธ Canonical domain response time is slow: ${response_time}s" fi # Check content size - content_size=$(curl -s -L --max-time 30 https://${{ env.DOMAIN }}/ | wc -c) + content_size=$(curl -s -L --max-time 30 https://${{ env.CANONICAL_DOMAIN }}/ | wc -c) echo "Content size: $content_size bytes" if [ $content_size -gt 1000 ]; then @@ -188,6 +219,21 @@ jobs: exit 1 fi + - name: Test Performance (Custom Domain) + run: | + echo "โšก Testing performance for custom domain: ${{ env.DOMAIN }}" + + # Measure response time including any redirects + response_time=$(curl -s -o /dev/null -w "%{time_total}" -L --max-time 30 https://${{ env.DOMAIN }}/) + echo "Custom domain response time (with redirects): ${response_time}s" + + # More lenient for custom domain due to potential redirects + if (( $(echo "$response_time < 15.0" | bc -l) )); then + echo "โœ… Custom domain response time is acceptable" + else + echo "โš ๏ธ Custom domain response time is slow: ${response_time}s" + fi + test-infrastructure: name: Infrastructure Tests runs-on: ubuntu-latest diff --git a/scripts/setup-environments.sh b/scripts/setup-environments.sh new file mode 100644 index 0000000..2b7475f --- /dev/null +++ b/scripts/setup-environments.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +# Setup GitHub Environments for Protection Rules +# This script documents the manual steps needed in GitHub UI + +echo "๐Ÿ”ง Setting up GitHub Environments for Auto-Promotion Pipeline" +echo "" +echo "๐Ÿ“‹ Manual Steps Required in GitHub Repository Settings:" +echo "" +echo "1. Go to Settings โ†’ Environments" +echo "2. Create 'production-approval' environment" +echo "3. Add required reviewers (yourself)" +echo "4. Set deployment protection rules" +echo "" +echo "Environment Configuration:" +echo "- Environment Name: production-approval" +echo "- Required Reviewers: Repository admins" +echo "- Wait Timer: 0 minutes (immediate on approval)" +echo "- Deployment Branches: main branch only" +echo "" +echo "This ensures production deployments require manual approval" +echo "while dev โ†’ staging promotion happens automatically on successful tests." +echo "" +echo "๐Ÿ”— Navigate to: https://github.com/YOUR_USERNAME/k8s-game-2048/settings/environments"