nunit / nunit3-vs-adapter

NUnit 3.0 Visual Studio test adapter for use under VS 2012 or later
https://nunit.org
MIT License
203 stars 105 forks source link

Use GitVersion to determine the version for each build #199

Open CharliePoole opened 8 years ago

CharliePoole commented 8 years ago

@asbjornu Could you comment on the following output I got from GitVersion locally when working on this issue? I'm using the defaults. See questions below the output...

DumpGitVersion

Executing task: DumpGitVersion Major = 3 Minor = 2 Patch = 1 PreReleaseTag = issue-199.1 PreReleaseTagWithDash = -issue-199.1 PreReleaseLabel = issue-199 PreReleaseNumber = 1 BuildMetaData = 27 BuildMetaDataPadded = 0027 FullBuildMetaData = 27.Branch.issue-199.Sha.49ec2a90884a87792162557c9dc4791c2966 ccaa MajorMinorPatch = 3.2.1 SemVer = 3.2.1-issue-199.1 LegacySemVer = 3.2.1-issue-199-1 LegacySemVerPadded = 3.2.1-issue-199-0001 AssemblySemVer = 3.2.1.0 FullSemVer = 3.2.1-issue-199.1+27 InformationalVersion = 3.2.1-issue-199.1+27.Branch.issue-199.Sha.49ec2a90884a877 92162557c9dc4791c2966ccaa BranchName = issue-199 Sha = 49ec2a90884a87792162557c9dc4791c2966ccaa NuGetVersionV2 = 3.2.1-issue-199-0001 NuGetVersion = 3.2.1-issue-199-0001 CommitsSinceVersionSource = 27 CommitsSinceVersionSourcePadded = 0027 CommitDate = 2016-07-07 Finished executing task: DumpGitVersion

I don't understand where semver 3.2.1 came from. Listing tags on this branch give me 3.4 as the last one - 3.2 was the one before that.

The number 27 seems to be the number of commits since "VersionSource" - what does that mean?

What is the .1 that is added to the pre-release suffix? Is that PreReleaseNumber as well? Where does it come from?

CharliePoole commented 8 years ago

@asbjornu Did you see this?

asbjornu commented 8 years ago

@CharliePoole Sorry, haven't seen it until now. And it's way past bedtime, so I'll have to look at it tomorrow. 😴

asbjornu commented 8 years ago

If the branch issue-199 is created from the current tip of master (commit 49ec2a90884a87792162557c9dc4791c2966ccaa), my local graph should look fairly similar to yours. This is what I'm seeing in SmartGit's log window:

screen shot 2016-07-08 at 13 43 07

As you can see quite clearly, the first reachable tag from the issue-199 branch is 3.2 on commit 52dfed446f90aab0adaea1fc7831048073df0581. The 3.4 tag on commit 81e037b2ae5b2b338e7dacabe7ef5cf72952f184 is not reachable since it has not been merged into master and I assume issue-199 has not been created from the release-3.4 branch either.

asbjornu commented 8 years ago

To see reachable commits from the current one, you can do this on the command line:

git log --graph --format="%h %cr %d" --decorate --date=relative --all --remotes=*
CharliePoole commented 8 years ago

@asbjornu I think I figured some of this out.

The merging in of the release-3.2 branch was exactly 27 commits back. There is a 3.4 tag on the branch, but comes from a merged commit made a while back.

I guess this has to do with our various experiments in how to do releases. For 3.4 and 3.4.1, we never merged the actual release branch to master because it only had the version number change on it. This is a practice we have been trying out in order to avoid updating master to a new patch level when we are already working on a new minor. GitFlow should solve this once we get going.

I still don't know what that .1 is about though?

CharliePoole commented 8 years ago

@asbjornu In this repo, I'm experimenting with using the Cake tool, which is just a wrapper around the command-line. If I use it to update assemblyinfo before building, what do we then do with the modified file? On AppVeyor it won't matter because the agent goes away when we are done. But on a local build it would leave a modified file in the working directory. I'm thinking about doing a checkout command to get the file back to its original state.

Using this approach is just an experiment for now, but I want to carry it through before deciding whether to go this way or use the task.

CharliePoole commented 8 years ago

@asbjornu I have discovered that GitVersion command (through Cake) is in fact able to add version info to an AssemblyInfo file that doesn't have any. Must be a changed behavior.

CharliePoole commented 8 years ago

@asbjornu Ah ha! I see you did answer me... seems like what you are saying is close to what I discovered in rooting about.

