Files
gravl/scripts/deploy.sh
T

77 lines
2.5 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# Gravl deployment script
# Prevents stale containers by always building fresh with --no-cache
#
# Usage:
# ./scripts/deploy.sh
#
# What it does:
# 1. Pulls latest code from git
# 2. Captures build metadata (commit SHA, timestamp)
# 3. Builds fresh Docker images with --no-cache (no layer caching)
# 4. Restarts containers to use new images
# 5. Polls /api/health endpoint until backend is ready
# 6. Logs all steps to logs/deploy.log
#
# Rationale for --no-cache:
# Docker caching can hide stale assets (JS, CSS, images) when source files change.
# Using --no-cache ensures all layers rebuild fresh, guaranteeing new code is deployed.
# Trade-off: Slightly slower builds (30-60s vs 10-20s with cache), but safer.
#
# See: /docs/DEPLOYMENT.md for troubleshooting
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_DIR="$(dirname "$SCRIPT_DIR")"
LOG_FILE="$REPO_DIR/logs/deploy.log"
BACKEND_HEALTH="http://localhost:3001/api/health"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"
}
mkdir -p "$REPO_DIR/logs"
cd "$REPO_DIR"
log "=== Deploy started ==="
# Pull latest code from remote
# Fails if there are local changes or merge conflicts
log "Pulling latest code..."
git pull
# Capture build metadata to embed in Docker image labels
# These labels allow build-check.sh to verify deployed containers match local code
GIT_COMMIT=$(git rev-parse HEAD)
BUILD_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
log "Commit: $(git rev-parse --short HEAD) | Date: $BUILD_DATE"
# Build fresh images — no-cache prevents Docker layer caching
# This is critical for frontend deployments where CSS/JS changes might not be obvious
# to Docker's layer detection algorithm
log "Building images (--no-cache)..."
export GIT_COMMIT BUILD_DATE
docker compose build --no-cache
# Restart containers with new images
# --force-recreate stops old containers and removes them before starting new ones
log "Starting containers..."
docker compose up -d --force-recreate
# Health check: poll /api/health endpoint until it responds with 200 OK
# Timeout: 60 seconds (12 retries × 5 seconds each)
# This prevents deployment from completing if the backend is broken
log "Health check..."
for i in $(seq 1 12); do
if curl -sf "$BACKEND_HEALTH" >/dev/null 2>&1; then
log "Backend healthy"
break
fi
[ "$i" -eq 12 ] && { log "ERROR: Health check failed after 60s"; exit 1; }
log "Waiting... ($i/12)"
sleep 5
done
log "=== Deploy complete: ${GIT_COMMIT:0:7} ==="