Cake build
Package | Release | Pre-release |
---|---|---|
Contoso.Hello.Logic |
||
Contoso.Hello.SuperLogic |
CI | Status | Platform(s) | Framework(s) | Test Framework(s) |
---|---|---|---|---|
AppVeyor | Windows |
netstandard2.0 , net461 |
net6.0 , net461 |
|
Azure DevOps | Linux |
netstandard2.0 |
net6.0 |
|
CircleCI | Docker : mcr.microsoft.com/dotnet/sdk:6.0-focal |
netstandard2.0 |
net6.0 |
|
GitHub | Windows |
netstandard2.0 , net461 |
net6.0 , net461 |
Demonstrates a basic build of a .NET
NuGet
package using Cake.
I tried to create a somewhat realistic scenario without writing too much code:
- The solution contains two projects which will be packed as
NuGet
packages.- The
SuperLogic
project depends fromLogic
and when packing this project reference will be turned into aNuGet
package reference (handled out of the box bydotnet pack
). - The
Logic
project references aNuGet
package from nuget.org via aPackageReference
,dotnet pack
will turn this into a package reference.
- The
- The projects target both
netstandard2.0
andnet461
so they can be used with the.NET Framework
(net461
and above). - The solution contains a test project.
- Use
SemVer
to version theDLLs
and theNuGet
packages.- Note:
SemVer
is implemented viaGitVersion
.
- Note:
I wrote a blog post about this experiment.
Table of contents
- Pinning the version of Cake
- Running locally
- Benefits over a nuspec file
- Referencing a project without turning it into a package reference
- CI
- Status checks
Pinning the version of Cake
Pinning the version of Cake
guarantees you'll be using the same version of Cake
on your machine and on the build server.
This is done by using Cake
as a .NET
local tool. The version is specified in .config\dotnet-tools.json
.
Running locally
Pre-requisites
- .NET SDK 6.0.x and higher
Initial setup on Windows
.\bootstrap.ps1
Initial setup on Linux / OS X
./bootstrap.sh
Run build script
dotnet cake build.cake
Benefits over a nuspec file
- A single file describing the package and the project instead of two (
*.csproj
and*.nuspec
) - References (projects or
NuGet
packages) are resolved automatically. There is no need to tweak a file manually any more!
Referencing a project without turning it into a package reference
The SuperLogic
project depends on the ExtraLogic
project but we don't want to ship ExtraLogic
as a package. Instead we want to include Contoso.Hello.ExtraLogic.dll
in the SuperLogic
package directly. Currently this is not supported out of the box but the team is tracking it.
Luckily this issue provides a workaround. All the modifications will take place in SuperLogic.csproj
.
- In the
<PropertyGroup>
section add the following line:
<TargetsForTfmSpecificBuildOutput>$(TargetsForTfmSpecificBuildOutput);IncludeReferencedProjectInPackage</TargetsForTfmSpecificBuildOutput>
- Prevent the project to be added as a package reference by making all assets private.
<ProjectReference Include="..\ExtraLogic\ExtraLogic.csproj">
<PrivateAssets>all</PrivateAssets>
</ProjectReference>
- Finally add the target responsible of copying the
DLL
:
<Target Name="IncludeReferencedProjectInPackage">
<ItemGroup>
<BuildOutputInPackage Include="$(OutputPath)Contoso.Hello.ExtraLogic.dll" />
</ItemGroup>
</Target>
CI
Each time a commit is pushed to main
or features/*
; AppVeyor
, Azure DevOps
, CircleCI
and GitHub
will build the changes.
In case of a successful build GitHub
will:
- On
main
- On
features/*
When running on a platform that is not Windows, we can't target the .NET
full Framework, hence the build script is calling IsRunningOnLinuxOrDarwin
to detect the available capabilities.
AppVeyor
Build status is visible here.
- Supports
Linux
,macOS
andWindows
hosted agents - Can create a
GitHub
release andtag
therepository
if required - Supports artifacts and test results
- You can modify
AppVeyor
's build number programaticallyCake
integrates withAppVeyor
: publish test results, upload artifacts, update build number...
- Partially supports files exclusion (commits are skipped as soon as they contain one file in the excluded list)
Azure DevOps
Azure DevOps does not offer a free an unlimited plan for open-source projects any more.
Build status is visible here.
- Supports
Docker
,Linux
,macOS
andWindows
hosted agents - Supports artifacts and test results
- Supports files exclusion
CircleCI
Build status is visible here.
- Supports
Docker
,Linux
,macOS
andWindows
hosted agents - Supports artifacts
CircleCI
has a few limitations:
- Test results have to be in
JUnit
format, you can use the package JunitXml.TestLogger for aJUnit
logger - Can't exclude files easily
GitHub
Build status is visible here.
- Supports
Docker
,Linux
,macOS
andWindows
hosted agents - Supports artifacts
- Supports files exclusion
GitHub
has a few limitations:
- A third-party / custom Action is required to report test results
- A third-party / custom Action is required to create a GitHub release
Status checks
The main
branch is protected
:
- Force push is disabled on
main
main
cannot be deleted- Non-protected branches (such as
features/*
) cannot be merged intomain
until they satisfy:- An
AppVeyor
passing build - An
Azure DevOps
passing build - A
CircleCI
passing build - A
GitHub
passing build
- An
After a branch was configured as protected
, GitHub
will suggest available status checks.