Drupal 8: Мой процесс разработки и деплоя на июнь 2018

Как устроен мой процесс разработки и деплоя изменений.

03.07.2018
29 комментариев
3 мин.

Меня часто спрашивают, как у меня устроен процесс разработки. Также, общаясь с теми кто мне пишет, часто вижу, что некоторые проблемы возникают из-за неправильного процесса разработки. Из-за чего друпал становится ещё сложнее и "запутаннее". Хотя, в 8-ой версии есть все инструменты для облегчения жизни.

In nutshell

Если вы уже более-менее в теме, то весь процесс моей разработки строится следующим образом:

  • Локальная разработка всего и вся. (S)FTP использую только для очень мелких правок, читай хотфиксов.
  • Деплою через конфиги и git.
  • Зависимости контролирую через composer.
  • В качестве ядра использую composer drupal project.

Вода

Ничего особенного в моём процессе разработки и деплоя проекта совершенно нет. Я не открою вам Америки, всё очень тривиально. Этот подход сам вырисовывается в процессе работы над 8-кой.

Я в 99 из 100 случаев, работаю над проектом один, есть возможность что кто-то внесет какие-то изменения в админке, но именно в кодовой базе, как правило я единственный участник. Учитывайте это, но мой процесс спокойно сможет отскалироваться до целой команды.

Почему локальная разработка? Я считаю, что заниматься разработкой с Drupal 8 на сервере лишено смысла:

  1. Для разработки в Drupal 8 нужно отключать полностью кэширование, включать отладку Twig и прочие прелести. Это не такое же отключение как в 7-ке. Нагрузку такой сайт начинает создавать очень и очень приличную. Если вы раньше могли заниматься разработкой Drupal 7, на условном VPS $10 от DO и попутно держать там продакшен проекты, то теперь, такой сервачек спокойно может быть сложен парочкой сайтов на 8-ке в режиме разработки. Это потребует более мощного сервера.
  2. Для удобного написания кода, без IDE уже не обойтись. А для этого нужно иметь всё ядро и все сторонние зависимости под рукой IDE, чтобы она могла анализировать кодовую базу и подсказывать нам. Гонять ядро через (S)FTP боль даже на Drupal 7, на 8-ке даже пробовать нет смысла. Если в 7-ке это легко разруливалось, скачиванием ядра с drupal.org и закидыванием всех популярных модулей к нему и скармливание IDE, то в 8-ке это уже не гарантированное решение. Зависимости композера, так или иначе будут появляться, а собирать ядро на все случаи жизни для кормления IDE неудобно. Из-за различных сервисов и прочих новшеств Drupal 8, ядро с солянкой может ввести в заблуждение. В общем, как минимум, придется держать копию проекта для IDE, и опять же, в чем тогда смысл удаленной разработки? Проще делать на локалке, иначе придется регулярно кодовую базу актуализировать. Гибче и быстрее.
  3. Для 8-ки чаще приходится поднимать xdebug, для отладки сложных моментов кода. Поднимая xdebug на сервере, вы создаете серьезную нагрузку для всех проектов которые там хостятся, даже в режиме ожидания xdebug жрет очень много. Что уж говорить о моменте отладки. Да и проброс портов для xdebug — занятие не из приятных. Когда на локалке всё просто работает и всё. Постоянно включать и отключать его на сервере тоже, дело не из приятных. А если там несколько разработчиков? Придется оставить включенным, в итоге мешаться будет всем, при этом делать, зачастую, необоснованную нагрузку на весь сервер, и лишает возможности держать продакшен проекты рядом с dev\stage сайтами. А ещё на локалке можно бесплатно использовать blackfire для профилирования, что тоже приятно.
  4. В случае отключения интернета и других аномалий, например, бана РКН, никаких проблем не будет. Вся разработка локальная. Меня уже это неоднократно спасало, пока провайдер вел тех. работы с интернетом, я спокойно мог работать над сайтом, это никак меня не ограничивало. Также, если у вас офисы и студия, то для юр. лиц цены на интернет намного более злые, а скорость очень низкая. Гонять туда-сюда кучу трафика для 8-ки, также может стать проблемой для кого-то. А ещё можно сюда закинуть любителей работать на нотубках, в поездках, кафешках и т.д. где скорость WiFi и вообще доступ к сети может быть проблемой, не говоря о безопасности таких подключений. Зато деплой через SSH в размере паре десятков, а может и сотен кб, при любом подключении пройдет моментально с минимальными затратами трафика.
  5. Самый главный пункт — нет проблем с переносом изменений. Деплой всех изменений, уже проверенных и готовых к показу, занимает не более 1 минуты. Серьезно.
  6. Опять же, в случае необходимости развернуть с ничего, полноценную копию с прода, дело 5, ну максимум 10 минут. С докерами это нереально просто и быстро, а главное, безболезненно.

