Проблема.
Несколько месяцев назад я рассказывал, как удобно и безболезненно создавать AssemblyVersion для проекта. Теперь настало время рассказать о решении второй части задачи – версионирование сборок и nuget-пакетов. Решение ограничено двумя условиями:
- Система контроля версий – git.
- Версия сборки и пакета должна хранится в git, или генерироваться из метаданных git.
- AssemblyVersion, включая Major, Minor и Revision.
- Nuget version, включая Major, MInor, Revision и Prerelease version. (подробнее в документации по версионированию nuget-packet’ов).
- AssemblyInformationVersion, включает все предыдущие, а также SHA-1 hash. Это позволит точно определить, из какой ревизии создана сборка. Для краткости принято брать первые семь символов.
Решение
Идею я позаимствовал у UppercuT, и немного ее расширил. В основе лежат аннотированные теги git’a. Название тега должно соответствовать соглашению по именованию – Major.Minor-PrereleaseVersion, например 0.9-beta. Далее буду продолжать на основе репозитория enhima, и с использованием консоли git bash. Сначала поставим тег на первый commit в репозитории git.
Juso@ULTIMA /v/enhima (master)$ git tag -a 0.9-beta f262324 -m "first public beta"
Juso@ULTIMA /v/enhima (master)$ git tag0.9-beta
Где f262324 – первые семь символов хеша ревизии, на которую надо повесить тег. Как видно, команда git tag показывает все теги в репозитории, но не даёт двух вещей: номера ревизии и хеша ревизии. К счастью, в git есть более полезная команда: git describe.
Juso@ULTIMA /v/enhima (master)$ git describe --abbrev=640.9-beta-21-gf8542552ae0e9c7e478fe9ac3e6a02c2060e965a
И в итоге мы получим все необходимые данные одной командой, остаётся только их разобрать с помощью регулярных выражений. Честно говоря, до этой задачи мне не приходилось плотно работать с регулярками, но rubular научит любого строить регулярку за полчаса. Итак, у нас есть всё что нужно для версионирования:
Хотя у вас наверно возник вопрос, откуда взялась цифра 21? Это количество commit’ов, сделанных после последнего аннотированного тега. Она конечно не является уникальным номером ревизии, но для целей создания AssemblyVersion подойдёт. А уникальность можно определить по хешу.
Генерируем AssemblyVersion с помощью rake
Пора сделать последний шаг. Автоматизировать сборку скрипта с помощью какого-либо build-инструмента. Мой фаворит в последнее время – rake + albacore. (Как начать работу с rake для .net-программиста). И вот что у меня получилось:
desc "Generate solution version "
assemblyinfo do |asm|
#Assuming we have tag '0.9-beta' git describe --abbrev=64 returns 0.9-beta-18-g408122de9c62e64937f5c1956a27cf4af9648c12
#If we have tag '0.9' git describe --abbrev=64 returns 0.9-18-g408122de9c62e64937f5c1956a27cf4af9648c12
#It should be parsed by to generate correct assembly and nuget package version
output = `git describe --abbrev=64`version_parts = output.match /(\d+).(\d+)-?([a-zA-Z]*)-(\d+)-(\w{7})/major = version_parts[1]minor = version_parts[2]revision = version_parts[4] || 0version_type = version_parts[3]hash = version_parts[5]@version = "#{major}.#{minor}.#{revision}"
@package_version = @version@package_version += "-#{version_type}" if (version_type || "").length > 0@product_version = @version@product_version += ("-#{version_type}" if (version_type || "").length > 0) + "-#{hash}"asm.version = @versionasm.file_version = @versionasm.custom_attributes :AssemblyInformationalVersionAttribute => @product_versionasm.output_file = "SolutionVersion.cs"
asm.description = @descriptionend
И результат работы:
1: using System.Reflection;
2: using System.Runtime.InteropServices;
3: [assembly: AssemblyDescription("Lightweight near zero-configuration library for easy conventional mapping for nhibernate.")]
4: [assembly: AssemblyVersion("0.9.21")]
5: [assembly: AssemblyFileVersion("0.9.21")]
6:7: [assembly: AssemblyInformationalVersionAttribute("0.9.21-beta-gf85425")]
8:9:
Именно то, что требовалось. Полную версию скрипта можно найти в репозитории enhima. Надеюсь это поможет вам подружить git и .net. :)
Комментариев нет:
Отправить комментарий