Типичная картина на магазине, который развивался «как получится»: разработчик открывает FileZilla, подключается к боевому серверу, правит template.php прямо в каталоге сайта, обновляет страницу — и либо всё хорошо, либо покупатели видят белый экран с фатальной ошибкой PHP. Истории изменений нет, отката нет, ревью нет. Любая правка — это ставка на выручку в прямом эфире. Рано или поздно такой подход стоит либо потерянного заказа, либо нескольких часов ночного восстановления «как было». CI/CD и Git существуют ровно для того, чтобы этой лотереи не было: код версионируется, проходит проверки на копии боевого окружения и выкатывается на прод по единому, повторяемому и обратимому сценарию.
Эта статья — практическая карта того, как выстроить деплой для 1С-Битрикс по-взрослому. Разберём, почему правки на проде по FTP — это плохо, как применять Git для 1С-Битрикс (что версионировать: /local, шаблоны, компоненты, свой код; что игнорировать: ядро /bitrix, загрузки, кэш, настройки базы), как устроены окружения dev/stage/prod и как их синхронизировать, в чём главная особенность платформы — разделение данных и кода (контент живёт в базе, а не в репозитории), что такое миграции битрикс для структуры (свойства инфоблоков, пользовательские поля, опции модулей), как собрать пайплайн (сборка → тесты → деплой → откат), как сделать деплой без простоя с атомарным переключением и прогревом кэша, как хранить секреты по окружениям через .settings.php и почему обновление ядра идёт отдельным потоком. Материал — выжимка из практики наших highload-проектов на 1С-Битрикс, где цена простоя и ошибки релиза особенно высока.
Коротко
- Правки на проде по FTP лишают проект истории, ревью, тестов и отката — на боевом магазине это прямой риск для выручки.
- Git для 1С-Битрикс версионирует код:
/local, шаблоны, компоненты, свой код и миграции; игнорирует ядро/bitrix,/upload, кэш и настройки базы с паролями. - Окружения dev/stage/prod дают ступени проверки: пишем на dev, принимаем на stage (копия прода), выкатываем на prod только проверенное.
- Данные и код разделены: контент из базы и
/uploadсинхронизируют с прода назад, а структуру (свойства, опции) двигают вперёд через миграции битрикс. - Пайплайн CI/CD — commit → build → test → deploy; деплой без простоя делают атомарным переключением симлинка с прогревом кэша, откат — обратным переключением.
Зачем магазину на Битриксе CI/CD и Git
1С-Битрикс — платформа, на которой держатся тысячи боевых магазинов со сложной логикой: каталоги на десятки тысяч товаров, обмен с 1С, оплаты, интеграции. Цена ошибки на таком проекте измеряется не «неудобством», а потерянными заказами и репутацией. При этом исторически многие проекты на Битриксе развивались без инженерной дисциплины: код правили прямо на сервере, никакого репозитория, никаких окружений. Это работает ровно до первого серьёзного инцидента.
CI/CD и Git решают три задачи, которые чувствуются на каждом проекте с первого же дня:
- Предсказуемость. Каждый релиз проходит один и тот же путь: коммит, проверка, выкладка. Не «как в этот раз получится», а повторяемый сценарий, который ведёт себя одинаково.
- Обратимость. Любое изменение можно откатить — код к предыдущему коммиту, релиз к предыдущему каталогу. Инцидент перестаёт быть катастрофой и становится рабочей ситуацией на пару минут.
- Прозрачность. История в Git отвечает на вопросы «кто, что и зачем поменял», а код-ревью ловит ошибки до того, как они доедут до покупателя.
Важно сразу зафиксировать: CI/CD на Битриксе — это не «поставить модный инструмент», а изменить процесс. Инструменты (Git, раннеры, скрипты деплоя) вторичны. Первично разделение окружений, дисциплина «код только через репозиторий» и понимание, что на этой платформе живёт в Git, а что нет. С этого понимания и начнём.
Почему «правки на проде по FTP» — это плохо
«Быстро поправить прямо на боевом» кажется экономией времени, но на деле это отказ сразу от нескольких страховок. Разберём по пунктам, что именно теряется, — потому что каждый пункт превращается в реальный инцидент.
- Нет истории изменений. После правки по FTP невозможно ответить, каким файл был вчера, кто его трогал и что именно поменялось. Восстановление «как было» превращается в археологию по памяти.
- Нет ревью. Код едет на прод без второго взгляда. Логическая ошибка, забытый
var_dump, случайно закомментированная проверка прав — всё это уходит сразу к покупателям. - Нет тестового прогона. Синтаксическая ошибка в PHP роняет страницу мгновенно. При правке «вживую» посетитель может попасть на файл ровно в момент, когда он сохранён наполовину.
- Нет атомарности. Пока вы загружаете три связанных файла по одному, сайт какое-то время работает на несогласованном наборе: новый шаблон и старый компонент, которые друг друга не понимают.
- Нет отката одним движением. Чтобы вернуть рабочее состояние, нужно вручную вспомнить и откатить всё, что трогали. Под стрессом инцидента это получается плохо.
- Расхождение окружений. Правка на проде не попадает обратно в код разработчика — dev и prod начинают жить своей жизнью, и следующий деплой затирает «горячую» правку.
Отдельная опасность — потеря правок при обновлении. Если кто-то поправил прямо в компоненте ядра или в тиражном шаблоне в каталоге /bitrix, ближайшее обновление модуля просто перезапишет эту правку. Именно поэтому в Битриксе всё кастомное выносят в /local — но об этом ниже.
Git для 1С-Битрикс: что это меняет
Git — это система контроля версий: она хранит полную историю изменений кода, позволяет вести параллельные ветки, сливать их, откатываться к любому состоянию и работать команде над одним проектом без затирания правок друг друга. Для Битрикса Git — фундамент всего CI/CD: именно репозиторий становится единственным источником правды о коде проекта.
Что конкретно меняется, когда проект переезжает под Git:
- Единый источник правды. Актуальный код — это то, что в репозитории, а не то, что случайно оказалось на конкретном сервере. Любое окружение можно воспроизвести из Git.
- Ветки под задачи. Каждая доработка живёт в своей ветке и не мешает остальным. Готовую ветку ревьюят и вливают, недоделанную — нет.
- История и вина коммита. По каждой строке видно, в каком коммите, кем и в рамках какой задачи она появилась. Это бесценно при разборе инцидентов.
- Основа автоматизации. Событие «пришёл коммит/влилась ветка» запускает пайплайн: сборку, тесты, деплой. Без Git автоматизировать нечего.
Но у Битрикса есть своя специфика, которая отличает его от «обычного» PHP-проекта. Здесь код перемешан с ядром платформы в одной файловой структуре, а значительная часть системы вообще не является файлами — она в базе данных. Поэтому нельзя просто сделать git init в корне сайта и закоммитить всё подряд: в репозиторий попадёт гигантское ядро, пользовательские загрузки и пароли от базы. Первый и главный навык работы с Git на Битриксе — чётко понимать, что версионировать, а что нет. Этому посвящён следующий раздел.
Что версионировать, а что игнорировать
Разделение файлов Битрикса на «код проекта» и «всё остальное» — центральное решение при настройке репозитория. Ошибка здесь дорого обходится: закоммитите лишнее — получите конфликты с обновлениями ядра и утечку паролей; забудете нужное — потеряете часть проекта. Держите перед глазами простое правило: в Git едет то, что создаёт разработчик и что одинаково для всех окружений.
| Что | В Git? | Почему |
|---|---|---|
/local целиком | Да | Свои компоненты, шаблоны, модули, обработчики /local/php_interface — это ваш код |
| Шаблоны сайта | Да | Вёрстка, стили, скрипты шаблона — создаются руками, одинаковы на всех средах |
| Кастомные компоненты | Да | Ваши component.php, шаблоны компонентов, result_modifier |
| Миграции структуры | Да | Версионированные сценарии изменения свойств, полей, опций |
| Конфиги окружений (без секретов) | Да | Шаблоны настроек, composer.json, скрипты деплоя, CI-конфиги |
Ядро /bitrix | Нет | Обновляется механизмом SiteUpdate — не должно ехать через деплой |
Загрузки /upload | Нет | Пользовательский контент; место в резервных копиях, не в Git |
Кэш /bitrix/cache, managed_cache | Нет | Генерируется на лету, специфичен для среды |
.settings.php, dbconn.php | Нет | Содержат пароли и параметры конкретного окружения |
Почему /local — герой этой истории. Битрикс поддерживает два каталога для кастомизации: старый /bitrix/templates, /bitrix/components и параллельный /local с той же структурой. Всё, что лежит в /local, платформа подхватывает автоматически, но обновления ядра его не трогают. Поэтому современный подход — держать весь свой код в /local: тогда репозиторий проекта — это, по сути, каталог /local плюс несколько файлов конфигурации, а не вся файловая структура сайта. Это радикально упрощает и Git, и деплой.
Почему ядро /bitrix и загрузки /upload вне Git. Ядро — это не ваш код, а тело платформы, которое живёт своей жизнью: его правит обновлятор Битрикса. Если положить /bitrix в репозиторий, вы получите постоянные конфликты между деплоем и SiteUpdate. Каталог /upload — это пользовательский контент (картинки товаров, документы, аватары): он огромный, меняется на проде каждую минуту и не имеет никакого отношения к коду. Ему место в системе резервного копирования, о которой мы подробно пишем в статье про хостинг и инфраструктуру BitrixVM.
.gitignore для проекта на Битриксе
Практическое воплощение предыдущего раздела — файл .gitignore в корне репозитория. Он описывает, что Git должен игнорировать. Есть два подхода к структуре репозитория: держать в Git весь корень сайта, но игнорировать лишнее, либо (что чище) сделать репозиторием только каталог /local. Ниже — вариант .gitignore для случая, когда репозиторий охватывает корень сайта:
# Ядро платформы — обновляется механизмом SiteUpdate, не через деплой
/bitrix/*
# Но свои правки в настройках админки можно версионировать выборочно
!/bitrix/.gitkeep
# Пользовательский контент и загрузки — в резервные копии, не в Git
/upload/
# Кэш всех видов — генерируется на лету
/bitrix/cache/
/bitrix/managed_cache/
/bitrix/stack_cache/
/bitrix/html_pages/
# Секреты и настройки конкретного окружения — НИКОГДА в Git
/bitrix/.settings.php
/bitrix/php_interface/dbconn.php
/bitrix/.settings_extra.php
.env
# Логи, временные и системные файлы
*.log
/bitrix/tmp/
.DS_Store
Thumbs.db
# Зависимости, которые ставятся при сборке
/local/vendor/
/node_modules/
Несколько принципиальных замечаний. Строку с .settings.php и dbconn.php нельзя ослаблять ни при каких условиях — это файлы с паролем от базы данных и ключами. Если они хоть раз попадут в историю Git, считайте пароли скомпрометированными: их придётся менять, а историю чистить. Каталог /upload исключён целиком, потому что версионировать пользовательский контент бессмысленно и вредно — он раздувает репозиторий и постоянно расходится между окружениями.
git status и убедитесь, что в списке на добавление нет /upload, ядра /bitrix и файлов с настройками базы. Если .settings.php уже попал в индекс — уберите его через git rm --cached до коммита. Утечку секретов проще предотвратить, чем потом вычищать из всей истории репозитория.
Окружения dev, stage, prod
Второй столп CI/CD после Git — разделение окружений. Окружение (environment) — это отдельная площадка, где работает копия проекта со своей базой и своими данными, но с одним и тем же кодом. Классическая схема — три окружения, каждое со своей ролью.
| Окружение | Роль | Данные | Кто работает |
|---|---|---|---|
| dev (development) | Разработка и отладка кода | Тестовые или обезличенная копия | Разработчики |
| stage (staging, предпрод) | Приёмка релиз-кандидата, регресс, проверка миграций | Свежая обезличенная копия прода | QA, заказчик, тимлид |
| prod (production) | Боевой сайт для покупателей | Реальные «живые» данные | Только автоматический деплой |
Логика движения кода простая и односторонняя: изменение рождается на dev, проходит ревью и вливается в основную ветку, автоматически едет на stage, где его принимают и проверяют миграции на копии боевой базы, и только после успешной приёмки выкатывается на prod. Ничего не попадает на прод, минуя stage, — это железное правило.
Критически важное требование к stage — максимальная похожесть на prod. Одинаковая версия PHP, те же настройки веб-сервера и модулей, тот же стек BitrixVM, актуальная по структуре база. Если stage отличается от прода по версии PHP или конфигурации, проверка на нём теряет смысл: релиз может пройти на stage и упасть на проде. Именно на stage прогоняют приёмочное тестирование и QA магазина перед каждым выкатом.
Синхронизация окружений
Из схемы выше видно главное: код и данные синхронизируются в противоположных направлениях. Это, пожалуй, самая частая точка непонимания у команд, которые впервые строят CI/CD на Битриксе, поэтому разберём подробно.
Код едет вперёд. Новые компоненты, шаблоны, обработчики, миграции создаются на dev и через Git и деплой продвигаются к проду. Направление всегда одно: dev → stage → prod. Обратно код с прода не забирают — на проде его никто не пишет.
Данные едут назад. Реальные товары, заказы, страницы, картинки живут на проде и там же меняются каждую минуту. Чтобы разработка и тесты были реалистичными, свежую копию боевой базы и каталога /upload периодически переносят на stage и dev. Направление обратное: prod → stage → dev.
При переносе данных назад есть обязательный шаг — обезличивание персональных данных. Копия боевой базы содержит телефоны, адреса и e-mail покупателей, и на dev/stage их держать в открытом виде нельзя ни по закону, ни по здравому смыслу. Поэтому после копирования базы прогоняют скрипт анонимизации: заменяют персональные данные на фиктивные, обнуляют реальные платёжные реквизиты, подменяют e-mail сотрудников на тестовые, чтобы случайные письма из dev не улетали клиентам.
Данные против кода: контент в БД, а не в Git
Теперь — о самой болезненной особенности Битрикса в контексте деплоя. В «классическом» PHP-приложении почти вся логика — это файлы, и Git ими полностью управляет. В Битриксе значительная часть системы живёт не в файлах, а в базе данных: структура инфоблоков и их свойства, пользовательские поля, настройки модулей, сами товары и заказы, тексты страниц, настройки форм, права доступа. Git этого не видит и видеть не должен.
Из этого следует ключевое разделение, которое нужно держать в голове всё время:
- Контент (данные) — товары, заказы, страницы, картинки, значения свойств. Это «живёт» на проде, меняется покупателями и контент-менеджерами, и его нельзя выкатывать релизом. Его синхронизируют с прода назад дампами.
- Структура (метаданные) — какие есть свойства у инфоблока, какие пользовательские поля, какие включены опции модулей. Это часть логики: на неё опирается код. Её продвигают вперёд через миграции.
- Код — компоненты, шаблоны, обработчики. Это чистые файлы, ими управляет Git.
Почему нельзя просто «выгрузить базу с dev и залить на prod». Потому что база прода — живая. Пока разработчик неделю пилил фичу на dev, на проде оформили сотни заказов, поменяли остатки, зарегистрировались новые пользователи. Заливка dev-базы на prod уничтожит всё это. Поэтому базу целиком в направлении «вперёд» не двигают никогда — вперёд едут только точечные, описанные кодом изменения структуры.
Отсюда и вырастает необходимость миграций. Если разработчик добавил на dev новое свойство инфоблока через админку, это изменение застряло в его локальной базе. Код, который на это свойство рассчитывает, поедет через Git на прод — а свойства там не будет, и код упадёт. Миграция решает эту рассинхронизацию: она описывает изменение структуры как код и применяет его на каждом окружении отдельно.
Миграции структуры: свойства, поля, опции
Миграция — это версионированный сценарий изменения структуры данных, который применяется одинаково на всех окружениях и хранит отметку, что он уже проведён. Идея пришла из мира фреймворков (Laravel, Symfony), но для Битрикса особенно важна из-за того, что «структура» здесь особенно богата: свойства инфоблоков, пользовательские поля, highload-блоки, опции модулей, почтовые события, типы плательщиков.
Что обычно оформляют миграциями на Битриксе:
- Свойства инфоблоков — добавить новое свойство товара (например, «Гарантия» или «Бренд»), изменить его тип или список значений.
- Пользовательские поля (UF) — поля для заказов, разделов, highload-блоков.
- Highload-блоки — создание самого блока и его полей.
- Опции модулей — включить/выключить настройку модуля, задать значение параметра.
- Служебные сущности — типы почтовых событий, шаблоны писем, статусы заказов, свойства заказа.
Как это работает механически. Каждая миграция — это класс или файл с методами «применить» (up) и «откатить» (down). Система хранит в базе список уже применённых миграций. При деплое пайплайн вызывает команду «провести непроведённые миграции», она находит новые файлы, применяет их по порядку и записывает отметки. На следующем окружении та же команда прогонит те же миграции — структура придёт к идентичному состоянию.
В экосистеме Битрикса для этого есть готовые модули миграций (например, известные решения от сообщества), которые умеют не только выполнять произвольный код в up/down, но и «снимать» изменения структуры из админки в виде готовой миграции — это удобно, когда свойство проще создать мышкой, а потом зафиксировать как код. Упрощённо файл миграции выглядит так:
<?php
// Миграция: добавить строковое свойство "Бренд" к инфоблоку товаров
class AddBrandProperty20240326 extends Migration
{
public function up()
{
$iblockId = $this->getIblockIdByCode('catalog');
$this->addIblockProperty($iblockId, [
'NAME' => 'Бренд',
'CODE' => 'BRAND',
'PROPERTY_TYPE' => 'S', // строка
'IS_REQUIRED' => 'N',
'SORT' => 500,
]);
}
public function down()
{
// Обратное действие — удалить свойство при откате миграции
$iblockId = $this->getIblockIdByCode('catalog');
$this->deleteIblockPropertyByCode($iblockId, 'BRAND');
}
}
Дисциплина здесь такая же строгая, как с Git: любое изменение структуры оформляется миграцией, а не «руками на проде». Если контент-менеджеру нужно свойство «на посмотреть» — это одно, но всё, на что опирается код, обязано существовать как миграция. Иначе рано или поздно stage или prod получат код без структуры под него, и релиз упадёт.
.settings.php и секреты по окружениям
Раз код в Git одинаков для всех окружений, а параметры подключения к базе, ключи интеграций и адреса сервисов у dev, stage и prod разные, нужен механизм, который разводит секреты по окружениям. В Битриксе основные точки — файл /bitrix/.settings.php (современное хранилище настроек ядра: подключение к базе, кэш, соединения) и старый dbconn.php. Оба содержат пароли и оба исключены из Git.
Правильная схема работы с настройками окружений:
- Сам
.settings.php— вне Git. На каждом окружении он свой, с реальными паролями. Его кладут на сервер один раз при развёртывании окружения и не трогают деплоем. - Шаблон настроек — в Git. В репозитории держат
.settings.php.exampleили отдельный конфиг с плейсхолдерами, чтобы было видно, какие параметры нужны, но без реальных значений. - Секреты интеграций — в защищённом хранилище. Ключи платёжных шлюзов, токены API, пароли SMTP хранят в переменных окружения или в секретах CI-системы (об этом ниже), а не в коде.
- Определение окружения в коде. Через переменную окружения или файл-маркер код понимает, где он выполняется, и включает нужное поведение (например, тестовый режим оплаты на stage).
Битрикс позволяет расширять настройки через .settings_extra.php — этот файл тоже вне Git и дополняет основной. Удобный приём — определять окружение через переменную окружения веб-сервера и подмешивать её в код:
<?php
// В /local/php_interface/init.php — определяем текущее окружение
$environment = getenv('APP_ENV') ?: 'prod'; // dev | stage | prod
define('APP_ENV', $environment);
// Дальше по окружению включаем нужное поведение
if (APP_ENV !== 'prod') {
// На не-боевых окружениях — режим отладки и подмена почты
define('BX_DEBUG', true);
}
// Ключи и адреса интеграций берём из окружения, а не из кода
$paymentApiKey = getenv('PAYMENT_API_KEY'); // разный для dev/stage/prod
$oneCUrl = getenv('ONE_C_EXCHANGE_URL');
Главное правило безопасности повторим ещё раз, потому что оно стоит дороже всего: секретам не место в репозитории. Пароль от боевой базы, попавший в историю Git, — это инцидент безопасности, даже если репозиторий приватный. Разграничение доступа и защита секретов — часть более широкой темы безопасности, которую мы затрагиваем в материале про безопасное обновление 1С-Битрикс.
Ветки, code review и модель работы
Git даёт ветки — но пользоваться ими нужно по договорённости, иначе в репозитории быстро наступит хаос. Команде нужна ветвочная модель (branching strategy) — согласованные правила, как заводить ветки, как их называть и как вливать.
Для проектов на Битриксе обычно достаточно облегчённой модели с несколькими типами веток:
- Основная ветка (
mainилиmaster) — всегда в рабочем, готовом к релизу состоянии. Прямые коммиты в неё запрещены — только через слияние проверенных веток. - Ветки задач (
feature/catalog-filter,fix/basket-total) — под каждую доработку своя ветка от основной. Здесь идёт вся работа. - Опционально ветка релиза/стейджа — если процесс требует отдельного среза, который сначала едет на stage.
Механика такая. Разработчик заводит ветку под задачу, пишет код, коммитит осмысленными порциями с внятными сообщениями. Когда задача готова — открывает запрос на слияние (Pull Request / Merge Request). Здесь начинается code review: другой разработчик читает изменения, задаёт вопросы, просит поправить. Одновременно CI-система на этот PR прогоняет автоматические проверки — линтеры, тесты. Ветка вливается в основную только когда пройдено и ревью, и автопроверки.
Зачем это на Битриксе, где «и так всё работало». Ревью ловит целый класс ошибок до прода: обращение к несуществующему свойству, отсутствующую миграцию под новый код, забытую проверку прав, неоптимальную выборку, которая положит каталог под нагрузкой. Один потраченный на ревью час экономит несколько часов ночного разбора инцидента. А привязка PR к задаче даёт прослеживаемость: по любой строке кода видно, зачем она появилась.
Пайплайн CI/CD: из чего он состоит
Когда есть Git, окружения и миграции, поверх них выстраивают пайплайн — автоматизированную последовательность шагов, которую проходит каждое изменение от коммита до боевого сайта. Пайплайн запускается автоматически по событию (пуш в ветку, слияние PR) и выполняет шаги по порядку; если шаг падает — конвейер останавливается и дальше код не едет.
Канонический пайплайн для Битрикса состоит из последовательности этапов:
- Commit (коммит и триггер). Разработчик пушит ветку или вливает PR в основную. CI-система ловит событие и запускает пайплайн — с этого момента всё автоматически.
- Build (сборка). Ставятся зависимости (
composer install, сборка фронтенда), собираются ассеты, готовится артефакт — набор файлов, который поедет на сервер. Ничего, что можно собрать заранее, не делается на боевом сервере. - Test (проверки и тесты). Прогоняются линтеры, проверка синтаксиса PHP (
php -l), статический анализ и автотесты. Падение любой проверки останавливает пайплайн — плохой код на прод не поедет. - Deploy на stage. Артефакт выкладывается на предпрод, прогоняются миграции, окружение прогревается. Здесь идёт приёмка и регресс на копии боевых данных.
- Deploy на prod. После приёмки — выкладка на боевой сайт атомарным переключением, прогон миграций, прогрев кэша. Обычно этот шаг запускают вручную (по кнопке), чтобы контролировать момент релиза.
- Rollback (откат) при сбое. Если после релиза что-то пошло не так, одной командой возвращаемся на предыдущий релиз. Возможность отката — обязательная часть пайплайна, а не «на всякий случай».
Обратите внимание: между «test» и «deploy на prod» стоит человеческий контроль — приёмка на stage и, как правило, ручной запуск боевого релиза. Полностью автоматический деплой на прод (continuous deployment) на магазинах применяют осторожно: цена ошибки высока, и большинство команд оставляет финальную кнопку за человеком. Это нормальный и разумный компромисс.
Сборка проекта (build)
Этап сборки часто недооценивают на Битриксе — «зачем что-то собирать, это же просто PHP-файлы». Но как только на проекте появляются зависимости через Composer, сборка фронтенда (Webpack, Vite, сборка стилей) или генерируемые ассеты, шаг build становится необходимым. Его смысл — подготовить готовый к работе артефакт до того, как он попадёт на сервер.
Что обычно делают на этапе сборки:
- Установка PHP-зависимостей.
composer install --no-dev --optimize-autoloader— без dev-пакетов и с оптимизированным автозагрузчиком для боевого окружения. - Сборка фронтенда. Компиляция стилей и скриптов шаблона, минификация, версионирование ассетов для сброса кэша браузера.
- Проверка целостности. Быстрые проверки, что артефакт собрался корректно и содержит всё нужное.
- Формирование артефакта. Итоговый набор файлов (обычно каталог
/localс установленными зависимостями и собранными ассетами), который поедет на сервер как единое целое.
Главный принцип: ничего тяжёлого не делается на боевом сервере. Устанавливать Composer-зависимости или собирать фронтенд прямо на проде во время релиза — плохо: это долго, нагружает сервер и создаёт окно, когда файлы уже частично обновлены. Всё это делают на раннере (машине сборки) заранее, а на сервер отправляют уже готовый, проверенный артефакт.
# Пример шага сборки (упрощённо)
# 1. Ставим PHP-зависимости для боевого окружения
composer install --no-dev --optimize-autoloader --no-interaction
# 2. Собираем фронтенд шаблона
npm ci
npm run build
# 3. Готовим артефакт — только то, что едет на сервер
tar -czf build.tar.gz local/ composer.json composer.lock
Тесты и проверки в пайплайне
Этап проверок — то, что превращает пайплайн из «просто автозаливки» в защитный барьер. Его задача — не пустить заведомо сломанный код дальше по конвейеру. Проверки идут от самых дешёвых и быстрых к более дорогим, и первая же неудача останавливает пайплайн.
Типичный набор проверок для проекта на Битриксе:
- Синтаксис PHP. Прогон
php -lпо всем изменённым файлам ловит опечатки, которые иначе уронили бы страницу с фатальной ошибкой. Это самая дешёвая и обязательная проверка. - Линтеры и стиль кода. PHP CodeSniffer, проверка стандарта кодирования — держат кодовую базу единообразной и ловят подозрительные конструкции.
- Статический анализ. PHPStan или Psalm находят обращения к несуществующим методам, ошибки типов, недостижимый код — без запуска программы.
- Автотесты. Юнит-тесты бизнес-логики и, где возможно, интеграционные и e2e-тесты ключевых сценариев (корзина, оформление заказа).
Специфика Битрикса в том, что полноценные автотесты писать сложнее, чем в чистом фреймворке: ядро завязано на глобальное состояние и базу. Поэтому на многих проектах на Битриксе тестовый этап начинается с малого — синтаксис, линтеры, статический анализ и приёмочное тестирование на stage вручную — и постепенно обрастает автотестами для критичных участков. Как выстроить тестирование магазина системно, от чек-листов до автоматизации, подробно разобрано в статье про тестирование и QA интернет-магазина на 1С-Битрикс.
# Пример этапа проверок в пайплайне
# Синтаксис всех изменённых PHP-файлов
git diff --name-only --diff-filter=ACM origin/main | grep '\.php$' \
| xargs -r -n1 php -l
# Статический анализ и стандарт кода
vendor/bin/phpstan analyse local/ --level=5
vendor/bin/phpcs --standard=PSR12 local/
# Автотесты
vendor/bin/phpunit --testsuite=unit
Деплой: как код попадает на сервер
Деплой — этап доставки готового артефакта на сервер и его активации. Способов доставки несколько, и они принципиально различаются по надёжности и удобству отката.
- Rsync / SCP «поверх». Файлы копируются прямо в рабочий каталог сайта, перезаписывая старые. Просто, но неатомарно: во время копирования сайт работает на смеси старого и нового кода, а откат — только из бэкапа.
- Git pull на сервере. На сервере лежит рабочая копия репозитория, и деплой — это
git pull. Лучше, чем FTP, но всё ещё неатомарно и смешивает роль «рабочего каталога» и «репозитория». - Релизы через симлинк (рекомендуемый). Каждый релиз выкладывается в отдельный каталог, а сайт указывает на него символической ссылкой. Переключение атомарно, откат мгновенный. Это подход инструментов вроде Deployer.
Для боевого магазина на Битриксе третий вариант — стандарт де-факто, потому что только он даёт атомарность и мгновенный откат. Структура каталогов при таком подходе выглядит так:
/var/www/shop/
├── releases/ # все выложенные релизы
│ ├── 2024-03-25-1410/
│ ├── 2024-03-26-0930/
│ └── 2024-03-26-1530/ # текущий
├── shared/ # общее для всех релизов
│ ├── upload/ # загрузки — не копируются с релизом
│ ├── bitrix/ # ядро — общее, обновляется отдельно
│ └── .settings.php # секреты окружения
└── current -> releases/2024-03-26-1530/ # симлинк на активный релиз
Здесь current — символическая ссылка, на которую настроен веб-сервер. Общие для всех релизов вещи (загрузки, ядро, настройки) вынесены в shared и подключаются к каждому релизу симлинками — поэтому они не дублируются и переживают переключение. Сам новый релиз готовится в стороне, никак не влияя на работающий сайт, — и только финальное переключение current делает его активным.
Деплой без простоя и прогрев кэша
Главная ценность релизов через симлинк — деплой без простоя (zero-downtime). Разберём по шагам, как одно изменение выкатывается на боевой магазин так, чтобы ни один посетитель не увидел ни ошибки, ни «сайт на техобслуживании».
- Выкладка нового релиза в сторону. Артефакт распаковывается в новый каталог
releases/2024-03-26-1530. Веб-сервер в это время продолжает отдавать старый релиз черезcurrent— посетители ничего не замечают. - Подключение общих ресурсов. К новому релизу симлинками подключаются
shared/upload,shared/bitrix, реальный.settings.php. Релиз становится полноценным, но пока неактивным. - Прогон миграций. Применяются непроведённые миграции структуры. Важно: миграции пишут совместимыми с обеими версиями кода (об этом ниже), чтобы старый релиз не сломался, пока переключение ещё не произошло.
- Атомарное переключение. Симлинк
currentодной операцией переводится на новый каталог. Это происходит мгновенно; запросы, начатые на старом релизе, завершаются на нём, новые идут на новый. - Прогрев кэша. Скрипт делает запросы к ключевым страницам (главная, каталог, карточка товара), чтобы сгенерировать кэш заранее. Первый живой посетитель попадает уже на «тёплый» сайт, а не на медленную холодную генерацию.
Отдельно про кэш Битрикса. После переключения релиза часть кэша может стать неактуальной (изменились шаблоны компонентов). Поэтому в сценарий деплоя включают сброс нужных видов кэша и последующий прогрев. Делать это надо аккуратно: полный сброс всего кэша на нагруженном магазине в час пик создаёт всплеск нагрузки, пока кэш регенерируется. Как устроены слои кэша и как их правильно инвалидировать, мы разбираем в отдельном материале по кэшированию Битрикса; здесь важно правило — сбрасывать точечно и сразу прогревать.
Откат релиза
Возможность быстрого отката — не «приятная опция», а обязательная часть зрелого деплоя. Идея проста: если после релиза обнаружилась проблема, вы должны вернуть рабочее состояние быстрее, чем будете разбираться в причине. Сначала стабилизировать сайт, потом чинить — а не наоборот, под давлением идущих ошибок.
При релизах через симлинк откат кода тривиален: старые релизы никуда не делись, они лежат в releases/. Откат — это переключение current обратно на предыдущий каталог, ровно та же атомарная операция, что и выкат, только в обратную сторону:
# Откат: вернуть симлинк current на предыдущий релиз
ln -sfn /var/www/shop/releases/2024-03-26-0930 /var/www/shop/current
# Сбросить и прогреть кэш под откатанный релиз
php /var/www/shop/current/local/tools/cache_clear.php
curl -s -o /dev/null https://shop.example.ru/ # прогрев главной
Но у Битрикса откат сложнее, чем «переключить файлы обратно», из-за миграций и данных. Код откатывается мгновенно, а вот изменения структуры базы так просто не отматываются. Здесь два принципа спасают ситуацию:
- Обратимые миграции. Каждая миграция должна иметь честный метод
down, который отменяет её изменения. Тогда откат структуры — тоже команда, а не ручное восстановление. - Совместимость вперёд. Миграции пишут так, чтобы новая структура не ломала старый код. Тогда откат кода без отката структуры безопасен: добавленное свойство просто не используется старым релизом, но и не мешает ему.
Это подводит к важному правилу проектирования миграций: предпочитайте аддитивные, обратно совместимые изменения. Добавить новое свойство безопаснее, чем переименовать существующее; выкатывать удаление старого — отдельным, поздним релизом, когда уже точно ничего на него не опирается. Такой подход делает откат кода безопасным даже без отката базы — что на практике и требуется в 90% инцидентов.
down отменит структуру, но если миграция успела необратимо тронуть данные, единственная страховка — свежий бэкап. Автоматический снимок базы прямо перед прод-релизом — дешёвая страховка, которая однажды спасёт проект.
Обновление ядра отдельно от деплоя
Отдельная и часто недооценённая тема — обновления ядра Битрикса. Ключевой тезис: обновление ядра — это не деплой вашего кода, это независимый поток изменений, у которого свои правила. Смешивать их нельзя.
Причина в том, что каталог /bitrix принадлежит платформе, а не вам, и меняется собственным механизмом — технологией SiteUpdate. Обновлятор скачивает новые версии модулей, применяет патчи к файлам ядра и, что важно, вносит изменения в структуру базы данных под новую версию. Если положить /bitrix в Git и выкатывать релизом, вы получите два конфликтующих источника правды: деплой перезапишет то, что обновил SiteUpdate, версия файлов разъедется с версией базы, и начнутся трудноуловимые ошибки.
Поэтому потоки разводят:
- Ваш код (
/local, шаблоны, миграции) едет через Git и CI/CD, как описано выше. Ядро в этом потоке не участвует и в репозитории отсутствует. - Ядро обновляется отдельной контролируемой процедурой: сначала на stage (копии прода), с резервной копией и проверкой совместимости с вашим кодом, и только потом — на проде.
Порядок безопасного обновления ядра такой же дисциплинированный, как и деплой: сделать бэкап, обновить на stage, прогнать регресс (особенно то, что касается изменённых модулей), убедиться, что ваш код совместим с новой версией, и лишь затем повторить на проде в спокойное время с бэкапом под рукой. Эта тема заслуживает отдельного разговора — как обновлять ядро и модули, не сломав боевой магазин, мы подробно разбираем в статье про безопасное обновление 1С-Битрикс.
Практический вывод для CI/CD: ваш пайплайн должен уметь работать с окружением, где ядро обновляется независимо. Отсюда и вынос /bitrix в shared при релизах через симлинк — ядро общее для всех релизов вашего кода и живёт своей жизнью, не привязанной к вашим выкатам.
Инструменты CI/CD под Битрикс
Процесс важнее инструментов, но без инструментов процесс не автоматизировать. Коротко о том, из чего обычно собирают конвейер для проекта на Битриксе — без привязки к конкретному вендору, потому что принципы одинаковы.
| Слой | Что делает | Типичные варианты |
|---|---|---|
| Хостинг репозитория | Хранит код, ветки, PR, ревью | GitLab, GitHub, Gitea, Bitbucket |
| CI-раннер | Запускает пайплайн: сборку, тесты | GitLab CI, GitHub Actions, Jenkins |
| Инструмент деплоя | Доставка и атомарное переключение | Deployer, самописные скрипты, Ansible |
| Модуль миграций | Версионирование структуры Битрикса | Решения сообщества для миграций |
| Хранилище секретов | Ключи и пароли по окружениям | Секреты CI, переменные окружения, Vault |
Как это связывается в единое целое. Код лежит в GitLab/GitHub. При пуше в ветку CI-раннер (GitLab CI / GitHub Actions) поднимает окружение, ставит зависимости, гоняет проверки. При слиянии в основную ветку раннер собирает артефакт и вызывает инструмент деплоя (например, Deployer), который выкладывает релиз через симлинк на stage, прогоняет миграции и прогревает кэш. Прод-релиз запускается по кнопке. Секреты берутся из защищённого хранилища CI, а не из кода. Ниже — как выглядит фрагмент описания пайплайна для одной из систем:
# .gitlab-ci.yml — упрощённый пример конвейера
stages: [build, test, deploy]
build:
stage: build
script:
- composer install --no-dev --optimize-autoloader
- npm ci && npm run build
artifacts:
paths: [local/]
test:
stage: test
script:
- find local -name '*.php' -print0 | xargs -0 -n1 php -l
- vendor/bin/phpstan analyse local/ --level=5
deploy_stage:
stage: deploy
script:
- vendor/bin/dep deploy stage # выкладка релиза + миграции
environment: stage
deploy_prod:
stage: deploy
script:
- vendor/bin/dep deploy prod
environment: prod
when: manual # прод — только по кнопке
Не гонитесь за «идеальным стеком» сразу. Рабочая стратегия — начать с малого: репозиторий с правильным .gitignore, два-три окружения, простой скрипт деплоя, проверка php -l. Это уже радикально надёжнее правок по FTP. Дальше конвейер обрастает миграциями, автотестами и атомарным переключением по мере роста проекта. Внедрение и поддержку такой инфраструктуры мы берём на себя в рамках поддержки 1С-Битрикс.
Частые ошибки
CI/CD на Битриксе спотыкается о повторяющийся набор граблей. Зная их заранее, вы обойдёте большинство болезненных инцидентов.
- Правки прямо на проде «в обход» деплоя. Даже при настроенном CI/CD кто-то «по-быстрому» правит файл на боевом — и следующий релиз затирает эту правку. Договорённость железная: на прод только через пайплайн.
- Секреты в репозитории.
.settings.phpили ключи API, попавшие в Git, — инцидент безопасности. Держите секреты в.gitignoreи в защищённом хранилище, проверяйтеgit statusдо коммита. - Ядро
/bitrixв Git. Ведёт к конфликтам с SiteUpdate и рассинхронизации версий файлов и базы. Ядро — вне репозитория, обновляется отдельным потоком. - Каталог
/uploadв репозитории. Раздувает Git до неприличных размеров и постоянно конфликтует между окружениями. Загрузки — в резервные копии, не в Git. - Изменения структуры руками на проде. Свойство инфоблока, добавленное мышкой на dev, не доедет до прода — код упадёт. Любое изменение структуры — миграцией.
- Заливка базы «вперёд». Попытка выкатить dev-базу на прод уничтожит живые заказы и данные. База едет только назад, дампами; вперёд — только миграции структуры.
- Stage, не похожий на prod. Разная версия PHP или конфигурация делает проверку бессмысленной: прошло на stage, упало на проде. Держите предпрод максимально близким к боевому.
- Деплой без атомарности. Копирование файлов «поверх» на живой сайт создаёт окно несогласованного состояния. Используйте релизы через симлинк с атомарным переключением.
- Миграции без метода
down. Необратимая миграция превращает откат в ручное восстановление из бэкапа. Пишите обратимые, аддитивные, совместимые вперёд миграции. - Полный сброс кэша в час пик. Обнуление всего кэша на нагруженном магазине без прогрева даёт всплеск нагрузки. Сбрасывайте точечно и сразу прогревайте.
- Нет резервной копии перед прод-релизом. Даже с откатом кода необратимое изменение данных спасёт только свежий бэкап. Делайте снимок базы автоматически перед боевым выкатом.
Чек-лист внедрения CI/CD
Короткий список, по которому удобно свериться при постановке процесса деплоя на проекте 1С-Битрикс:
- Код проекта в Git; правки на прод идут только через пайплайн, а не по FTP.
.gitignoreисключает ядро/bitrix,/upload, кэш и файлы с секретами (.settings.php,dbconn.php).- Весь свой код в
/local; тиражные компоненты и шаблоны ядра не правятся напрямую. - Есть три окружения: dev для разработки, stage как копия прода, prod для покупателей.
- Stage максимально похож на prod по версии PHP, конфигурации и структуре базы.
- Код движется вперёд (dev → stage → prod), данные — назад (обезличенная копия прода на stage/dev).
- На не-боевых окружениях отключены боевая почта, обмен с 1С и платёжные шлюзы.
- Любое изменение структуры (свойства, поля, опции) оформлено миграцией с методами
upиdown. - Секреты — по окружениям через переменные окружения и хранилище CI, не в коде.
- Ветки под задачи, обязательное code review и автопроверки перед слиянием в основную ветку.
- Пайплайн проходит этапы build → test → deploy; падение проверки останавливает выкат.
- Деплой атомарный (релизы через симлинк), с прогревом кэша после переключения.
- Откат — обратное переключение симлинка; перед прод-релизом делается бэкап базы.
- Обновление ядра идёт отдельным контролируемым потоком, не через деплой кода.
Вывод
CI/CD и деплой для 1С-Битрикс — это не про модные инструменты, а про инженерную дисциплину, которая убирает лотерею из работы с боевым магазином. Фундамент — Git с чётким разделением «код в репозитории, ядро/данные/секреты вне его»: в версионирование едет /local, шаблоны, компоненты, свой код и миграции, а ядро /bitrix, загрузки /upload, кэш и .settings.php остаются за его пределами. Поверх Git выстраиваются окружения dev/stage/prod, где код движется вперёд, а обезличенные данные — назад, и пайплайн build → test → deploy, который не пускает сломанный код к покупателям.
Главная особенность платформы, которую нельзя игнорировать, — разделение данных и кода: контент живёт в базе и синхронизируется дампами, а структуру (свойства инфоблоков, поля, опции) продвигают вперёд миграциями с обратимыми down. Деплой без простоя достигается атомарным переключением симлинка с прогревом кэша, откат — обратным переключением, а обновление ядра идёт отдельным контролируемым потоком, не смешиваясь с выкатом кода. Начать можно с малого — репозиторий, правильный .gitignore, stage и простой скрипт деплоя — и это уже несоизмеримо надёжнее правок по FTP. Если нужно поставить такой процесс под ваш проект, мы делаем это в рамках highload-проектов на 1С-Битрикс и поддержки. Смежные материалы по теме — тестирование и QA магазина, хостинг и инфраструктура BitrixVM, безопасное обновление Битрикса и вся рубрика «Разработка и архитектура».