Для локальной разработки, на данный момент, я пользуюсь Docker4Drupal. Опять же, это тоже можно закинуть как ещё один пунктик. Так как под каждый проект можно будет делать своё окружение, но это можно сделать и на сервере, если заморочиться.

Почему и для чего использую git? Git я стал использовать уже давно, ещё с 7-ки. Это удобно и безопасно, так ещё и спасательный круг. Ох, как мне пару раз он спасал жизнь, когда заказчик выдавал доступы "своим" разработчикам и они поверх Drupal заливали что-то своё и всё ломая, а git reset --HARD возвращал всё назад. Также легко заметить, кто-то влезал в кодовую базу кроме меня или нет. И если это был кто-то левый, можно предъявить, типа, это кто-то из ваших лазил и сделать это, то и сё. И ведь такое тоже пригодилось!

Но с 8-кой гит заиграл новыми красками. Из-за конфигов, стало возможным деплоить не только код, но и то что "накликано" в админке. И это просто нереально круто! Поработали, запушили, спулили на продакшене\деве\стейдже — все изменения внесены. Это занимает ~1 минуту. И в случае проблем, можно всегда откатиться на предыдущую версию конфигураций, которые были рабочие.

Также, если у проекта намечается крупный редизайн, можно вести его в отдельной ветке, пока он не будет готов, при этом внося изменения в действующий проект. А по завершению новой темы, смерджить и всё будет как надо. Уж за плюсы гита рассказывать думаю совершенно лишено смысла. Но вот в контексте Drupal, я им деплою конфигурации, кастомные модули, темы, composer.lock\json и возможно ещё чего по мелочи.

В качестве репозитория последние месяца 2-3 использую GitLab. Перешел на них с Bitbucket, понравилось, в принципе и не дергаюсь. А так, разницы, на самом деле, для своего процесса я не заметил.

Деплой я произвожу используя SSH ключи. Для того чтобы постоянно не вводить пароли, что неимоверно ускоряет процесс деплоя и внедрения.

А сам процесс деплоя состоит из следующих шагов:

  1. (локалка) На локалке, экспортирую актуальные конфиги drush cex -y.
  2. (локалка) Добавляю все изменения и пишу коммит git add -A, git commit -m "Some changes was made.".
  3. (локалка) Отправляю изменения в репо git push.
  4. (сервер) Захожу на сервер по SSH и в папку проекта. Забираю все изменения с репозитория git fetch && git pull (можно просто git pull)/
  5. (сервер) Если вижу что изменился composer.lock (ставил новые зависимости\обновлял существующие). Тогда пишу composer install.
  6. (сервер) Если были изменения в конфигурациях, то drush cim -y. Обратите внимание что влив конфигов должен быть после пункта 5.
  7. (сервер) В некоторых случаях, например при больших изменениях в теме, сбрасываю кэш drush cr. Как правило это не требуется, изменения применяются сразу.

Может вам покажется что это сложно и замороченно. Но просто гляньте видео где я это всё делаю попутно болтая (отвлекаясь), и все равно это смело укладывается в 1 минуту, а то и меньше. В идеале ещё можно вебхуки и чтобы сервак сам делал всё что начинается с пункта 4, но пока особой надобности у меня в этом нет.

Как использую composer? Composer у меня отвечает за все возможные зависимости, ядро друпала, модули, темы, сторонние зависимости, включая JS библиотеки. А также патчинг модулей. У меня есть про него отдельный материал, так что особо тут разжевывать и нечего.

Но добавлю, что все зависимости я устанавливаю на локалке. В репозитории у меня всегда имеется composer.json и composer.lock (!). Я их деплою через git. Но на продакшене и прочих версиях сайта, я выполняю только composer install (он устанавливает зависимости из .lock файла). Это не жрет так много памяти как require, даже на самом говеном хостинге все установится, да и сам процесс установки будет кратно быстрее, так как он устанавливает из уже распарсенных версий и не запрашивает все репозитории. Также, это защищает от того, что версии на продакшене и локалке могут разойтись. Ставятся те, что поставили в момент установки на локалке. Собственно и обновляю я также, сначала на локалке, деплою изменения через git, вливаю их через composer install. И это ещё один плюсик в копилку локалки, ловили memory exceeded в момент запроса на сервачке? А вот с composer install не будет.

