Сегодня я хочу поделиться опытом как лучше хранить проекты на Drupal 9+ в git-репозитории. Мне периодически попадают в работу чужие проекты, где в репозитории лежит ядро Drupal, контрибные модули и тд. Я считаю это нецелесообразно и избыточно.
В свое время перейти на использование composer+git меня вдохновили статьи Никлана, в частности эта. Позже, с переходом на drupal/recommended-project стало возможно хранить еще меньше файлов в репозитории, благодаря пакету drupal-scaffold
Что такое scaffold?
Слово scaffold дословно означает "строительные леса". Скаффолдинг позволяет не хранить в репозитории файлы, которые хоть и не лежат в папке core, но при этом относятся к ядру. Например index.php, default.settings.php, различные README и многое другое. Полный список таких файлов можно найти в репозитории ядра.
Как работает drupal-scaffold?
Когда вы запускаете composer (например update или install) drupal-scaffold проверяет наличие и контрольные суммы файлов и если файлы отсутствуют или устарели, то копирует их из папки core/assets/scaffold/files в папку назначения.
А если я не хочу перезаписывать некоторые файлы?
Есть возможность прописать в composer.json какие файлы нужно игнорировать при скаффолдинге.
"locations": {
"web-root": "web/"
},
"file-mapping": {
"[web-root]/.htaccess": false
}
},
В данном случае файл .htaccess не будет перезаписываться. Однако, не рекомендую злоупотреблять этим. Ведь в тот же .htaccess периодически вносятся параметры исправляющие какие-нибудь проблемы или уязвимости. У нас в сообществе многие любят отключать скаффолдинг полностью или игнорировать перезапись файлов, но рано или поздно это может сыграть с ними злую шутку. Если вы недавно работаете с друпалом, то я не рекомендую отключать скаффолдинг.
Что же хранить в репозитории?
В корне проекта у меня такой перечень файлов:
Папка с конфигами - ведь вы используете конфиги для деплоя, верно?
Папка для приватных файлов - необязательно, но требуется для модулей типа webform. Лучше сразу добавить
Папка web - веб-рут
composer.json и composer.lock - настройки композера вашего проекта
phpcs.xml - необязательно. Там прописаны параметры для PHPCS. Вы же проверяете свои кастомные модули на стандарты кодирования PHP и Drupal?
README.md - необязательно. README вашего проекта в репозитории
.gitignore - какие файлы игнорировать в корне проекта.
Для игнора файлов скаффолда в корне проекта у вас должны быть добавлены файлы:
.gitattributes
Переходим в папку веб-рута
modules, profiles, themes, sites - эти папки рассмотрим чуть позже
autoload.php - вообще этот файл должен генерироваться скаффолдом, но у меня этого не происходило.
.gitignore - какие файлы игнорировать в веб-руте проекта.
Для игнора файлов скаффолда в веб-руте проекта у вас должны быть добавлены файлы:
.eslintignore
.eslintrc.json
.ht.router.php
.htaccess
example.gitignore
index.php
INSTALL.txt
README.txt
robots.txt
update.php
web.config
README.md
Да, да, всё это необязательно коммитить в репозиторий!
Переходим в папку modules. Там должен быть только файл .gitignore c содержимым:
README.txt
Аналогично в папках profiles и themes
В папке sites содержимого тоже немного:
Для игнора файлов скаффолда в папке sites проекта у вас должны быть добавлены файлы:
development.services.yml
example.settings.local.php
example.sites.php
Переходим в папку default:
Комментарий по поводу settings.php. Вообще его не обязательно хранить в репозитории, но я это делаю, чтобы хранить в нем единые настройки для ВСЕХ ОКРУЖЕНИЙ (локалка, dev, stage, prod), а уже специфичные настройки для каждого окружения хранятся в файле settings.local.php. Это очень удобно, если нужно добавить какой-то параметр сразу для всех окружений, просто добавляем, коммитим в репозиторий и вуаля. Если хранение settings.php противоречит вашим внутренним принципам или вы работаете сразу на хостинге, то можете заигнорить settings.php в .gitignore
Для игнора файлов скаффолда в папке default проекта у вас должны быть добавлены файлы:
default.settings.php
Итоги
Вот и всё. Благодаря скаффолду ваш репозиторий с проектом на Drupal 9+ будет иметь минимальное количество файлов и минимальный размер. Пример такого репозитория вы можете посмотреть в моем гитлабе
Комментарии
Хорошая статья! Лично для меня, пожалуй, ничего нового, но многим будет полезно. Единственный вопрос, который остался за кадром - это хранить ли скомпилированные стили и скрипты темы. Лично на мой взгляд, если над проектом работает сразу несколько разработчиков, то лучше не хранить, т.к. замучаешься мерджить изменения в этих файлах. А если на проекте всего один разработчик, либо всего один разработчик работает с темой, то удобнее и проще будет всё же хранить стили и скрипты в репе.
Тема хранения стилей тоже холиварная, да) По моему опыту работы над темой одному или вдвоем - удобнее хранить CSS в гите.
А еще часто сайты клиента на шаредах и проще скомпиленный CSS туда задеплоить
Сборкой проекта должен заниматься CI/CD сервис, а значит - скрипты, стили, папка vendor, результаты работы других скриптов, а тем более node_modules не должны быть в репозитории.
В любом случае, если даже разработчик один - может возникнуть момент когда он переключается на другую ветку и потом начинаются проблемы с мержем
Я честно говоря не понимаю смысла отказываться от хранения что кода ядра, что даже вендора в гите.
Во-первых, гит- удобный способ деплоя.
Во-вторых, ты всегда уверен в том, что код у тебя и код на проде/у другого дева вполне конкретных версий, без каких-то случайностей с заменами файлов.
В-третьих, это дополнительная защита от взлома, любое изменение файлов не пройдет незамеченным для гита.
В-четвертых, не нужен композер на проде. Сейчас это менее актуально, но еще совсем недавно жрал он памяти просто не в себя, да и не на всяких хостингах он вообще есть.
Ну а из минусов- ну будет у тебя гит репа 80-100Мб, и что?
1. Должно быть четко понятно: что является скаченным с орга, а что деятельностью разработчика. Поэтому ядро и контриб в репу не вносим. А свои доделки к контрибу оформляем в виде патчей. По моему - ну очень удобно.
2. Мне кажеться если на хостинг владельцу сайта закинуть уже собранное - этому владельцу будет гораздо сложнее поменять разработчика.
1. Кому должно быть ясно? Клиенту это до фонаря, девы и сами знают, что взято с орга, а что самописное.
2. В моей практике, если владельца разработчик устраивает, то менять смысла нет, это куча лишнего гемора. А если разработчика меняют, то усложнение жизни новым разрабам скорее всего будет отмечено и добавит еще больше негатива владельцу в ваш адрес.
Это если вы отформляете самопис в папку custom - я знаю. А если патчите ядро и модули - нет. Да, мне известно про модуль hacked, но вот как им пользоваться, когда сайт композером собран я не знаю.
Опять же, указывая патчи в composer.json, я вижу для чего они и пробиваю по названию файла на орге.
"drupal/core": {
"Требуется для работы vote up down": "web/patches/drupal-exclude-csrf-parameters-2670798-27.patch",
"Добавляет линию для текста после вставки изображения в CKEditor": "web/patches/3090661-16-ckeditor-insert-space-after-image.patch",
"Для подсчета комментариев": "web/patches/sql_mode_fullgroupby_issue-3098307-15.patch"
}
}
У клиента должна быть возможность менять разработчика. Да стоимость на внедренние нового разработчика может на любой системе быть сопоставима со стоимостью разработки нового сайта.
А на хостинге только собранное - новому разработчику еще предстоит в композер все запихивать.
Даже во времена первого композера команда composer install проходила без проблем даже на самых захудалых хостингах. А сейчас и подавно. А кроме composer install на проде больше ничего не надо запускать.
Контриб и ядро в гите - это удобно до тех пор, пока на проекте не появляется код ревью.
У нас с вами разный опыт захудалых хостингов. Мне регулярно приходилось настойчиво рекомендовать клиентам определенные хостинги в том числе потому, что то, что выбирали они, композер потянуть не могли никак.
По поводу код ревью- не вполне понятно как оно сказывается на проекте, если разделять апдейт кора и контриба от коммитов кастома.
Очень часто вместе с апдейтом ядра или контрибов нужно адаптировать к новым версиям кастом, а иногда и тему.
Согласен, но все-таки не понимаю, в чем проблема с код ревью. Для апдейта кора/контриба создается отдельный бранч куда сначала коммитится кор/контриб, а потом коммиты с исправлениями. Все это добро после ревью и тестов мерджится с мастером. Т.е. стандартный гит функционал, который к тому же очень удобно откатить назад в случае внезапных и непредвиденных проблем на проде.
Проблема в том, то в этом огромном диффе никто не будет разбираться. Поэтому если в композере что-то пошло не так, например, не применился патч, этого никто не увидит. В итоге версии в composer.json и composer.lock не будут соответствовать реально установленным.
Если же работать по нормальному - без вендоров, ядра и контриба в гите, то в случае непредвиденности на проде всё теми же стандартными средствами гита можно откатить composer.json и composer.lock на другую версию и выполнить composer install.
По поводу захудалых хостингов: хватит вешать лапшу на уши. Если на хостинге есть php, композер не может не работать.
Я даже умудрился на захудалом HTS.ru composer установить и запустить
Отличная статья!
Могу добавить несколько комментариев
1. git не умеет хранить пустые папки, поэтому в папке private необходимо что-то создать. Общепринято создавать файл, который называется
.gitkeep
. Это не стандарт, просто общепринятая вещь.2. Есть одна очень широко известная штука - 12 Factor App. В ней описывается в каком виде и что необходимо как хранить. Это уже давно стандарт в индустрии и следовать ему прямо необходимо.
Кроме всего прочего там говорится о конфигах.
Очень удобно использовать Environment variables внутри settings.php и тогда правильно настроив окружение, можно этот файл вообще никогда не изменять и всё будет подтягиваться автоматически на всех окружениях.
<?php
$databases['default']['default'] = [
'database' => getenv("DB_NAME"),
'username' => getenv("DB_USER"),
'password' => getenv("DB_PASSWORD"),
'prefix' => '',
'host' => getenv('DB_HOST'),
'port' => getenv('DB_PORT'),
'namespace' => 'Drupal\\Core\\Database\\Driver\\mysql',
'driver' => 'mysql',
];?>
Спасибо за комментарии!
По поводу settings.local.php, то я там еще храню какой конфиг сплита активировать на этом окружении. Хотя не исключено, что можно и через Environment variables тоже это сделать
Спасибо большое за статью. Бесценно для тех, кто только знакомится с деплоем через git.
Возможно глупый вопрос, но почему в вашем проекте файл .gitignore имеется в каждом каталоге и подкаталоге? Не проще ли иметь один файл в корне где всё разом и прописать?
и еще вопрос. Если игнор drupal-scaffold файлов нужно прописывать в composer.json, то почему они у вас прописаны в .gitignore файлах внутри каталогов?