Все основные элементы системы MODX, такие как чанки, шаблоны, сниппеты и т.д, хранятся в БД, из этого появляется проблема осуществления контроля версий за этими элементами, а также сложности с разделением на development и production версии сайта.
Приведу основные требования, чего я хочу от своего рабочего процесса на MODX Revo:
На момент написания этой статьи я имел опыт веб-разработки чуть более года. Мне повезло, я начал свой путь в этой сфере именно с MODX Revo, но несмотря на все плюсы этого фреймворка, со временем я начал сталкиваться и с минусами. Пока что я не работал в команде над большими сложными проектами и не знаю как обычно люди справляются с указанными выше сложностями. В интернетах я не нашёл какого-либо конкретного решения, и это поспособствовало созданию своего workflow, который я хочу представить в этой статье. Сразу оговорюсь, я не придумал ничего принципиально нового, а просто собрал разбросанные по интернету куски информации в одно руководство как устроить свой рабочий процесс при работе с MODX Revolution.
Что нам понадобится.
— Git
— npm + Gulp
Для работы я использую IDE PHPStorm.
Первое что приходит на ум, когда думаешь как организовать рабочую (тестовую, dev) и релизную (боевой, prod) версии сайта, это просто иметь две его копии. Сначала ведём разработку на тестовом сайте, а после одобрения менеджером или клиентом, переносим всё на боевой. Просто и ясно, только вот этот процесс может превратиться в кошмар, т.к. всё делается вручную и существует немалая вероятность ошибки при переносе, потом придётся проверять, что ты не так сделал, а потом ещё окажется, что боевой сайт не вполне соответствует тестовому и нужно что-то ещё дополнительно править и т.д. и т.п. Нет, такого нам не надо.
Не буду долго рассуждать и скажу сразу, я предлагаю использовать один экземпляр сайта, в котором мы воспользуемся механизмом контекстов MODX Revo. Стандартный контекст web будет содержать релизную версию сайта. Плюс мы создадим ещё один контекст dev, работу с которым вынесем в поддомен. Таким образом, нам нужно:
— домен example.com, работающий в контексте web
— поддомен dev.example.com, работающий в контексте dev
При деплое мне нужно, чтобы изменения сделанные в контексте dev, каким бы то ни было образом сливались в web.
Эта часть работы начинается с того момента, когда у вас уже установлен движок и необходимые компоненты и настроены доменные имена, т.е. при обращении по обоим адресам example.com и dev.example.com открывается одна и та же стартовая страница MODX (корневая директория обоих доменов общая).
Теперь заходите в админ-панель → системные настройки → контексты и создайте новый контекст. Ключ укажите dev, имя — как угодно, я назвал Development. В контекстном меню слева у вас появится новый контекст. Первым делом создайте для него ресурс, а потом зайдите в настройки контекста (правой кнопкой по контексту → редактировать → настройки контекста) и задайте настройки
— site_start
— error_page
— unauthorized_page,
указав в них ID созданного ресурса. Это нужно, чтобы система не падала с ошибкой, если при работе в контексте dev не будет найдена какая-либо страница.