Почему composer drupal project? В качестве установки ядра я не использую стандартный способ. Все за и против я собрал в отдельном материале про два варианта установки ядра Drupal 8.

Я все веду через composer, что он позволяет вести, конечно ;)

Жизненный цикл у проекта

Тут тоже особо расписывать нечего. Но в контексте вышесказанного, это происходит следующим образом:

  1. Разворачиваю локальный сервер на Docker4Drupal.
  2. Устанавливаю ядро через composer drupal project. И сразу устанавливаю Drupal.
  3. Создаю репозиторий для проекта на gitlab, инициализирую репозиторий, и сразу же сливаю с конфигами после установки.
  4. На первых этапах проекта вся работа ведется на локалке, до тех пор, пока клиент не попросит показать, или не будет что-то уже более-менее готов для просмотра, например какой-нибудь калькулятор или ещё чего. Как правило, первую выгрузку делаю в момент начала верстки. Тут уже, как правило, основная часть функционала готова, и видно визуально как ведется работа над проектом.
  5. Практически до самой выгрузки сайта, в большинстве случаев я делаю коммиты в репозиторий в конце рабочего дня (над проектом), одним большим коммитом с комментарием "WIP" (Work In Progress). Так как на начальных этапах слишком много изменений, и документировать всё, как по мне — пустая трата времени, лишенная смысла. Но если разработчиков несколько, то я бы уже комментировал.
  6. Под конец я уже начинаю коммитить одним большим коммитом, но коммит содержит сводку изменений. Если же разработчиков по такому подходу будет работать более 1, то лучше коммит дробить на мелкие по задачкам. Так будет проще мерджить и решать конфликты в случае чего.
  7. Мелкие изменения, всегда делаю отдельным коммитом с осмысленным комментарием.
  8. Обновление ядра и модулей, аналогично, всегда отдельным коммитом. Правки с обновлениями стараюсь не мешать. На начальных этапах иногда такое получается из-за установки множества зависимостей, но именно обновления ядра и контриба после релиза или перед ним, всегда отделяю.
  9. БД, до тех пор, пока клиент не захочет начать работать над сайтом, периодически выгружаю с локалки затерая версию на деве\стейдже. Так, у клиента есть возможность поиграться с сайтом, сломать его, в общем оторваться по полной, не опасаясь что будут последствия.
  10. После выгрузки проекта и запуска его, работать продолжаю на локалке, деплой через git + composer + конфиги. Никаких перезаливов БД, естественно, нет. Как и проблем ?
  11. Никакие изменения (кроме очень важных хотфиксов), на продакшене не делаю. Никаких новых модулей и т.д. Переодически сливаю оттуда только конфиги. Например от какого-нибудь robotstxt модуля, где его настройки правятся SEO спецами, и мне надо чтобы конфиги были актуальны и не перетерали их изменения моими старыми. Для этого, я сливаю их кадый день перед началом работы проекта. Если же изменений небыло, то просто сразу начинаю работу на локалке. Это видно при вводе drush cex -y, который напишет что изменилось что-то в конфигах, или они до сих пор актуальны (с тем что были задеплоины гитом в прошлый раз).
  12. Если над проектом работа прекращается или крайне редкая, я либо дропаю контейнеры с проектом и оставляю только кодовую базу, либо вообще удаляю всё с локалки. А когда потребуется разворачиваю за пару минут, так как в репозитории находятся также файлы настроек docker для локалки. И все что мне нужно, создать папку под проекта, git clone REPO ., docker-compose up -d, composer install. Залить БД с продакшена, и всё готово к работе.

В принципе вот и всё. Даже не знаю, как о таком писать и что тут рассказывать. Поэтому, можете посмотреть видео, там я это показал наглядно. ?‍♂️ Ничего необычного тут не должно быть, всё очень даже стандартно, как по мне. Да я даже блог так веду, на продакшене только контент, всё изменения на локалке.

Drupal
Drupal 8

Комментарии

iamdroid   вт, 03/07/2018 - 12:46

