From 1e6f16fd9f888e2a04e5a8adec7eba8e8b61e66a Mon Sep 17 00:00:00 2001 From: lilsus Date: Thu, 16 Jul 2026 07:18:58 +0300 Subject: [PATCH] ci: deploy via ssh + tar (runner image has no rsync) --- .gitea/workflows/deploy.yml | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index d1a8ce1..f113db5 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -1,6 +1,6 @@ # ============================================================================= # deploy.yml — build every brand in this content repo with Hugo and deploy each -# to .lilsus.fun via rsync over SSH. Runs on every push to main (i.e. +# to .lilsus.fun via SSH (ssh + tar). Runs on every push to main (i.e. # after each n8n pipeline run that commits repo//...). # # INSTALL: copy this file to .gitea/workflows/deploy.yml in the CONTENT repo @@ -22,8 +22,9 @@ # SITE_TLD - base domain for per-brand hosts (default lilsus.fun) # # RUNNER REQUIREMENTS: a registered Gitea act_runner whose image has bash, git, -# curl, tar, rsync, openssh-client and Node.js >= 20 (for Tailwind/PostCSS). -# The default `gitea/runner`/`catthehacker/ubuntu` images include these. +# curl, tar, openssh-client and Node.js >= 20 (for Tailwind/PostCSS). rsync is +# NOT required (deploy uses ssh + tar). The default runner-images/ubuntu images +# include these. # ============================================================================= name: Build & Deploy Brands run-name: deploy ${{ gitea.sha }} @@ -116,9 +117,10 @@ jobs: npm install --no-audit --no-fund --ignore-scripts fi - # --- 5. Prepare the SSH deploy key for rsync. Host key is trusted on - # first connect and pinned thereafter (StrictHostKeyChecking=accept-new - # in the deploy step), so no SSH_KNOWN_HOSTS secret is required. --- + # --- 5. Prepare the SSH deploy key (deploy is plain ssh + tar, no rsync). + # Host key is trusted on first connect and pinned thereafter + # (StrictHostKeyChecking=accept-new in the deploy step), so no + # SSH_KNOWN_HOSTS secret is required. --- - name: Configure SSH run: | set -euo pipefail @@ -158,12 +160,17 @@ jobs: echo "::endgroup::" echo "::group::Deploy ${BRAND}" - # Ensure the target dir exists, then mirror public/ into it. - ssh $SSH_OPTS "${DEPLOY_USER}@${DEPLOY_HOST}" "mkdir -p '${DEPLOY_PATH}/${BRAND}'" - rsync -az --delete \ - -e "ssh $SSH_OPTS" \ - "$BUILD_DIR/public/" \ - "${DEPLOY_USER}@${DEPLOY_HOST}:${DEPLOY_PATH}/${BRAND}/" + # Deploy over plain SSH only (no rsync — not present in the runner image). + # Stream public/ as a tarball into a fresh temp dir on the server, then + # atomically swap it into place. Mirrors --delete semantics (stale files + # vanish because the live dir is fully replaced). Needs only ssh + tar. + REMOTE_TMP="${DEPLOY_PATH}/.deploy-${BRAND}-$(date +%s)" + tar -czf - -C "$BUILD_DIR/public" . | ssh $SSH_OPTS "${DEPLOY_USER}@${DEPLOY_HOST}" "\ + set -e; \ + mkdir -p '${REMOTE_TMP}' '${DEPLOY_PATH}'; \ + tar -xzf - -C '${REMOTE_TMP}'; \ + rm -rf '${DEPLOY_PATH}/${BRAND}'; \ + mv '${REMOTE_TMP}' '${DEPLOY_PATH}/${BRAND}'" echo "Deployed ${BRAND} to ${DEPLOY_USER}@${DEPLOY_HOST}:${DEPLOY_PATH}/${BRAND}/" echo "::endgroup::" done