stages: - build - deploy variables: CACHE_KEY: "node-modules-${CI_COMMIT_REF_SLUG}" BUILD_DIR: "dist" cache: key: $CACHE_KEY paths: - node_modules/ policy: pull-push # Build stage build: stage: build image: node:20-alpine script: - echo "Installing dependencies..." - npm ci - echo "Building project..." - npm run build - echo "Build completed!" artifacts: paths: - $BUILD_DIR/ expire_in: 1 hour only: - develop # Deploy to shared hosting via FTP deploy: stage: deploy image: alpine:latest before_script: - apk add --no-cache openssh-client sshpass rsync script: - echo "Starting deployment to $SSH_HOST on port $SSH_PORT..." - | if sshpass -p "$SSH_PASSWORD" rsync -avz --delete \ -e "ssh -p $SSH_PORT -o StrictHostKeyChecking=no" \ --exclude='.htaccess' \ --exclude='.env' \ --exclude='.git' \ $BUILD_DIR/ $SSH_USER@$SSH_HOST:$SSH_TARGET_DIR/; then echo "✅ Deployment successful!" echo "🌐 Website: $PRODUCTION_URL" else echo "❌ Deployment failed!" exit 1 fi environment: name: production url: $PRODUCTION_URL only: - develop when: manual retry: max: 2 when: - runner_system_failure - stuck_or_timeout_failure