name: Build and Deploy on: push: branches: ['**'] env: REGISTRY: registry.rose-ash.com:5000 APP_DIR: /root/rose-ash jobs: build-and-deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install tools run: | apt-get update && apt-get install -y --no-install-recommends openssh-client - name: Set up SSH env: SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }} DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }} run: | mkdir -p ~/.ssh echo "$SSH_KEY" > ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa ssh-keyscan -H "$DEPLOY_HOST" >> ~/.ssh/known_hosts 2>/dev/null || true - name: Build and deploy changed apps env: DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }} run: | ssh "root@$DEPLOY_HOST" " cd ${{ env.APP_DIR }} # Save current HEAD before updating OLD_HEAD=\$(git rev-parse HEAD 2>/dev/null || echo none) git fetch origin ${{ github.ref_name }} git reset --hard origin/${{ github.ref_name }} NEW_HEAD=\$(git rev-parse HEAD) # Detect what changed REBUILD_ALL=false if [ \"\$OLD_HEAD\" = \"none\" ] || [ \"\$OLD_HEAD\" = \"\$NEW_HEAD\" ]; then # First deploy or CI re-run on same commit — rebuild all REBUILD_ALL=true else CHANGED=\$(git diff --name-only \$OLD_HEAD \$NEW_HEAD) if echo \"\$CHANGED\" | grep -q '^shared/'; then REBUILD_ALL=true fi if echo \"\$CHANGED\" | grep -q '^docker-compose.yml'; then REBUILD_ALL=true fi fi # Map compose service name to source directory app_dir() { case \"\$1\" in sx_docs) echo \"sx\" ;; *) echo \"\$1\" ;; esac } for app in blog market cart events federation account relations likes orders test sx_docs; do dir=\$(app_dir \"\$app\") IMAGE_EXISTS=\$(docker image ls -q ${{ env.REGISTRY }}/\$app:latest 2>/dev/null) if [ \"\$REBUILD_ALL\" = true ] || echo \"\$CHANGED\" | grep -q \"^\$dir/\" || [ -z \"\$IMAGE_EXISTS\" ]; then echo \"Building \$app...\" docker build \ --build-arg CACHEBUST=\$(date +%s) \ -f \$dir/Dockerfile \ -t ${{ env.REGISTRY }}/\$app:latest \ -t ${{ env.REGISTRY }}/\$app:${{ github.sha }} \ . docker push ${{ env.REGISTRY }}/\$app:latest docker push ${{ env.REGISTRY }}/\$app:${{ github.sha }} else echo \"Skipping \$app (no changes)\" fi done # Deploy swarm stacks only on main branch if [ '${{ github.ref_name }}' = 'main' ]; then source .env docker stack deploy -c docker-compose.yml rose-ash echo 'Waiting for swarm services to update...' sleep 10 docker stack services rose-ash # Deploy sx-web standalone stack (sx-web.org) SX_REBUILT=false if [ \"\$REBUILD_ALL\" = true ] || echo \"\$CHANGED\" | grep -q '^sx/'; then SX_REBUILT=true fi if [ \"\$SX_REBUILT\" = true ]; then echo 'Deploying sx-web stack (sx-web.org)...' docker stack deploy -c /root/sx-web/docker-compose.yml sx-web sleep 5 docker stack services sx-web fi else echo 'Skipping swarm deploy (branch: ${{ github.ref_name }})' fi # Dev stack always deployed (bind-mounted source + auto-reload) echo 'Deploying dev stack...' docker compose -p rose-ash-dev -f docker-compose.yml -f docker-compose.dev.yml up -d echo 'Dev stack deployed' docker compose -p rose-ash-dev -f docker-compose.yml -f docker-compose.dev.yml ps "