Структура Mercurial Repository с мощными корпоративными коммуникациями, управлением конфигурацией и требованиями к тестированию

16

Я - еще один пользователь Subversion, пытающийся переучиться на Дао распределенного контроля версий.

Когда я использовал Subversion, я был большим поклонником подхода с незначительными проектами, и, с большинством моих бывших работодателей, мы структурировали наши филиалы репозитория; теги и багажник следующим образом:

branches-+
         +-personal-+
         |          +-alice-+
         |          |       +-shinyNewFeature
         |          |       +-AUTOMATED-+
         |          |                   +-shinyNewFeature
         |          +-bob-+
         |                +-AUTOMATED-+
         |                            +-bespokeCustomerProject
         +-project-+
                   +-shinyNewFeature
                   +-fixStinkyBug
tags-+
     +-m20110401_releaseCandidate_0_1
     +-m20110505_release_0_1
     +-m20110602_milestone
trunk

В самом фактическом исходном дереве мы будем использовать (что-то вроде) следующую структуру:

  (src)-+
        +-developmentAutomation-+
        |                       +-testAutomation
        |                       +-deploymentAutomation
        |                       +-docGeneration
        |                       +-staticAnalysis
        |                       +-systemTest
        |                       +-performanceMeasurement
        |                       +-configurationManagement
        |                       +-utilities
        +-libraries-+
        |           +-log-+
        |           |     +-build
        |           |     +-doc
        |           |     +-test
        |           +-statistics-+
        |           |            +-build
        |           |            +-doc
        |           |            +-test
        |           +-charting-+
        |           |          +-build
        |           |          +-doc
        |           |          +-test
        |           +-distributedComputing-+
        |           |                      +-build
        |           |                      +-doc
        |           |                      +-test
        |           +-widgets-+
        |                     +-build
        |                     +-doc
        |                     +-test
        +-productLines-+
        |              +-flagshipProduct-+
        |              |                 +-coolFeature
        |              |                 +-anotherCoolFeature
        |              |                 +-build
        |              |                 +-doc
        |              |                 +-test
        |              +-coolNewProduct
        +-project-+
                  +-bigImportantCustomer-+
                  |                      +-bespokeProjectOne
                  |                      +-bespokeProjectTwo
                  +-anotherImportantCustomer-+
                                             +-anotherBespokeProject

Идея состояла в том, чтобы (и все еще остается) использовать структуру хранилища, чтобы помочь структурировать взаимодействие между командой разработчиков; ориентированная на клиента часть бизнеса и различные другие заинтересованные стороны и эксперты в данной области.

То есть: исходные документы, которые находятся в одном из каталогов «проекта», используются (и зарабатывают деньги) только один раз. Документы, которые находятся в одном из каталогов «productLines», зарабатывают столько раз, сколько продается продукт из этой конкретной линии. Документы, которые находятся в одном из «библиотечных» каталогов, зарабатывают столько раз, сколько продается любой из продуктов, которые их используют.

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

Это также означает, что существует общая структура, над которой могут работать наши инструменты автоматизации сборки. (Наши сценарии компоновки обходят дерево исходных текстов в поисках папок «компоновки», в которых они находят файлы конфигурации, определяющие, как должен создаваться каждый компонент; аналогичный процесс происходит для генерации и тестирования документации).

Важно отметить, что для продуктов, над которыми я работаю, обычно требуется ДЛИННОЕ время для проведения тестов измерения и характеристики производительности; от 20 до 200 часов; генерирование от нескольких ГБ до нескольких ТБ обработанных результатов испытаний / промежуточных данных (которые должны храниться и привязываться к конкретной конфигурации системы, чтобы можно было измерить улучшение производительности во времени). Эта проблема делает управление конфигурацией важным фактором, а также предъявляет некоторые требования к централизации, поскольку обычно вычислительные ресурсы, необходимые для выполнения измерений производительности и тестов характеристик, ограничены; (небольшой кластер из 64-128 ядер).

В качестве одного последнего замечания; система непрерывной интеграции знает, что она должна инициировать сборку; статический анализ; Тест дыма и модульный тест запускаются каждый раз, когда ствол изменяется, каждый раз, когда изменяется любая ветка «tag», и каждый раз, когда изменяется любая ветка «AUTOMATED». Таким образом, отдельные разработчики могут использовать систему CI со своими персональными ветвями, что является важной возможностью, IMHO.

