Tool for comparing .NET assembly files against a NuGet package in order to determine next SemVer version to use for the package.
For our librares we use (and partially publish) NuGet packages. In order to follow Semantic Versioning guidelines correctly we wanted to have tool support for discovering changes to the binary API of the assembly being built and published.
Given an assembly, the tool can create a list of its public parts (types and members) which reflects (no pun intended) the public API of the assembly.
Given this list created for two assembly versions, the difference between these can tell whether the public API is unchanged, changed but non-breaking (members or types were added), or breaking (members or types were removed).
- The AssemblyComparer loads the given .nuspec file and uses it to determine the package ID.
- The latest version of the package is retrieved from NuGet, so that the currently released assembly files and the package version are known.
- The
file
tags in the .nuspec file are used to determine which assemblies to take into account. - For each assembly, a public part list is created of both the version in the package as well as the version on disk (locating the files on disk like
nuget pack
would do). - After comparing all files matched by the filter, the old and new part lists are compared:
- If parts were removed (breaking binary API change), increase the major version and reset minor and patch version numbers.
- If parts were added (non-breaking binary API change), increase the minor version and reset the patch version number.
- If the parts are identical, increase the patch version.
- Apply the new version in TeamCity through Build Script Interaction:
##teamcity[buildNumber '1.2.3']
- Patch the .nuspec file with the new version.
- Patch any
AssemblyVersion
,AssemblyFileVersion
andAssemblyInformationalVersion
attributes found inAssemblyInfo.cs
files under thebasepath
.
Disclaimer: The tool is specific to our use case so your mileage may vary.
Sometimes some members are public but not intended to be part of the public API. Therefore, these should be able to be changed without being detected as a API change.
Coincidentally, obfuscation tools face the same challenge: they need to know which types and members may be obfuscated (public but private-use) and which have to remain unchanged (public API). Therefore, the AssemblyComparer tool takes the settings specified in the ObfuscateAssemblyAttribute
and ObfuscationAttribute
into account.
Additionally, any type or method with a [Conditional("DEBUG")]
attribute will be ignored as well. This allows to use debug assemblies during version comparison against release NuGet packages.
We roughly have the following build steps in place to integrate AssemblyComparer:
- Restore packages
- Create Debug Build
- Run tests
- Run AssemblyComparer
- Create Release Build (now with the newly determined version)
- Create NuGet package
Argument | Description |
---|---|
file.nuspec |
Required. .nuspec file path (relative to the current directory). |
--Source ... |
Optional. Accepts one (or more) NuGet package feeds to use as source for the baseline version of the NuGet package containing the assemblies. If not specified, the nuget.org feed will be used. |
-p ... , --Properties ... |
Optional. Accepts key=value pairs of properties. This can be used for filling placeholders in the paths of the nuspec file, e.g. bin\$Configuration$\some.dll and a -p Configuration=Debug , the resulting path would be bin\Debug\some.dll . Note: missing properties will cause a runtime exception. |
--Files ... |
Optional. File patterns matched against the src attribute of the .nuspec file elements. If not specified, all files with the .dll extension will be matched. |
--DryRun |
Optional. If specified, the analysis is output to the console but no changes are made. |
-i , --CheckInheritance |
Optional. Controls whether the inheritance is seen as relevant or not during analysis. If enabled, the base type must match and only declared members are checked. If a base type is introduced and some members are moved to it, having the option enabled will cause a major version increment due to removed members on the type being analyzed, whereas without inheritance check only a minor version increment is done since the effective public API remains the same. |
--BasePath ... |
Optional. The base path to use. By default it uses path where the .nuspec file is located. |
https://github.com/siriusch/AssemblyComparer
- MIT license
- Copyright 2018 © Sirius Technologies AG.