Мы начали с одного разработчика и одного репозитория SVN, содержащего весь наш код:
^/foo/trunk/module-a
^/foo/trunk/module-b
^/foo/trunk/module-b/submodule-b1
^/foo/trunk/website1
(в то время это было большое улучшение). После того, как у этого появился шанс немного подрасти, у нас начались проблемы с циклическими зависимостями, медленными тестовыми наборами и общими трудностями при повторном использовании кода (поскольку, например, набор функций website1 попал в общий модуль-a).
Желая модулировать кодовую базу и ожидая, что мы вскоре перейдем к git (и прочитав где-то, что git не любит svn mega-repos), мы перешли к гораздо более детальной структуре:
^/module-a/trunk/
^/module-b/trunk/
^/module-b/trunk/sumbmodule-b1
^/earlier-sub-sub-sub-module-c/trunk
etc. (about 120 such modules)
Это было концептуально здорово. Более модульный код, намного более быстрые тестовые наборы, более легкое документирование и т. Д. Мы открыли некоторые из наших более общих компонентов и сделали все модули готовыми к установке (используя их pip install -e .
для установки в development
virtualenv).
Мы создали ^/srv/trunk
репозиторий, содержащий структуру папок среды выполнения, т.е. ^/srv/trunk/lib
для модулей, /srv/trunk/src
для остатков ^/foo/trunk
, ^/srv/trunk/www
для веб-сайтов и т. д.
И наконец (взяв идею из перформанса, с которым я работал очень давно [ https://www.perforce.com/perforce/r12.1/manuals/cmdref/client.html] ), мы создали «vcs- «Получить текстовый файл», в котором перечислены все соответствующие репозитории и где их следует извлечь в среду разработки, и соответствующую команду для этого. Например, строка vcs-fetc:
svn srv/lib/module-a ^/module-a/trunk
вызовет либо (первый раз)
cd /srv/lib && svn co ^/module-a/trunk module-a
или (потом)
cd /srv/lib/module-a && svn up
и аналогично для репозиториев github (как наших собственных, так и измененных / неизмененных пакетов поставщиков).
Мы использовали тот же процесс vcs-fetch для создания производственной среды, но мы быстро обнаруживаем, что у нас нет способа узнать, какая версия использовалась в prod после выполнения vcs-fetch.
С мега-репо мы могли просто записать номер ревизии, прежде чем обновлять prod из транка, и вернуться назад было просто svn -r nnn up .
. С кодом как в SVN, так и в Git (и один модуль в HG) - и ~ 120 репозиториев, не очевидно, как это сделать ..
Сегодня я читаю http://12factor.net/ , и первый фактор - это «Одна кодовая база», поэтому мне также интересно, ухожу ли я с правильного пути?
У меня была одна идея - создать сценарий развертывания, который бы создавал pip-устанавливаемые колеса «развертывания» и «связывал» их вместе в requirements.txt
файл. Развертывание будет включать создание нового virtualenv, установку pip-файла require.txt со списком колес развертывания и переключение активного virtualenv. Возврат к предыдущему будет просто включать переключение virtualenv обратно (но если мы не хотим вечно хранить virtualenvs, это не позволит нам вернуться к любому моменту времени - в моем опыте, который никогда не был необходим).
В этот момент мне интересно, иду ли я в неправильном направлении, или я просто недостаточно далеко зашел по правильному пути? (все, что я читаю, говорит о «вашем приложении», и я не знаю, как это приводит к запуску 14 сайтов с одной и той же кодовой базой ...)
источник
Ответы:
Похоже, вы пропустили ветви (или, скорее, «теги» или «выпустить» ветви).
Вместо того, чтобы использовать ваш SVN revnum в качестве справочного материала для определения, какую версию вы устанавливаете, вы должны создать ветку с этой выпущенной ревизией. Затем вы развернете имя этой ветви.
Это упрощает ветвление, даже если нет никаких изменений, поэтому каждый модуль сохраняет один и тот же номер выпуска, однако вашим пакетам OSS может не понравиться ветвление без изменений, поэтому следующая лучшая вещь - сохранить скрипт зависимостей - так, версия 5 вашего продукта требует OSS модуль X v2 и так далее.
Вы изменили бы свой сценарий, чтобы перестать ссылаться на версии и вместо этого работать с именами веток (хотя они могут быть любыми, лучше выбрать фиксированное соглашение об именах, например Release_1_2_3)
Другой совет - поддерживать файл с каждым модулем, описывающим текущую версию, вы можете автоматически сгенерировать их при необходимости и, возможно, включить полный журнал изменений, но это означает, что любой может увидеть, какая версия развернута, просто просмотрев.
источник
Я думаю, что у вас уже есть много хороших идей, я использовал большинство из них в различных проектах на протяжении многих лет, и вашей главной заботой, кажется, была неспособность сказать, какая версия всех модулей включена в данный пакет, если вы разбили их вверх.
Я все за то, чтобы разделить их на некотором уровне детализации, особенно если у вас несколько команд и разные циклы выпуска, как упоминает @ Ext3h.
Поскольку я не уверен, насколько изолированы ваши модули или насколько подробно вы хотите, чтобы ваше управление версиями было, я предложу несколько вариантов.
Используйте подмодули git. С помощью субмодулей вы можете хранить каждый модуль в отдельном git-репо, аналогично настройке svn, а также тому, о чем вы думаете. Затем вы связываете эти модули с корневым проектом, который будет содержать ссылку на соответствующий коммит каждого подмодуля, для каждого из его собственных коммитов.
ИМО, это теоретически хорошая настройка и достаточно простая. Основными недостатками являются то, что рабочий процесс для подмодулей немного неуклюжий, однако вы, кажется, уже хорошо решали такие вещи с помощью сценариев, поэтому это может быть не реальной проблемой.
Другим предостережением является то, что ссылки коммита подмодуля будут просто SHA1, никогда не будет никаких читабельных подробностей о том, какая вы ветвь, и вам может понадобиться вручную извлекать нужную ветку, когда вы захотите выполнить работу непосредственно в подмодуле.
Однако я не использовал этот шаблон широко, поэтому я не знаю, насколько серьезной может быть проблема для такого крупного проекта, как ваш.
Другой альтернативой является использование своего рода менеджера зависимостей. Для этого требуется, чтобы каждый модуль или набор модулей можно было создавать, упаковывать и публиковать по отдельности, а также чтобы у вас была система, которая может объединять эти пакеты так, как вы хотите, когда вы этого хотите.
Вы уже предлагаете pip, и что, по-видимому, отсутствует в вашем предложении, это сохранение результирующего файла require.txt вместе со сборкой или в репозитории корневого проекта, чтобы вы могли заново создать virtualenv позже, а не сохранять это на диске.
Есть и другие системы; Я создал довольно большой проект, используя слегка настроенную версию Apache Ivy как инструмент для упаковки и публикации каждого модуля, а также собрал их вместе для окончательного проекта. Ivy также хранит манифест со списком всех версий всех модулей, на которые вы ссылаетесь, если вам потребуется заново создать настройку позже.
источник