Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 

README.md

Blueshift.MSBuildSdk

The standard MSBuild SDK used by Blueshift Software. This SDK is meant to be opinionated: it is primarily meant to reduce copy-and-paste boilerplate that can pollute and muddle MSBuild project files, while applying a standard set of build artifact configuration values.

Primarily, Blueshift.MSBuildSdk adds CI-friendly metadata to build outputs. AssembyMetadata values such as BuildYear, Company, and Copyright, as well as values from Git such as GitCommitId, GitAuthorEmail, GitTag, and even GitSourceBranch for builds on non-default branches.

Many of the SDK's rules are customizable through MSBuild properties, which can be applied through environment variables, overriden in individual projects, included globally through Directory.Build.props/targets, or via specific before- and after.props and -.targets files.

CI Environment Variables

The MSBuild SDK is deisnged to work well with CI tools. Build platforms such as Jenkins and Azure DevOps Server can be confiugured to set various environment variables on build agents. This SDK can import certain variables, and will automatically assign them to appropriate build metadata.

The SDK uses the following environment variables:

Name Description
BUILD_AUTHORS The authors of a particular. This is useful for individuals or teams within a company who maintain specific packages. This value will be set in the authors field of any NuGet package produced by the build.
BUILD_COMPANY The name of the company. This value is stored in the CompanyAttribute.
CI If set to any non-empty string (e.g.: Jenkins), declares the current system to be a build agent for the given CI platform. This affects some minor logic throughout the SDK.

Currently, the SDK only supports CI environment variables from Jenkins. The following variables are currently supported:

Name Description
BUILD_NUMBER Used to set the Build number field of the assembly Version.
GIT_BRANCH The name of the Git source branch currently being built. If this is not the default branch, this value will be used to populate VersionSuffix. If unspecified, the SDK will execute git rev-parse --abbrev-ref HEAD to read the value from the current working directory.
GIT_COMMIT A commit-ish value used to set the GitCommitId assembly metadata value. If unspecified, the SDK will execute git rev-parse HEAD to read the value from the current working directory.
GIT_URL The URL of the repository. This value is used to populate the PackageProjectUrl and RepositoryUrl values, unless they are otherwise set.
JENKINS_HOME This is set by Jenkins (and should not be set directly by the user). If present, the SDK will set the CI variable to "Jenkins".

Note: CI variable loading can be skipped by setting the IgnoreCIVariables to true.

Git

The SDK assumes that Git is the current source control version system (CVS) used by the project. If otherwise unspecified, the SDK will read several values from the current working directory and use them to populate various properties of the build output.

These values are cached in [ProjectFile].blueshift.git.props under the project's MSBuildProjectExtensionsPath. This prevents extra unnecessary executions of git commands on subsequent builds. The cache file is regenerated whenever the contents of the Git directory change (such as by checking out a new branch or creating a new commit).

The following table lists these values, the command that would be executed to read them if otherwise unspecificed, and their effect:

Name Command Description
CentralVersionFileDiff git diff $(GitHeadCommitId)..$(GitCommitId) -G"<VersionPrefix&>.*</VersionPrefix&>" -- $(CentralVersionFile) For non-default branches, this property will contain the difference between the Central Version File on the current branch and the default branch. This diff specifically looks for a change to the VersionPrefix property, and affects versioning requirements within the SDK.
GitCommitAuthorEmail git show -s --format=%25ae $(GitCommitId) The email of the author who committed the most recent changes. On non-CI systems, the SDK will first attempt to read this value from git config user.email in order to get the current developer's email.
Note: if the current branch is not the default branch, or the current system is not a CI system, this value will be stored in an AssemblyMetadataAttribute. This is intended to discourage distribution of non-release build artifacts, especially artifacts created on development systems.
GitCommitId git rev-parse HEAD The commit-ish of the most recent commit. This value will be stored in an AssemblyMetadataAttribute.
GitDefaultBranch git ls-remote --symref $(GitRemote) HEAD The name of the default branch for the current remote. If unspecified, this value is parsed from the output of the specified command.
GitDirectory git rev-parse --git-dir The directory where information on the current Git working copy is stored. This is usually a .git folder directory under the root of the repository. The files in this directory are used as target inputs to determine wether or not the current set of git properties need to be reloaded, and the cache file regenerated.
GitHeadCommitId git ls-remote --symref $(GitRemote) HEAD The git commit id for the HEAD of the default branch for the current remote. If unspecified, this value is parsed from the output of the specified command.
GitRemote git remote show The name of the current remote, usually "origin". This value is used to read out informaton about the remote such as the default branch name.
GitRepositoryUrl git config --get remote.$(GitRemote).url The URL of the Git repo. This is used when packing the target into a NuGet package.
GitSourceBranch git rev-parse --abbrev-ref HEAD The name of the current branch being built. If this is different from GitDefaultBranch, this value will be used to populate VersionSuffix (unless otherwise specified).
This value will be stored in an AssemblyMetadataAttribute.
GitTag git tag --contains HEAD The git tag for the HEAD of the current branch. If this tag is of the format vX.Y[.Z[.A]], it will be treated as a version string and used to override the version of the build output. This is useful for rebuilding specific tagged versions in the event that the package management system suffers a catastrophic data loss.
If this tag is not the same as the GitCommitId, it will be stored in an AssemblyMetadataAttribute.

