Files
motovaultpro/.gitlab-ci.yml
Eric Gullickson 065fed8d98 Fix GitLab CI backend health check
Use docker exec curl instead of node http.get from host.
Port 3001 is not exposed to host, so health checks must run inside the container.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-20 12:06:44 -06:00

161 lines
6.1 KiB
YAML

# MotoVaultPro GitLab CI/CD Pipeline
# GitLab 18.6+ with shell executor
# See docs/CICD-DEPLOY.md for complete documentation
# v1.5
stages:
- validate
- build
- deploy
- verify
variables:
# Use stable clone path instead of runner-specific path
GIT_CLONE_PATH: $CI_BUILDS_DIR/motovaultpro
DEPLOY_PATH: $CI_BUILDS_DIR/motovaultpro
DOCKER_COMPOSE_FILE: docker-compose.yml
DOCKER_COMPOSE_PROD_FILE: docker-compose.prod.yml
# Fix permissions after every job - docker creates files as root
default:
after_script:
- echo "Fixing file permissions..."
- sudo chown -R gitlab-runner:gitlab-runner "$DEPLOY_PATH" 2>/dev/null || true
# Validate Stage - Check prerequisites
validate:
stage: validate
only:
- main
script:
- echo "=========================================="
- echo "Validating deployment prerequisites..."
- echo "=========================================="
- echo "Checking Docker..."
- 'docker info > /dev/null 2>&1 || (echo "ERROR: Docker not accessible" && exit 1)'
- echo "OK Docker is accessible"
- echo "Checking Docker Compose..."
- 'docker compose version > /dev/null 2>&1 || (echo "ERROR: Docker Compose not available" && exit 1)'
- echo "OK Docker Compose is available"
- echo "Checking deployment path..."
- 'test -d "$DEPLOY_PATH" || (echo "ERROR: DEPLOY_PATH not found" && exit 1)'
- echo "OK Deployment path exists"
- echo "=========================================="
- echo "Validation complete"
- echo "=========================================="
# Build Stage - Build Docker images
build:
stage: build
only:
- main
script:
- echo "=========================================="
- echo "Building Docker images..."
- echo "=========================================="
- cd "$DEPLOY_PATH"
- echo "Building images..."
- docker compose -f $DOCKER_COMPOSE_FILE build --no-cache
- echo "=========================================="
- echo "Build complete"
- echo "=========================================="
# Deploy Stage - Inject secrets and deploy services
deploy:
stage: deploy
only:
- main
environment:
name: production
url: https://motovaultpro.com
script:
- echo "=========================================="
- echo "Deploying MotoVaultPro..."
- echo "=========================================="
- cd "$DEPLOY_PATH"
- echo "Step 1/7 Injecting secrets..."
- chmod +x scripts/inject-secrets.sh
- ./scripts/inject-secrets.sh
- echo "Step 2/7 Stopping existing services..."
- docker compose -f $DOCKER_COMPOSE_FILE -f $DOCKER_COMPOSE_PROD_FILE down --timeout 30 || true
- echo "Step 3/7 Pulling base images..."
- docker compose -f $DOCKER_COMPOSE_FILE pull
- echo "Step 4/7 Starting database services..."
- docker compose -f $DOCKER_COMPOSE_FILE -f $DOCKER_COMPOSE_PROD_FILE up -d mvp-postgres mvp-redis
- echo "Waiting for database to be ready..."
- sleep 15
- echo "Step 5/7 Running database migrations..."
- docker compose -f $DOCKER_COMPOSE_FILE run --rm mvp-backend npm run migrate || echo "Migration skipped"
- echo "Step 6/7 Running vehicle ETL import..."
- |
docker exec -i mvp-postgres psql -U postgres -d motovaultpro < data/vehicle-etl/migrations/001_create_vehicle_database.sql
docker exec -i mvp-postgres psql -U postgres -d motovaultpro -c "TRUNCATE TABLE vehicle_options RESTART IDENTITY CASCADE; TRUNCATE TABLE engines RESTART IDENTITY CASCADE; TRUNCATE TABLE transmissions RESTART IDENTITY CASCADE;"
docker exec -i mvp-postgres psql -U postgres -d motovaultpro < data/vehicle-etl/output/01_engines.sql
docker exec -i mvp-postgres psql -U postgres -d motovaultpro < data/vehicle-etl/output/02_transmissions.sql
docker exec -i mvp-postgres psql -U postgres -d motovaultpro < data/vehicle-etl/output/03_vehicle_options.sql
- echo "Flushing Redis cache..."
- docker exec mvp-redis redis-cli FLUSHALL
- echo "Vehicle ETL import completed"
- echo "Step 7/7 Starting all services..."
- docker compose -f $DOCKER_COMPOSE_FILE -f $DOCKER_COMPOSE_PROD_FILE up -d
- echo "Waiting for services to initialize..."
- sleep 30
- echo "=========================================="
- echo "Deployment complete"
- echo "=========================================="
# Verify Stage - Health checks
verify:
stage: verify
only:
- main
script:
- echo "=========================================="
- echo "Verifying deployment..."
- echo "=========================================="
- cd "$DEPLOY_PATH"
- echo "Checking container status..."
- |
FAILED=0
for service in mvp-traefik mvp-frontend mvp-backend mvp-postgres mvp-redis; do
status=$(docker inspect --format='{{.State.Status}}' $service 2>/dev/null || echo "not found")
if [ "$status" != "running" ]; then
echo "ERROR: $service is not running (status: $status)"
docker logs $service --tail 50 2>/dev/null || true
FAILED=1
else
echo "OK: $service is running"
fi
done
if [ $FAILED -eq 1 ]; then
echo "One or more services failed to start"
exit 1
fi
- echo "Checking backend health..."
- |
HEALTH_OK=0
for i in 1 2 3 4 5 6; do
if docker exec mvp-backend curl -sf http://localhost:3001/health > /dev/null 2>&1; then
echo "OK: Backend health check passed"
HEALTH_OK=1
break
fi
echo "Attempt $i/6: Backend not ready, waiting 10s..."
sleep 10
done
if [ $HEALTH_OK -eq 0 ]; then
echo "ERROR: Backend health check failed after 6 attempts"
docker logs mvp-backend --tail 100
exit 1
fi
- echo "Checking frontend..."
- |
if docker compose -f $DOCKER_COMPOSE_FILE exec -T mvp-frontend curl -sf http://localhost:3000 > /dev/null 2>&1; then
echo "OK: Frontend is accessible"
else
echo "WARNING: Frontend check failed (might need Traefik routing)"
fi
- echo "=========================================="
- echo "Deployment verified successfully!"
- echo "=========================================="