112 lines
3.4 KiB
Bash
Executable File
112 lines
3.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -Eeuo pipefail
|
|
|
|
# Deploy script for Forgejo Actions
|
|
# Uses Forgejo environment variables instead of GitLab CI variables
|
|
|
|
: "${DEPLOY_USER:?DEPLOY_USER is required}"
|
|
: "${DEPLOY_HOST:?DEPLOY_HOST is required}"
|
|
: "${APP_IMAGE:?APP_IMAGE is required}"
|
|
: "${DEPLOY_SSH_PRIVATE_KEY:?DEPLOY_SSH_PRIVATE_KEY is required}"
|
|
|
|
DEPLOY_PORT="${DEPLOY_PORT:-22}"
|
|
DEPLOY_PATH="${DEPLOY_PATH:-/opt/vault-dash}"
|
|
COMPOSE_FILE="${COMPOSE_FILE:-docker-compose.deploy.yml}"
|
|
COMPOSE_SERVICE="${COMPOSE_SERVICE:-vault-dash}"
|
|
DEPLOY_TIMEOUT="${DEPLOY_TIMEOUT:-120}"
|
|
HEALTHCHECK_URL="${HEALTHCHECK_URL:-http://127.0.0.1:${APP_PORT:-8000}/health}"
|
|
REMOTE_ENV_FILE="${REMOTE_ENV_FILE:-$DEPLOY_PATH/.env}"
|
|
|
|
SSH_OPTS=(-p "$DEPLOY_PORT" -o StrictHostKeyChecking=accept-new)
|
|
SCP_OPTS=(-P "$DEPLOY_PORT" -o StrictHostKeyChecking=accept-new)
|
|
|
|
REMOTE_TARGET="${DEPLOY_USER}@${DEPLOY_HOST}"
|
|
|
|
echo "=== Deploying vault-dash ==="
|
|
echo "Host: $DEPLOY_HOST:$DEPLOY_PORT"
|
|
echo "Path: $DEPLOY_PATH"
|
|
echo "Image: $APP_IMAGE"
|
|
|
|
# Create deployment directory
|
|
ssh "${SSH_OPTS[@]}" "$REMOTE_TARGET" "mkdir -p '$DEPLOY_PATH'"
|
|
|
|
# Write environment file
|
|
echo "=== Writing environment file ==="
|
|
ssh "${SSH_OPTS[@]}" "$REMOTE_TARGET" "cat > '$REMOTE_ENV_FILE'" <<EOF
|
|
APP_IMAGE=$APP_IMAGE
|
|
APP_ENV=${APP_ENV:-production}
|
|
APP_NAME=${APP_NAME:-Vault Dashboard}
|
|
APP_PORT=${APP_PORT:-8000}
|
|
APP_BIND_ADDRESS=${APP_BIND_ADDRESS:-127.0.0.1}
|
|
REDIS_URL=${REDIS_URL:-}
|
|
DEFAULT_SYMBOL=${DEFAULT_SYMBOL:-GLD}
|
|
CACHE_TTL=${CACHE_TTL:-300}
|
|
WEBSOCKET_INTERVAL_SECONDS=${WEBSOCKET_INTERVAL_SECONDS:-5}
|
|
NICEGUI_MOUNT_PATH=${NICEGUI_MOUNT_PATH:-/}
|
|
NICEGUI_STORAGE_SECRET=${NICEGUI_STORAGE_SECRET:-}
|
|
CORS_ORIGINS=${CORS_ORIGINS:-*}
|
|
EOF
|
|
|
|
# Upload docker-compose file
|
|
echo "=== Uploading docker-compose.deploy.yml ==="
|
|
scp "${SCP_OPTS[@]}" docker-compose.deploy.yml "$REMOTE_TARGET:$DEPLOY_PATH/$COMPOSE_FILE"
|
|
|
|
# Deploy on remote
|
|
echo "=== Running deployment on remote ==="
|
|
ssh "${SSH_OPTS[@]}" "$REMOTE_TARGET" "bash -s" <<EOF
|
|
set -Eeuo pipefail
|
|
|
|
cd "$DEPLOY_PATH"
|
|
|
|
# Save current image for rollback
|
|
if [[ -f .last_successful_image ]]; then
|
|
PREVIOUS_IMAGE="\$(cat .last_successful_image)"
|
|
echo "Previous image: \$PREVIOUS_IMAGE"
|
|
fi
|
|
|
|
# Pull new image
|
|
echo "Pulling $APP_IMAGE..."
|
|
docker pull "$APP_IMAGE" || {
|
|
echo "Failed to pull image"
|
|
exit 1
|
|
}
|
|
|
|
# Save new image for rollback
|
|
echo "$APP_IMAGE" > .last_successful_image
|
|
|
|
# Stop existing container
|
|
echo "Stopping existing containers..."
|
|
docker compose -f "$COMPOSE_FILE" --env-file "$REMOTE_ENV_FILE" down --remove-orphans || true
|
|
|
|
# Start new container
|
|
echo "Starting new container..."
|
|
docker compose -f "$COMPOSE_FILE" --env-file "$REMOTE_ENV_FILE" up -d --remove-orphans
|
|
|
|
# Wait for health check
|
|
echo "Waiting for health check..."
|
|
COUNTER=0
|
|
MAX_WAIT=$DEPLOY_TIMEOUT
|
|
while [ \$COUNTER -lt \$MAX_WAIT ]; do
|
|
if curl -sf "${HEALTHCHECK_URL}" > /dev/null 2>&1; then
|
|
echo "Health check passed after \${COUNTER}s"
|
|
echo "=== Deployment successful ==="
|
|
exit 0
|
|
fi
|
|
sleep 1
|
|
COUNTER=\$((COUNTER + 1))
|
|
done
|
|
|
|
# Health check failed - rollback
|
|
echo "Health check failed after \${MAX_WAIT}s"
|
|
|
|
if [[ -n "\${PREVIOUS_IMAGE:-}" ]]; then
|
|
echo "Rolling back to \$PREVIOUS_IMAGE..."
|
|
sed -i.bak "s|^APP_IMAGE=.*|APP_IMAGE=\$PREVIOUS_IMAGE|" "$REMOTE_ENV_FILE"
|
|
docker compose -f "$COMPOSE_FILE" --env-file "$REMOTE_ENV_FILE" up -d --remove-orphans
|
|
echo "Rollback complete"
|
|
fi
|
|
|
|
exit 1
|
|
EOF
|
|
|
|
echo "=== Deployment complete ===" |