Теперь мой вопрос: как я могу воспроизвести все вышеперечисленное (и улучшить его, если это возможно) с Mercurial.

--редактировать:

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

Уильям Пейн
источник
1
Вау. Думаю, хорошим ответом на это будет очень длинное эссе.
Эд Джеймс
Я думаю, что ключевой вопрос заключается в том, как и где происходит слияние кода, поскольку это, вероятно, определит путь наименьшего сопротивления. Итак, как код сливается?
Уайетт Барнетт
Как правило, слияние может происходить из личной ветви в ветку проекта или компонента, а затем в транк. Я никогда не испытывал слишком много трудностей со слияниями (мы использовали TortoiseSVN на Win32), хотя мы никогда не работали слишком долго (максимум одна итерация) без интеграции обратно в транк. В любом случае, мы, как правило, выполняли большую часть нашей работы в транке, хотя цель состояла в том, чтобы упростить управление людьми, а не процесс разработки. (Один ведущий разработчик, много независимо работающих разработчиков, поэтому наличие всего в стволе облегчало отслеживание происходящего.)
Уильям Пейн
Одним из ключевых моментов была сильная зависимость от тестирования, проводимого системой CI, особенно на уровне системных тестов. Это должно было помочь укрепить уверенность в том, что разные разработчики не мешают друг другу, и продвинуть менталитет с множеством маленьких итераций. (Кроме того, вычислительная нагрузка, необходимая для запуска системных тестов, означала, что было меньше конкуренции за вычислительные ресурсы, если люди работали в основном на транке).
Уильям Пейн

Ответы:

10

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

Филиальная организация

С Mercurial вы можете счастливо игнорировать всю вашу первую организационную структуру. Как говорит Спок, каждый репозиторий имеет свой собственный набор тегов, ветвей (именованных и анонимных) и может быть организован в соответствии с потребностями бизнеса.

Если вам bespokeProjectTwoнужна специальная версия chartingбиблиотеки, то вы должны перейти charting, добавить новые средства и использовать ее в bespokeProjectTwo. Новые средства (и их ошибки) не будут использоваться другими проектами, которые будут ссылаться на стандартную chartingбиблиотеку. Если в основной chartingбиблиотеке исправлены ошибки, вы можете объединить эти изменения в ветке. Если другие проекты также нуждались в этих средствах, вы можете либо заставить эти проекты использовать специальную ветку, либо объединить ветку в основную линию и закрыть ветку.

Кроме того, ничто не мешает вам иметь политику структурирования имен веток для предоставления определенных средств, таких как ветки AUTOMATION.

Справочная организация

Нет никаких причин, по которым вы не можете хранить исходный каталог в точности так же, как в Mercurial. Единственное отличие состоит в том, что тогда как в Subversion у вас есть один монолитный (src)репозиторий, в Mercurial лучше разбить на репозитории, которые логически сгруппированы. Из вашей исходной древовидной структуры я бы, вероятно, выделил каждое из следующих в качестве отдельных репозиториев:

src-+
      +-(developmentAutomation)
      +-libraries-+
      |           +-(log)
      |           +-(statistics)
      |           +-(charting)
      |           +-(distributedComputing)
      |           +-(widgets)
      +-productLines-+
      |              +-(flagshipProduct)
      |              +-(coolNewProduct)
      +-project-+
                +-bigImportantCustomer-+
                |                      +-(bespokeProjectOne)
                |                      +-(bespokeProjectTwo)
                +-anotherImportantCustomer-+
                                           +-(anotherBespokeProject)

Это позволяет любому продукту или заказному проекту использовать любую комбинацию библиотек в любой редакции. Посмотрите на mercurial sub-repositories для простого способа управлять тем, какие библиотеки используются для любой данной версии продукта или проекта.

Workflow

Альтернативой предлагаемому рабочему процессу Spoike (разработчик извлекает данные из благословенного репо, работает локально, выдает запрос на извлечение и, наконец, интегратор извлекает эти изменения и объединяет их) было бы использование системы непрерывной интеграции в качестве посредника.

Как и прежде, разработчик извлекает из благословенного репо и работает локально, но когда он закончил, он снова извлекает из благословенного репо и объединяется, прежде чем перейти в необъявленное репо. Любые изменения в неподтвержденном репо затем проверяются (либо вручную, либо автоматически) и перемещаются в благословенное репо, только если они одобрены.

