# 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 # Keep data directories owned by container user - sudo chown -R 1001:1001 "$DEPLOY_PATH/data/backups" "$DEPLOY_PATH/data/documents" 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/8 Initializing data directories..." - mkdir -p data/backups data/documents - sudo chown -R 1001:1001 data/backups data/documents - chmod 755 data/backups data/documents - echo "Step 2/8 Injecting secrets..." - chmod +x scripts/inject-secrets.sh - ./scripts/inject-secrets.sh - echo "Step 3/8 Stopping existing services..." - docker compose -f $DOCKER_COMPOSE_FILE -f $DOCKER_COMPOSE_PROD_FILE down --timeout 30 || true - echo "Step 4/8 Pulling base images..." - docker compose -f $DOCKER_COMPOSE_FILE pull - echo "Step 5/8 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 6/8 Running database migrations..." - docker compose -f $DOCKER_COMPOSE_FILE run --rm mvp-backend npm run migrate || echo "Migration skipped" - echo "Step 7/8 Vehicle catalog data..." # Schema and data now loaded via standard migration system # Migration runner handles table creation and data loading automatically - echo "Vehicle catalog loaded via platform feature migration" - echo "Flushing Redis cache..." - docker exec mvp-redis redis-cli FLUSHALL - echo "Step 8/8 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 "=========================================="