прим. Я создал контекст dev (Development) и переименовал стандартный контекст Website на Production, ключ стандартного контекста остался прежним — web.
Теперь в папке core/elements/common/plugins/ (создайте необходимые папки) создайте файл switchContext.php со следующим содержимым
Поясню, что делает плагин. При работе с сайтом через админку, т.е. в контексте mgr, ничего не делает. При работе с фронтальной частью сайта на домене dev.example.com переключает контекст на dev. При работе на фронт-енде на основном домене тоже ничего не делает. Но в случае, если исполнение скрипта каким-то образом попадает в default, то выводит ошибку в лог. Такое может случиться, например, при переносе сайта на новое доменное имя, и это сообщение призвано облегчить жизнь тому разработчику, который будет разбираться, почему после переноса ничего не работает. Когда я проверял описанную здесь схему работы на удалённом сервере, я как раз забыл исправить доменные имена в этом плагине и по ошибке в логе сразу понял что не так. В очередной раз сам себе сказал «Спасибо».
Обратите внимание, в самом конце файла плагина необходимо поставить оператор return, если плагин не должен ничего возвращать, это необходимо для того, чтобы переписать возв��ащающее значение оператора include, который мы используем при подключении файла плагина.
Через админ-панель создайте новый плагин, который будет подтягивать созданный файл
повесьте запуск плагина на событие OnHandleRequest.
Теперь у нас есть два контекста, как их использовать в дальнейшей разработке будет показано ниже.
Создаём репозиторий проекта, например на GitHub, при этом в рабочем каталоге будут только файлы и папки, не относящиеся к движку. Примерно так
При этом, мы будем также контролировать файлы, получаемые в результате сборки (assets/web/ и core/elements/web/), чтобы иметь возможность откатиться после неудачного деплоя. Такая структура папок будет объяснена ниже.
Разработчики, как обычно, работают в своих локальных репозиториях и пушат коммиты в удалённый репозиторий. Кроме того, должен существовать репозиторий в корне сайта.
Пример файла .gitignore
Когда я выше говорил о Develpoment и Production версиях, я предложил использовать один экземпляр сайта. Это также предполагает отсутствие его локальной копии (не путать с локальным git-репозиторием проекта). Мы будем править файлы на локальной машине, но при этом в нашем локальном рабочем каталоге будут только файлы и папки, не относящиеся к движку. Мы будем вносить правки в имеющиеся файлы, затем делать upload этих файлов на сайт. После выполнения какой-либо задачи делаем коммит в локальном репозитории, после чего, если нужно, пушим изменения на GitHub, или где вы там собираетесь держать проект.
Теперь я расскажу, как я предлагаю устроить версионирование основных элементов системы — шаблонов, чанков, сниппетов и плагинов, и описать рабочий процесс через IDE PHPStorm в связке с панелью администрирования MODX. В этом нам поможет легендарный pdoTools и используемый им шаблонизатор Fenom.
Как известно, парсер pdoTools позволяет подключать внешние файлы прямо в теле чанка, и именно эта фича лежит в основе всего устройства контроля версий.
Компонент pdoTools имеет системную настройку pdotools_elements_path со значением по умолчанию {core_path}elements/. Что ж, соответственно, создаём папку elements/ (если ещё не создана) в папке core/ движка и внутри создаём следующую структуру папок:
Собственно разработка ведётся в папке dev/ при этом действует важное правило для всей команды: «Никто и никогда не должен проводить никакие правки в папке web/». При деплое всё содержимое папки dev/ копируется в web/ с помощью Gulp. Папка common/ содержит общие для обоих контекстов файлы, например, плагин переключающий текущий контекст, описанный выше.
Такая структура папок позволяет при подключении внешних файлов при помощи шаблонизатора Fenom использовать значение плейсхолдера [[*context_key]] примерно так
В первой строке мы складываем в переменную $ctx ключ текущего контекста (dev или web), а во второй строке используем это значение в пути к файлу. Это и позволяет иметь две версии сайта на одном движке.

прим. Подключения чанков в файле шаблона
Помимо файлов, содержащих основные элементы системы, нам также нужно вести контроль версий файлов вёрстки и js. Как правило, эти файлы расположены в папке assets/ следующим образом.
По старой схеме предлагаю создать следующую структуру
Работая с файлами вёрстки и скриптов следует учесть следующий момент. Например, в папке dev/js/ может лежать несколько файлов .js (к примеру, calendar.module.js и search-form.module.js), но при деплое в продакшн эти файлы следует объединить в один и минифицировать (например, main.bundle.min.js), так что в чанках нельзя просто взять и вписать в путь файла необходимое звено [[*context_key]], следует поступить примерно следующим образом и развернуть такую конструкцию
Шаблоны создаём в папке core/elements/dev/templates/, в которых подключаем чанки из папки core/elements/dev/chunks, используя синтаксис шаблонизатора Fenom. При этом, создавая файл шаблона, мы также должны создать соответствующий ему шаблон в админ-панели. Только мы не будем создавать статический шаблон, так как не можем указать конкретный путь к файлу, потому что он зависит от контекста, в котором шаблон используется. Вместо этого в теле шаблона мы пропишем одну единственную строку
Таким образом, этот шаблон послужит своеобразным переключателем файла шаблона для ресурсов в различных контекстах.

