name: Build & Deploy SimO on: push: branches: - main - master paths: - 'src/**' - 'package.json' - 'package-lock.json' - 'tailwind.config.ts' - 'next.config.mjs' - 'postcss.config.js' - 'tsconfig.json' - 'Dockerfile' - 'nginx.conf' - 'docker-stack.yml' - '.gitea/workflows/deploy.yml' workflow_dispatch: env: IMAGE_NAME: simo/web jobs: build-and-deploy: name: ๐Ÿ—๏ธ Build & Deploy runs-on: ubuntu-latest steps: - name: ๐Ÿ“ฅ Checkout code uses: https://github.com/actions/checkout@v4 - name: ๐Ÿ” Debug - Check secrets run: | echo "SWARM_MANAGER_HOST length: ${#SWARM_MANAGER_HOST}" echo "SWARM_USER length: ${#SWARM_USER}" echo "SWARM_SSH_KEY length: ${#SWARM_SSH_KEY}" if [ -z "$SWARM_MANAGER_HOST" ]; then echo "โŒ SWARM_MANAGER_HOST is empty!"; fi if [ -z "$SWARM_USER" ]; then echo "โŒ SWARM_USER is empty!"; fi if [ -z "$SWARM_SSH_KEY" ]; then echo "โŒ SWARM_SSH_KEY is empty!"; fi env: SWARM_MANAGER_HOST: ${{ secrets.SWARM_MANAGER_HOST }} SWARM_USER: ${{ secrets.SWARM_USER }} SWARM_SSH_KEY: ${{ secrets.SWARM_SSH_KEY }} - name: ๐Ÿ” Setup SSH env: SSH_KEY: ${{ secrets.SWARM_SSH_KEY }} SSH_HOST: ${{ secrets.SWARM_MANAGER_HOST }} run: | mkdir -p ~/.ssh echo "$SSH_KEY" > ~/.ssh/deploy_key chmod 600 ~/.ssh/deploy_key ssh-keyscan -H $SSH_HOST >> ~/.ssh/known_hosts - name: ๐Ÿ“ฆ Copy source to server env: SSH_USER: ${{ secrets.SWARM_USER }} SSH_HOST: ${{ secrets.SWARM_MANAGER_HOST }} run: | tar -czf /tmp/source.tar.gz \ --exclude='node_modules' \ --exclude='.next' \ --exclude='out' \ --exclude='.git' \ . scp -i ~/.ssh/deploy_key /tmp/source.tar.gz "$SSH_USER@$SSH_HOST":/tmp/simo-source.tar.gz echo "โœ… Source copied" - name: ๐Ÿณ Build Docker Image env: SSH_USER: ${{ secrets.SWARM_USER }} SSH_HOST: ${{ secrets.SWARM_MANAGER_HOST }} run: | COMMIT_SHA=$(git rev-parse --short HEAD) echo "๐Ÿ“Œ Commit: $COMMIT_SHA" ssh -i ~/.ssh/deploy_key ${SSH_USER}@${SSH_HOST} << ENDSSH set -e mkdir -p /tmp/simo-build cd /tmp/simo-build rm -rf * tar -xzf /tmp/simo-source.tar.gz echo "๐Ÿณ Building image: simo/web:$COMMIT_SHA" docker build -t simo/web:$COMMIT_SHA \ -t simo/web:latest . echo "๐Ÿงน Cleaning old images..." docker image prune -f echo "โœ… Image built: simo/web:$COMMIT_SHA" ENDSSH - name: ๐Ÿš€ Deploy to Swarm env: SSH_USER: ${{ secrets.SWARM_USER }} SSH_HOST: ${{ secrets.SWARM_MANAGER_HOST }} run: | COMMIT_SHA=$(git rev-parse --short HEAD) scp -i ~/.ssh/deploy_key ./docker-stack.yml ${SSH_USER}@${SSH_HOST}:/tmp/simo-stack.yml ssh -i ~/.ssh/deploy_key ${SSH_USER}@${SSH_HOST} << ENDSSH set -e echo "๐Ÿš€ Deploying stack..." IMAGE_TAG=$COMMIT_SHA docker stack deploy -c /tmp/simo-stack.yml simo echo "๐Ÿ”„ Forcing service update..." docker service update --force --image simo/web:$COMMIT_SHA simo_web echo "โณ Waiting for service to stabilize..." sleep 10 echo "๐Ÿ“Š Service status:" docker service ls --filter name=simo docker service ps simo_web --no-trunc echo "โœ… Deployment complete!" ENDSSH - name: ๐Ÿฅ Health Check env: SSH_USER: ${{ secrets.SWARM_USER }} SSH_HOST: ${{ secrets.SWARM_MANAGER_HOST }} run: | ssh -i ~/.ssh/deploy_key ${SSH_USER}@${SSH_HOST} << ENDSSH echo "๐Ÿฅ Running health check..." for i in 1 2 3 4 5 6 7 8 9 10; do STATUS=\$(curl -sf -o /dev/null -w "%{http_code}" https://simo.antopoid.com/ 2>/dev/null || echo "000") if [ "\$STATUS" = "200" ]; then echo "โœ… SimO is live! (HTTP \$STATUS)" echo "๐ŸŒ https://simo.antopoid.com" exit 0 fi echo "โณ Waiting for SimO... (\$i/10) โ€” HTTP \$STATUS" sleep 5 done echo "โŒ Health check failed!" echo "" echo "๐Ÿ“‹ Service logs:" docker service logs simo_web --tail 50 echo "" echo "๐Ÿ“Š Service tasks:" docker service ps simo_web --no-trunc exit 1 ENDSSH - name: ๐Ÿงน Cleanup if: always() run: | rm -f ~/.ssh/deploy_key echo "โœ… Pipeline finished!"