Деплой php приложений с Github Actions

Deployer

Одним из основных компонентов деплоя будет утилита deployer. Добавим ее в проект

composer require deployer/deployer

После этого в корне проекта создаем файл deploy.php

<?php
namespace Deployer;

require 'recipe/yii2-app-basic.php';

// Project name
set('application', 'app_name');

// Project repository
set('repository', 'git@github.com.vendor/repo.git');

// Shared files/dirs between deploys
add('shared_files', [
'.env',
]);
add('shared_dirs', [
'/runtime'
]);

// Writable dirs by web server
add('writable_dirs', []);

// Hosts
host('server name or ip')
->multiplexing(false)
->set('deploy_path', '/home/project_folder'')
->stage('production')
->user('debian');

// Tasks

task('change:permissions', function () {
run('sudo chmod -R 777 /home/project_folder/current/runtime');
run('sudo chmod -R 777 /home/project_folder/current/web/assets');
});

after('deploy', 'change:permissions');

// [Optional] if deploy fails automatically unlock.
after('deploy:failed', 'deploy:unlock');

task('reload:php-fpm', function () {
run('sudo /etc/init.d/php7.4-fpm reload');
});

after('deploy', 'reload:php-fpm');

Deployer имеет исчерпывающую документацию, я пробегусь по основным моментам в файле.

Вначале мы определяем название приложения, репозиторий, папку на удаленном сервере, куда будем деплоить, а так же файлы и папки, которые остануться неизменными между релизами. В данном примере общий файл .env и папка /runtime.

Далее идут определения хостов (куда деплоить) и тип деплоя. В данном случае один сервер, типа production.

В конце идут дополнительные команды: выставление прав доступа на папки и рестарт php-fpm.

Под капотом deployer на удаленном сервере создает структура папок:

current -> releases/11
.dep
releases
shared

Необходимо перенастроить сервер так, что бы document root смотрел в папку current.

При каждом релизе deployer создает подпапку с номером релиза в папке releases и, при успешной сборке, создает на нее символическую ссылку. В примере выше номер релиза - 11. Php-fpm не всегда может подхватить изменения символических ссылок, поэтому финальной задачей в файле deploy.php идет перезагрузка сервиса fpm.

Теперь можно проверить деплой с локальной машины:

./vendor/bin/dep deploy production

Github Actions

После успешного тестового деплоя, можно перейти к автоматизации. Создаем файл .github/workflows/php.yml с содержимым

name: PHP Composer

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

jobs:
build:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2

- name: Validate composer.json and composer.lock
run: composer validate

- name: Cache Composer packages
id: composer-cache
uses: actions/cache@v2
with:
path: vendor
key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
restore-keys: |
${{ runner.os }}-php-

- name: Install dependencies
if: steps.composer-cache.outputs.cache-hit != 'true'
run: composer install --prefer-dist --no-progress --no-suggest

- name: Deploy
uses: musps/action-deployer-php@master
with:
args: deploy production -vvv
env:
SSH_PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }}

Этот файл добавляет функционал actions к репозиторию.

В начале файла мы обьявляем что будем реагировать на push и pull request в ветку master. Далее говорим что мы будем делать:

  • клонируем репозиторий
  • валидируем файлы composer
  • устанавливаем зависимости и кешируем их
  • запускаем deployer

Теперь github будет выполнять данный сценарий. Внутри он оперирует docker контейнерами, которые можно подменить на свои а так же довить свой функционал. Но deployer запускается внутри контейнера, который не сможет подключиться к серверу, на который будет деплой. Для этого в последней строчке мы прописываем переменную, в которой лежит приватный ключ. Ключ необходимо добавить в интерфейсе github в репозитории, в разделе settings перейти в подраздел secrets.