From 02797013153058884f04c6a1eac888717a483401 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9C=D0=98=D0=9D?= Date: Fri, 29 May 2026 04:16:00 +0300 Subject: [PATCH] =?UTF-8?q?ci:=20=D1=83=D0=B1=D1=80=D0=B0=D1=82=D1=8C=20li?= =?UTF-8?q?nt=20=D0=B8=D0=B7=20needs=20deploy-job?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Deploy зависит от lint через needs:, поэтому при failure lint (исторический долг empty-блоков) deploy не запускается ВООБЩЕ (висит pending бесконечно). Lint опциональный — не в branch protection required-checks. Deploy должен зависеть только от Build + Secret-scan. --- .gitea/workflows/ci.yml | 242 ++++++++++++++++++++++++++-------------- 1 file changed, 157 insertions(+), 85 deletions(-) diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml index 7dcc91f..d31f195 100644 --- a/.gitea/workflows/ci.yml +++ b/.gitea/workflows/ci.yml @@ -1,85 +1,157 @@ -# CI студии Рублокса. -# Запускается на каждый push и pull_request. -# -# Что проверяем: -# 1. lint — ESLint без warning'ов -# 2. format-check — Prettier формат не нарушен -# 3. build — vite build проходит без ошибок -# 4. secret-scan — trufflehog не нашёл утечек секретов -# 5. size-check — PR не больше 1000 строк (предупреждение) -name: CI - -on: - push: - branches: [main] - pull_request: - branches: [main] - -jobs: - lint: - name: Lint - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - with: - node-version: '18' - - run: npm ci - # format:check временно отключён до массового npx prettier --write - # (см. docs/ONBOARDING.md → «Форматирование кода»). После прогона - # верни строку `- run: npm run format:check` перед npm run lint. - - run: npm run lint - - build: - name: Build - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - with: - node-version: '18' - - run: npm ci - - run: npm run build - - name: Save build size - run: | - du -sh build/ - ls -la build/assets/ | head -10 - - secret-scan: - name: Secret scan - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - name: Install trufflehog - run: | - curl -sSfL https://raw.githubusercontent.com/trufflesecurity/trufflehog/main/scripts/install.sh \ - | sh -s -- -b /usr/local/bin - - name: Run trufflehog - run: | - trufflehog git "file://$(pwd)" \ - --only-verified --fail \ - --exclude-paths .trufflehog-ignore 2>&1 | tee scan.log || EXIT=$? - if [ -n "$EXIT" ] && [ "$EXIT" -ne 0 ]; then - echo "::error::Найдены секреты в коммитах! См. лог выше." - exit 1 - fi - - size-check: - name: PR size check - if: github.event_name == 'pull_request' - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - name: Check PR size - run: | - ADDED=$(git diff origin/${{ github.base_ref }}...HEAD --shortstat | grep -oE '[0-9]+ insertion' | grep -oE '[0-9]+' || echo 0) - REMOVED=$(git diff origin/${{ github.base_ref }}...HEAD --shortstat | grep -oE '[0-9]+ deletion' | grep -oE '[0-9]+' || echo 0) - TOTAL=$((ADDED + REMOVED)) - echo "PR изменяет $TOTAL строк (+$ADDED / -$REMOVED)" - if [ "$TOTAL" -gt 1000 ]; then - echo "::warning::PR изменяет $TOTAL строк (> 1000). Подумай о дроблении на несколько меньших." - fi +# CI студии Рублокса. +# Запускается на каждый push и pull_request. +# +# Что проверяем: +# 1. lint — ESLint без warning'ов +# 2. format-check — Prettier формат не нарушен +# 3. build — vite build проходит без ошибок +# 4. secret-scan — trufflehog не нашёл утечек секретов +# 5. size-check — PR не больше 1000 строк (предупреждение) +name: CI + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: '18' + - run: npm ci + # format:check временно отключён до массового npx prettier --write + # (см. docs/ONBOARDING.md → «Форматирование кода»). После прогона + # верни строку `- run: npm run format:check` перед npm run lint. + - run: npm run lint + + build: + name: Build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: '18' + - run: npm ci + - run: npm run build + - name: Save build size + # set -o pipefail (default Gitea Actions) валит весь step если head + # закроет pipe раньше. Делаем команды непадающими через || true. + run: | + du -sh build/ || true + ls -la build/assets/ 2>/dev/null | head -10 || true + + secret-scan: + name: Secret scan + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Install trufflehog + run: | + curl -sSfL https://raw.githubusercontent.com/trufflesecurity/trufflehog/main/scripts/install.sh \ + | sh -s -- -b /usr/local/bin + - name: Run trufflehog + run: | + trufflehog git "file://$(pwd)" \ + --only-verified --fail \ + --exclude-paths .trufflehog-ignore 2>&1 | tee scan.log || EXIT=$? + if [ -n "$EXIT" ] && [ "$EXIT" -ne 0 ]; then + echo "::error::Найдены секреты в коммитах! См. лог выше." + exit 1 + fi + + size-check: + name: PR size check + if: github.event_name == 'pull_request' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: Check PR size + run: | + ADDED=$(git diff origin/${{ github.base_ref }}...HEAD --shortstat | grep -oE '[0-9]+ insertion' | grep -oE '[0-9]+' || echo 0) + REMOVED=$(git diff origin/${{ github.base_ref }}...HEAD --shortstat | grep -oE '[0-9]+ deletion' | grep -oE '[0-9]+' || echo 0) + TOTAL=$((ADDED + REMOVED)) + echo "PR изменяет $TOTAL строк (+$ADDED / -$REMOVED)" + if [ "$TOTAL" -gt 1000 ]; then + echo "::warning::PR изменяет $TOTAL строк (> 1000). Подумай о дроблении на несколько меньших." + fi + + # ──────────────────────────────────────────────────────────────────── + # DEPLOY — собирает прод-бандл и заливает на ОБА сервера (S1+S2) + # параллельно через rsync over SSH. + # + # Запускается ТОЛЬКО на push в main (т.е. после успешного мержа PR). + # PR-проверки выше (lint/build/secret-scan/size-check) гарантируют + # что в main попадает только корректный код. + # + # Секреты: + # DEPLOY_SSH_KEY — приватный ed25519 ключ (CI-only, отдельный от + # админских), pubkey уже на ~min/.ssh/authorized_keys + # на S1 VM 124 и S2 VM 124 + # KNOWN_HOSTS — host-keys S1 и S2 (защита от MITM) + # + # Цели (на VM 124 обоих серверов): + # /var/www/rublox-studio/build/ + # + # При сбое деплоя ни один сервер не остаётся в полу-задеплоенном + # состоянии: rsync делает атомарную замену с --delete-after. + # ──────────────────────────────────────────────────────────────────── + deploy: + name: Deploy to S1 + S2 + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + # Lint needs ( empty- + # , . branch protection 'CI / Lint' required). + # Deploy Build Secret-scan . + needs: [build, secret-scan] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version: '18' + - name: Install deps + run: npm ci + - name: Production build + run: npm run build + - name: Prepare SSH + env: + DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }} + KNOWN_HOSTS: ${{ secrets.KNOWN_HOSTS }} + run: | + mkdir -p ~/.ssh && chmod 700 ~/.ssh + echo "$DEPLOY_SSH_KEY" > ~/.ssh/id_deploy + chmod 600 ~/.ssh/id_deploy + echo "$KNOWN_HOSTS" > ~/.ssh/known_hosts + chmod 600 ~/.ssh/known_hosts + - name: Install rsync + run: sudo apt-get update -qq && sudo apt-get install -y rsync openssh-client + - name: Deploy to S1 (85.175.7.40:1998) + run: | + rsync -az --delete-after --human-readable \ + -e "ssh -i ~/.ssh/id_deploy -o UserKnownHostsFile=~/.ssh/known_hosts -p 1998" \ + build/ min@85.175.7.40:/var/www/rublox-studio/build/ + - name: Deploy to S2 (192.168.0.124:22, runner в той же сети) + run: | + rsync -az --delete-after --human-readable \ + -e "ssh -i ~/.ssh/id_deploy -o UserKnownHostsFile=~/.ssh/known_hosts -p 22" \ + build/ min@192.168.0.124:/var/www/rublox-studio/build/ + - name: Verify deploy + run: | + echo "=== S1 ===" + ssh -i ~/.ssh/id_deploy -o UserKnownHostsFile=~/.ssh/known_hosts -p 1998 \ + min@85.175.7.40 \ + "ls /var/www/rublox-studio/build/index.html && du -sh /var/www/rublox-studio/build/" + echo "=== S2 ===" + ssh -i ~/.ssh/id_deploy -o UserKnownHostsFile=~/.ssh/known_hosts -p 22 \ + min@192.168.0.124 \ + "ls /var/www/rublox-studio/build/index.html && du -sh /var/www/rublox-studio/build/" -- 2.47.2