прим. Подключение файла шаблона
При таком подходе разработки следует отдельно оговорить внедрение в систему новых плагинов.
Аналогично ситуации с шаблонами, плагины создаём в папке core/elements/dev/plugins/, в которых пишем логику работы плагина. Далее, заходим в админ-панель и создаём соответствующий ему плагин (НЕ статический!), в котором подключаем файл плагина через include следующим образом
Не забываем, конечно, в админ-панели задать события, на которые вешается плагин. Если нам нужен плагин, общий для обоих контекстов, в переменную context складываем значение «common», как это было сделано в плагине switchContext.
Вот мы и подошли к самому ответственному моменту. Выкатываем тестовую версию сайта на продакшн. Предварительно необходимо выполнить кое-какие действия с репозиторием на сервере, а именно создать SSH ключ, зарегистрировать его и прописать в настройках репозитория на GitHub. Описывать здесь этот процесс я не буду. Ссылка на иснтуркцию по генерации и регистрации ключа я оставлю внизу.
Итак, город засыпает, разработчики прекращают свою работу, все файлы закоммичены и запушены в удалённый репозиторий. Просыпается тимлид, его задача — максимально быстро выкатить всю произведённую работу в релиз. Предлагаю такой порядок действий.

прим. Пример дерева коммитов.
Выше описанное относится к деплою шаблонов, чанков и сниппетов, а также файлов вёрстки, но что же у нас с ресурсами?
Рассмотрим такую задачу. На сайте есть раздел Новости, со временем количество публикаций стало очень большим и было принято решение создать новый раздел сайта Архив новостей.
В dev контексте вы создаёте соответствующий контейнер, добавляете пару экземпляров архивных новостей, создаёте чанки, если нужно шаблон и т.п. В результате на домене dev.example.com появляется новый раздел. После одобрения заказчиком, вы производите деплой, описанный выше, но нового раздела на продакшене, конечено, не появится, хотя все файлы будут приведены к необходимому виду. Конечно, это произойдёт, потому что созданный раздел (имеется в виду совокупность созданных ресурсов) будет находиться в контексте dev и не будет доступна в контексте web.
— И что делать?
— Копипаст, товарищи, увы.
А точнее перенос. Мы просто переносим созданный раздел в контекст web, а после повторно создаём его копию в dev, чтобы структура dev-версии сайта соответствовала продакшену.
Да, полностью избавиться от копипаста у меня не получилось.
Таким образом, мне удалось организовать рабочий процесс, который бы устроил, в первую очередь, меня. В реальной работе эта схема ещё не применялась, поэтому подводных камней пока не обнаружено. Может быть более профессиональный взгляд читателей увидит существенные недостатки, поэтому прошу написать об этом в комментариях. И кстати, это моя первая статья, и я бы хотел узнать насколько доступно и ясно мне удалось изложить свои мысли, буду благодарен за конструктивную критику.
Шаблон для разработки, созданный по ходу написания статьи, доступен на Github https://github.com/vanyaraspopov/start-code-modx.
pdoTools. Парсер
pdoTools. Файловые элементы
Синтаксис Fenom
Переключение контекстов в зависимости от URL
Contexts | MODX Revolution
Using One Gateway Plugin to Manage Multiple Domains
Настройка IDE PHPStorm
Приятная сборка frontend проекта
8 двухколёсных советов по MODX Revolution
Generating a new SSH key and adding it to the ssh-agent
GitHub. vanyaraspopov/start-code-modx
Приведу основные требования, чего я хочу от своего рабочего процесса на MODX Revo:
- контроль версий везде, где пишу какой-либо код (html, css, js, php),
- иметь отдельную dev-версию сайта, на которой ведётся текущая разработка, а после — деплоить все изменения в продакшн, причём, желательно, автоматизировать этот процесс,
- минимум копипаста при разработке и деплое.
Содержание
- Введение
- Development и Production версии сайта
- Контроль версий
- Схема работы
- Деплой
- Заключение
- Ссылки
Введение
На момент написания этой статьи я имел опыт веб-разработки чуть более года. Мне повезло, я начал свой путь в этой сфере именно с MODX Revo, но несмотря на все плюсы этого фреймворка, со временем я начал сталкиваться и с минусами. Пока что я не работал в команде над большими сложными проектами и не знаю как обычно люди справляются с указанными выше сложностями. В интернетах я не нашёл какого-либо конкретного решения, и это поспособствовало созданию своего workflow, который я хочу представить в этой статье. Сразу оговорюсь, я не придумал ничего принципиально нового, а просто собрал разбросанные по интернету куски информации в одно руководство как устроить свой рабочий процесс при работе с MODX Revolution.
Что нам понадобится.
— Git
— npm + Gulp
Для работы я использую IDE PHPStorm.
Development и Production версии сайта
Первое что приходит на ум, когда думаешь как организовать рабочую (тестовую, dev) и релизную (боевой, prod) версии сайта, это просто иметь две его копии. Сначала ведём разработку на тестовом сайте, а после одобрения менеджером или клиентом, переносим всё на боевой. Просто и ясно, только вот этот процесс может превратиться в кошмар, т.к. всё делается вручную и существует немалая вероятность ошибки при переносе, потом придётся проверять, что ты не так сделал, а потом ещё окажется, что боевой сайт не вполне соответствует тестовому и нужно что-то ещё дополнительно править и т.д. и т.п. Нет, такого нам не надо.
Не буду долго рассуждать и скажу сразу, я предлагаю использовать один экземпляр сайта, в котором мы воспользуемся механизмом контекстов MODX Revo. Стандартный контекст web будет содержать релизную версию сайта. Плюс мы создадим ещё один контекст dev, работу с которым вынесем в поддомен. Таким образом, нам нужно:
— домен example.com, работающий в контексте web
— поддомен dev.example.com, работающий в контексте dev
При деплое мне нужно, чтобы изменения сделанные в контексте dev, каким бы то ни было образом сливались в web.
Создаём контекст dev
Эта часть работы начинается с того момента, когда у вас уже установлен движок и необходимые компоненты и настроены доменные имена, т.е. при обращении по обоим адресам example.com и dev.example.com открывается одна и та же стартовая страница MODX (корневая директория обоих доменов общая).
Теперь заходите в админ-панель → системные настройки → контексты и создайте новый контекст. Ключ укажите dev, имя — как угодно, я назвал Development. В контекстном меню слева у вас появится новый контекст. Первым делом создайте для него ресурс, а потом зайдите в настройки контекста (правой кнопкой по контексту → редактировать → настройки контекста) и задайте настройки
— site_start
— error_page
— unauthorized_page,
указав в них ID созданного ресурса. Это нужно, чтобы система не падала с ошибкой, если при работе в контексте dev не будет найдена какая-либо страница.

