From 09ec016b6aa88d4f288c4dc324be51ad5370b44a Mon Sep 17 00:00:00 2001 From: Greg Date: Mon, 30 Jun 2025 23:18:14 -0700 Subject: [PATCH] feat: Implement proper branch-based auto-promotion strategy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ๐Ÿš€ **New Branching Strategy:** - develop โ†’ triggers dev deployment โ†’ auto-promotes to staging branch - staging โ†’ triggers staging deployment โ†’ manual approval โ†’ promotes to main branch - main โ†’ triggers production deployment ๐Ÿ“ **Workflow Changes:** - deploy-dev.yml: Now triggers on develop branch - deploy-staging.yml: Now triggers on staging branch push - deploy-prod.yml: Now triggers on main branch push - auto-promote.yml: Tests dev โ†’ merges develop to staging branch - promote-to-production.yml: Tests staging โ†’ requires approval โ†’ merges staging to main - build-image.yml: Now builds on all branches (main, develop, staging) ๐ŸŽฏ **Auto-Promotion Flow:** 1. Push to develop โ†’ Deploy to dev โ†’ Test โ†’ Auto-merge to staging 2. Staging deployment โ†’ Test โ†’ Manual approval โ†’ Auto-merge to main 3. Main deployment โ†’ Production live! This provides proper separation between environments with appropriate gates. --- .github/workflows/auto-promote.yml | 135 +++++-------------- .github/workflows/build-image.yml | 4 +- .github/workflows/deploy-dev.yml | 4 +- .github/workflows/deploy-prod.yml | 2 + .github/workflows/deploy-staging.yml | 2 + .github/workflows/promote-to-production.yml | 138 ++++++++++++++++++++ 6 files changed, 178 insertions(+), 107 deletions(-) create mode 100644 .github/workflows/promote-to-production.yml diff --git a/.github/workflows/auto-promote.yml b/.github/workflows/auto-promote.yml index 96e8747..cec02ed 100644 --- a/.github/workflows/auto-promote.yml +++ b/.github/workflows/auto-promote.yml @@ -5,17 +5,19 @@ on: workflows: ["Deploy to Development"] types: - completed - branches: [ main ] + branches: [ develop ] jobs: - test-and-promote: - name: Test Dev and Auto-Promote + test-and-promote-to-staging: + name: Test Dev and Auto-Promote to Staging runs-on: ubuntu-latest if: ${{ github.event.workflow_run.conclusion == 'success' }} steps: - name: Checkout repository uses: actions/checkout@v4 + with: + ref: develop - name: Wait for dev deployment to settle run: | @@ -92,35 +94,44 @@ jobs: fi echo "โœ… Performance test passed: ${response_time}s" - - name: Auto-promote to staging + - name: Auto-promote develop to staging branch uses: actions/github-script@v7 with: github-token: ${{ secrets.GITHUB_TOKEN }} script: | - console.log('๐Ÿš€ All dev tests passed! Auto-promoting to staging...'); + console.log('๐Ÿš€ All dev tests passed! Auto-promoting develop to staging branch...'); - 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' + // Create a merge from develop to staging + try { + const response = await github.rest.repos.merge({ + owner: context.repo.owner, + repo: context.repo.repo, + base: 'staging', + head: 'develop', + commit_message: 'Auto-promote: Merge develop to staging after successful dev tests' + }); + + console.log('โœ… Successfully merged develop to staging branch'); + console.log('This will trigger staging deployment automatically'); + + return response; + } catch (error) { + if (error.status === 409) { + console.log('โ„น๏ธ No new commits to merge - staging is already up to date'); + } else { + throw error; } - }); - - console.log('โœ… Staging deployment triggered'); - - return response; + } - name: Create promotion summary run: | - echo "## ๐ŸŽฏ Auto-Promotion Summary" >> $GITHUB_STEP_SUMMARY + echo "## ๐ŸŽฏ Auto-Promotion Summary (Develop โ†’ Staging)" >> $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 "| Staging Branch | ๐Ÿš€ Updated | Auto-promotion completed |" >> $GITHUB_STEP_SUMMARY + echo "| Staging Deploy | โณ Triggered | Deployment will start automatically |" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "### ๐Ÿ“‹ Tests Performed" >> $GITHUB_STEP_SUMMARY echo "- SSL certificate validation" >> $GITHUB_STEP_SUMMARY @@ -129,88 +140,6 @@ jobs: 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 deployment will start automatically" >> $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 + echo "- Production promotion requires manual approval via staging โ†’ main merge" >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/build-image.yml b/.github/workflows/build-image.yml index 6cd70b6..a9da9ce 100644 --- a/.github/workflows/build-image.yml +++ b/.github/workflows/build-image.yml @@ -2,9 +2,9 @@ name: Build and Push Container Image on: push: - branches: [ main ] + branches: [ main, develop, staging ] pull_request: - branches: [ main ] + branches: [ main, develop, staging ] env: REGISTRY: ghcr.io diff --git a/.github/workflows/deploy-dev.yml b/.github/workflows/deploy-dev.yml index db8e3c6..c342eba 100644 --- a/.github/workflows/deploy-dev.yml +++ b/.github/workflows/deploy-dev.yml @@ -5,9 +5,9 @@ on: workflows: ["Build and Push Container Image"] types: - completed - branches: [ main ] + branches: [ develop ] push: - branches: [ main ] + branches: [ develop ] workflow_dispatch: inputs: image_tag: diff --git a/.github/workflows/deploy-prod.yml b/.github/workflows/deploy-prod.yml index 814a352..7239d32 100644 --- a/.github/workflows/deploy-prod.yml +++ b/.github/workflows/deploy-prod.yml @@ -1,6 +1,8 @@ name: Deploy to Production on: + push: + branches: [ main ] workflow_dispatch: inputs: image_tag: diff --git a/.github/workflows/deploy-staging.yml b/.github/workflows/deploy-staging.yml index c0cd265..c442b16 100644 --- a/.github/workflows/deploy-staging.yml +++ b/.github/workflows/deploy-staging.yml @@ -1,6 +1,8 @@ name: Deploy to Staging on: + push: + branches: [ staging ] workflow_dispatch: inputs: image_tag: diff --git a/.github/workflows/promote-to-production.yml b/.github/workflows/promote-to-production.yml new file mode 100644 index 0000000..fc849d0 --- /dev/null +++ b/.github/workflows/promote-to-production.yml @@ -0,0 +1,138 @@ +name: Promote to Production + +on: + workflow_run: + workflows: ["Deploy to Staging"] + types: + - completed + branches: [ staging ] + +jobs: + test-staging-and-promote-to-main: + name: Test Staging and Promote to Main + runs-on: ubuntu-latest + if: ${{ github.event.workflow_run.conclusion == 'success' }} + environment: production-approval # This requires manual approval + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + ref: staging + + - name: Wait for staging deployment to settle + run: | + echo "โณ Waiting for staging deployment to fully settle..." + sleep 120 + + - name: Run comprehensive staging tests + run: | + echo "๐Ÿงช Running comprehensive tests on staging environment..." + + # Test canonical staging domain first (primary test) + 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 validation on canonical domain + echo "Testing staging content validation..." + 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 "โŒ 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 staging content validation tests passed" + + # Test staging performance on canonical domain + 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/) + if (( $(echo "$response_time > 10.0" | bc -l) )); then + echo "โŒ Response time too slow: ${response_time}s" + exit 1 + fi + echo "โœ… Staging performance test passed: ${response_time}s" + + - name: Auto-promote staging to main branch + uses: actions/github-script@v7 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + console.log('๐ŸŽฏ All staging tests passed! Auto-promoting staging to main branch...'); + + // Create a merge from staging to main + try { + const response = await github.rest.repos.merge({ + owner: context.repo.owner, + repo: context.repo.repo, + base: 'main', + head: 'staging', + commit_message: 'Auto-promote: Merge staging to main after successful staging tests - Deploy to Production' + }); + + console.log('โœ… Successfully merged staging to main branch'); + console.log('This will trigger production deployment automatically'); + + return response; + } catch (error) { + if (error.status === 409) { + console.log('โ„น๏ธ No new commits to merge - main is already up to date'); + } else { + throw error; + } + } + + - name: Create production promotion summary + run: | + echo "## ๐ŸŽ‰ Production Promotion Summary (Staging โ†’ Main)" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "| Stage | Status | Action |" >> $GITHUB_STEP_SUMMARY + echo "|-------|--------|--------|" >> $GITHUB_STEP_SUMMARY + echo "| Staging Tests | โœ… Passed | Comprehensive validation completed |" >> $GITHUB_STEP_SUMMARY + echo "| Main Branch | ๐Ÿš€ Updated | Auto-promotion completed |" >> $GITHUB_STEP_SUMMARY + echo "| Production Deploy | โณ Triggered | Deployment will start automatically |" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "### ๐Ÿ“‹ Tests Performed" >> $GITHUB_STEP_SUMMARY + echo "- Staging canonical domain accessibility" >> $GITHUB_STEP_SUMMARY + echo "- Staging custom domain accessibility" >> $GITHUB_STEP_SUMMARY + echo "- Content and functionality validation" >> $GITHUB_STEP_SUMMARY + echo "- Performance testing" >> $GITHUB_STEP_SUMMARY + echo "" >> $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 + echo "- **Production**: ๐Ÿš€ Deploying to https://game-2048-prod.game-2048-prod.wa.darknex.us" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "### ๐Ÿ”— Next Steps" >> $GITHUB_STEP_SUMMARY + echo "- Production deployment will start automatically" >> $GITHUB_STEP_SUMMARY + echo "- Monitor the production deployment workflow" >> $GITHUB_STEP_SUMMARY + echo "- All environments will be live with the latest code!" >> $GITHUB_STEP_SUMMARY