Кращі практики / рекомендації щодо підтримки номерів версій збірки


154

Я шукаю вказівники, пропозиції та навіть диктант про те, як керувати трьома різними номерами версій для складання .NET. Версія продукту найпростіша, оскільки це, як видається, зазвичай диктується бізнесом. Потім, здається, версія файлу призначена для версії між розгортаннями, де фактична версія збірки використовується лише при доставці.

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


Відповіді:


211

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

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

Що означає номер версії

Те, що версія означає для однієї людини, може означати щось інше для іншої, загальна структура - основна, другорядна, макро, мікро. Те, як я дивлюсь на номер версії, - це розбити її на дві частини. У першій половині описується основна версія (основна) та будь-які ключові оновлення (мінор). Друга половина вказує, коли вона була побудована та якою була версія вихідного коду. Номери версій також означають різні речі залежно від контексту, це API, веб-додаток тощо.

Major. Minor. Build.Revision

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

Виняток із правила

З правила завжди є винятки, і вам доведеться адаптуватися, коли ви натрапляєте на них. Мій оригінальний підхід базувався на використанні підриву, але нещодавно я перейшов до Git. Управління джерелами, як підривна та безпечна для джерел, що використовують центральний сховище, має номер, який може бути використаний для ідентифікації певного набору джерел у заданий час. Це не стосується управління розподіленими джерелами, наприклад, 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>

Сподіваюсь, я зрозумів, але в цьому багато чого. Будь ласка, задайте будь-які питання. Я буду використовувати будь-який зворотній зв'язок, щоб скласти більш стисну публікацію в блозі.


Чи обдумали ви використовувати теги версій від GitHub? Мені дуже цікаво, як це впишеться у головоломку.
raRaRa

1
@raRaRa - Це досить старий пост. Хоча більшу частину цього я все ще стою, є деякі речі, які я б робив інакше. Версія NuGet змінила те, як я роблю речі, і я використовую теги Git для успішних збірок, але наприкінці дня номер версії на збірці повинен відповідати версії збірки на сервері збирання та версії тегів у керуванні джерелом.
Bronumski

57

[AssemblyVersion] - це дуже велика справа в .NET. Одна з філософій, яку заохочує Microsoft, полягає в тому, що ви дозволяєте їй автоматично збільшуватися, змушуючи перекомпілювати всі проекти, які залежать від складання. Працює нормально, якщо ви використовуєте сервер збірки. Ніколи це неправильно робити, але остерігайтеся людей, які носять мечі.

Інший, більш тісний з його фактичним значенням, полягає в тому, що число є репрезентативним для версії публічного інтерфейсу збірки. Іншими словами, ви змінюєте його лише тоді, коли ви змінюєте загальнодоступний інтерфейс або клас. Оскільки лише така зміна вимагає перекомпілювати клієнтів збірки. Це потрібно зробити вручну, хоча система збірки недостатньо розумна для автоматичного виявлення такої зміни.

Ви можете додатково розширити цей підхід, лише збільшивши версію, коли збірка була розгорнута на машинах поза вашим досяжністю. Це такий підхід, який використовує Microsoft, а їх номери версій .NET дуже рідко змінюються. Переважно через дуже великий біль, який він завдає своїм клієнтам.

Отже, що Microsoft проповідує, це не те, що практикується. Процес його збирання та управління версією, однак, мають безпрецедентний характер, навіть у них є спеціалізований програмний інженер, який слідкує за процесом. Не дуже добре вийшло, зокрема, перевантаження WaitHandle.WaitOne (int) викликало неабияку біль . Виправлено у .NET 4.0 із зовсім іншим підходом, але це виходить трохи поза рамки.

Швидше залежати від вас і вашої впевненості в тому, наскільки добре ви можете контролювати процес збирання та цикли випуску, щоб зробити власний вибір. Крім цього, автоматичне збільшення [AssemblyFileVersion] автоматично є дуже доречним. Однак незручність у тому, що це не підтримується.


11

Ви можете використати частину Build з номера версії для автоматичного збільшення.

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

У вашому оточенні тестова версія - це версія, яка має версію збірки! = 0. Після випуску ви збільшуєте незначну частину та встановлюєте частину збірки на 0, саме так ви б ідентифікували звільнені збірки.

Якщо ви встановлюєте свої збори в GAC, ваш GAC з часом переповнюється безліччю різних версій, тому майте це на увазі. Але якщо ви використовуєте котеджі лише локально, я думаю, що це хороша практика.


Мені подобається номер збірки 0 для версій версій.
ПрофК

1
Звичайно, це означає, що сильна назва вашої збірки буде змінюватися з кожним складанням, хочете ви цього чи ні.
Річард

9

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

Кращим способом дотримання стандарту було б використання Major.Minor+Build.Revision. Це не обов'язково для використання в AssemblyVersionAttribute, але замість нього може бути використаний спеціальний атрибут або статичний клас.

Semver в TeamCity повинен бути доступний за допомогою пакета живлення Meta-runner. Що стосується git з git-flow (особливо у світі .NET), я виявив корисний GitVersion .


2
Цікаво, я це перевірю. Формат номера версії, який ви згадали, може бути використаний в атрибуті AssemblyInformationalVersion.
Бронумський

1

Немає жорсткого і швидкого правила, коли мова йде про збірки версій, тому сміливо спробуйте, який коли-небудь буде працювати для вас, але я б запропонував вам скористатися підходом у чотирьох частинах, оскільки у вас буде гнучкість, якщо ви хочете внести деякі зміни у майбутньому.

... для напр .: 1.0.0. *

Зарезервовано - це додає додаткової гнучкості, якщо ви хочете внести будь-які зміни в майбутньому. Але за замовчуванням збережіть це як 0.

Крім того, розгляньте можливість підписання збірки сильним ключем. Це вирішить проблему конфлікту складання, якщо у вас є кілька версій збірки, зареєстрованих у GAC. MSDN Посилання

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.