прим. Я создал контекст dev (Development) и переименовал стандартный контекст Website на Production, ключ стандартного контекста остался прежним — web.
Теперь в папке core/elements/common/plugins/ (создайте необходимые папки) создайте файл switchContext.php со следующим содержимым
<?php /** * @var modX $modx */ /* don't execute if in the Manager */ if ($modx->context->get('key') == 'mgr') { return; } switch ($_SERVER['HTTP_HOST']) { case 'dev.example.com': $modx->switchContext('dev'); break; case 'example.com': break; default: $modx->log(modX::LOG_LEVEL_ERROR, 'Check this plugin! May be your headache coming from here.'); break; } return;
Поясню, что делает плагин. При работе с сайтом через админку, т.е. в контексте mgr, ничего не делает. При работе с фронтальной частью сайта на домене dev.example.com переключает контекст на dev. При работе на фронт-енде на основном домене тоже ничего не делает. Но в случае, если исполнение скрипта каким-то образом попадает в default, то выводит ошибку в лог. Такое может случиться, например, при переносе сайта на новое доменное имя, и это сообщение призвано облегчить жизнь тому разработчику, который будет разбираться, почему после переноса ничего не работает. Когда я проверял описанную здесь схему работы на удалённом сервере, я как раз забыл исправить доменные имена в этом плагине и по ошибке в логе сразу понял что не так. В очередной раз сам себе сказал «Спасибо».
Обратите внимание, в самом конце файла плагина необходимо поставить оператор return, если плагин не должен ничего возвращать, это необходимо для того, чтобы переписать возв��ащающее значение оператора include, который мы используем при подключении файла плагина.
Через админ-панель создайте новый плагин, который будет подтягивать созданный файл
<?php $filepath = 'plugins/switchContext.php'; $context = 'common'; $plugin = $modx->getOption('pdotools_elements_path') . "$context/$filepath"; if (file_exists($plugin)) { return include $plugin; }
повесьте запуск плагина на событие OnHandleRequest.
Теперь у нас есть два контекста, как их использовать в дальнейшей разработке будет показано ниже.
Контроль версий
Создаём репозиторий проекта, например на GitHub, при этом в рабочем каталоге будут только файлы и папки, не относящиеся к движку. Примерно так
assets/ |-- dev/ |-- css/ |-- js/ |-- img/ \-- scss/ |-- web/ |-- css/ |-- js/ \-- img/ core/ \-- elements/ |-- common/ |-- plugins/ |-- dev/ |-- chunks/ |-- plugins/ |-- snippets/ \-- templates/ |-- web/ |-- chunks/ |-- plugins/ |-- snippets/ \-- templates/ \-- plugins/ .gitignore gulpfile.js package.json
При этом, мы будем также контролировать файлы, получаемые в результате сборки (assets/web/ и core/elements/web/), чтобы иметь возможность откатиться после неудачного деплоя. Такая структура папок будет объяснена ниже.
Разработчики, как обычно, работают в своих локальных репозиториях и пушат коммиты в удалённый репозиторий. Кроме того, должен существовать репозиторий в корне сайта.
Пример файла .gitignore
# IntelliJ project files .idea/ *.iml out gen # ignore MODX files /assets/* /connectors/* /core/* /manager/* /setup/* /config.core.php /index.php /.htaccess # ignore node modules /node_modules/ # do not ignore !/assets/dev/ !/assets/web/ !/core/elements/
Схема работы
Когда я выше говорил о Develpoment и Production версиях, я предложил использовать один экземпляр сайта. Это также предполагает отсутствие его локальной копии (не путать с локальным git-репозиторием проекта). Мы будем править файлы на локальной машине, но при этом в нашем локальном рабочем каталоге будут только файлы и папки, не относящиеся к движку. Мы будем вносить правки в имеющиеся файлы, затем делать upload этих файлов на сайт. После выполнения какой-либо задачи делаем коммит в локальном репозитории, после чего, если нужно, пушим изменения на GitHub, или где вы там собираетесь держать проект.
Теперь я расскажу, как я предлагаю устроить версионирование основных элементов системы — шаблонов, чанков, сниппетов и плагинов, и описать рабочий процесс через IDE PHPStorm в связке с панелью администрирования MODX. В этом нам поможет легендарный pdoTools и используемый им шаблонизатор Fenom.
Как известно, парсер pdoTools позволяет подключать внешние файлы прямо в теле чанка, и именно эта фича лежит в основе всего устройства контроля версий.
Необходимо выставить настройке pdotools_fenom_parser (Использовать Fenom на страницах) значение Да
Компонент pdoTools имеет системную настройку pdotools_elements_path со значением по умолчанию {core_path}elements/. Что ж, соответственно, создаём папку elements/ (если ещё не создана) в папке core/ движка и внутри создаём следующую структуру папок:
elements/ |-- common/ |-- plugins/ |-- dev/ |-- chunks/ |-- plugins/ |-- snippets/ \-- templates/ |-- web/ |-- chunks/ |-- plugins/ |-- snippets/ \-- templates/ \-- plugins/
Собственно разработка ведётся в папке dev/ при этом действует важное правило для всей команды: «Никто и никогда не должен проводить никакие правки в папке web/». При деплое всё содержимое папки dev/ копируется в web/ с помощью Gulp. Папка common/ содержит общие для обоих контекстов файлы, например, плагин переключающий текущий контекст, описанный выше.
Такая структура папок позволяет при подключении внешних файлов при помощи шаблонизатора Fenom использовать значение плейсхолдера [[*context_key]] примерно так
{set $ctx = $_modx->resource.context_key} {include "file:$ctx/chunks/common/head.tpl"}
В первой строке мы складываем в переменную $ctx ключ текущего контекста (dev или web), а во второй строке используем это значение в пути к файлу. Это и позволяет иметь две версии сайта на одном движке.

