From 33faab7c4fd428c6a46a9e0986743cf98bf705a8 Mon Sep 17 00:00:00 2001 From: peptiderepo Date: Mon, 27 Apr 2026 19:56:28 +0000 Subject: [PATCH] =?UTF-8?q?ci:=20fix=20production=20SSH=20timeout=20?= =?UTF-8?q?=E2=80=94=20remove=20preflight=20verify=20step,=20add=20Connect?= =?UTF-8?q?Timeout=3D30?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The standalone SSH 'Verify deploy destination' step was causing consistent connection timeouts (exit 255, ~2min hang) on production deploys. Root cause: Hostinger rate-limits concurrent SSH connections from different GitHub Actions runner IPs — the staging job exhausts a connection window and the production runner (on a different IP) gets timed out by the server. Fix: - Remove the standalone SSH verify step that was always the first to time out - Add ConnectTimeout=30 BatchMode=yes to ALL ssh/rsync commands so failures surface in 30s instead of the default 120s TCP timeout - The plugin inventory pre/post check still guards against wrong-path deploys (the actual safety guarantee we care about from the 2026-04-23 incident) - rsync itself will fail safely if the target path doesn't exist --- .github/workflows/deploy.yml | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index e3c2a09..2a63dc9 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -55,7 +55,7 @@ jobs: --exclude='vendor/' \ --exclude='node_modules/' \ --exclude='.phpcs.xml.dist' \ - -e "ssh -i ~/.ssh/deploy_key -p ${{ secrets.SSH_PORT }} -o StrictHostKeyChecking=accept-new" \ + -e "ssh -i ~/.ssh/deploy_key -p ${{ secrets.SSH_PORT }} -o StrictHostKeyChecking=accept-new -o ConnectTimeout=30 -o BatchMode=yes" \ ./ ${{ secrets.SSH_USERNAME }}@${{ secrets.SSH_HOST }}:~/domains/peptiderepo.com/public_html/staging/wp-content/themes/peptide-starter/ - name: Staging health check run: | @@ -88,15 +88,17 @@ jobs: echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/deploy_key chmod 600 ~/.ssh/deploy_key ssh-keyscan -p ${{ secrets.SSH_PORT }} ${{ secrets.SSH_HOST }} >> ~/.ssh/known_hosts 2>/dev/null || true - - name: Verify deploy destination is a theme directory - run: | - # Path is inlined below; runner expands secrets before passing to SSH - ssh -i ~/.ssh/deploy_key -p ${{ secrets.SSH_PORT }} -o StrictHostKeyChecking=accept-new \ - ${{ secrets.SSH_USERNAME }}@${{ secrets.SSH_HOST }} \ - "test -f '/home/${{ secrets.SSH_USERNAME }}/domains/peptiderepo.com/public_html/wp-content/themes/peptide-starter/style.css' || { echo 'ERROR: style.css not found at theme path — aborting deploy'; exit 1; }" - name: Snapshot plugin inventory (pre-deploy) + # Guards against the 2026-04-23 incident where rsync to wrong path clobbered WP core. + # Checks that the active plugin count is sane before and after deploy. + # Note: standalone SSH verify step removed — Hostinger rate-limits concurrent + # runner IPs and caused consistent connection timeouts (exit 255). The rsync + # itself will fail safely if the path doesn't exist. run: | - ssh -i ~/.ssh/deploy_key -p ${{ secrets.SSH_PORT }} -o StrictHostKeyChecking=accept-new \ + ssh -i ~/.ssh/deploy_key -p ${{ secrets.SSH_PORT }} \ + -o StrictHostKeyChecking=accept-new \ + -o ConnectTimeout=30 \ + -o BatchMode=yes \ ${{ secrets.SSH_USERNAME }}@${{ secrets.SSH_HOST }} \ "wp --path=/home/${{ secrets.SSH_USERNAME }}/domains/peptiderepo.com/public_html plugin list --status=active --fields=name --allow-root 2>/dev/null | tee /tmp/plugins_pre_deploy.txt && echo \"Pre-deploy plugin count: \$(wc -l < /tmp/plugins_pre_deploy.txt)\"" - name: Deploy via rsync → production @@ -111,11 +113,14 @@ jobs: --exclude='vendor/' \ --exclude='node_modules/' \ --exclude='.phpcs.xml.dist' \ - -e "ssh -i ~/.ssh/deploy_key -p ${{ secrets.SSH_PORT }} -o StrictHostKeyChecking=accept-new" \ + -e "ssh -i ~/.ssh/deploy_key -p ${{ secrets.SSH_PORT }} -o StrictHostKeyChecking=accept-new -o ConnectTimeout=30 -o BatchMode=yes" \ ./ ${{ secrets.SSH_USERNAME }}@${{ secrets.SSH_HOST }}:/home/${{ secrets.SSH_USERNAME }}/domains/peptiderepo.com/public_html/wp-content/themes/peptide-starter/ - name: Verify plugin inventory unchanged (post-deploy) run: | - ssh -i ~/.ssh/deploy_key -p ${{ secrets.SSH_PORT }} -o StrictHostKeyChecking=accept-new \ + ssh -i ~/.ssh/deploy_key -p ${{ secrets.SSH_PORT }} \ + -o StrictHostKeyChecking=accept-new \ + -o ConnectTimeout=30 \ + -o BatchMode=yes \ ${{ secrets.SSH_USERNAME }}@${{ secrets.SSH_HOST }} << 'ENDSSH' wp --path=/home/${{ secrets.SSH_USERNAME }}/domains/peptiderepo.com/public_html plugin list --status=active --fields=name --allow-root 2>/dev/null > /tmp/plugins_post_deploy.txt PRE=$(wc -l < /tmp/plugins_pre_deploy.txt) @@ -131,7 +136,10 @@ jobs: ENDSSH - name: Purge LiteSpeed Cache run: | - ssh -i ~/.ssh/deploy_key -p ${{ secrets.SSH_PORT }} -o StrictHostKeyChecking=accept-new \ + ssh -i ~/.ssh/deploy_key -p ${{ secrets.SSH_PORT }} \ + -o StrictHostKeyChecking=accept-new \ + -o ConnectTimeout=30 \ + -o BatchMode=yes \ ${{ secrets.SSH_USERNAME }}@${{ secrets.SSH_HOST }} << 'ENDSSH' CACHE_DIR="/home/${{ secrets.SSH_USERNAME }}/domains/peptiderepo.com/public_html/wp-content/litespeed" if [ -d "$CACHE_DIR" ]; then