Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework buildscripts for easier management #749

Closed
wants to merge 12 commits into from

Conversation

zvirja
Copy link
Member

@zvirja zvirja commented Apr 7, 2017

I've reworked build scripts and CI configuration to simplify release management. Now current package version is calculated automatically based on the last tag and number of commits since tag. Also I've configured both CI and our build.fsx to automatically push packages to appropriate NuGet feeds.

The matrix is following (0 means any digit):

Trigger Result Version Action
Add tag v0.0.0 or v.0.0.0-RC0 0.0.0 or 0.0.0-RC0 Build, push to NuGet and MyGet feeds
Add tag v0.0.0-aplha0 (any pre suffix) 0.0.0-aplha0 Build, push to MyGet feed
Push 2 commits after tag v0.0.0 to master/v4 0.0.0.2 Build, push to MyGet feed
Create a PR - Build

Other changes:

  • Update FAKE to latest version. Switch to FAKE.Core package usage as it takes less space.
  • Add tasks to Fake script to calculate Git version, patch assembly version attributes and push to NuGet.
  • Add AssemblyInformationalVersion to each assembly.
  • Move CI configuration to appveyor.yml
  • Add production keys to appveyor.yml
  • Recreated project in AppVeyor, because old project didn't work with appveyor.yml. Likely, that is because of this.

After I merge this PR to master, I'll merge it to v4 and will tune it a bit for .NET Core projects (e.g. change VS image version).

P.S. Large number of changes is caused by FAKE update. The only interesting changes might be build.fsx, appveyor.yml and AssemblyInfo.cs files.

@moodmosaic
Copy link
Member

Now current package version is calculated automatically based on the last tag and number of commits since tag.

What does this mean regarding Semantic Versioning? (AutoFixture follows Semantic Versioning 2.0.0)

@zvirja
Copy link
Member Author

zvirja commented Apr 8, 2017

@moodmosaic A good question. Likely, it was too wide statement so it caused some confusion :) Let me describe why I added it.

I wanted to simplify version management, so it's controlled by tags only. Idea is that if you create a tag, it's used as a version for your assemblies. Additionally I wanted to add support for the Dev feed to have a place which we could consume before a new release is tagged and published to NuGet. Feed might be more suitable as CI artifacts as you can consume it by VS easier.
Both this things required a mechanism to calculate the current assembly version based on repo status, so I added this feature.

For the Production feed (NuGet) the SemVer is never violated - we push on tags only. For such cases number of commits since last tag is always zero. Release manager will manage tags according to SemVer, so it will be honored.

For the Dev feed (MyGet) SemVer will not be violated for the v4 branch, as I'm going to push a tag v4.0.0-alpha at the beginning of our work (or just hardcode version on CI).
However it might be violated for the Dev feed and the master branch after we push commits since last tag. Example: we create a tag v3.7.1 and merge a PR to master after that. The next artifact on Dev feed will have version e.g. 3.7.1.2- this violates SemVer as bugfix or a new feature might appear. However I'd say this is fine as the Dev feed is not designed for the public usage. Rather, it's a feed where you can find the latest artifacts and it will be used in rare cases only. In this case you are aware that you are using something internal.

It would be very redundant to track SemVer for the Dev feed, so we 2 options only - disable Dev feed for the Master branch or have it knowning that this is a private feed with latest artifacts. I'd vote for the last option as such a feed might be very useful sometimes.

@zvirja zvirja closed this Apr 8, 2017
@zvirja zvirja reopened this Apr 8, 2017
@zvirja zvirja force-pushed the rework-buildscripts-for-easier-management branch from d924a61 to f3f92e9 Compare April 9, 2017 14:00
@zvirja
Copy link
Member Author

zvirja commented Apr 9, 2017

I've just rebased my code to remove doc for FAKE from repo - it takes about 10MB :)

Again, most changes were done for a few files only, so likely you could focus on the following files only:

Copy link
Member

@ecampidoglio ecampidoglio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for contributing this! I support the idea of automating the release process by baking it into the build script 👍

However, there are a few issues that need to be addressed before we can move forward.

Build.fsx Outdated
@@ -173,6 +173,7 @@ Target "PublishNuGetRelease" (fun _ -> publishPackagesToNuGet
(getBuildParam "NuGetReleaseKey"))

Target "CompleteBuild" (fun _ -> ())
Target "PublishNuGetAll" (fun _ -> ())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How are the changes in this file related to the commit message? Shouldn't this be part of another commit or even be committed separately?

Copy link
Member Author

@zvirja zvirja Apr 10, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done - moved this change to the previous commit.