прим. Подключения чанков в файле шаблона
Помимо файлов, содержащих основные элементы системы, нам также нужно вести контроль версий файлов вёрстки и js. Как правило, эти файлы расположены в папке assets/ следующим образом.
assets/ |-- css/ |-- js/ \-- img/
По старой схеме предлагаю создать следующую структуру
assets/ |-- dev/ |-- css/ |-- js/ |-- img/ \-- scss/ |-- web/ |-- css/ |-- js/ \-- img/
Работая с файлами вёрстки и скриптов следует учесть следующий момент. Например, в папке dev/js/ может лежать несколько файлов .js (к примеру, calendar.module.js и search-form.module.js), но при деплое в продакшн эти файлы следует объединить в один и минифицировать (например, main.bundle.min.js), так что в чанках нельзя просто взять и вписать в путь файла необходимое звено [[*context_key]], следует поступить примерно следующим образом и развернуть такую конструкцию
[[*context_key:is=`dev`:then=` <script src="[[++assets_url]][[*context_key]]/js/calendar.module.js"></script> <script src="[[++assets_url]][[*context_key]]/js/search-form.module.js"></script> <!-- остальные скрипты --> `]] [[*context_key:is=`web`:then=` <script src="[[++assets_url]][[*context_key]]/js/main.bundle.min.js"></script> `]]
Связываем ресурсы с шаблонами
Шаблоны создаём в папке core/elements/dev/templates/, в которых подключаем чанки из папки core/elements/dev/chunks, используя синтаксис шаблонизатора Fenom. При этом, создавая файл шаблона, мы также должны создать соответствующий ему шаблон в админ-панели. Только мы не будем создавать статический шаблон, так как не можем указать конкретный путь к файлу, потому что он зависит от контекста, в котором шаблон используется. Вместо этого в теле шаблона мы пропишем одну единственную строку
{include 'file:[[*context_key]]/templates/base.tpl'}
Таким образом, этот шаблон послужит своеобразным переключателем файла шаблона для ресурсов в различных контекстах.