It seems unfortunate that there is no way to simply use GitVersionTask and have it leave behind the info we want to use in creating packages. But until that's possible, it seems like using both the task and the tool are really necessary. Do you agree?

AGBrown commented 6 years ago

@CharliePoole - I'm very late to the party, so I'm not sure if this is still relevant.

We put together a small nuget which is installed into one of the projects to be built in any solution that needs to know about it's git version info, for nuget packaging as an example.

The version info nuget contains a .targets file which is added to the .csproj by the install, and uses an Install.ps1 file to update .gitignore to add an exclusion for the file which will be written after builds. The .targets itself writes out the gitversion details to a file after gitversiontask has run. It does this by adding a Target element with AfterTargets="GetVersion". Future build or deployment pipeline tasks can then read that data file and use the details in it to do whatever they need.

I've never done much more with it in terms of open sourcing it, and the ps1 file is a bit of a nasty hack IMHO. However it is used in all our projects which create NuGet packages, and we don't seem to have problems with it. So, warning: WOMM (or at least, in all our environments).

.targets file:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">$(MSBuildProjectDirectory)\..\</SolutionDir>

    <OutputPropertiesFile Condition=" '$(OutputPropertiesFile)' == '' ">java</OutputPropertiesFile>
  </PropertyGroup>

  <Target Name="OutputJavaPropertiesFile" AfterTargets="GetVersion" Condition="$(OutputPropertiesFile) == 'java'">
    <Message Importance="High" Text="Writing output to Java Properties File" />
    <WriteLinesToFile File="$(SolutionDir)gitversion.properties" Overwrite="true"  Lines="GitVersion_Major = $(GitVersion_Major)" />
    <WriteLinesToFile File="$(SolutionDir)gitversion.properties" Overwrite="false" Lines="GitVersion_Minor = $(GitVersion_Minor)" />
    <WriteLinesToFile File="$(SolutionDir)gitversion.properties" Overwrite="false" Lines="GitVersion_Patch = $(GitVersion_Patch)" />
    <WriteLinesToFile File="$(SolutionDir)gitversion.properties" Overwrite="false" Lines="GitVersion_BuildMetaData = $(GitVersion_BuildMetaData)" />
    <WriteLinesToFile File="$(SolutionDir)gitversion.properties" Overwrite="false" Lines="GitVersion_BuildMetaDataPadded = $(GitVersion_BuildMetaDataPadded)" />
    <WriteLinesToFile File="$(SolutionDir)gitversion.properties" Overwrite="false" Lines="GitVersion_FullBuildMetaData = $(GitVersion_FullBuildMetaData)" />
    <WriteLinesToFile File="$(SolutionDir)gitversion.properties" Overwrite="false" Lines="GitVersion_BranchName = $(GitVersion_BranchName)" />
    <WriteLinesToFile File="$(SolutionDir)gitversion.properties" Overwrite="false" Lines="GitVersion_Sha = $(GitVersion_Sha)" />
    <WriteLinesToFile File="$(SolutionDir)gitversion.properties" Overwrite="false" Lines="GitVersion_MajorMinorPatch = $(GitVersion_MajorMinorPatch)" />
    <WriteLinesToFile File="$(SolutionDir)gitversion.properties" Overwrite="false" Lines="GitVersion_SemVer = $(GitVersion_SemVer)" />
    <WriteLinesToFile File="$(SolutionDir)gitversion.properties" Overwrite="false" Lines="GitVersion_LegacySemVer = $(GitVersion_LegacySemVer)" />
    <WriteLinesToFile File="$(SolutionDir)gitversion.properties" Overwrite="false" Lines="GitVersion_LegacySemVerPadded = $(GitVersion_LegacySemVerPadded)" />
    <WriteLinesToFile File="$(SolutionDir)gitversion.properties" Overwrite="false" Lines="GitVersion_FullSemVer = $(GitVersion_FullSemVer)" />
    <WriteLinesToFile File="$(SolutionDir)gitversion.properties" Overwrite="false" Lines="GitVersion_AssemblySemVer = $(GitVersion_AssemblySemVer)" />
    <WriteLinesToFile File="$(SolutionDir)gitversion.properties" Overwrite="false" Lines="GitVersion_NuGetVersion = $(GitVersion_NuGetVersion)" />
    <WriteLinesToFile File="$(SolutionDir)gitversion.properties" Overwrite="false" Lines="GitVersion_PreReleaseTag = $(GitVersion_PreReleaseTag)" />
    <WriteLinesToFile File="$(SolutionDir)gitversion.properties" Overwrite="false" Lines="GitVersion_PreReleaseTagWithDash = $(GitVersion_PreReleaseTagWithDash)" />
    <WriteLinesToFile File="$(SolutionDir)gitversion.properties" Overwrite="false" Lines="GitVersion_PreReleaseLabel = $(GitVersion_PreReleaseLabel)" />
    <WriteLinesToFile File="$(SolutionDir)gitversion.properties" Overwrite="false" Lines="GitVersion_PreReleaseNumber = $(GitVersion_PreReleaseNumber)" />
    <WriteLinesToFile File="$(SolutionDir)gitversion.properties" Overwrite="false" Lines="GitVersion_InformationalVersion = $(GitVersion_InformationalVersion)" />
    <WriteLinesToFile File="$(SolutionDir)gitversion.properties" Overwrite="false" Lines="GitVersion_CommitDate = $(GitVersion_CommitDate)" />
    <WriteLinesToFile File="$(SolutionDir)gitversion.properties" Overwrite="false" Lines="GitVersion_CommitsSinceVersionSource = $(GitVersion_CommitsSinceVersionSource)" />
    <WriteLinesToFile File="$(SolutionDir)gitversion.properties" Overwrite="false" Lines="GitVersion_CommitsSinceVersionSourcePadded = $(GitVersion_CommitsSinceVersionSourcePadded)" />
  </Target>