Спасибо, классная статья и видео. Подумываю о внедрении этого процесса на нескольких проектах.
Однако есть ряд довольно обычных практик, которые пока не понятно как лучше наложить на эту схему. Хотел уточнить как вы с этим обходитесь. Предположим деплой происходит не реже 2 раз в неделю. На боевом сайте не должны быть включены и установленны технические модули типа devel, а не локальном должны быть отключены кеши и всякие advagg. Как можно автоматизировать синхронизацию конфигураций в этом случае? Еще часто в проекте для локальной среды нужны дополнительные файлы, типа settings.local.php, где их лучше хранить, в git или все же нужно дополнительное место для файлов помимо репозитория?

Niklan   вт, 03/07/2018 - 13:14

На боевом сайте не должны быть включены и установленны технические модули типа devel, а не локальном должны быть отключены кеши и всякие advagg. Как можно автоматизировать синхронизацию конфигураций в этом случае?

Configuration Split — я ещё не добрался до него, так как не критично. Но он именно для этого и создан. Он с пинка не заведется, придется покурить мануалы. Ничего сложного там быть не должно.

Еще часто в проекте для локальной среды нужны дополнительные файлы, типа settings.local.php, где их лучше хранить, в git или все же нужно дополнительное место для файлов помимо репозитория?

По умолчанию в composer drupal project settings.local.php заблокирован на добавление в репозиторий. Если будет удобнее, думаю, никаких проблем добавить его туда нет. Единственное, если только разработчиков больше 1, то каждому может потребоваться собственная настройка данного файла. А таким подходом они будут перезаписывать друг у друга. Создать такой файлик крайне быстро и просто, он же просто копируется из example.settings.local.php. Если на проекте много кастомных настроек для данного файла, думаю проще добавить аналогичный файл-пример, для копипаста в /sites/default или же, создать settings.local.php, не убирая его из .gitginore, но добавив его туда единожды через git add -f path/to/settings.local.php. Так он будет в репозитории, но его изменения на любом окружении не будут переноситься.

Даже если такой файл попадет в репо, не вижу проблем. Он же не заработает до тех пор, пока не расскоментировать в settings.php:

# if (file_exists($app_root . '/' . $site_path . '/settings.local.php')) {
#   include $app_root . '/' . $site_path . '/settings.local.php';
# }

А на продакшене по любому это закомментировано, а settings.php в репо, аналогично нет. Поэтому файл просто не загрузится, и никакие кэши не отключатся и дебаги не включатся.

Вадим   вт, 03/07/2018 - 18:25

Как добавить публичный ключ только для репозитория GitLab? Попробовал сделать это в "Deploy Keys", но при попытке git pull/push консоль все равно запрашивает логин/пароль.

Niklan   ср, 04/07/2018 - 06:28

Внесу ясности.

На локалке у меня сгенерирован публичный ключ используя мой пароль. Он добавлен в профиль на GitLab а также на сервер, чтобы я мог входить на него без пароля. Но ключи постоянно просят пароли, то есть просто так это лишь позволяет заходить под паролем ключа, а не настоящим паролем юзера. Это, естественно, особо погоды не меняет. Для этого есть пара команд, которые позволяют ввести пароль в активном терминале один раз, и до тех пор пока он не закрыт, там пароль для ключа спрашиваться не будет.

Для этого я в конфиг файл своего шела добавил функцию с алиасом:

addSshKey() {
  eval "$(ssh-agent -s)"
  ssh-add ~/.ssh/id_rsa
}
alias ssh-no-pass="addSshKey"

Когда у меня стартует ПК и я начинаю работать, я просто в любой момент в шеле ввожу ssh-no-pass, ввожу пароль от ключа, и всё. Больше он просить не будет, ни на ssh, ни на git. Будет сразу заходить и команды выполняться без подтверждения пароля.

На сервере я генерирую ключ без пароля, просто в момент генерации ключа, когда просится ввести passphrase я жму enter. И ключ юзера с сервера где сайт, добавляю в репозиторий. И это также, из-за того что нет пароля, позволяет пушить и пулить без запросов.

Но если на продакшене это ещё не так страшно и можно на пуш сделать запрет. То на локалке ключи без паролей очень плохая затея. Так как ключ может отвечать не только за 1 репозиторий сайта, да ещё и ограниченного доступа. А различные ssh авторизации, все репозитории какие есть, включая запись, если это аккаунт владельца или есть соответствующие права. Лучше добавить алиас. 1 раз в сутки ввести не проблема :)

