|
|
|
@@ -9,6 +9,26 @@ on:
|
|
|
|
|
jobs:
|
|
|
|
|
a11y:
|
|
|
|
|
runs-on: ubuntu-latest
|
|
|
|
|
timeout-minutes: 20
|
|
|
|
|
|
|
|
|
|
# Полноценный PostgreSQL для CI: схема Лидерры — чисто PG (RLS, партиции,
|
|
|
|
|
# роли БД, raw schema.sql через load_initial_schema), на SQLite не грузится.
|
|
|
|
|
# Без живой БД 14 авторизованных Pa11y-маршрутов не могут залогиниться под
|
|
|
|
|
# admin@demo.local → таймаут на "wait for path /dashboard" → красный CI.
|
|
|
|
|
services:
|
|
|
|
|
postgres:
|
|
|
|
|
image: postgres:16
|
|
|
|
|
env:
|
|
|
|
|
POSTGRES_USER: postgres
|
|
|
|
|
POSTGRES_PASSWORD: postgres
|
|
|
|
|
POSTGRES_DB: liderra
|
|
|
|
|
ports:
|
|
|
|
|
- 5432:5432
|
|
|
|
|
options: >-
|
|
|
|
|
--health-cmd "pg_isready -U postgres"
|
|
|
|
|
--health-interval 5s
|
|
|
|
|
--health-timeout 5s
|
|
|
|
|
--health-retries 12
|
|
|
|
|
|
|
|
|
|
steps:
|
|
|
|
|
- name: Checkout
|
|
|
|
@@ -35,8 +55,27 @@ jobs:
|
|
|
|
|
run: composer install --no-progress --no-interaction --prefer-dist --optimize-autoloader
|
|
|
|
|
|
|
|
|
|
- name: Install app JS deps
|
|
|
|
|
# --legacy-peer-deps: Histoire 1.0-beta.1 заявляет peerDep vite ^7,
|
|
|
|
|
# установлено vite 8 (memory feedback_environment.md #74) — как в deploy.yml.
|
|
|
|
|
working-directory: app
|
|
|
|
|
run: npm ci --no-audit --no-fund
|
|
|
|
|
run: npm ci --no-audit --no-fund --legacy-peer-deps
|
|
|
|
|
|
|
|
|
|
- name: Create PostgreSQL roles
|
|
|
|
|
# Базовая schema.sql грузится без ролей (GRANT'ы обёрнуты в DO $$ EXISTS-check),
|
|
|
|
|
# но поздние миграции (snapshot, lead-region) делают необёрнутый
|
|
|
|
|
# GRANT ... TO crm_app_user/crm_supplier_worker → роли должны существовать.
|
|
|
|
|
# SET ROLE crm_migrator в этих миграциях с guard'ом has_schema_privilege →
|
|
|
|
|
# под postgres-суперюзером корректно делает RESET ROLE (грантов на public нет).
|
|
|
|
|
env:
|
|
|
|
|
PGPASSWORD: postgres
|
|
|
|
|
run: |
|
|
|
|
|
psql -h 127.0.0.1 -U postgres -d liderra -v ON_ERROR_STOP=1 \
|
|
|
|
|
-v crm_app_password=ci_pa11y \
|
|
|
|
|
-v crm_admin_password=ci_pa11y \
|
|
|
|
|
-v crm_migrator_password=ci_pa11y \
|
|
|
|
|
-v crm_audit_writer_password=ci_pa11y \
|
|
|
|
|
-v crm_supplier_worker_password=ci_pa11y \
|
|
|
|
|
-f db/00_create_roles.sql
|
|
|
|
|
|
|
|
|
|
- name: Bootstrap .env + key
|
|
|
|
|
working-directory: app
|
|
|
|
@@ -44,19 +83,56 @@ jobs:
|
|
|
|
|
cp .env.example .env
|
|
|
|
|
php artisan key:generate --force
|
|
|
|
|
|
|
|
|
|
- name: Prepare SQLite for CI (avoid pg-on-CI fixture cost)
|
|
|
|
|
- name: Configure .env for CI PostgreSQL + Sanctum SPA
|
|
|
|
|
# phpdotenv: первое вхождение ключа выигрывает → не дописываем дубли,
|
|
|
|
|
# а удаляем строку и добавляем заново (детерминированный override).
|
|
|
|
|
# APP_ENV=local нужен, чтобы DatabaseSeeder вызвал DemoSeeder (admin@demo.local)
|
|
|
|
|
# и чтобы session-cookie не был secure-only (вход по http в CI).
|
|
|
|
|
# SANCTUM_STATEFUL_DOMAINS обязан включать localhost:8000 — иначе Sanctum
|
|
|
|
|
# считает запрос с Pa11y-хоста (localhost:8000) stateless → сессия не залипает.
|
|
|
|
|
working-directory: app
|
|
|
|
|
run: |
|
|
|
|
|
touch database/database.sqlite
|
|
|
|
|
sed -i 's/DB_CONNECTION=.*/DB_CONNECTION=sqlite/' .env
|
|
|
|
|
sed -i 's|DB_DATABASE=.*|DB_DATABASE=/home/runner/work/${{ github.event.repository.name }}/${{ github.event.repository.name }}/app/database/database.sqlite|' .env
|
|
|
|
|
setenv() { sed -i "/^$1=/d" .env; echo "$1=$2" >> .env; }
|
|
|
|
|
setenv APP_ENV local
|
|
|
|
|
setenv APP_DEBUG true
|
|
|
|
|
setenv APP_URL http://localhost:8000
|
|
|
|
|
setenv DB_CONNECTION pgsql
|
|
|
|
|
setenv DB_HOST 127.0.0.1
|
|
|
|
|
setenv DB_PORT 5432
|
|
|
|
|
setenv DB_DATABASE liderra
|
|
|
|
|
setenv DB_USERNAME postgres
|
|
|
|
|
setenv DB_PASSWORD postgres
|
|
|
|
|
setenv DB_SSLMODE disable
|
|
|
|
|
setenv SESSION_DRIVER file
|
|
|
|
|
setenv CACHE_STORE file
|
|
|
|
|
setenv QUEUE_CONNECTION sync
|
|
|
|
|
setenv MAIL_MAILER log
|
|
|
|
|
setenv SANCTUM_STATEFUL_DOMAINS localhost:8000,127.0.0.1:8000,localhost,127.0.0.1
|
|
|
|
|
|
|
|
|
|
- name: Run migrations (postgres superuser → guarded SET ROLE works)
|
|
|
|
|
working-directory: app
|
|
|
|
|
run: php artisan migrate --force
|
|
|
|
|
|
|
|
|
|
- name: Create current-month partitions
|
|
|
|
|
# schema.sql создаёт baseline-партиции; cron-команда докидывает текущий +2
|
|
|
|
|
# месяца (идемпотентно) — нужно для demo-сделок DemoSeeder'а за «сегодня».
|
|
|
|
|
working-directory: app
|
|
|
|
|
run: php artisan partitions:create-months --ahead=2
|
|
|
|
|
|
|
|
|
|
- name: Seed demo data (PricingTier + DemoSeeder admin@demo.local)
|
|
|
|
|
working-directory: app
|
|
|
|
|
run: php artisan db:seed --force
|
|
|
|
|
|
|
|
|
|
- name: Build frontend assets
|
|
|
|
|
working-directory: app
|
|
|
|
|
run: npm run build
|
|
|
|
|
|
|
|
|
|
- name: Start Laravel dev-server
|
|
|
|
|
# PHP_CLI_SERVER_WORKERS>1: встроенный сервер обслуживает SPA + sub-resources
|
|
|
|
|
# параллельно, чтобы Pa11y-навигации не упирались в однопоточность.
|
|
|
|
|
working-directory: app
|
|
|
|
|
env:
|
|
|
|
|
PHP_CLI_SERVER_WORKERS: 4
|
|
|
|
|
run: nohup php artisan serve --host=127.0.0.1 --port=8000 > /tmp/laravel-serve.log 2>&1 &
|
|
|
|
|
|
|
|
|
|
- name: Wait for dev-server ready
|
|
|
|
@@ -72,9 +148,14 @@ jobs:
|
|
|
|
|
tail -50 /tmp/laravel-serve.log
|
|
|
|
|
exit 1
|
|
|
|
|
|
|
|
|
|
- name: Run Pa11y (live Vue)
|
|
|
|
|
- name: Run Pa11y (live Vue, 7 public + 14 authenticated routes)
|
|
|
|
|
run: npm run a11y
|
|
|
|
|
|
|
|
|
|
- name: Laravel log tail on failure
|
|
|
|
|
if: failure()
|
|
|
|
|
working-directory: app
|
|
|
|
|
run: tail -120 storage/logs/laravel.log || echo "no laravel.log"
|
|
|
|
|
|
|
|
|
|
- name: Upload Pa11y screenshots
|
|
|
|
|
if: always()
|
|
|
|
|
uses: actions/upload-artifact@v4
|
|
|
|
|