Это хорошая практика для хранения номеров версий программного обеспечения в VCS?

22

Версия продукта, например v1.0.0.100, представляет собой не только уникальный производственный выпуск программного обеспечения, но и помогает определить наборы функций и этапы исправлений для указанного продукта. Прямо сейчас я вижу два способа поддержки окончательной версии пакета / сборки / двоичной версии продукта:

  1. Контроль версий. Файл где-то хранит номер версии. На сервере сборки Continuous Integration (CI) будет создан сценарий для сборки программного обеспечения, использующего этот зарегистрированный номер версии, чтобы применить его ко всем областям необходимого программного обеспечения (двоичные файлы, пакеты установщика, страницы справки, документация и т. Д.).

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

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

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

В обоих случаях могут быть определенные аспекты номера версии, которые не были известны до сборки CI. Например, сборка CI может программно поместить 4-й компонент, который на самом деле является автоматическим номером сборки (например, 140-й сборкой на ветви). Это также может быть номер редакции в VCS.

Каков наилучший способ узнать номер версии программного обеспечения? Должны ли "известные" детали всегда поддерживаться в VCS? И если да, то являются ли конфликты между основными ветвями проблемой?

Прямо сейчас мы поддерживаем наш номер версии с помощью параметров, указанных и поддерживаемых в плане сборки CI (Atlassian Bamboo). Перед слиянием с нашей masterветкой мы должны быть осторожны, чтобы номера версий были правильно установлены до начала сборки CI . Что касается рабочего процесса Gitflow, я чувствую, что если бы номер версии отслеживался в управлении исходным кодом, мы могли бы гарантировать, что он настроен правильно, когда мы создаем нашу releaseветку при подготовке к выпуску. QA будет выполнять окончательное интеграционное / дымовое / регрессионное тестирование в этой ветви, и после подписания происходит слияние, masterкоторое сигнализирует о приверженности к выпуску.

void.pointer
источник
3
Трудно ли разрешить конфликт слияния двух версий файла, в version.txtкотором одна версия содержит одну строку, 1.0.7а другую - 1.2.0трудно? Если это единственный конфликт в слиянии двух ветвей, я бы посчитал себя счастливчиком. Как часто это происходит? Если это происходит, разве не стоит задуматься о том, какой номер версии должна иметь объединенная версия? (Извините за неоднозначное использование слова «версия».)
5gon12eder
1
@ 5gon12eder Трудности или чувства по поводу самого слияния не имеют значения. Это просто негативный аспект общего решения.
void.pointer

Ответы:

28

Лично я выбираю вариант 3: хранить информацию о версиях в метаданных VCS , в частности, теги.

Git делает это очень легко, потому что есть команда git describe, которая может уникально описать коммит, основанный на теге. Вот как это работает:

  • Если текущий коммит помечен, выведите имя тега.
  • В противном случае, ходить задом истории , пока вы не найдете тег и затем выводится описание в следующем формате: <tag>-<number of commits since the tag>-g<abbreviated commit hash>.
  • Если в рабочем дереве есть незафиксированные изменения, добавьте -dirty.

Таким образом, если вы делаете сборку релиза и помечаете коммит 1.2.3, он будет выводиться 1.2.3. Если вы в настоящее время работаете над 1.2.4, и вы сделали 4 коммита с 1.2.3, и у вас есть незафиксированные изменения в дереве, он выведет 1.2.3-4-gdeadbee-dirty.

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

Йорг Миттаг
источник
Мне очень нравится эта идея, но с JIRA + Bamboo это кажется сложным. Bamboo работает только на ветвях, а не на тегах, поэтому вам нужно убедиться, что тег выдвинут до создания сборки. Это подвержено ошибкам.
void.pointer
1
git describeтакже работает с ветвями: « --all - вместо использования только аннотированных тегов, используйте любой ref, найденный в refs/пространстве имен. Этот параметр позволяет сопоставить любую известную ветку, ветвь удаленного отслеживания или облегченный тег». Не уверен, как это работает с Bamboo, хотя. (Это, конечно, потребует тщательного присвоения имен ветвям, как в обычном режиме с тегами.)
Йорг Миттаг
1
Я знаю некоторых людей, которые делают полностью автоматические релизы из Git. Строка версии git describeсоздается с помощью ChangeLog git shortlog(на самом деле, из сценария, который анализирует выходные данные git log --pretty=tformat:<some custom format string>), а примечания к выпуску генерируются из описания тега и git notesприкрепляются к важным вехам коммитов.
Йорг Миттаг
Я хочу сказать , что тег должен быть создан до релиза, чтобы коммиты после того, как он правильно версировался с базовым номером. Это противоречит принципу пометки во время или во время выпуска. Bamboo автоматически собирает сборки на основе коммитов master( developпомните, я использую gitflow). Что если кто-то отправит слияние masterбез тега? Он не будет использовать правильную версию (на самом деле он будет использовать версию последнего выпуска)
void.pointer
Если вы используете схему , как это, пометка будет выпускать. Ах, я понимаю, к чему ты клонишь, я думаю. Итак, в настоящее время ваш CI-сервер является драйвером релиза, и с этим изменением SCM является драйвером релиза, но вы хотели бы, чтобы он оставался таким?
Йорг Миттаг
8

Да. Хорошей практикой является сохранение большей части номера версии в vcs. Если мы рассмотрим семантическое управление версиями semver.org, где у нас есть major.minor.patch.build, первые три должны жить в vcs. Последний может быть инкрементным числом с вашего сервера сборки, который используется для возврата конкретного коммита, из которого сделан бинарный файл.

Чтобы упростить это в .NET, мы создали небольшую строку cmd, которая предназначена для git. При событии перед сборкой он выбирает номер сборки, который teamcity отметил во время сборки. Этот инструмент строки cmd автоматически генерирует класс с одной константой, содержащей номер сборки. Остальная часть номера версии: major.minor.patch - это обычная константа в другом файле. Эти два общих файла включены в каждую сборку в решении в виде ссылки (alt + shift-drag).

Этот подход является достаточно мощным, чтобы мы могли создавать и тестировать наш код teamcity. Нажмите на лазурь и попросите Куду собрать его снова, но с номером сборки teamcity в качестве версии dll.

Эсбен Сков Педерсен
источник