Files
portal/deploy
Дмитрий 42e907c882 Merge gitea/main into feat/sales-finder — сведение с боевым перед выкатом
Ветка разошлась с боевым 28.06 (334 коммита в main / 215 у нас). Влито ВСЁ боевое:
автоподбор конкурентов, мобильный адаптив портала, свой учёт посетителей, мониторинг
внешних сервисов, фиксы поставщика/биллинга/бота/разборов.

ПОБАЙТОВАЯ СВЕРКА: из 1008 файлов, изменённых боевым, 989 совпадают точно;
19 отличаются — все с нашей законной работой (обе стороны внутри). Затёртых — 0.

24 конфликта разобраны вручную. Ключевое:
- VerifySupplierOrderJob — взята БОЕВАЯ версия (фикс инцидента 11-12.07: площадка
  берётся из src, а не из имени; наша была старой и вернула бы баг, терявший заявки).
- SyncSupplierProjectsJobTest — 15 боевых тестов + наш уникальный (limit-1 → только B1).
- routes/web, router/index, config/services, bootstrap/app — обе стороны сложены.
- NewProjectDialog — зелёные дни недели (наше) + мобильная раскладка (боевое).
- CHANGELOG схемы — номера версий столкнулись, наши перенумерованы в v8.67-v8.70.
- composer — обе зависимости (laravel-dompdf наш + geoip2 боевой).

Гейты: бэкенд 2907/2911 (0 падений), Larastan 0, фронт 1333/1333, сборка OK.
Baseline статанализа принял пре-существующий долг боевого кода (автоподбор/чат).
@mixin в 26 моделях — требование статанализа, dev-докблок, на рантайм не влияет.

Откат: git reset --hard pre-merge-main-20260714

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-14 17:49:28 +03:00
..

deploy/

Скрипты применения обновлений на боевом портале lk.liderra.ru (liderra.ru = лендинг).

🔴 ОБНОВЛЕНО 09.07.2026:

  • Каноническая процедура выкатаdocs/superpowers/runbooks/2026-06-18-gitea-prod-deploy-pipeline.md (сборка из main на сервере, хирургический overlay). Этот файл — про серверный redeploy.sh (scp-эпоха), исторический контекст.
  • Миграции — на ЖИВОЙ Managed PG кластер c9q2cvtjpq3hgq6l0r96 как crm_migrator, НЕ через sudo -u postgres psql на VM (= мёртвая rollback-копия). См. §6b канонического ранбука. artisan migrate тоже не годится (config закэширован, crm_app_user не владелец).
  • Выкат — из ветки main (с 09.07 main = боевой прод).

redeploy.sh

Server-side половина деплоя. На боевом лежит в /var/www/liderra/redeploy.sh (вне репозитория Laravel). Здесь — каноническая копия для версионирования и аудита.

Workflow деплоя:

  1. Локально — собрать архив кода + Vite-сборку:

    git archive HEAD app/ db/ | gzip > /tmp/deploy-code.tgz
    tar czf /tmp/deploy-build.tgz -C app/public build/
    
  2. scp обоих архивов на сервер.

  3. На сервере — распаковать в /var/www/liderra/app/, выставить владельца www-data:www-data, запустить bash /var/www/liderra/redeploy.sh.

NB: redeploy.sh НЕ делает git pull — он рассчитан на то, что код уже залит scp. Если запустить без предварительного scp — будет no-op (composer install / migrate / optimize / restart на той же кодовой базе).

Квирк 107 (фикс встроен): строка sudo -u www-data php artisan optimize обязательна. Без неё optimize запускался от ubuntubootstrap/cache/config.php с владельцем ubuntu → php-fpm (под www-data) не мог прочитать → 503 на всём портале. Инцидент 24.05.2026 03:46 UTC, портал лежал 18 минут.

Грабли composer-прав (фикс встроен, инцидент 23.06.2026): vendor/ принадлежит www-data, а redeploy.sh бежит от ubuntu. Голый composer install падал autoload_classmap.php: Permission denied, и из-за set -e скрипт рвался ДО optimize и рестарта → новый код на диске, classmap новых классов НЕ пересобран → прод 500. Фикс: sudo env COMPOSER_ALLOW_SUPERUSER=1 composer install … + sudo chown -R www-data:www-data vendor. Также: при ручном восстановлении кэши надо пересобирать ДО рестарта php-fpm — opcache держит старые до перезапуска (затяжной 500, пока fpm не рестартнут ПОСЛЕ кэшей).

Грабли миграций crm_migrator (инцидент 19.06 + 23.06; ОБНОВЛЕНО 09.07 под Managed PG): таблицы принадлежат crm_migrator, штатной .env-ролью crm_app_user НЕ альтерятся (must be owner). С переезда 26.06 живая база = Managed-кластер, НЕ VM. Применять миграцию ВРУЧНУЮ под crm_migrator на rw-endpoint Managed-кластера (точный host + пароль Lockbox + sslmode=require — §6b канонического ранбука) ДО redeploy.sh + INSERT INTO migrations (migration, batch) VALUES ('<имя_без_php>', (SELECT COALESCE(MAX(batch),0)+1 FROM migrations)). Тогда artisan migrate --force в скрипте = no-op. ⚠️ НЕ sudo -u postgres psql на VM — это мёртвая копия, миграция туда живую базу не меняет. Точный рецепт — §6b канонического ранбука.

Расхождение с боевым: если правится этот файл — синкать на боевой (scp + проверка хеша). Боевой = source of truth для исполнения, репо = source of truth для рецепта.