Build.fsx Outdated
@@ -19,7 +19,9 @@ let build target configuration =
let properties = [ "Configuration", configuration ] @ keyFile

solutionsToBuild
|> MSBuild "" target properties
|> Seq.iter (fun s -> build (fun p -> { p with Verbosity = Some(Minimal)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why set the verbosity to minimal? Don't we want to have as much information as possible when troubleshooting?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did that intentionally, as it was impossible to track review the build log on CI - browser hung after the pressure of number of build entries.
However, later (in migration to .NET Core branch I'm currently working on) I found that we perform a lot of redundant rebuilds, so probably we could revert this setting back. Will update soon.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done - keep normal verbosity

Build.fsx Outdated

let releaseFolder = "Release"
let nunitToolsFolder = "Packages/NUnit.Runners.2.6.2/tools"
let nuGetOutputFolder = "NuGetPackages"
let solutionsToBuild = !! "Src/*.sln"
let signKeyPath = FullName "Src/AutoFixture.snk"

type GitVersion = { apiVersion:string; nugetVersion:string; }
let getGitVersion =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the idea of letting the version number be calculated based on the history. 👍
However, I strongly suggest we use an established tool like GitVersion for that instead of rolling our own.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do like idea of switching to GitVersion tool, FAKE even have helpers for it, however I don't have experience with that tool. It would take some time for me to read the documentation.

Currently I'm focused on migration to .NET Core, so would like to have this PR merged as soon as possible.
Would it be OK for you if merge this PR as is and switch to GitVersion in v4 branch later?

Build.fsx Outdated
@@ -13,7 +13,7 @@ let nuGetOutputFolder = "NuGetPackages"
let solutionsToBuild = !! "Src/*.sln"
let signKeyPath = FullName "Src/AutoFixture.snk"

type GitVersion = { apiVersion:string; nugetVersion:string; }
type GitVersion = { apiVersion:string; nugetVersion:string }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this whole commit should be squashed into 6e6dad9 as it's unclear what it does on its own. What's the "optimization" here?

Copy link
Member Author

@zvirja zvirja Apr 10, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done - squashed entire commit with the previous one

Build.fsx Outdated
@@ -17,7 +17,7 @@ type GitVersion = { apiVersion:string; nugetVersion:string }
let getGitVersion =
let desc = Git.CommandHelper.runSimpleGitCommand "" "describe --tags --long --match=v*"
// Example for regular: v3.50.2-288-g64fd5c5b, for prerelease: v3.50.2-alpha1-288-g64fd5c5b
let result = Regex.Match(desc, @"^v(?<maj>\d+)\.(?<min>\d+)\.(?<rev>\d+)(?<pre>-(alpha|beta|rc)\d*)?-(?<num>\d+)-g(?<sha>[a-z0-9]+)$", RegexOptions.IgnoreCase).Groups
let result = Regex.Match(desc, @"^v(?<maj>\d+)\.(?<min>\d+)\.(?<rev>\d+)(?<pre>-\w+\d*)?-(?<num>\d+)-g(?<sha>[a-z0-9]+)$", RegexOptions.IgnoreCase).Groups
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, it would be better if we didn't have to support all these use cases on our own. See my previous comment.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See reply below. Let's close this thread ;)

@@ -1,4 +1,4 @@
#r @"packages/FAKE.4.19.0/tools/FakeLib.dll"
#r @"packages/FAKE.Core/tools/FakeLib.dll"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's hard to get an overview of the changes related to updating FAKE when there are another 150K+ deleted lines. Could you please commit the deletion of the old package separately?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want me to perform the rebase and just separate add/remove as separate commits, or want me to rebase and remove this from PR at all, so it will be fired via separate PR later?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think a separate commit for deleting the old package (and its related documentation) is enough. No need for a new PR. 😉

Copy link
Member Author

@zvirja zvirja Apr 10, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done - separated to 2 standalone commits.

@ecampidoglio
Copy link
Member

@zvirja Thank you for your contribution! I left a few comments in my review.

Also, I noticed that the build on AppVeyor is currently broken on master. 😢 I understand that you needed to modify the configuration in order to test these changes, but I really think we should get the build up and running as quickly as possible while this PR is being reviewed.

Could you please make a new PR with a new appveyor.yml file that reproduces the old process? Of course, if you don't have time, I can also do it myself.

@zvirja
Copy link
Member Author

zvirja commented Apr 10, 2017

I do understand your concern regarding the build failing for the master, however there was no other way. I needed to remove the previous AppVeyor project, so currently it relies on appveyor.yml. This file never existed before, therefore now master is broken.

Do you believe that it makes sense to create a temp appveyor.yml? I expect this PR will be merged soon, so everything will become fixed. We don't have too much activities on AF project now, so it might be acceptable to wait for a couple of days. Let me know if you disagree with that and still persist on creation of a temp appveyor.yml via separate PR... :)

@ecampidoglio
Copy link
Member

@zvirja

I expect this PR will be merged soon

In OSS, "soon" could literally mean anything 😉

I still think we should get the build running on master in the meantime. We might have to fix something in the released version, you never know. Plus, it's unhealthy for the project to have a broken build for any extended period of time.

@zvirja zvirja force-pushed the rework-buildscripts-for-easier-management branch from f3f92e9 to 488db65 Compare April 10, 2017 10:02
@zvirja
Copy link
Member Author

zvirja commented Apr 10, 2017

@ecampidoglio I've followed up all the points above and fixed them (except the GitVersion one). Thank you for such a brilliant code review.

Let's follow this way. If PR is not approved by you and {@moodmosaic or @adamchester} till evening, I'll create this file and add it directly to master - it's pretty simple.

@zvirja
Copy link
Member Author

zvirja commented Apr 10, 2017

@ecampidoglio I noticed that you liked the reply, but haven't replied here and haven't approved the PR. Does that mean that you don't agree? 😏

FAKE should be updated to support MSBuild from VS 2017.
FAKE.Core package is used instead of full FAKE because it's smaller,
while all the required functionality is present.
@zvirja zvirja force-pushed the rework-buildscripts-for-easier-management branch from 488db65 to de25f50 Compare April 10, 2017 18:43
@zvirja
Copy link
Member Author

zvirja commented Apr 10, 2017

@ecampidoglio I've pushed legacy configuration, so now our CI is green.

I've also spent few hours playing with GitVersion tool and I hate it 😠 While I find it awesome in some aspects, there is one thing which blows my head up. Tool simply doesn't work property with pre-release tags ending with numbers. Consider the following flow:

  1. You release RC1 and add a tag v4.0.0-rc1. Tool version: v4.0.0-rc0001. I understand that padding, because NuGet doesn't support SemVer 2.0 properly.
  2. You add 2 more commits. Tool version: v4.0.0-rc0002. WHAT?
  3. You add 2 more commits and create a tag v4.0.0-rc2. What do you guess is the tool version? It's 4.0.0-rc0002!

The issue is that SemVer tool simply trims numbers at the end of your pre-release tag. Meaning, that you cannot release rc1 and rc2 builds, as you might end up with same version for absolutely different releases.

If you tweak configuration a bit and play with ContinuousDelivery, ContinuousDeployment and branch specific configuration, you might observe different set of behavior (e.g. it simply ignores commits after the tag assigning them the same NuGet version). But none of them is what I expect to see.

I'm too silly to make it work fine 😢 Therefore, if you could find free time, please rework approach to use this tool instead of the regular expressions. In the meanwhile, I'd like to ask to approve as is. I've improved my clutch to format with commits number with padding - I've found that NuGet might not support SemVer 2.0 properly. I'd be really happy it you can adapt GitVersion tool for tags with ending numbers.

Last tag and number of commits since last tag is used to determine
version. Resolved version is written to the AssemblyInformationalVersion
attribute for each assembly. Later during NuGet pack this version is
used as a NuGet version.

This approach allows to simplify Release Management by controlling
releases via tags creation only.
It appears that NuGet doesn't fully support SemVer 2.0.
Format commits number wtih 4 digits so lex comparison will compare
values correctly
@zvirja zvirja force-pushed the rework-buildscripts-for-easier-management branch from de25f50 to bfb5643 Compare April 10, 2017 21:26
@moodmosaic
Copy link
Member

moodmosaic commented Apr 11, 2017

I've been viewing this item on-and-off the past few days and I have to admit that I'm having a hard time understanding what it does 😕 Though, as long as @ecampidoglio is reviewing this, I feel safe 😃

But maybe we should consider splitting this in smaller pull requests?

@zvirja
Copy link
Member Author

zvirja commented Apr 11, 2017

@moodmosaic Thank you for the time you spent on this. Likely, the most confusion is caused by the FAKE update which brought a huge number of diffs.

Could you clarify which exact parts caused the confusion to you? We could split it to a separate PRs if that is needed, but I need to understand which exact commits you want to group.

@moodmosaic
Copy link
Member

@zvirja, I just can't understand what happens next if/when this pull request gets merged 😕 (I'm not saying that the pull request is bad, just that I can't understand exactly what it does.)

@ecampidoglio
Copy link
Member

ecampidoglio commented Apr 11, 2017

From what I gather, this PR does a few different things:

  • Updates to a new version of FAKE
  • Switches to using the Fake.Core package
  • Moves the CI configuration to appveyor.yml instead of having it in the AppVeyor portal
  • Adds automatic versioning based on the state of the history
  • Adds deployment to NuGet for stable releases
  • Adds deployment to MyGet for prerelease releases

They all go under the umbrella of automating the release process, but I have to say that multiple PRs for each of those items would be easier to manage.

@zvirja
Copy link
Member Author

zvirja commented Apr 11, 2017

Ok, let me describe that :) As I mentioned above, the main purpose of these changes is to use repository status to understand current version, rather than need to patch all the AssemblyInfo files instead. We use current/last tag and number of commits since last tag to automatically generate assembly version. Also I added the MyGet feed for the pre-release builds (e.g. for the v4).

Changes by files:

  • appveyor.yml - Extract all the CI logic to a file. I've added a set of logic to push to different feeds (NuGet and MyGet) depending on different situations. You might find this logic here.

  • build.fsx - A few changes were applied to this file:

    • Add PublishNuGetPreRelease and PublishNuGetRelease tasks to publish produced NuGet artifacts to the feed. I use these tasks in the appveyor.yml file.
    • Add getGitVersion function to resolve version based on current repository status.
    • Add PatchAssemblyVersions target to automatically patch all the AssemblyInfo.cs files before build using the version provided by the getGitVersion function.
    • Given that sign key is now added to repo, I've added parameter to MSBuild to pass that key directly.
  • Switch to FAKE.Core instead of FAKE.

All this staff just allows you to simplify the release procedure. Now all you need is just to create a SemVer tag - build script will use it as a version for versions and nuget packages.

@moodmosaic
Copy link
Member

@ecampidoglio, @zvirja, if you agree, based on this and this, it will be faster then to get this done if it gets split into smaller, separate pull requests.

@zvirja
Copy link
Member Author

zvirja commented Apr 11, 2017

@ecampidoglio appeared to be quicker than me 😉
Agreed! I'll split that to 2 PRs - Update of the FAKE and everything else. Are you fine with that? I don't see a reason to make them smaller.. That should be definitely enough for the better understanding.

@moodmosaic
Copy link
Member

@zvirja, probably it's just me, but I see each item on this list by @ecampidoglio as a separate pull request.

@ecampidoglio
Copy link
Member

Actually, I would prefer to have separate PRs for each of the items that I listed here, assuming I'm not missing anything.

The reason is that we might not want to have everything. For example, while the automatic versioning might be good, we might want to hold off on the MyGet feed.

@zvirja
Copy link
Member Author

zvirja commented Apr 11, 2017

Thanks for the feedback. Likely, that is how review system works in OSS projects - you need to make small granularity changes.

I could rework that to the small sub-sets, the are couple of issues with that:

  1. All these changes are iterative, meaning that I will need to create PRs one by one. That will take a lot of time, before all them are finally merged. It doesn't play well with our plan to release v4 in the nearest future :)
  2. Do you really want to throw something out? If yes - it would make sense to do that. If not - it would be just a process for a process. I do understand that it was my mistake to mix all these changes together and I promise to not do that in future. But this will require me to rework everything just to make granular changes. I've spent almost 1.5 weeks trying to find the working solution for that it it's sad for me to rework everything just for a good history, while the current history is not too bad.

However, by submitting that I'm ready to do that. If you really need that, feel that it would be better for everybody and we cannot accept 2 PRs with FAKE update and everything else - I'll do that! I appreciate the time you spend on this, I want to collaborate and to not make a chaos in our project 😉

@zvirja zvirja mentioned this pull request Apr 11, 2017
@ecampidoglio
Copy link
Member

@zvirja Thank you for understanding. Your efforts are very appreciated 😃

In the future, it's better to discuss your proposed changes with the team first, before you do any actual work (with the exception of a small POC, if necessary). That way, you'll avoid investing a huge chunk of your time doing something that might not align with the vision the rest of the team has for the project.

The preferred way to do that is to create an issue and have the initial discussion there. Once we agree on the course of action, you can submit one or more PRs in reference to that issue.

Again, I want to empathize that I really appreciate your enthusiasm and your will to do good! We just need to dial it back a little so that we don't rock the boat too hard 😉

@zvirja
Copy link
Member Author

zvirja commented Apr 11, 2017

@ecampidoglio Thanks for the appreciation 😌

Ok, let's follow this way. I've already created the first PR with FAKE update and will create more after it will be approved.

I close this one as it will not be merged.

@zvirja zvirja closed this Apr 11, 2017
@zvirja zvirja deleted the rework-buildscripts-for-easier-management branch April 11, 2017 13:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants