Лучшие практики / рекомендации по ведению номеров версий сборки

154

Я ищу указатели, предложения и даже указания о том, как управлять тремя различными номерами версий сборки .NET-сборки. Версия продукта является самой простой, так как это обычно диктуется бизнесом. Затем версия файла, по-видимому, предназначена для управления версиями между развертываниями, где фактическая версия сборки используется только при доставке.

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

ProfK
источник
1
Проверьте это ... codinghorror.com/blog/2007/02/…
Рахул Сони

Ответы:

211

Версионирование - это то, чем я очень увлечен и потратил много времени, пытаясь придумать простую в использовании систему управления версиями. Из того, что вы уже сказали в своем вопросе, ясно, что вы поняли один важный момент: номера версий сборки не являются синонимами версии продукта. Один - технически, а другой - бизнес.

Далее предполагается, что вы используете некоторую форму контроля версий и сервер сборки. Для контекста мы используем TeamCity и Subversion / Git. TeamCity бесплатен для небольшого (10) числа проектов и является очень хорошим сервером сборки, но есть и другие, некоторые из которых полностью бесплатны.

Что означает номер версии

То, что версия означает для одного человека, может означать что-то отличное от другого, общая структура мажорная, минорная, макро, микро. То, как я смотрю на номер версии, состоит в том, чтобы разбить его на две части. Первая половина описывает основную версию (Major) и любые ключевые обновления (Minor). Вторая половина указывает, когда это было построено и какова версия исходного кода. Номера версий также означают разные вещи в зависимости от контекста, это API, веб-приложение и т. Д.

Major, Minor, Build,Revision

  • Revision Это число, взятое из системы контроля версий для определения того, что на самом деле было построено.
  • BuildЭто постоянно увеличивающееся число, которое можно использовать для поиска конкретной сборки на сервере сборки. Это важное число, потому что сервер сборки мог создать один и тот же источник дважды с другим набором параметров. Использование номера сборки в сочетании с номером источника позволяет определить, что и как было построено.
  • MinorЭто должно измениться только в случае значительных изменений в общедоступном интерфейсе. Например, если это API, будет ли компилироваться потребляющий код? Этот номер должен быть сброшен на ноль при изменении основного номера.
  • Majorуказывает, на какой версии продукта вы находитесь. Например, основной из всех сборок VisualStudio 2008 - 9, а VisualStudio 2010 - 10.

Исключение из правила

Из этого правила всегда есть исключения, и вам придется приспосабливаться, когда вы сталкиваетесь с ними. Мой оригинальный подход был основан на использовании Subversion, но недавно я перешел на Git. Управление исходным кодом, такое как Subversion и Safe Source, которые используют центральный репозиторий, имеют номер, который можно использовать для идентификации определенного набора источников в данный момент времени. Это не относится к распределенному управлению источниками, такому как Git. Поскольку Git использует распределенные репозитории, которые есть на каждом компьютере разработчика, нет никакого автоматического увеличения числа, которое вы можете использовать, есть взлом, который использует количество проверок, но это уродливо. Из-за этого мне пришлось развивать свой подход.

Major, Minor, Macro,Build

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

Что установить

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

  • 1.2.0.0 (AssemblyVersion)
  • 1.2.3.4 (FileVersion)

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

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

Как связать это вместе

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

  • Удалите AssemblyVersionи AssemblyFileVersionатрибуты из всех файлов проекта AssemblyInfo.cs.
  • Создайте общий файл информации о сборке (назовите его VersionInfo.cs) и добавьте его в качестве связанного элемента во все ваши проекты.
  • Добавьте AssemblyVersionи AssemblyFileVersionатрибуты к версии со значениями «0.0.0.0».
  • Создайте проект MsBuild, который создает файл вашего решения.
  • Добавьте задачу перед сборкой, которая обновляет VersionInfo.cs. Существует несколько библиотек MsBuild с открытым исходным кодом, которые включают задачу AssemblyInfo, которая может установить номер версии. Просто установите его на произвольное число и проверьте.
  • Добавьте группу свойств, содержащую свойство для каждого из сегментов номера сборки. Здесь вы устанавливаете мажор и минор. Номер сборки и ревизии должны быть переданы в качестве аргументов.

С подрывной деятельностью:

