I’ve been using FAKE since roughly 2009 when Steffen Forkmann first introduced it. I’ve used it for OSS and work projects, builds and deployments, and even committed features to it. I think FAKE is a fantastic tool, and I loved the changes that came in FAKE 5.
However, I’ve been reconsidering my use of FAKE as a default build scripting tool in smaller projects and wanted to write up my reasons for switching to dotnet
CLI builds for new projects and migrating some OSS projects to do the same.
Build Script
I have always thought FAKE was quite easy to set up for a project, as you can see from the Getting Started page. With the addition of installation as a dotnet local tool, it’s really easier than ever. However, compare that with the following:
dotnet restore
dotnet build --no-restore -c Release
dotnet test --no-restore --no-build -c Release
dotnet pack --no-restore --no-build -c Release -o bin --include-symbols
I can run that from the command line or put it into a script or .yml
file for use in a CI/CD tool. It’s simple, consistent, and portable without trying hard. It’s certainly simpler than even a simple FAKE script.
Versioning
I have used several methods for managing version is my FAKE scripts in the past. I generally copied the same set of functions from project to project. Note: that’s functions, plural. In the past, this required setting up things for modifying AssemblyInfo
, but with the introduction of VersionPrefix
, Version
, and VersionSuffix
in the .*proj
formats, managing this with a Directory.Build.props
and a little bit of PowerShell, which is also cross-platform, is even simpler. Here’s an example from the FSharp.Control.Reactive project:
[xml]$doc = Get-Content .\src\Directory.Build.props
$version = $doc.Project.PropertyGroup.VersionPrefix # the version under development, update after a release
$versionSuffix = '-build.0' # manually incremented for local builds
function isVersionTag($tag){
$v = New-Object Version
[Version]::TryParse($tag, [ref]$v)
}
if ($env:appveyor){
$versionSuffix = '-build.' + $env:appveyor_build_number
if ($env:appveyor_repo_tag -eq 'true' -and (isVersionTag($env:appveyor_repo_tag_name))){
$version = $env:appveyor_repo_tag_name
$versionSuffix = ''
}
Update-AppveyorBuild -Version "$version$versionSuffix"
}
dotnet tool restore
dotnet build -c Release /p:Version=$version$versionSuffix
dotnet test --no-build -c Release tests
dotnet pack --no-restore -c Release /p:Version=$version$versionSuffix -o $psscriptroot/bin
Feel free to disagree. I don’t love PowerShell like I love F#, but this is a worthwhile tradeoff for me.
Release Notes
The one thing that kept me with FAKE the longest was its excellent support for managing versions and release notes with its RELEASE_NOTES.md
support. I recently stumbled across a post describing how to manage release notes outside of a .*proj
file. While I don’t love using MSBuild tasks, this is another one where the benefits outweigh the cost. The nice thing here is that I’m able to include this once in my Directory.Build.props
file and have it apply to all of the packaged .nupkg
s. Here’s the relevant snippet from the FSharp.Control.Reactive project:
<Target Name="PreparePackageReleaseNotesFromFile" BeforeTargets="GenerateNuspec">
<ReadLinesFromFile File="..\..\RELEASE_NOTES.md">
<Output TaskParameter="Lines" ItemName="ReleaseNoteLines" />
</ReadLinesFromFile>
<PropertyGroup>
<PackageReleaseNotes>@(ReleaseNoteLines, '%0a')</PackageReleaseNotes>
</PropertyGroup>
</Target>
This will put the full contents of the RELEASE_NOTES.md
file into my FSharp.Control.Reactive.*.nupkg
package. I still need to do a little work to take only the relevant lines for the current version, I don’t mind the simplicity.
What’s Left for FAKE?
With all of the above, you may wonder whether there is anything for which I would still use FAKE. I certainly continue to use FAKE for many other purposes. Here’s a list of things for which I continue to use FAKE:
- Generating documentation
- Building and migrating SQL Server databases with SqlPackage
- Complex deployments
- Slide decks
FAKE is a really good tool, and I still highly recommend it. I think the team working on it is doing a great job, and if the things I describe above are not trade-offs you are willing to make, then by all means stick with FAKE.
What do you think? Agree or disagree with any of the directions I’ve taken above? I’m open to changing my mind on these things, and I would love to hear your opinions. Leave a comment!
One thought on “My Take on FAKE in 2020”
Comments are closed.