feat: add dynamic versioning and automated deployment with rollback capability
- Implement setuptools-scm for dynamic version management from git tags - Refactor CI/CD into separate build and deploy jobs with artifact sharing - Add versioned releases with timestamp-based deployment directories - Implement health checks and automatic rollback on deployment failure - Extract deployment logic into reusable shell scripts - Add Docker layer caching to speed up builds - Include version info in Django context and build args
This commit is contained in:
parent
46619bd5e1
commit
f20c4f9474
14 changed files with 719 additions and 233 deletions
120
scripts/manage-releases.sh
Normal file
120
scripts/manage-releases.sh
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
# Manage deployment releases
|
||||
# Usage: ./manage-releases.sh REPO_PROJECT_PATH COMMAND [ARGS]
|
||||
|
||||
if [ $# -lt 2 ]; then
|
||||
echo "Error: Invalid number of arguments"
|
||||
echo "Usage: $0 REPO_PROJECT_PATH COMMAND [ARGS]"
|
||||
echo "Commands:"
|
||||
echo " list - List all releases"
|
||||
echo " current - Show current release"
|
||||
echo " rollback VERSION - Rollback to specific version"
|
||||
echo " cleanup [KEEP] - Clean up old releases (default: keep 5)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
REPO_PROJECT_PATH="$1"
|
||||
COMMAND="$2"
|
||||
CURRENT_LINK_PATH="${REPO_PROJECT_PATH}/current"
|
||||
RELEASES_PATH="${REPO_PROJECT_PATH}/releases"
|
||||
|
||||
case "$COMMAND" in
|
||||
list)
|
||||
echo "📋 Available releases:"
|
||||
if [ -d "$RELEASES_PATH" ]; then
|
||||
for release in $(ls -dt "${RELEASES_PATH}"/*/); do
|
||||
version=$(basename "$release")
|
||||
status=""
|
||||
|
||||
# Check if it's current
|
||||
if [ -L "$CURRENT_LINK_PATH" ] && [ "$(readlink -f "$CURRENT_LINK_PATH")" = "$(realpath "$release")" ]; then
|
||||
status=" [CURRENT]"
|
||||
fi
|
||||
|
||||
# Check if it failed
|
||||
if [ -f "${release}/.failed" ]; then
|
||||
status="${status} [FAILED]"
|
||||
fi
|
||||
|
||||
echo " - ${version}${status}"
|
||||
done
|
||||
else
|
||||
echo "No releases found"
|
||||
fi
|
||||
;;
|
||||
|
||||
current)
|
||||
if [ -L "$CURRENT_LINK_PATH" ]; then
|
||||
current_version=$(basename "$(readlink -f "$CURRENT_LINK_PATH")")
|
||||
echo "📌 Current version: ${current_version}"
|
||||
else
|
||||
echo "❌ No current deployment found"
|
||||
fi
|
||||
;;
|
||||
|
||||
rollback)
|
||||
if [ $# -lt 3 ]; then
|
||||
echo "Error: VERSION required for rollback"
|
||||
exit 1
|
||||
fi
|
||||
TARGET_VERSION="$3"
|
||||
TARGET_PATH="${RELEASES_PATH}/${TARGET_VERSION}"
|
||||
|
||||
if [ ! -d "$TARGET_PATH" ]; then
|
||||
echo "Error: Version ${TARGET_VERSION} not found"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "🔄 Rolling back to version: ${TARGET_VERSION}"
|
||||
|
||||
# Read environment from target version
|
||||
if [ -f "${TARGET_PATH}/.deployment_env" ]; then
|
||||
IS_PROD=$(cat "${TARGET_PATH}/.deployment_env")
|
||||
else
|
||||
echo "Warning: Could not determine environment, assuming staging"
|
||||
IS_PROD="false"
|
||||
fi
|
||||
|
||||
# Stop current containers
|
||||
if [ -L "$CURRENT_LINK_PATH" ] && [ -d "$CURRENT_LINK_PATH" ]; then
|
||||
cd "$CURRENT_LINK_PATH"
|
||||
docker compose -f docker-compose_web.yml down || true
|
||||
[ "$IS_PROD" = "false" ] && docker compose -f docker-compose_staging.yml down || true
|
||||
docker compose -f docker-compose_core.yml down || true
|
||||
fi
|
||||
|
||||
# Update symlink
|
||||
ln -sfn "$TARGET_PATH" "$CURRENT_LINK_PATH"
|
||||
|
||||
# Start containers
|
||||
cd "$CURRENT_LINK_PATH"
|
||||
docker compose -f docker-compose_core.yml up -d --no-build
|
||||
if [ "$IS_PROD" = "true" ]; then
|
||||
docker compose -f docker-compose_web.yml up -d --no-build
|
||||
else
|
||||
docker compose -f docker-compose_web.yml -f docker-compose_staging.yml up -d --no-build
|
||||
fi
|
||||
|
||||
echo "✅ Rollback completed"
|
||||
;;
|
||||
|
||||
cleanup)
|
||||
KEEP_COUNT="${3:-5}"
|
||||
echo "🗑️ Cleaning up old releases (keeping last ${KEEP_COUNT})"
|
||||
|
||||
if [ -d "$RELEASES_PATH" ]; then
|
||||
cd "$RELEASES_PATH"
|
||||
ls -dt */ 2>/dev/null | tail -n +$((KEEP_COUNT + 1)) | xargs -r rm -rf || true
|
||||
echo "✅ Cleanup completed"
|
||||
else
|
||||
echo "No releases directory found"
|
||||
fi
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Error: Unknown command: $COMMAND"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
Loading…
Add table
Add a link
Reference in a new issue