Страницы

четверг, 23 февраля 2012 г.

AssemblyVersion и git. Давайте жить дружно.

Проблема.

  Несколько месяцев назад я рассказывал, как удобно и безболезненно создавать AssemblyVersion для проекта. Теперь настало время рассказать о решении второй части задачи – версионирование сборок и nuget-пакетов. Решение ограничено двумя условиями:
  • Система контроля версий – git.
  • Версия сборки и пакета должна хранится в git, или генерироваться из метаданных git.
  На выходе надо получить:

 

Решение

  Идею я позаимствовал у 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 tag
0.9-beta

  Где  f262324 – первые семь символов хеша ревизии, на которую надо повесить тег. Как видно, команда git tag показывает все теги в репозитории, но не даёт двух вещей: номера ревизии и хеша ревизии. К счастью, в git есть более полезная команда: git describe.
Juso@ULTIMA /v/enhima (master)
$ git describe --abbrev=64
0.9-beta-21-gf8542552ae0e9c7e478fe9ac3e6a02c2060e965a

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

image

  Хотя у вас наверно возник вопрос, откуда взялась цифра 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] || 0
 version_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 = @version
 asm.file_version = @version
 asm.custom_attributes :AssemblyInformationalVersionAttribute => @product_version
 asm.output_file = "SolutionVersion.cs"
 asm.description = @description
end

  И результат работы:
  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. :)

Комментариев нет:

Отправить комментарий