feat(ci): GitHub Actions deploy workflow for liderra.ru — fundamental fix for dev→prod SSH block
Adds .github/workflows/deploy.yml — manual workflow_dispatch trigger that: 1) checkouts requested ref (default main) 2) builds frontend (npm ci + npm run build) 3) tarballs app + db excluding .env/storage/vendor/node_modules/bootstrap-cache 4) ssh-deploys via stored secret LIDERRA_SSH_KEY to ubuntu@111.88.246.137 5) extracts overlay + runs /var/www/liderra/redeploy.sh (composer + migrate + restart) 6) backfills today's snapshot (slepok-stage-2 Task 2.12 Step 3) 7) runs smoke tests (migrate:status, snapshots count, service health, portal http) Why this is needed: My dev VM (89.144.17.119) → prod VM (111.88.246.137) traffic passes TCP-handshake but app-layer banner exchange times out. Same VPC, SG 0.0.0.0/0, iptables empty, fail2ban clean — drop happens on YC backbone between specific source/dest pair. GitHub Actions runners come from Azure IPs, NOT affected by this filter. One-time setup needed: GitHub Settings → Secrets → Actions → New secret Name: LIDERRA_SSH_KEY Value: content of ~/.ssh/liderra_deploy (private key, full file) Future deploys: `gh workflow run deploy.yml -f ref=main` from anywhere. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,146 @@
|
||||
name: Deploy to liderra.ru
|
||||
|
||||
# Запускается вручную через web-интерфейс GitHub или через `gh workflow run`.
|
||||
# Решает проблему «дев-машина не достучится по SSH до прод-сервера через YC backbone»:
|
||||
# GitHub Actions runner — внешний по отношению к YC, его IP не блокируется тем
|
||||
# фильтром что блокирует мой dev-IP `89.144.17.119`.
|
||||
#
|
||||
# Требуемые secrets (Settings → Secrets and variables → Actions):
|
||||
# LIDERRA_SSH_KEY — содержимое приватного ключа `~/.ssh/liderra_deploy`
|
||||
# (начинается с `-----BEGIN OPENSSH PRIVATE KEY-----`).
|
||||
# Host/user захардкожены — публичная информация, нет смысла в secrets.
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ref:
|
||||
description: 'Branch/tag/SHA для деплоя (по умолчанию main)'
|
||||
required: true
|
||||
default: 'main'
|
||||
type: string
|
||||
backfill_snapshot:
|
||||
description: 'Запустить snapshot:backfill за сегодня (default yes)'
|
||||
required: false
|
||||
default: true
|
||||
type: boolean
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
name: Deploy code + run redeploy.sh
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 20
|
||||
concurrency:
|
||||
group: liderra-prod-deploy
|
||||
cancel-in-progress: false
|
||||
|
||||
env:
|
||||
LIDERRA_HOST: 111.88.246.137
|
||||
LIDERRA_USER: ubuntu
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.inputs.ref }}
|
||||
|
||||
- name: Setup Node 20
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
cache-dependency-path: app/package-lock.json
|
||||
|
||||
- name: Install frontend deps
|
||||
working-directory: app
|
||||
run: npm ci
|
||||
|
||||
- name: Build frontend
|
||||
working-directory: app
|
||||
run: npm run build
|
||||
|
||||
- name: Verify build artifacts present
|
||||
run: |
|
||||
test -f app/public/build/manifest.json
|
||||
ls app/public/build/assets/ | head -5
|
||||
du -sh app/public/build/
|
||||
|
||||
- name: Create deploy tarball
|
||||
run: |
|
||||
tar czf /tmp/deploy.tgz \
|
||||
--exclude='app/.env' \
|
||||
--exclude='app/.env.example' \
|
||||
--exclude='app/.env.production' \
|
||||
--exclude='app/storage' \
|
||||
--exclude='app/vendor' \
|
||||
--exclude='app/node_modules' \
|
||||
--exclude='app/bootstrap/cache' \
|
||||
app db
|
||||
ls -lh /tmp/deploy.tgz
|
||||
|
||||
- name: Setup SSH key
|
||||
run: |
|
||||
mkdir -p ~/.ssh
|
||||
echo "${{ secrets.LIDERRA_SSH_KEY }}" > ~/.ssh/liderra_deploy
|
||||
chmod 600 ~/.ssh/liderra_deploy
|
||||
ssh-keyscan -H ${{ env.LIDERRA_HOST }} >> ~/.ssh/known_hosts 2>/dev/null
|
||||
|
||||
- name: Upload tarball to prod
|
||||
run: |
|
||||
scp -i ~/.ssh/liderra_deploy -o StrictHostKeyChecking=accept-new \
|
||||
/tmp/deploy.tgz ${{ env.LIDERRA_USER }}@${{ env.LIDERRA_HOST }}:/tmp/deploy.tgz
|
||||
|
||||
- name: Extract + run redeploy.sh on prod
|
||||
run: |
|
||||
ssh -i ~/.ssh/liderra_deploy ${{ env.LIDERRA_USER }}@${{ env.LIDERRA_HOST }} 'bash -s' <<'REMOTE'
|
||||
set -euo pipefail
|
||||
TS=$(date -u +%Y%m%d-%H%M%S)
|
||||
echo "=== Backup current app ==="
|
||||
sudo tar czf /home/ubuntu/deploy-backups/app-pre-deploy-${TS}.tgz \
|
||||
--exclude='storage' --exclude='vendor' --exclude='node_modules' --exclude='public/build' \
|
||||
-C /var/www/liderra app
|
||||
ls -lh /home/ubuntu/deploy-backups/app-pre-deploy-${TS}.tgz
|
||||
|
||||
echo "=== Extract overlay ==="
|
||||
cd /var/www/liderra
|
||||
sudo tar xzf /tmp/deploy.tgz
|
||||
sudo chown -R www-data:www-data /var/www/liderra/app /var/www/liderra/db
|
||||
|
||||
echo "=== redeploy.sh (composer + migrate + optimize + restart) ==="
|
||||
sudo bash /var/www/liderra/redeploy.sh
|
||||
|
||||
rm -f /tmp/deploy.tgz
|
||||
REMOTE
|
||||
|
||||
- name: Backfill today's snapshot
|
||||
if: ${{ github.event.inputs.backfill_snapshot != 'false' }}
|
||||
run: |
|
||||
ssh -i ~/.ssh/liderra_deploy ${{ env.LIDERRA_USER }}@${{ env.LIDERRA_HOST }} 'bash -s' <<'REMOTE'
|
||||
set -e
|
||||
cd /var/www/liderra/app
|
||||
sudo -u www-data php artisan snapshot:backfill --date=$(date +%Y-%m-%d) || \
|
||||
echo "WARN: backfill returned non-zero — проверь вручную"
|
||||
REMOTE
|
||||
|
||||
- name: Smoke tests
|
||||
run: |
|
||||
ssh -i ~/.ssh/liderra_deploy ${{ env.LIDERRA_USER }}@${{ env.LIDERRA_HOST }} 'bash -s' <<'REMOTE'
|
||||
set -e
|
||||
cd /var/www/liderra/app
|
||||
echo '=== Migrations status (last 5) ==='
|
||||
sudo -u www-data php artisan migrate:status 2>&1 | tail -5
|
||||
echo '=== Snapshots count (last 3 dates) ==='
|
||||
sudo -u postgres psql -d liderra -c "SELECT snapshot_date, COUNT(*) AS rows FROM project_routing_snapshots GROUP BY 1 ORDER BY 1 DESC LIMIT 3;" || true
|
||||
echo '=== Service status ==='
|
||||
systemctl is-active nginx php8.3-fpm postgresql liderra-queue
|
||||
echo '=== Internal portal health ==='
|
||||
curl -sf -o /dev/null -w 'https=%{http_code} time=%{time_total}s\n' --max-time 8 https://127.0.0.1/ -k || true
|
||||
REMOTE
|
||||
|
||||
- name: External portal health (from runner)
|
||||
run: |
|
||||
curl -sf -o /dev/null -w 'external https=%{http_code} time=%{time_total}s\n' \
|
||||
--max-time 15 https://liderra.ru/ || echo "external health returned non-zero"
|
||||
|
||||
- name: Cleanup SSH key
|
||||
if: always()
|
||||
run: rm -f ~/.ssh/liderra_deploy
|
||||
Reference in New Issue
Block a user