だいぶ前に、.NET Framework でAssemblyInfoをいじってファイルバージョンを自動採番するというのをやったのですが、
最近は、.NET Coreのプロジェクトが始まってやり方が色々違うし、どうやらJavaでやってたようにGitのコミットIDを入れられそうだというので試してみました。 あと、最近はNexusリポジトリにNugetパッケージをアップしているのですが、開発中にファイル名が同じだとキャッシュが更新されないことがあったのでビルドのたびにファイル名を変えたいというのがあります。 合わせて中身のDllの製品バージョンも一緒にできるといいなーと。
ここのサイトでは、GitVersioningとGitInfoが紹介されていたのでまずはシンプルそうなGitInfoを試してみました。
プロジェクトを新規作成
>dotnet new console -o assemblyInfoTest cd assemblyInfoTest >dotnet run Hello World!
プロジェクトにGitInfoを追加
>dotnet add package GitInfo --version 2.0.20
早速Gitの情報を取得してみます。
using System; using System.Diagnostics; using System.Reflection; namespace assemblyInfoTest { class Program { static void Main(string[] args) { Console.WriteLine("Hello World!"); Console.WriteLine($"GitBranch: {ThisAssembly.Git.Branch}"); Console.WriteLine($"GitCommit: {ThisAssembly.Git.Commit}"); Console.WriteLine($"GitSha: {ThisAssembly.Git.Sha}"); Console.WriteLine($"GitBaseVersionMajor: {ThisAssembly.Git.BaseVersion.Major}"); Console.WriteLine($"GitBaseVersionMinor: {ThisAssembly.Git.BaseVersion.Minor}"); Console.WriteLine($"GitBaseVersionPatch: {ThisAssembly.Git.BaseVersion.Patch}"); Console.WriteLine($"GitCommits: {ThisAssembly.Git.Commits}"); Console.WriteLine($"GitTag: {ThisAssembly.Git.Tag}"); Console.WriteLine($"GitBaseTag: {ThisAssembly.Git.BaseTag}"); Console.WriteLine($"GitSemVerMajor: {ThisAssembly.Git.SemVer.Major}"); Console.WriteLine($"GitSemVerMinor: {ThisAssembly.Git.SemVer.Minor}"); Console.WriteLine($"GitSemVerPatch: {ThisAssembly.Git.SemVer.Patch}"); Console.WriteLine($"GitSemVerLabel: {ThisAssembly.Git.SemVer.Label}"); Console.WriteLine($"GitSemVerDashLabel: {ThisAssembly.Git.SemVer.DashLabel}"); Console.WriteLine($"GitSemVerSource: {ThisAssembly.Git.SemVer.Source}"); Console.WriteLine($"GitIsDirty: {ThisAssembly.Git.IsDirty}"); var assemblyVersion = Assembly.GetExecutingAssembly().GetName().Version; var fileVersion = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion; var productVersion = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).ProductVersion; Console.WriteLine($"assemblyVersion: {assemblyVersion}"); Console.WriteLine($"fileVersion: {fileVersion}"); Console.WriteLine($"productVersion: {productVersion}"); } } }
C:\home\gozu\projects\assemblyInfoTest>dotnet run Hello World! GitBranch: master GitCommit: 5ac94b0 GitSha: 5ac94b013eef929d3b8a932247966bd5f9a87952 GitBaseVersionMajor: 0 GitBaseVersionMinor: 0 GitBaseVersionPatch: 0 GitCommits: 2 GitTag: GitBaseTag: GitSemVerMajor: 0 GitSemVerMinor: 0 GitSemVerPatch: 2 GitSemVerLabel: GitSemVerDashLabel: GitSemVerSource: Default GitIsDirty: True assemblyVersion: 1.0.0.0 fileVersion: 1.0.0.0 productVersion: 1.0.0
簡単に取れました。
Git情報を埋め込んでみる
以下を追加しました。
[assembly: AssemblyVersion(ThisAssembly.Git.BaseVersion.Major + "." + ThisAssembly.Git.BaseVersion.Minor + ThisAssembly.Git.BaseVersion.Patch)] [assembly: AssemblyFileVersion(ThisAssembly.Git.SemVer.Major + "." + ThisAssembly.Git.SemVer.Minor + "." + ThisAssembly.Git.SemVer.Patch)] [assembly: AssemblyInformationalVersion(ThisAssembly.Git.SemVer.Major + "." + ThisAssembly.Git.SemVer.Minor + "." + ThisAssembly.Git.SemVer.Patch + "-" + ThisAssembly.Git.Branch + "+" + ThisAssembly.Git.Commit)]
>dotnet run obj\Debug\netcoreapp2.2\assemblyInfoTest.AssemblyInfo.cs(12,12): error CS0579: System.Reflection.AssemblyFileVersionAttribute' 属性が重複しています。 [C:\home\gozu\projects\assemblyInfoTest\assemblyInfoTest.csproj] obj\Debug\netcoreapp2.2\assemblyInfoTest.AssemblyInfo.cs(13,12): error CS0579: System.Reflection.AssemblyInformationalVersionAttribute' 属性が重複しています。 [C:\home\gozu\projects\assemblyInfoTest\assemblyInfoTest.csproj] obj\Debug\netcoreapp2.2\assemblyInfoTest.AssemblyInfo.cs(16,12): error CS0579: System.Reflection.AssemblyVersionAttribute' 属性が重複しています。 [C:\home\gozu\projects\assemblyInfoTest\assemblyInfoTest.csproj] ビルドに失敗しました。ビルド エラーを修正して、もう一度実行してください。
.NET CoreだとAssemblyInfo.csが生成されるので書き換えたいプロパティの生成を抑制する必要があるらしい。
csprojに以下を追加しました。
<PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp2.2</TargetFramework> <GenerateAssemblyFileVersionAttribute>false</GenerateAssemblyFileVersionAttribute> <GenerateAssemblyInformationalVersionAttribute>false</GenerateAssemblyInformationalVersionAttribute> <GenerateAssemblyVersionAttribute>false</GenerateAssemblyVersionAttribute> </PropertyGroup>
>dotnet run Hello World! GitBranch: master GitCommit: 37fdbb4 GitSha: 37fdbb48f4c47b29089f6dd0ce36178c21500861 GitBaseVersionMajor: 0 GitBaseVersionMinor: 0 GitBaseVersionPatch: 0 GitCommits: 3 GitTag: GitBaseTag: GitSemVerMajor: 0 GitSemVerMinor: 0 GitSemVerPatch: 3 GitSemVerLabel: GitSemVerDashLabel: GitSemVerSource: Default GitIsDirty: False assemblyVersion: 0.0.0.0 fileVersion: 0.0.3 productVersion: 0.0.3-master+37fdbb4
おー、出来た!
CIで外部から指定できるように
想定ではJenkinsでnupkgのファイル名とDllの製品バージョンをビルドごとに一意なバージョンにするなので、GitのコミットIDを付加する方向で行きます。
外部から指定できるようにcsprojに Version
を定義しておきます。
1.0.0としてますが書き換わるので気にしない。
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>netcoreapp2.2</TargetFramework> <GenerateAssemblyFileVersionAttribute>false</GenerateAssemblyFileVersionAttribute> <!--GenerateAssemblyInformationalVersionAttribute>false</GenerateAssemblyInformationalVersionAttribute--> <!--GenerateAssemblyVersionAttribute>false</GenerateAssemblyVersionAttribute--> <Version>1.0.0</Version> </PropertyGroup> <ItemGroup> <PackageReference Include="GitInfo" Version="2.0.20"> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <PrivateAssets>all</PrivateAssets> </PackageReference> </ItemGroup> </Project>
コードの方も調整します。 FileVersionだけは入れておこうかという感じです。
using System; using System.Diagnostics; using System.Reflection; //[assembly: AssemblyVersion(ThisAssembly.Git.BaseVersion.Major + "." + ThisAssembly.Git.BaseVersion.Minor + ThisAssembly.Git.BaseVersion.Patch)] [assembly: AssemblyFileVersion(ThisAssembly.Git.SemVer.Major + "." + ThisAssembly.Git.SemVer.Minor + "." + ThisAssembly.Git.SemVer.Patch)] //[assembly: AssemblyInformationalVersion("1.0.0" + "-alpha." + ThisAssembly.Git.Commit)] namespace assemblyInfoTest { class Program { static void Main(string[] args) { Console.WriteLine("Hello World!"); Console.WriteLine($"GitBranch: {ThisAssembly.Git.Branch}"); Console.WriteLine($"GitCommit: {ThisAssembly.Git.Commit}"); Console.WriteLine($"GitSha: {ThisAssembly.Git.Sha}"); Console.WriteLine($"GitBaseVersionMajor: {ThisAssembly.Git.BaseVersion.Major}"); Console.WriteLine($"GitBaseVersionMinor: {ThisAssembly.Git.BaseVersion.Minor}"); Console.WriteLine($"GitBaseVersionPatch: {ThisAssembly.Git.BaseVersion.Patch}"); Console.WriteLine($"GitCommits: {ThisAssembly.Git.Commits}"); Console.WriteLine($"GitTag: {ThisAssembly.Git.Tag}"); Console.WriteLine($"GitBaseTag: {ThisAssembly.Git.BaseTag}"); Console.WriteLine($"GitSemVerMajor: {ThisAssembly.Git.SemVer.Major}"); Console.WriteLine($"GitSemVerMinor: {ThisAssembly.Git.SemVer.Minor}"); Console.WriteLine($"GitSemVerPatch: {ThisAssembly.Git.SemVer.Patch}"); Console.WriteLine($"GitSemVerLabel: {ThisAssembly.Git.SemVer.Label}"); Console.WriteLine($"GitSemVerDashLabel: {ThisAssembly.Git.SemVer.DashLabel}"); Console.WriteLine($"GitSemVerSource: {ThisAssembly.Git.SemVer.Source}"); Console.WriteLine($"GitIsDirty: {ThisAssembly.Git.IsDirty}"); var assemblyVersion = Assembly.GetExecutingAssembly().GetName().Version; var fileVersion = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion; var productVersion = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).ProductVersion; Console.WriteLine($"assemblyVersion: {assemblyVersion}"); Console.WriteLine($"fileVersion: {fileVersion}"); Console.WriteLine($"productVersion: {productVersion}"); } } }
Jenkinsfileで以下のようにdotnetコマンドを実行してビルドとパッケージングをします。
bat """chcp 65001 for /f "usebackq tokens=*" %%a in (`git rev-parse --short HEAD`) do @set GIT_COMMIT=%%a for /f "usebackq tokens=*" %%a in (`git rev-parse --abbrev-ref HEAD`) do @set GIT_BRANCH=%%a dotnet build -p:Version="1.0.0-alpha.%GIT_COMMIT%" dotnet pack --no-build -p:PackageVersion="1.0.0-alpha.%GIT_COMMIT%" """
これで、製品バージョンに 1.0.0-alpha.xxxxxxx
と埋め込まれたDllを含めた、 assemblyInfoTest.1.0.0-alpha.xxxxxxx.nupkg
が出来ました。
1.0.0-aplpha
のところはまあどこかで一元的に定義しないといけないですけどね。