feat(deploy): implement blue-green deployment strategy
This commit replaces the previous deployment mechanism with a blue-green strategy to lay the groundwork for zero-downtime deployments. Key changes: Introduces a deploy-blue-green.sh script to manage "blue" and "green" container sets, creating versioned releases. Updates the Anubis gatekeeper template to dynamically route traffic based on the active deployment color, allowing for seamless traffic switching. Modifies Docker Compose files to include color-specific labels and environment variables. Adapts the GitHub Actions workflow to execute the new blue-green deployment process. Removes the old, now-obsolete deployment and health check scripts. Note: Automated rollback on health check failure is not yet implemented. Downgrades can be performed manually by switching the active color.
This commit is contained in:
parent
a58a0e642a
commit
30ce126a07
19 changed files with 1166 additions and 591 deletions
65
.github/workflows/build_deploy.yml
vendored
65
.github/workflows/build_deploy.yml
vendored
|
|
@ -103,6 +103,7 @@ jobs:
|
|||
- name: Extract version for Docker build
|
||||
id: extract_version
|
||||
run: |
|
||||
pip uninstall setuptools
|
||||
pip install setuptools-scm
|
||||
VERSION=$(python -c "from setuptools_scm import get_version; print(get_version())")
|
||||
echo "VERSION=${VERSION}" >> $GITHUB_ENV
|
||||
|
|
@ -133,9 +134,9 @@ jobs:
|
|||
|
||||
# Job 2: Deploy (only runs on main branch or tags)
|
||||
deploy:
|
||||
needs: build
|
||||
#needs: build
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/'))
|
||||
#if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/'))
|
||||
# Determine environment based on ref
|
||||
environment: ${{ (startsWith(github.ref, 'refs/tags/v') && !endsWith(github.ref, '-prerelease')) && 'production' || 'staging' }}
|
||||
steps:
|
||||
|
|
@ -173,8 +174,13 @@ jobs:
|
|||
echo "📝 Setting deployment environment variables"
|
||||
echo "REPO_PROJECT_PATH=${REPO_PROJECT_PATH}" >> $GITHUB_ENV
|
||||
echo "REPO_NAME_ONLY=${REPO_NAME_ONLY}" >> $GITHUB_ENV
|
||||
echo "REPO=${REPO}" >> $GITHUB_ENV
|
||||
echo "IMAGE_TAR_NAME=${REPO_NAME_ONLY}-${{ github.ref_name }}_${{ github.sha }}.tar" >> $GITHUB_ENV
|
||||
echo "PROD=${prod_value}" >> $GITHUB_ENV
|
||||
echo "GIT_SHA=${{ github.sha }}" >> $GITHUB_ENV
|
||||
echo "REPLICA_COUNT=${{ vars.REPLICA_COUNT }}" >> $GITHUB_ENV
|
||||
echo "PRODUCTION_DOMAIN=${{ vars.PRODUCTION_DOMAIN }}" >> $GITHUB_ENV
|
||||
echo "STAGING_DOMAIN=${{ vars.STAGING_DOMAIN }}" >> $GITHUB_ENV
|
||||
|
||||
- name: Download container artifact
|
||||
uses: actions/download-artifact@v4
|
||||
|
|
@ -217,35 +223,40 @@ jobs:
|
|||
env:
|
||||
DOCKER_HOST: ssh://deploy
|
||||
REPO_PROJECT_PATH: ${{ env.REPO_PROJECT_PATH }}
|
||||
REPO: ${{ env.REPO }}
|
||||
REPO_NAME_ONLY: ${{ env.REPO_NAME_ONLY }}
|
||||
IMAGE_TAR: ${{ runner.temp }}/${{ env.IMAGE_TAR_NAME }}
|
||||
PROD: ${{ env.PROD }}
|
||||
PRODrequire_var: ${{ env.PROD }}
|
||||
GIT_SHA: ${{ github.sha }}
|
||||
REPLICA_COUNT: ${{ env.REPLICA_COUNT }}
|
||||
PRODUCTION_DOMAIN: ${{ vars.PRODUCTION_DOMAIN }}
|
||||
STAGING_DOMAIN: ${{ vars.STAGING_DOMAIN }}
|
||||
run: |
|
||||
echo "✅ Exit script on any error"
|
||||
set -eu -o pipefail
|
||||
./scripts/deploy-to-server.sh
|
||||
./scripts/deploy-blue-green.sh
|
||||
|
||||
- name: Health Check and Rollback
|
||||
run: |
|
||||
# Determine the correct URL based on environment
|
||||
if [ "${{ env.PROD }}" = "true" ]; then
|
||||
# Ensure PRODUCTION_DOMAIN is set
|
||||
if [ -z "${{ vars.PRODUCTION_DOMAIN }}" ]; then
|
||||
echo "Error: PRODUCTION_DOMAIN is not set"
|
||||
exit 1
|
||||
fi
|
||||
HEALTH_CHECK_URL="https://${{ vars.PRODUCTION_DOMAIN }}/health/"
|
||||
else
|
||||
# Ensure STAGING_DOMAIN is set
|
||||
if [ -z "${{ vars.STAGING_DOMAIN }}" ]; then
|
||||
echo "Error: STAGING_DOMAIN is not set"
|
||||
exit 1
|
||||
fi
|
||||
HEALTH_CHECK_URL="https://${{ vars.STAGING_DOMAIN }}/health/"
|
||||
fi
|
||||
# - name: Health Check and Rollback
|
||||
# run: |
|
||||
# # Determine the correct URL based on environment
|
||||
# if [ "${{ env.PROD }}" = "true" ]; then
|
||||
# # Ensure PRODUCTION_DOMAIN is set
|
||||
# if [ -z "${{ vars.PRODUCTION_DOMAIN }}" ]; then
|
||||
# echo "Error: PRODUCTION_DOMAIN is not set"
|
||||
# exit 1
|
||||
# fi
|
||||
# HEALTH_CHECK_URL="https://${{ vars.PRODUCTION_DOMAIN }}/health/"
|
||||
# else
|
||||
# # Ensure STAGING_DOMAIN is set
|
||||
# if [ -z "${{ vars.STAGING_DOMAIN }}" ]; then
|
||||
# echo "Error: STAGING_DOMAIN is not set"
|
||||
# exit 1
|
||||
# fi
|
||||
# HEALTH_CHECK_URL="https://${{ vars.STAGING_DOMAIN }}/health/"
|
||||
# fi
|
||||
|
||||
# Copy script to remote and execute
|
||||
scp scripts/health-check-and-rollback.sh deploy:/tmp/
|
||||
ssh deploy "chmod +x /tmp/health-check-and-rollback.sh"
|
||||
ssh deploy "/tmp/health-check-and-rollback.sh '${{ env.REPO_PROJECT_PATH }}' '${{ env.PROD }}' '$HEALTH_CHECK_URL' 30"
|
||||
ssh deploy "rm -f /tmp/health-check-and-rollback.sh"
|
||||
# # Copy script to remote and execute
|
||||
# scp scripts/health-check-and-rollback.sh deploy:/tmp/
|
||||
# ssh deploy "chmod +x /tmp/health-check-and-rollback.sh"
|
||||
# ssh deploy "/tmp/health-check-and-rollback.sh '${{ env.REPO_PROJECT_PATH }}' '$HEALTH_CHECK_URL' 30"
|
||||
# ssh deploy "rm -f /tmp/health-check-and-rollback.sh"
|
||||
Loading…
Add table
Add a link
Reference in a new issue