Sega   пт, 06/07/2018 - 12:48

Отличная статья! Вопрос по Drush, может не сюда пишу, но все же. drupal-composer/drupal-project добавляет локальный drush в проект. Не пойму как его правильно использовать. Писать алиас типа drush71='/php/php71/bin/php ../vendor/drush/drush/drush', не могу найти документацию... С алиасом большинство команд работают, но при попытке сделать drush71 updatedb выкатывается ошибка "The command could not be executed successfully (returned: PHP Fatal error: Default value for parameters with a class type hint can only be NULL in /home/.../public_html/vendor/symfony/var-dumper/Dumper/CliDumper.php on line 61 , code: 255)". Не сталкивался с такой проблемой? )

Заранее спасибо! )

Niklan   пт, 06/07/2018 - 12:56

drupal-composer/drupal-project добавляет локальный drush в проект

В реалиях Drupal 8 это правильно. Драш должен устанавливаться с проектом (крайне желательно).

Для такого подхода есть Drush Launcher который ставится вместо /usr/local/bin/drush или там где стоит старый drush или ставился раньше. То есть Drush Launcher ставится глобально "как" Drush. А затем вызывая его, он ищет Drush в во всех возможных местах проекта и вызывает его. Так становится не важно какая структура у проекта, откуда вызвана команда, и какой там версии драш. Это просто небольшой скриптик ищущий бинарник. Для старых версий я ставлю composer global require drush/drush:7. И у Drush Luancher есть возможность указать фолбек export DRUSH_LAUNCHER_FALLBACK=~/.config/composer/vendor/bin/drush.

В общем у них есть вся инструкция. Там всё просто. ;) Главное понять что Drush Launcher ставится глобально под командой драша, а внутри там просто скрипт ищущий драш по различным папкам, и если не нашел, вызывает фолбек драш (для Drupal 7, у 8-ок он находит драш куда его не засунь).

Sega   вс, 08/07/2018 - 10:04

Вопрос начинающего git пользователя ) Я добавил тему с помощью composer require drupal/theme Запушил изменения. Затем сделал git pull на сервере, composer install, drush cim -y. Все работает как надо.

А теперь я решил отменить эти изменения, т.е. откатиться к коммиту до установки темы. Гугл выдает несколько вариантов отката: checkout commit, reset --hard commit, revert commit. Вот я в них что-то и запутался ) Какой способ наиболее предпочтителен в моем случае?

Заранее спасибо!

Niklan   вс, 08/07/2018 - 14:33

Я не откатываю, так как не приходится. Но вариантов, да, несколько и все зависит от задачи.

Я так понимаю что git checkout [hash] . это самый оптимальный способ. Я бы это делал аккуратно, заранее запушил текущий вариант в удаленный репозиторий и пробовал откатить локально. И если только получилось, пушить в удаленный. revert походу лучше, но у него есть какие-то недостатки. Думаю для приватного репо это не критично будет.

Как уже сказал, не приходится пользоваться, поэтому я тут не подскажу более точно. Как по мне. В данной ситуации проще отключить и удалить нужную тему, и сделать новый коммит и запушить. Так куда естественнее. Откаты имеют смысл только при больших изменениях или на очень дальнее изменение.

Sergey   вс, 15/07/2018 - 17:42

Спасибо за статью и видео, разъяснил для себя некоторые моменты с конфигами. Кстати, можно было ещё немного времени съэкономить и поставить друпал командой - drush si standard --db-url=mysql://drupal:drupal@mariadb/drupal --account-name=admin --account-pass=admin -y --site-name=Drupal8

Roman   чт, 19/07/2018 - 23:38

Никита, подскажи как переводы переносить при деплои на стейдж.

Андрей   чт, 31/01/2019 - 17:04

Никита, будет время напиши, пожалуйста, что для тебя явилось решающим для переезда с bitbucket на gitlab, кроме того, что drupal.org туда тоже засобирался..

Niklan   пт, 01/02/2019 - 06:57

Ну мне битбакет в принципе не особо нравился. Он не очень удобный, как по мне, плюс в последнее время что я им пользовался он часто в даунтайм уходил.

Гитлаб больше понравился, плюс больше умеет. Можно посмотреть сюда например или прямое сравнение GitLab vs Bitbucket.

