Непрерывная интеграция для Laravel с помощью Github Actions

Laravel Continuous integration

Github предлагает сервис Непрерывной Интеграции (CI — Continuous Integration), который называется Github Actions. Процессы CI-сборки называются воркфлоу (workflows — рабочие процессы). Они запускаются, когда в вашем github-репозитории происходят определенные события: коммиты, пул-реквесты.

Если вы работаете в команде разработчиков, то Github Actions поможет автоматически проверить пул-реквесты, запустив для них необходимые тесты. После этого можно с уверенностью принимать его и вливать в проект.

Github Actions никак не ограничивает время сборки для публичных репозиториев. Для частных же бесплатная учетная запись дает 2000 минут в месяц. Для соло-разработчика этого более чем достаточно.

Laravel CI обычно состоит из нескольких этапов, чтобы убедиться, что приложение работает без сбоев, когда оно заливается на продакшн. Мы создадим воркфлоу для выполнения следующих задач при открытии пул-реквеста:

  1. Проверим, что можно установить зависимости composer.
  2. Проверим, что можно установить зависимости npm.
  3. Запустим сборку фронтенд-ресурсов для проверки успешного минимизирования файлов css и js.
  4. Проверим, что запускаются миграции в базу данных (для этого мы будем использовать временную sqlite-БД).
  5. Запустим модульные тесты и убедимся, что код пул-реквеста ничего не ломает.

После успешного выполнения этих этапов мы можем без проблем принимать пул-реквест, если конечно его код вас устраивает.

Создание workflow-файла для Laravel

Все воркфлоу-файлы должны находиться в папке .github/workflows в корне вашего проекта. Создадим два этих каталога.

mkdir .github && mkdir .github/workflows

Воркфлоу-файлы для определения задач используют yaml-синтаксис. Один файл может содержать несколько задач.

Давайте создадим наш файл в папке .github/workflows. Назовём его laravel-ci.yml. Вы можете использовать любое название, какое захотите. Просто убедитесь, что у него правильное расширение: yml или yaml.

touch .github/workflows/laravel-ci.yml

Откроем файл в редакторе и добавим в него следующий код:

name: Laravel CI

on:
  pull_request:
    branches: [ master, staging ]

jobs:
  laravel-tests:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2

Это базовый скелет для нашей сборки Github Actions Laravel CI. Он настроен для запуска воркфлоу в свежей версии ubuntu при появлении пул-реквеста в ветках master или staging.

Пока наш воркфлоу не выполняет никакие задачи. Давайте их добавим.

1. Настройка PHP (необязательно)

Образ ubuntu-latest уже идёт с установленной свежей версией PHP. Если вашему приложению требуется PHP 7.3 и ниже, то добавьте следующий код в раздел steps для переключения на нужную версию PHP.

- name: Setup PHP
  uses: shivammathur/setup-php@v2
  with:
    php-version: 7.2 # Измените на версию, нужную вам
    extensions: mbstring, bcmath # Установите нужные вам php-расширения

2. Создание файла .env

Каждое Laravel-приложение должно иметь свой .env-файл для управления переменными среды. Первая задача, которую мы выполняем в нашем воркфлоу — копирование файла .env.example в .env.

Обновите раздел steps как показано ниже:

- name: Copy .env.example to .env
  run: php -r "file_exists('.env') || copy('.env.example', '.env');

3. Установка зависимостей composer

Следующий шаг — установка зависимостей композера. Проверяя их, мы убеждаемся, что в пул-реквесте нет поломанных пакетов.

- name: Install composer dependencies
  run: composer install

4. Устанавливаем права доступа к каталогу

Laravel требует, чтобы определенные каталоги были доступны веб-серверу для записи. Мы можем установить эти права как 777, так как это всего лишь CI-сервер.

Не устанавливайте права доступа 777 на реальном сервере. Это может привести к несанкционированному доступу к конфиденциальным файлам.

- name: Set required directory permissions
  run: chmod -R 777 storage bootstrap/cache

5. Генерация ключа шифрования

Поскольку мы сами создаем .env-файл, то в нём не будет ключа шифрования. Нужно его сгенерировать.

- name: Generate encryption key
  run: php artisan key:generate

6. Создание временной базу данных

Далее нужно запустить миграции и модульные тесты. Для этого нам нужна временная база данных. Создадим её добавив в воркфлоу следующую задачу:

- name: Create temporary sqlite database
  run: |
    mkdir -p database
    touch database/database.sqlite

7. Запуск миграций

Теперь мы можем выполнить миграции в созданную нами временную базу данных. Таким образом мы сможем убедиться, что и новые и уже существующие миграции по-прежнему работают.

Перед запуском миграций нужно настроить переменные DB_CONNECTION и DB_DATABASE на свежесозданную sqlite. Можно установить эти переменные с помощью команды env, как показано ниже:

- name: Run laravel database migrations
  env:
    DB_CONNECTION: sqlite
    DB_DATABASE: database/database.sqlite
  run: php artisan migrate --force

8. Установка NPM зависимостей

Следующий шаг — установка node зависимостей. Проверяя их установку, мы убеждаемся, что пул-реквест не использует поломанных npm-пакетов.

- name: Install NPM dependencies
  run: npm install

9. Минимизация CSS и JS файлов

Мы можем запустить команду npm run prod и проверить, что команда сборки фронтенда работает и минимизирует css и js.

- name: Minify CSS and JS files
  run: npm run prod

10. Запуск модульных тестов

Наконец, наше приложение полностью подготовлено к запуску со всеми необходимыми пакетами. У него есть временная база данных, env-файл, а фронтенд-ресурсы скомпилированы и минимизированы.

Теперь мы можем заняться нашими модульными тестами, чтобы убедиться, что новые изменения в коде не нарушили существующую функциональность.

- name: Run unit tests via PHPUnit
  env:
    DB_CONNECTION: sqlite
    DB_DATABASE: database/database.sqlite
  run: ./vendor/bin/phpunit

Полный воркфлоу-файл

Если вы выполнили все шаги правильно, то ваш файл должен выглядеть так:

name: Laravel CI

on:
  pull_request:
    branches: [ master, staging ]

jobs:
  laravel-tests:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    - name: Copy .env.example to .env
      run: php -r "file_exists('.env') || copy('.env.example', '.env');"
    - name: Install composer dependencies
      run: composer install
    - name: Set required directory permissions
      run: chmod -R 777 storage bootstrap/cache
    - name: Generate encryption key
      run: php artisan key:generate
    - name: Create temporary sqlite database
      run: |
        mkdir -p database
        touch database/database.sqlite
    - name: Run laravel database migrations
      env:
        DB_CONNECTION: sqlite
        DB_DATABASE: database/database.sqlite
      run: php artisan migrate --force
    - name: Install NPM dependencies
      run: npm install
    - name: Minify CSS and JS files
      run: npm run prod
    - name: Run unit tests via PHPUnit
      env:
        DB_CONNECTION: sqlite
        DB_DATABASE: database/database.sqlite
      run: ./vendor/bin/phpunit

После того, как вы закоммитите этот файл в свой репозиторий, Github будет запускать указанные задачи при появлении нового пул-реквеста в ветках master и staging.

Статус Failure/Success выполнения воркфлоу будет отображаться прямо в пул-реквесте, откуда он был запущен.

Вы можете просмотреть все запуски воркфлоу определенного репозитория, перейдя на вкладку actions в навигационной панели.

Автор: Srinath Dudi
Перевод: Алексей Широков

Наш Телеграм-канал — следите за новостями о Laravel.