/cake-build

Demonstrates a basic build of a .NET Core NuGet package using https://cakebuild.net/

Primary LanguageC#MIT LicenseMIT

Cake build

Package Release Pre-release
Contoso.Hello.Logic MyGet MyGet
Contoso.Hello.SuperLogic MyGet MyGet
CI Status Platform(s) Framework(s) Test Framework(s)
AppVeyor Build Status Windows netstandard2.0, net461 netcoreapp2.2.0, net461
Azure DevOps Build Status Linux netstandard2.0 netcoreapp2.2.0
CircleCI Build Status Docker: microsoft/dotnet:2.2.103-sdk-bionic netstandard2.0 netcoreapp2.2.0
Travis CI Build Status Linux, OS X netstandard2.0 netcoreapp2.2.0

Demonstrates a basic build of a .NET Core 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 from Logic and when packing this project reference will be turned into a NuGet package reference (handled out of the box by dotnet pack).
    • The Logic project references a NuGet package from nuget.org via a PackageReference, dotnet pack will turn this into a package reference.
  • The projects target both netstandard2.0 and net461 so they can be used with the .NET Framework (net461 and above).
  • The solution contains a test project.
  • Use SemVer to version the DLLs and the NuGet packages.

I wrote a detailed blog post about this experiment.

Running locally

Pre-requisites

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 anymore!

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>
<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>

Pinning the version of Cake

Pinning the version of Cake guarantees you'll be using the same version of Cake on your machine and in the build server.

CI

Each time a commit is pushed to master or features/*; AppVeyor, Azure DevOps, CircleCI and Travis CI will build the changes.

In case of a successful build AppVeyor will:

  • On master
    • Create a GitHub release
    • Publish the NuGet packages (including symbols) to gabrielweyer feed
  • On features/*
    • Create a GitHub pre-release
    • Publish the NuGet packages (including symbols) to gabrielweyer-pre-release feed

AppVeyor

Build status is visible here.

  • Windows and Linux
  • Can target both .NET Core and .NET Framework when running on Windows
    • For this reason we'll publish the NuGet packages using AppVeyor
  • Can create a GitHub release and tag the repository if required
  • Supports artifacts and test results
  • You can modify AppVeyor's build number programatically
    • Cake integrates with AppVeyor: publish test results, upload artifacts, update build number...
  • Supports files exclusion

Azure DevOps

Build status is visible here.

  • Linux, OS X and Windows
  • Can target both .NET Core and .NET Framework when running on Windows
  • Supports artifacts and test results
  • Supports files exclusion

CircleCI

Build status is visible here.

  • Linux and OS X
  • Build in Docker containers
  • Supports artifacts and test results
    • Test results have to be in JUnit format, you can use the package dotnet-xunit-to-junit to do the transformation
  • Can't exclude files easily

Travis CI

Build status is visible here.

Travis CI has a few limitations:

  • Linux and OS X only so you can't build any net* Frameworks
    • For this reason I'm not publishing the NuGet packages from Travis CI
    • build.cake has been modified
      • Targets netstandard2.0 / netcoreapp2.2.0 only on Travis (search for TravisCI.IsRunningOnTravisCI)
  • Doesn't parse test result files
  • Artifacts have to be uploaded to S3
  • Can't exclude files easily

Status checks

The master branch is protected:

  • Force push is disabled on master
  • master cannot be deleted
  • Non-protected branches (such as features/*) cannot be merged into master until they satisfy:
    • An AppVeyor passing build
    • A Travis passing build
    • A CircleCI passing build

After a branch was configured as protected, GitHub will suggest available status checks.