Это означает, что интегратор должен только принять или отклонить изменение, но не выполнять слияние. По моему опыту, для разработчика, написавшего код, почти всегда лучше выполнить слияние, чем для кого-то другого.

Как предлагается в ртутной книге, для автоматизации этой процедуры могут использоваться хуки :

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

Другие вопросы

Проблема больших наборов тестовых данных также может быть решена путем помещения этих тестовых данных в ртутный суб-репозиторий . Это предотвратит переполнение хранилища кода тестовыми данными, сохраняя тестовые данные под контролем версий.

Марк Бут
источник
Опять другой отличный и информативный ответ. Спасибо.
Уильям Пейн
RE: Филиальная организация. Я согласен, что первую организационную структуру можно с радостью игнорировать. Во всяком случае, он не очень хорошо отражал рабочий процесс и поэтому не давал никакой реальной полезности, кроме усиления соглашения. Однако я хотел бы заменить его чем-то, что решительно связывает (простой, насколько это возможно) рабочий процесс и поощряет частые коммиты. Возможно, так можно было бы назвать основную ветку «ствол / разработка» «ежедневно»?
Уильям Пейн
RE: Справочник организации. Я использовал исходную организацию каталогов как подсознательное средство общения; наложение неявной структуры на организацию кода (и через это на бизнес в целом). Я начинаю понимать, что Mercurial, как правило, используется очень и очень гибко; но я действительно хочу ограничить часть этой гибкости, чтобы навязать структуру того, как люди думают о бизнесе, навязывая структуру того, как их документы организованы на их рабочих станциях и в наших сетевых хранилищах. (Больше корпоративных коммуникаций, чем технологий.)
Уильям Пейн
RE: рабочий процесс. Я думаю, что самым простым рабочим процессом было бы извлечь из «ежедневного» хранилища, работать с ним локально, а затем (часто) вернуться к «ежедневному» хранилищу, начиная статический анализ, тесты дыма и регрессионные тесты через систему CI. Я рад, что основной репо будет «сломан», если я знаю об этом, и пока он быстро исправляется. Фактически, я рассматриваю возможность сделать коммит на «ежедневное» репо единственным способом, который можно скомпилировать и построить, чтобы поощрять частые коммиты и хорошее тестовое покрытие. (Гораздо важнее, чем умение работать в изоляции, ИМХО).
Уильям Пейн
@WilliamPayne - Спасибо. В то время как Mercurial является гибким, с соответствующими репозиториями, ветками и хуками вы можете встроить любые ограничения на уровне организации или хранилища. Лично я бы просто начал с организационных элементов управления и нескольких хуков CI и расширил бы эти элементы управления в будущем, когда их потребность станет очевидной. Кроме того, разумное использование суб-репо может, например, побудить людей проверять вещи локально в той же структуре, что и на сервере, например, имея productLinesили в bigImportantCustomerкачестве супер-репо.
Марк Бут
9

Хорошо, пытаюсь ответить на это просто.

Что тебе нужно знать

Первое, что вам нужно знать: Mercurial - это распределенный контроль версий и обладает некоторыми свойствами, о которых вам следует знать, перечисленными ниже.

  • Источник взят из одного репозитория, где этот репозиторий можно клонировать. Все клонированные репозитории могут обмениваться кодом друг с другом посредством синхронизации (с помощью команд pull и push, доступ к которым может быть ограничен).
  • Каждый пользователь, имеющий копию кода, имеет клон репозитория. Если они хотят разветвляться, они могут сделать это в своем локальном клоне. Это означает, что вам не нужно организовывать, как каждый пользователь должен переходить. Они могут сделать это для себя.
  • Теги создаются в Mercurial коммитом (что аналогично жестким тегам в git). Это означает, что вам не нужен каталог внутри структуры репозитория для тегов.
  • Обычная модель, с которой люди работают в DVCS (которая используется в github и bitbucket), состоит в том, чтобы сделать это полуцентрализованным.

    У каждого пользователя есть общедоступное хранилище (в некотором общем ресурсе или на защищенном сервере) и частное хранилище (на своих рабочих станциях). Оба они являются клонами «благословенного» хранилища интегратора. Всякий раз, когда они чувствуют, что готовы опубликовать свой код, они могут перенести изменения в свой общедоступный репозиторий. Интегратор может затем выбрать пользователей, которые будут загружать код в «благословенный» репозиторий.

    Если интегратор не может легко объединить код какого-либо пользователя, то изменения отклоняются, и этот конкретный пользователь может самостоятельно обновить свой репозиторий и исправить слияние. Обычно это не так сложно, если вы часто объединяетесь (поскольку требуется объединить меньше кода), и обычно этот пользователь должен знать, что пошло не так с объединением.