By default, these values are loaded and used to set metadata on the output assemblies. However, this can be prevented by setting the GenerateGitAssemblyMetadata MSBuild property to false before loading the SDK.

Versioning

By default, the SDK requires a Version.props file to exist somewhere up the build directory hierarchy from the current project. This requirement can be relaxed by setting the EnableCentralVersioning MSBuild to false.

The SDK also strictly enforces Semantic Versioning 2.0.0: at a minimum, a VersionPrefix must be specified with a Major and Minor version (eg: 1.0, 0.1, 99.99, etc). This restriction cannot be disabled. VersionPrefix will be expanded to the minimum three-field versioning (e.g.: a prefix of 1.0 will become 1.0.0) required by SemVer 2.0.0.

The SDK will further refine VersionPrefix and VersionSuffix based on the current branch.

Default Branch

If specified, BuildNumber will be appended onto VersionPrefix if it does not already define a Build (4th) value.

Non-Default (Feature) Branches

If VersionSuffix is not already specified, it will be set to the name of the current branch (ie: $(GitSourceBranch)).

If present, BuildNumber will be appended onto VersionSuffix. This allows CI systems to publish branch version tags which NuGet clients will recognize as updates, and thus can be consumed and tested by other applications prior to merging.

Version will be set to [VersionPrefix]-[VersionSuffix] using the updated properties.

Git Tags

When building tagged Git commits, the tag can be used to specify a version. If the Git tag is of the form vX.Y[Z[.A]](-[SUFFIX])?, (notice the leading 'v') it will override the Version and set it to the specified X.Y[.Z[.A]] value regardless of the values of VersionPrefix, VersionSuffix, BuildNumber, or GitSourceBranch.

Building Git tags is useful for rebuilding specific versions of a package in the event of an unrecoverable, catastrophic data loss in the NuGet package management system.

Enforcement

If central versioning is enabled, but the CentralVersionFile cannot be found, the SDK will issue an explicit error with instructions for creating it. Since it is central, the file should be located in a directory above any projects consuming this SDK (preferrably the repository or solution root directory).

Regardless of whether or not central versioning is enabled, the SDK will also enforce semantic versioning rules. At a miminmum, VersionPrefix must have an explicit value, and must set a Major and Minor version number. The SDK will default the Revision to 0, and will set the Build version to the value of BuildNumber if one is supplied by the CI platform.

If central versioning and git metadata generation are both enabled, the SDK will also enforce branch-based versioning. That is, every feature branch must update the VersionPrefix property in the central version file. The SDK will diff the central version file against the default branch and look for changes to a line containing <VersionPrefix>.*</VersionPrefix>. Currently, the SDK does not further inspect these changes to enforce a strict version increase, but that may change in the future.

If the central version file has not changed, the SDK will issue an error when attempting to build a feature branch. Note: for feature branches with no commits (ie: still in the initial local dev phase), this will just be a warning as a reminder to bump the version number.

NuGet Properties

Finally, the SDK affects the Pack target. By default, PackageVersion will be set to the Version as computed in the previous section. This is handled by NuGet's own Pack targets.

Additionally, the SDK will set the following NuGet properties (unless otherwise specified):

  • PackageProjectUrl will be set to the value of GitRepositoryUrl.
  • RepositoryBranch will be set to the value of GitSourceBranch, if it is not the default branch.
  • RepositoryCommit will be to the value of GitCommitId.
  • RepositoryType will be set to "Git".
  • RepositoryUrl will be set to the value of GitRepositoryUrl.

This behavior can be disabled by setting GenerateGitPackageMetadata to false.

Customization

The behavior of the SDK can be fine-tuned by setting any of the following custom MSBuild props and/or targets filename variables prior to loading the SDK:

Property Description
CustomBeforeBlueshiftMSBuildSdkProps The name of a custom props file to be loaded at the beginning of Sdk.props.
CustomAfterBlueshiftMSBuildSdkProps The name of a custom props file to be loaded at the end of Sdk.props.
CustomBeforeBlueshiftMSBuildSdkTargets The name of a custom targets file to be loaded at the beginning of Sdk.target.
CustomAfterBlueshiftMSBuildSdkTargets The name of a custom targets file to be loaded at the end of Sdk.target.