Add build version using GitHub Actions
Tags: dotnet, ukrainian, github, tutorial
Published: 2021-07-04 15:01:20

Коли реліз все ближче і потрібно підтримувати кілька середовищ, а потім кілька версій, то постає питання: "Як можна додати версійність до програмного продукту?".
 
## Semantic Versioning
Semantic Versioning ([SemVer](https://semver.org/)) - стандарт схеми версіювання, який не прив'язаний до жодної з мов програмування. Він описується наступною моделлю **major.minor.patch-pre-release.build**, до прикладу **0.1.0-rc.44**. Коли ми робимо зміни в нашій аплікації/бібліотеці нам необхідно збільшувати цифровий ідентифікатор. Наступні правила описують зміну цифрового ідентифікатора:
* **major** - архітектурні зміни, несумісний API
* **minor** - новий функціонал, додали зворотну сумісність до API
* **patch** - виправлення помилок чи проблем безпеки
* **pre-release** - опційний аргумент, щоб ідентифікувати версію яка ще не готова до production - *alfa*, *beta*, *rc(release candidate)*
* **build** - опційний аргумент, що визначає версію збірки продукту.

## Add version to solution
Ми вже знаємо як створювати семантичну версію продукту. Щоб додати її до нашого рішення необхідно обрати **\*.csproj** або **Directory.build.props** до якого ми будемо додавати версійність і додати атрибут `VersionPrefix`. Відповідно цей атрибут буде доданий до нашої збірки.
```
<PropertyGroup>
  <VersionPrefix>0.1.0</VersionPrefix>
</PropertyGroup>
```
> Тут важливо використовувати атрибут `VersionPrefix`, а не `Version`, бо ми ще хочемо додавати **pre-release** опційний атрибут до нашої кінцевої версії.

## Add API for versions
Для того, щоб створити API, який буде повертати версію продукту необхідно створити контролер, який буде з атрибутів *assembly* отримувати версію. Код нижче описує як це можна зробити
```
[HttpGet]
public string GetVersion()
    => Assembly
      .GetExecutingAssembly()
      .GetCustomAttribute<AssemblyInformationalVersionAttribute>()
      .InformationalVersion;
```

## Add build version
Для завершення рішення залишилось додати білд версію. Для цього нам необхідно знати дві речі:
1. Команда `dotnet build` підтримує [параметр](https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-build#options) `--version-suffix` який додає суфікс до версії під час збору аплікації.
2. GitHub Actions надає набір [визначених змінних](https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#github-context) про контекст виконання одиниці автоматизації. Для нас є цікавим змінна **github.run_number** - унікальний ідентифікатор запуску одиниці автоматизації, який збільшується на одиницю під час кожного запуску і починається також з одиниці.

Зібравши попередні два пункти, ми можемо описати команду збору проекту наступним чином:
```
dotnet build -c Release --version-suffix rc+${{github.run_number}}
```
Додаємо цю команду в крок одиниці автоматизації і все готово.

## Summary
SemVer є стандартизованим підходом до версіювання, який спрощує інтеграцію аплікації з іншими системами; також з допомогою версіювання можна легко відслідкувати помилки в аплікації (ми розуміємо в якій версії помилка з'явилась і в якій її виправили).
Описаний вище підхід дозволяє досить швидко додавати версійність до аплікації, також його можна використовувати з іншими CI платформами. І ще одне, коли продукт/бібліотека використовує стандарт SemVer, то легко налаштувати dependabot, про який я описував [тут](https://dev.to/ohalay/ci-for-dotnet-project-with-github-action-5hmp), що буде автоматично апдейтити *patch* версії. Приклад GitHub проекту можна глянути нижче {% github ohalay/TestSonarCloud no-readme %}