Настройка репозитория на проект

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

  • Публичный репозиторий только для чтения, за который отвечает интегратор. Это "благословенно".

    Т.е. все пользователи могут извлекать / извлекать контент, но не имеют доступа к нему.

  • Каждый пользователь может иметь свой собственный общедоступный клон репозитория.

    Легче всего установить его как общий диск (хотя вы можете рассмотреть хостинг, такой как bitbucket). Интегратор получает запросы от пользователей и пытается извлечь новый код из этих репозиториев. Когда слияния выполняются без помех, они помещаются в репозиторий только для чтения. Если нет, то пользователей просят исправить возникающие конфликты слияний, обновляя и объединяя их для себя локально.

  • Каждый пользователь может иметь свои собственные клоны хранилища.

    Хорошей практикой является отстранение от публичного клона, но не имеет значения, вытаскивают ли они публичное или интеграторское. Все коммиты являются уникально идентифицируемыми, поэтому слияние коммитов, которое вы забыли извлечь из публичного, относительно легко исправить (передавая изменения из частного в общедоступное, оно также автоматически получает изменения интегратора).

Организация исходного кода

Что касается того, как организовать сам исходный код проекта - это то, что вам нужно продумать. Если артефакт должен контролироваться источником, поместите его в контроль источника. Лично мне не нравится идея проверять артефакты, создаваемые сборкой или средой выполнения (из-за высокого риска конфликтов слияния на этих типах артефактов), такие как двоичные файлы или файлы журналов.

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

Вы упоминаете, что у вас есть тестовые данные, которые необходимо привязать к какой-либо версии кода. Теперь это немного сложнее, потому что DVCS-системы, такие как Mercurial и Git, имеют тенденцию замедляться, когда вы регистрируете данные, которые ОГРОМНЫ. По моему опыту, это становится действительно невыносимым после 5 ГБ двоичных файлов (ваш milage может отличаться, поэтому вы должны проверить, как это работает для вас). Однако я бы порекомендовал вам поместить сгенерированные данные в его собственный репозиторий и попросить тестовую систему соответствующим образом пометить их при регистрации (и / или создать текстовые файлы для тех же целей метаданных).

Я надеюсь, что все это имеет смысл. Пожалуйста, прокомментируйте ниже, если я пропустил некоторые детали или если что-то требует дальнейшего объяснения, и я постараюсь отредактировать.

Spoike
источник
+1 за очень хороший ответ с несколькими очень полезными пунктами. В ответ на первый раздел вашего ответа я не осознал значение каждого пользователя, имеющего свой публичный репозиторий. Возможно, мне нужно больше думать о том, как могут быть организованы одноранговые рабочие процессы.
Уильям Пейн
В ответ на второй раздел вашего ответа, весь смысл (на мой взгляд) наличия единого хранилища для всей организации заключается в создании общего ментального образа для структурирования работы и облегчения поиска компонентов, которые могут быть повторно использованы. (Очень похоже на собор, а не на базар, но это среда, в которой я работаю). Мне бы очень хотелось узнать, как добиться такого же чувства структурированной организации (системы регистрации) с DCVS.
Уильям Пейн
В ответ на третий раздел вашего ответа: я полностью согласен с тем, что система контроля версий предназначена для исходных документов, и производные артефакты там не принадлежат. Я также согласен с тем, что нецелесообразно хранить большие двоичные файлы любого описания в VCS. Однако я считаю, что вы можете хранить большие двоичные файлы в согласованном сетевом расположении с определенным именем и ссылаться на них из VCS. Например, среда (и) сборки может храниться как именованные образы дисков ВМ, и на них можно ссылаться из различных сценариев сборки. (например: построить меня на build_env_A). То же самое относится к тестовым данным.
Уильям Пейн
В прошлом я использовал иерархию каталогов на сетевом диске, где имена каталогов получены из номера ревизии subversion + хеша расположения ветвей, чтобы связать промежуточные файлы и результаты тестирования с конкретными ревизиями. Это означает, что у нас есть прослеживаемость без необходимости хранить производные файлы в управлении версиями.
Уильям Пейн