<? phpukraine СПІВБЕСІДИ
Пошук по платформі
DEVOPS · MIDDLE

Що входить у мінімальний CI для PHP-проєкту?

Встановлення залежностей з кешем, перевірка стилю, статичний аналіз, тести на реальній базі й збірка артефакту; швидкі кроки першими, щоб пайплайн падав рано.

Як пришвидшити CI, що йде 20 хвилин?
Чи потрібен PHPStan у CI, якщо є тести?
У якому порядку запускати кроки пайплайну?
CI тести статичний аналіз

Мінімальний CI для PHP-проєкту складається з чотирьох кроків. Встановлення залежностей: composer validate, composer install строго за lock-файлом з кешем vendor по хешу composer.lock, composer audit для відомих вразливостей. Перевірка стилю: Pint або PHP-CS-Fixer у режимі перевірки без правок. Статичний аналіз: PHPStan або Psalm на зафіксованому рівні, для легасі з baseline. Тести: PHPUnit або Pest на тій самій базі, що в продакшені, піднятій як service-контейнер, бо SQLite відрізняється в типах, JSON і ALTER TABLE.

Порядок визначає принцип fail fast. Лінтер і аналіз відпрацьовують за секунди, тому вони йдуть першими або паралельно, а хвилинні тести після. Збірка Docker-образу відбувається лише після зелених перевірок і лише з гілки, з якої деплоять. Образ тегується SHA коміту, щоб будь-який деплой можна було відкотити до конкретної збірки.

Коли пайплайн росте до 20 хвилин, лікують не вимкненням кроків, а вимірюванням. Зазвичай час іде на залежності без кешу й на послідовні тести: кеш шарів, паралельні джоби, шарди тестів через --parallel, транзакції замість міграцій з нуля в кожному тесті, і винесення важких інтеграційних сьютів на етап merge. Статичний аналіз при цьому не прибирають: він ловить помилки типів у коді, до якого тести не дійшли, і робить це за секунди.

# .github/workflows/ci.yml — мінімальний, але повний пайплайн
name: CI
on: [push, pull_request]

jobs:
  static:                      # секунди: падаємо рано
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: shivammathur/setup-php@v2
        with: { php-version: '8.4', coverage: none }
      - uses: actions/cache@v4
        with: { path: vendor, key: composer-${{ hashFiles('composer.lock') }} }
      - run: composer validate --strict && composer install --no-interaction --prefer-dist
      - run: composer audit
      - run: vendor/bin/pint --test
      - run: vendor/bin/phpstan analyse --no-progress --memory-limit=1G

  tests:                       # хвилини: реальна база, як у продакшені
    runs-on: ubuntu-latest
    needs: static
    services:
      postgres:
        image: postgres:17
        env: { POSTGRES_DB: app_test, POSTGRES_USER: app, POSTGRES_PASSWORD: secret }
        options: --health-cmd pg_isready --health-interval 5s
    steps:
      - uses: actions/checkout@v4
      - uses: shivammathur/setup-php@v2
        with: { php-version: '8.4', extensions: pdo_pgsql }
      - uses: actions/cache@v4
        with: { path: vendor, key: composer-${{ hashFiles('composer.lock') }} }
      - run: composer install --no-interaction --prefer-dist
      - run: vendor/bin/pest --parallel
        env: { DB_CONNECTION: pgsql, DB_HOST: localhost, DB_DATABASE: app_test, DB_USERNAME: app, DB_PASSWORD: secret }

  build:                       # лише після зелених перевірок
    runs-on: ubuntu-latest
    needs: tests
    if: github.ref == 'refs/heads/main'
    steps:
      - uses: actions/checkout@v4
      - run: docker build -t registry.example.com/app:${{ github.sha }} .
Конкретний набір: composer validate і install з кешем, Pint або PHP-CS-Fixer у режимі перевірки, PHPStan або Psalm на фіксованому рівні, PHPUnit або Pest, збірка Docker-образу лише після зелених перевірок.
Принцип fail fast: лінтер і статичний аналіз за секунди, тести за хвилини, тому спершу швидке, а незалежні кроки паралельно.
Що тести в CI ганяються на тій самій базі, що в продакшені, через service container, а не на SQLite, бо відмінності в SQL реальні.
Що composer.lock у репозиторії й install без update, composer audit для вразливостей, а версія PHP у CI збігається з образом продакшену.
Розуміння, який рівень PHPStan тримається і чому, і що baseline дозволяє впровадити аналіз у легасі без зупинки розробки.
Обмежуватись лише запуском тестів і вважати CI готовим.
Запускати тести на SQLite заради швидкості й ловити відмінності в SQL уже в продакшені.
Не кешувати vendor і залежності Docker-шарів, через що кожен запуск качає все з нуля.
Ставити збірку образу перед тестами або деплоїти з гілки без перевірок.
Використовувати composer update у CI замість install і отримувати різні залежності в кожному запуску.
ПОРАДА

Скажіть, який рівень PHPStan тримаєте і чому саме такий — це показує реальний досвід, а не список інструментів. Додайте, як розбили довгі тести на паралельні джоби.

оновлено 3 вересня 2026 · ліцензія CC-BY-SA-4.0 Знайшли неточність? Напишіть →
ПЕРЕВІРТЕ СЕБЕ

Мінімальний CI ловить стиль, типи і регресії до того, як код потрапить на сервер.