CI/CD для PHP, Bitrix и Laravel: настраиваем GitHub Actions по шагам
Руководство по CI/CD для PHP-проектов: GitHub Actions для 1C-Битрикс и Laravel. Проверка кода, Composer, тесты, деплой по SSH, секреты. Реальные примеры workflow и типичные ошибки при внедрении.
Требования
- Репозиторий на GitHub
- PHP 8.1+ (Bitrix) или 8.2+ (Laravel)
- Базовое понимание YAML и командной строки
CI/CD для PHP: Bitrix и Laravel на GitHub Actions
Деплой по SSH с ноутбука, страх трогать main перед выходными и проверка кода «на глаз» — знакомые сценарии. Когда так живёт проект, CI/CD либо отсутствует, либо существует только на бумаге. В этой статье — как сделать по-настоящему работающий пайплайн для PHP: разберём и Bitrix, и Laravel, с примерами конфигов и без лишней теории.
CI и CD — что это и зачем в PHP-мире
CI — непрерывная интеграция
CI (Continuous Integration) — это автоматическая проверка кода при каждом изменении в репозитории. Обычный сценарий:
- клонирование репозитория;
- установка зависимостей (Composer);
- проверка синтаксиса PHP;
- запуск тестов и линтеров.
Если что-то падает — пайплайн завершается с ошибкой, и в main не попадёт сломанный код.
По сути CI отвечает на вопрос: можно ли этот код вообще запускать?
CD — непрерывная доставка и деплой
CD (Continuous Delivery / Deployment) — следующий шаг: автоматическая доставка собранного и проверенного кода на staging или production. То есть не только «проверили», но и «выкатили» (или подготовили к выкладке).
CD отвечает на вопрос: безопасно ли выкатывать этот код?
Зачем CI/CD именно в PHP, Bitrix и Laravel
В PHP-проектах часто накапливаются типичные риски:
- Человеческий фактор — забыли обновить
vendor, не закоммитили файл, «у меня локально работало». - Разное окружение — версия PHP, расширения, права на папки, кеш, cron и агенты (в Bitrix).
- Страх продакшена — особенно на Bitrix, где фатал или ошибка в ядре могут дать белый экран.
CI/CD не решает все проблемы разом, но убирает лотерею при каждом мерже и деплое.
Почему выбирают GitHub Actions
Для репозиториев на GitHub Actions — естественный выбор:
- не нужен отдельный сервер (Jenkins, GitLab Runner);
- конфигурация лежит в
.github/workflows/рядом с кодом; - YAML-файлы читаются как пошаговый сценарий;
- бесплатный лимит для публичных репозиториев.
Для большинства PHP-проектов (в том числе Bitrix и Laravel) этого достаточно, чтобы поднять CI и при желании CD.
Где хранятся workflow-файлы
Структура в репозитории:
.github/
└── workflows/
└── ci.yml
Один YAML-файл — один сценарий (workflow). Можно добавить отдельные файлы, например deploy.yml для CD.
Базовый CI для PHP: синтаксис и Composer
Ниже — минимальный, но полноценный CI для проекта на PHP 8.2 с Composer. По документации GitHub Actions и shivammathur/setup-php используются стандартные действия.
Полный пример workflow
name: PHP CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
php-ci:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup PHP 8.2
uses: shivammathur/setup-php@v2
with:
php-version: "8.2"
extensions: mbstring, intl, pdo, pdo_mysql
coverage: none
- name: Install Composer dependencies
run: composer install --no-interaction --prefer-dist --no-progress
- name: Check PHP syntax
run: find . -path ./vendor -prune -o -type f -name "*.php" -print | xargs -n1 php -l
Важно: find с -path ./vendor -prune исключает папку vendor, чтобы не проверять сторонние пакеты. Так мы проверяем только свой код.
Зачем нужен composer install --prefer-dist
- Используется
composer.lock, сборка воспроизводима. - Меньше шансов на «у меня работает, у тебя нет» из-за разных версий зависимостей.
Триггеры: когда запускается CI
Блок on определяет события:
on:
push:
branches: [main]
pull_request:
branches: [main]
CI запускается при пуше в main и при каждом Pull Request в main. Без проверки PR смысл CI теряется: код может попадать в основную ветку без прогона тестов и линтеров.
Добавляем PHP_CodeSniffer (стиль кода)
Чтобы CI ругался на нарушение стандарта кодирования, а не только на синтаксис, добавляем PHP_CodeSniffer (предполагается, что он уже в composer.json как dev-зависимость):
- name: Run PHP_CodeSniffer
run: vendor/bin/phpcs --standard=PSR12 src/
Если структура проекта другая (например, local/ в Bitrix), замените src/ на нужный путь. Так код-ревью можно сосредоточить на логике, а не на отступах.
CI для Laravel: env, ключ, миграции, тесты
Laravel требует окружение (.env), ключ приложения и при необходимости — миграции. В CI обычно используют отдельную БД (часто SQLite в памяти), чтобы не зависеть от внешнего сервера.
Шаги в workflow для Laravel
- name: Copy environment
run: cp .env.example .env
- name: Generate application key
run: php artisan key:generate
- name: Run migrations
run: php artisan migrate --force
- name: Execute tests
run: php artisan test
В .env.example для CI можно задать:
APP_ENV=testing
APP_DEBUG=true
DB_CONNECTION=sqlite
DB_DATABASE=:memory:
Так тесты выполняются быстро и изолированно, без настройки MySQL на раннере.
CI для Bitrix: что реально проверять
В Bitrix полно «тяжёлого» ядра и модулей; поднимать весь сайт в CI нецелесообразно. Разумный подход — проверять только свой код: PHP-синтаксис, при необходимости статический анализ и стиль. Ядро и стандартные модули в CI не трогаем.
Что имеет смысл гонять в CI под Bitrix
- Проверка синтаксиса PHP в каталоге
/local(и при необходимости в своих модулях). - Composer — если проект использует зависимости (например, в
local/). - PHP_CodeSniffer или другой линтер по своему коду.
- Отсутствие фаталов при подключении критичных файлов (опционально, через простой bootstrap).
Пример CI только для кода в local/
name: Bitrix CI
on:
pull_request:
push:
branches: [main]
jobs:
bitrix-ci:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: shivammathur/setup-php@v2
with:
php-version: "8.1"
extensions: mbstring, gd, mysqli, intl
- name: Composer install (if composer.json in local)
run: |
if [ -f local/composer.json ]; then
cd local && composer install --no-interaction --prefer-dist
cd ..
fi
- name: PHP syntax check (local only)
run: |
find local -type f -name "*.php" | while read f; do
php -l "$f" || exit 1
done
Правило: CI проверяет ваш код и зависимости, а не ядро Bitrix.
Чем ещё полезен CI для битриксоидов
- Права на файлы — в деплое можно явно выставлять права на
upload, кеш и т.п.; список команд удобно держать в скрипте деплоя и вызывать из CD. - Кеш после деплоя — после
git pullна сервере имеет смысл очищать управляемый кеш (например, через вызов агентов или скрипт), это можно описать в том же deploy-шаге. - Агенты — CI не запускает агенты Bitrix; за их расписание и логи отвечает сервер. В документации Bitrix по настройке агентов и cron можно вынести напоминание команде, что после деплоя нужно убедиться в актуальности расписания.
Дополнительный полезный текст: если вы выкатываете обновления своих модулей или доработок в local/, CI гарантирует, что хотя бы синтаксис и (при наличии) тесты проходят до попадания в прод. Это сильно снижает риск «забыл файл» или «не обновил vendor» и даёт уверенность перед выходными.
CD: деплой на сервер по SSH
После успешного CI можно автоматизировать выкладку: по пушу в main подключаться к серверу по SSH и выполнять обновление кода и зависимостей.
Идея цепочки
- Разработчик пушит в
main(или мержит PR). - CI проходит (синтаксис, тесты, линтеры).
- Запускается job деплоя (только для ветки
main). - На сервере выполняется
git pull,composer install --no-devи при необходимости миграции или сброс кеша.
Где хранить учётные данные
В репозитории никогда не должны лежать пароли и приватные ключи. В GitHub:
Settings → Secrets and variables → Actions
Создайте секреты, например:
SSH_HOST— хост сервера (IP или домен);SSH_USER— пользователь для SSH;SSH_PRIVATE_KEY— содержимое приватного ключа (весь блок от-----BEGIN ...до-----END ...).
В workflow они подставляются через ${{ secrets.SSH_HOST }} и т.д.
Пример шага деплоя по SSH (Laravel-подобный сценарий)
- name: Deploy to production
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
env:
SSH_HOST: ${{ secrets.SSH_HOST }}
SSH_USER: ${{ secrets.SSH_USER }}
run: |
mkdir -p ~/.ssh
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/deploy_key
chmod 600 ~/.ssh/deploy_key
ssh -o StrictHostKeyChecking=no -i ~/.ssh/deploy_key ${SSH_USER}@${SSH_HOST} '
cd /var/www/myapp &&
git pull origin main &&
composer install --no-dev --no-interaction &&
php artisan migrate --force &&
php artisan config:cache
'
rm -f ~/.ssh/deploy_key
Для Bitrix вместо artisan migrate и config:cache будут свои команды: обновление кода, при необходимости composer install в local/, сброс кеша (скрипт или вызов через curl/CLI, если так принято в проекте).
Типовая схема CI/CD для PHP
Упрощённо цепочка выглядит так:
PR → CI (синтаксис, тесты, линтеры) → merge в main → снова CI → CD (деплой на сервер)
Один раз настроили — дальше процесс повторяемый и предсказуемый.
Частые ошибки при внедрении
- Запуск CI только вручную (нет срабатывания на
push/pull_request). - CI не настроен на PR — код попадает в
mainбез проверок. - Деплой срабатывает из любой ветки, а не только из
main. - Пароли или ключи в YAML или в коде.
- Один огромный job без разбиения: при падении одного шага непонятно, что именно сломалось.
- Нет внятных имён шагов — в логах трудно искать причину ошибки.
Что делать правильно
- Включать CI на все Pull Request в основную ветку.
- Запускать CD только при пуше в
main(или в ветку, с которой деплоите). - Хранить учётные данные только в GitHub Secrets (или аналоге), не в репозитории.
- Давать шагам осмысленные имена (
name:), чтобы по логам было понятно, где упало. - Держать конфиг простым: меньше «магии», больше явных шагов — так проще поддерживать и отлаживать.
Краткий итог
CI/CD в PHP-проектах — не привилегия «крупных» команд, а способ меньше ломать прод и спокойнее выкатывать изменения. Для Bitrix и Laravel:
- CI — обязательный минимум: синтаксис, зависимости, тесты (где есть), линтеры.
- CD — по желанию, но сильно упрощает жизнь при частых релизах.
- GitHub Actions — удобный и достаточный вариант для большинства таких проектов.
Настроив один раз проверку на PR и при пуше в main, вы переходите от ручного «задеплоил и надеюсь» к контролируемому процессу: код попадает на сервер только после прохождения заданных проверок.



Комментарии