Но всё это ерунда, пока не попробуешь GitLab CI, аналогов которому у других просто нету, и надо покупать платные сервисы, когда у гитлаба он бесплатный и можно ставить куда угодно. GitLab CI просто убивает все плюсы любого другого хостинга кода, особенно для закрытых проектов. Когда за тебя с локалки деплоят изменения, это мега-удобно и имеется лог и статус прямо на гитлабе о всех деплоях.

Андрей   пт, 01/02/2019 - 11:29

Для CI я смотрел в сторону CircleCI, теперь задумался.. Спасибо, брат!

Андрей   вт, 12/02/2019 - 16:02

Никита, ещё вопрос - как ты переносишь изменения в меню с локалки на хост?

Niklan   ср, 13/02/2019 - 12:53

Ручками. Если что-то серьезное потребуется, напишу hook_update_N().

ailo   пн, 01/07/2019 - 13:30

Привет. при импорте конфигурационных файлов, а конкретно при выполнении команды "drush cim -y" выяснил что у меня этой команда нет выходит сообщение "Command cim was not found", а при выводе списка команд "drush list" выводиться урезанное количество команд, в чем может быть проблема? подскажите пожалуйста

Niklan   чт, 04/07/2019 - 10:12

Уверены? Что выводит drush --version? Какое окружение? Если есть возможность, лучше в чатик (под статьей левая кнопка) заскочить ненадолго, быстрее дело сдвинется. Ибо нужно больше информации.

Как вариант, попробуйте ещё использовать команду без алиаса drush config:import.

ikode   пт, 02/08/2019 - 12:33

Какая же красота! Сейчас работаю над реальным проектом и вижу всю красоту этой связки composer + drush + git! Спасибо! Без вас бы еще очень долго бы до этого доходил :)

ikode   пт, 11/10/2019 - 05:01

В дополнение темы. Какие изменения переносятся системой контроля версий в друпале: http://ikode.ru/articles/kakie-izmeneniya-perenosyatsya-sistemoy-kontrolya-versiy-v-drupale Может кому будет полезно. Не сочтите за спам.

Savage   пт, 27/03/2020 - 13:32

Никита, спасибо за гайд! Вопрос по друпал 7 - что-то аналогичное для него есть? После такого изящного процесса морально тяжело возвращаться к семерке.

Дмитрий   сб, 06/03/2021 - 12:33

Никита приветствую! Жизненный цикл проекта не заканчивается же после загрузки его на продакшен и пердачи его клиенту. Это скорее только начало. Ведь сайт необходимо потом обновлять, что-то дорабатывать, изменять. Не каждый же готов разбираться с гитом, композером и тд. Как у тебя строится дальнейшее взаимодествие с клиентом?

Niklan   сб, 06/03/2021 - 17:38

У меня постоянные клиенты. Я обновляю проект каждый раз как сажусь работать с ним. Если я вношу правки раз в неделю, значит он обновляется раз в неделю.

Если с проектом давно не работал, как правило раз в месяц обновляется проект, просто чтобы быть в тонусе. Если никаких серьезных релизов безопасности не было, можно в принципе вообще раз в полгода обновляться на минорные релизы. Если в патч релизах нет ничего полезного для проекта, можно тоже пропускать. Главное не копить минорные релизы.

Всё же предсказуемо, в плане релизов:

  • Новые релизы каждую первую среду месяца.
  • Релизы безопасности (если появились), в третью среду месяца.
  • Минорные релизы раз в полгода.

В общем, даже с одними клиентами, разные сайты поддерживаются по разному. Но минорные у всех, кому не пофиг на свой сайт, всегда в актуальном состоянии.

alan   пн, 05/09/2022 - 11:19

Спасибо за статью и видео! Пробую разобраться в composer + git и сталкиваюсь с проблемой, решение которой в инете найти не смог. Все получается до момента первой заливки проекта с git на хостинг. Проект заливается. При вводе команды `composer install` ничего не происходит (Nothing to install, update or remove)
![Image](http://joxi.ru/8230oV7UzEVqlA)
Такая же проблема присутствует, если залить проект на локалку и попробовать его развернуть.
Подскажите, пожалуйста, как решить эту проблему?

Гермиона Грейнджер   чт, 03/08/2023 - 09:52

Статья актуальна на сегодняшний день? Можно ее использовать как руководство?

Niklan   пн, 07/08/2023 - 16:01

В общих чертах да, ничего не поменялось. Это базовая концепция деплоя в принципе. А дальше каждый под себя корректирует.