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>
161 lines
6.1 KiB
YAML
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 "=========================================="
|