<PropertyGroup>
    <Version-Major>0</Version-Major>
    <Version-Minor>0</Version-Minor>
    <Version-Build Condition=" '$(build_number)' == '' ">0</Version-Build>
    <Version-Build Condition=" '$(build_number)' != '' ">$(build_number)</Version-Build>
    <Version-Revision Condition=" '$(revision_number)' == '' ">0</Version-Revision>
    <Version-Revision Condition=" '$(revision_number)' != '' ">$(revision_number)</Version-Revision>
</PropertyGroup>

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

Bronumski
источник
Рассматривали ли вы использование тегов версий из GitHub? Мне очень любопытно, как это вписалось бы в загадку.
raRaRa
1
@raRaRa - Это довольно старый пост. Хотя большую часть этого я все еще поддерживаю, есть некоторые вещи, которые я бы сделал по-другому. Управление версиями в NuGet изменило мои действия, и я использую теги Git для успешных сборок, но в конце дня номер версии в сборке должен быть привязан к версии сборки на сервере сборки и версии тега в управлении исходным кодом.
Бронумски
57

[AssemblyVersion] является очень важным делом в .NET. Одна философия, поддерживаемая Microsoft, заключается в том, что вы разрешаете автоматическое увеличение, заставляя перекомпилировать все проекты, которые зависят от сборки. Работает нормально, если вы используете сервер сборки. Это никогда не неправильно , но остерегайтесь людей, несущих мечи.

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

Вы можете дополнительно расширить этот подход, увеличивая версию только тогда, когда сборка была развернута на машинах вне вашей досягаемости. Именно такой подход использует Microsoft, номера версий их сборок .NET меняются очень редко. Главным образом из-за очень значительной боли, которую это причиняет их клиентам.

Так что Microsoft проповедует не то, что практикует. Однако процесс сборки и управления версиями не имеет аналогов, у них даже есть специальный разработчик программного обеспечения, который следит за процессом. Не совсем удачно, перегрузка WaitHandle.WaitOne (int), в частности, вызывала изрядное количество боли . Исправлено в .NET 4.0 с совершенно другим подходом, но это выходит за рамки.

Это зависит от вас и вашей уверенности в том, насколько хорошо вы сможете контролировать процесс сборки и циклы выпуска, чтобы сделать свой собственный выбор. Помимо этого, автоматическое увеличение [AssemblyFileVersion] автоматически очень уместно. Однако, с неудобствами, которые не поддерживаются.

Ганс Пассант
источник
11

Вы можете использовать часть сборки номера версии для автоинкремента.

[assembly: AssemblyVersion("1.0.*")]

В вашей среде тестовая версия - это версия с версией сборки! = 0. При выпуске вы увеличиваете второстепенную часть и устанавливаете часть сборки на 0, так вы бы идентифицировали выпущенные сборки.

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

testalino
источник
Мне нравится номер сборки 0 для версий выпуска.
ProfK
1
Конечно, это означает, что строгое имя вашей сборки будет меняться с каждой сборкой, хотите вы того или нет.
Ричард
9

Добавление к Bronumskis ответа , я хочу отметить, что после того, как стандарт Семантический Versioning 2.0 в semver.org , Major.Minor.Build.Revisionбыло бы незаконным в связи с правилом , что после увеличения числа, все регулярные значения справа бы должны быть обнулены.

Лучше всего следовать стандарту Major.Minor+Build.Revision. Это явно не для использования в AssemblyVersionAttribute, но вместо этого можно использовать пользовательский атрибут или статический класс.

Semver в TeamCity должен быть доступен с помощью Meta-runner Power Pack. Для git с git-flow (особенно в мире .NET) я нашел GitVersion полезным.

Sunside
источник
2
Интересно, я проверю это. Упомянутый вами формат номера версии можно использовать в атрибуте AssemblyInformationalVersion.
Бронумски
1

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

... например: 1.0.0. *

Зарезервировано - это добавляет дополнительную гибкость, если вы хотите внести какие-либо изменения в будущем. Но по умолчанию оставьте его равным 0.

Также рассмотрите возможность подписи сборки сильным ключом. Это решит проблему конфликта сборки, если у вас есть несколько версий сборки, зарегистрированных в GAC. MSDN Link

Картик Махалингам
источник