</Project>

Install.ps1

param($installPath, $toolsPath, $package, $project)

$currentDir = [System.IO.Path]::GetDirectoryName($project.FullName)
Write-Host "Found project directory at '$currentDir'"
Write-Host "Looking for .git folder"

$dinf = new-object System.IO.DirectoryInfo $currentDir
$ok = $false
while ($true)
{
    $gitDirs = $dinf.GetDirectories(".git")
    if ($gitDirs.Length -eq 1) {
        $ok = $true
        Break
    }
    else {
        if ($dinf.Parent -eq $null) { 
            Write-Error "Could not find .git directory and could not therefore update .gitignore"; 
            Break
        }
        $dinf = $dinf.Parent
    }
}

if ($ok) {
    Write-Host "Found .git directory in '$($dinf.FullName)'. Updating .gitignore"
    $gitignores = $dinf.GetFiles(".gitignore")
    $outPath = [system.io.path]::Combine($dinf.FullName, ".gitignore")
    $lines = @(
        "#GitVersionTaskEx: comment out the following line if you really want to include gitversion.properties in your git repo (not recommended)",
        "gitversion.properties"
        )
    if ($gitignores.Length -eq 0) {
        Write-Host "Creating .gitignore"
        [System.IO.File]::WriteAllLines($outPath, $lines)
    }
    else {
        Write-Host "Updating .gitignore"
        $text = [System.IO.File]::ReadAllText($outPath)
        $ending = "`n" # LF
        if ($text.contains("`r")) {
            $ending = "`r`n" # CRLF
        }
        if ($text.contains("gitversion.properties")) {
            Write-Host ".gitignore already contains GitVersionTaskEx exclusion, will not update"
        } 
        else {
            $text = $text + $ending + $lines[0] + $ending + $lines[1] + $ending 
            Write-Host ".gitignore does not contain GitVersionTaskEx exclusion, updating now"
            [System.IO.File]::WriteAllText($outPath, $text)
        }
    }
}

Example of relevant sections in csproj file:

  <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
    <PropertyGroup>
      <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
    </PropertyGroup>
    <Error Condition="!Exists('..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Microsoft.Bcl.Build.1.0.21\build\Microsoft.Bcl.Build.targets'))" />
    <Error Condition="!Exists('..\packages\GitVersionTaskEx.1.2.0\build\portable-net+sl+win+wpa+wp\GitVersionTaskEx.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\GitVersionTaskEx.1.2.0\build\portable-net+sl+win+wpa+wp\GitVersionTaskEx.targets'))" />
    <Error Condition="!Exists('..\packages\GitVersionTask.3.6.5\build\dotnet\GitVersionTask.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\GitVersionTask.3.6.5\build\dotnet\GitVersionTask.targets'))" />
  </Target>
  <Import Project="..\packages\GitVersionTaskEx.1.2.0\build\portable-net+sl+win+wpa+wp\GitVersionTaskEx.targets" Condition="Exists('..\packages\GitVersionTaskEx.1.2.0\build\portable-net+sl+win+wpa+wp\GitVersionTaskEx.targets')" />
  <Import Project="..\packages\GitVersionTask.3.6.5\build\dotnet\GitVersionTask.targets" Condition="Exists('..\packages\GitVersionTask.3.6.5\build\dotnet\GitVersionTask.targets')" />