прим. Подключение файла шаблона
Создаём плагины
При таком подходе разработки следует отдельно оговорить внедрение в систему новых плагинов.
Аналогично ситуации с шаблонами, плагины создаём в папке core/elements/dev/plugins/, в которых пишем логику работы плагина. Далее, заходим в админ-панель и создаём соответствующий ему плагин (НЕ статический!), в котором подключаем файл плагина через include следующим образом
<?php $filepath = 'plugins/somePlugin.php'; $context = $modx->context->get('key'); $plugin = $modx->getOption('pdotools_elements_path') . "$context/$filepath"; if (file_exists($plugin)) { return include $plugin; }
Не забываем, конечно, в админ-панели задать события, на которые вешается плагин. Если нам нужен плагин, общий для обоих контекстов, в переменную context складываем значение «common», как это было сделано в плагине switchContext.
Деплой
Вот мы и подошли к самому ответственному моменту. Выкатываем тестовую версию сайта на продакшн. Предварительно необходимо выполнить кое-какие действия с репозиторием на сервере, а именно создать SSH ключ, зарегистрировать его и прописать в настройках репозитория на GitHub. Описывать здесь этот процесс я не буду. Ссылка на иснтуркцию по генерации и регистрации ключа я оставлю внизу.
Итак, город засыпает, разработчики прекращают свою работу, все файлы закоммичены и запушены в удалённый репозиторий. Просыпается тимлид, его задача — максимально быстро выкатить всю произведённую работу в релиз. Предлагаю такой порядок действий.
- На своей локальной машине нужно сделать синхронизацию файлов с удалённым репозиторием, чтобы убедиться, что в локальном репозитории все файлы в актуальном состоянии.
- Создаём метку, например «v1.0.666-pre», обозначая таким образом коммит, предшествующий сборке версии v1.0.666, для быстрого и удобного отката в случае неудачного деплоя.
$ git tag v1.0.666-pre
- С помощью Gulp собираем новую версию пр��екта.
$ gulp modx:build
Приводу пример gulp файла. Здесь я описал лишь одну задачу для копирования файлов из core/elements/dev в core/elements/web/, остальные таски, наверняка, сможете написать и сами.
'use strict'; var gulp = require('gulp'); var paths = { dist: { // output js: 'assets/web/js/', css: 'assets/web/css/', img: 'assets/web/img/', fonts: 'assets/web/fonts/', modx: 'core/elements/web/' }, src: { // sources js: 'assets/dev/js/**/*.js', style: 'assets/dev/sass/style.scss', img: 'assets/dev/img/**/*.*', fonts: 'assets/dev/fonts/**/*.*', modx: 'core/elements/dev/**/*.*' }, watch: { // files watch to js: 'assets/dev/js/**/*.js', style: 'assets/dev/sass/**/*.scss', img: 'assets/dev/img/**/*.*', fonts: 'assets/dev/fonts/**/*.*', modx: 'core/elements/dev/**/*.*' } }; gulp.task('modx:build', function () { return gulp.src(paths.src.modx) .pipe(gulp.dest(paths.dist.modx)) });
- В результате сборки будут добавлены новые или изменены старые файлы в папках /assets/web/ и /core/elements/web/. Делаем коммит, назначем ему метку и делаем push с флагом --tags, чтобы отправить в удалённый репозиторий созданные метки.
$ git add . $ git commit -m "Build v1.0.666" $ git tag v1.0.666 $ git push --tags
- Через SSH подключаемся к серверу и переходим в корневую директорию сайта, подтягиваем данные из удалённого репозитория и делаем hard reset, чтобы привести все файлы сайта к тому виду, в котором они хранятся в репозитории.
$ git fetch --all $ git reset --hard origin/master
- Смотрим результат в продакшене. Если я правильно представляю как устроен мир разработки и программирования, то примерно в 10 из десяти случаев что-то пойдёт не так. Поэтому переходим обратно в консоль, выполняем команду
$ git checkout v1.0.666-pre
т.е. переводим продакшн-файлы в состояние до сборки и начинаем разбираться что не так.

прим. Пример дерева коммитов.
Выше описанное относится к деплою шаблонов, чанков и сниппетов, а также файлов вёрстки, но что же у нас с ресурсами?
А что с ресурсами?
Рассмотрим такую задачу. На сайте есть раздел Новости, со временем количество публикаций стало очень большим и было принято решение создать новый раздел сайта Архив новостей.
В dev контексте вы создаёте соответствующий контейнер, добавляете пару экземпляров архивных новостей, создаёте чанки, если нужно шаблон и т.п. В результате на домене dev.example.com появляется новый раздел. После одобрения заказчиком, вы производите деплой, описанный выше, но нового раздела на продакшене, конечено, не появится, хотя все файлы будут приведены к необходимому виду. Конечно, это произойдёт, потому что созданный раздел (имеется в виду совокупность созданных ресурсов) будет находиться в контексте dev и не будет доступна в контексте web.
— И что делать?
— Копипаст, товарищи, увы.
А точнее перенос. Мы просто переносим созданный раздел в контекст web, а после повторно создаём его копию в dev, чтобы структура dev-версии сайта соответствовала продакшену.
Да, полностью избавиться от копипаста у меня не получилось.
Заключение
Таким образом, мне удалось организовать рабочий процесс, который бы устроил, в первую очередь, меня. В реальной работе эта схема ещё не применялась, поэтому подводных камней пока не обнаружено. Может быть более профессиональный взгляд читателей увидит существенные недостатки, поэтому прошу написать об этом в комментариях. И кстати, это моя первая статья, и я бы хотел узнать насколько доступно и ясно мне удалось изложить свои мысли, буду благодарен за конструктивную критику.
Шаблон для разработки, созданный по ходу написания статьи, доступен на Github https://github.com/vanyaraspopov/start-code-modx.
Ссылки
pdoTools. Парсер
pdoTools. Файловые элементы
Синтаксис Fenom
Переключение контекстов в зависимости от URL
Contexts | MODX Revolution
Using One Gateway Plugin to Manage Multiple Domains
Настройка IDE PHPStorm
Приятная сборка frontend проекта
8 двухколёсных советов по MODX Revolution
Generating a new SSH key and adding it to the ssh-agent
GitHub. vanyaraspopov/start-code-modx
