CI Integration
Eventually, builds are supposed to be executed in a continuous integration environment. That means that every push will trigger a build to verify committed changes. NUKE aims to seamlessly integrate with those CI systems, for instance by allowing to have typed access to environment variables, reporting warnings and errors in the required format, or publishing artifacts via method calls.
Configuration Generation
Supported for TeamCity, Azure Pipelines, AppVeyor, GitHub Actions.
NUKE goes one step further and allows to conveniently generate the related configuration files, for instance YML files, by using configuration generation attributes. Typically, these attributes are applied to the build class:
[TeamCity(
TeamCityAgentPlatform.Windows,
DefaultBranch = DevelopBranch,
VcsTriggeredTargets = new[] { nameof(Pack), nameof(Test) },
NightlyTriggeredTargets = new[] { nameof(Test) })]
[AzurePipelines(
AzurePipelinesImage.UbuntuLatest,
AzurePipelinesImage.WindowsLatest,
AzurePipelinesImage.MacOsLatest,
InvokedTargets = new[] { nameof(Test), nameof(Pack) })]
class Build : NukeBuild
{
}
Using the nameof
operator for targets and parameters ensures refactoring-safety and that the configuration files are always up-to-date with the actual implementation. After changing the build configuration (e.g., renaming targets), the build must be triggered once, for instance by calling nuke --help
. If any of the configuration files have changed, a warning is reported:
$ nuke --help
NUKE Execution Engine version 1.0.0 (OSX,.NETStandard,Version=v2.0)
Configuration files for TeamCity have changed.
Configuration files for AzurePipelines have changed.
Note
In TeamCity, the Import settings from .teamcity/settings.kts option must be chosen during project creation. Afterwards, Versioned Settings must be enabled as follows:
This approach still allows to apply manual changes to the configurations, like adding triggers, failure conditions, report tabs, and more. In this case, TeamCity will commit a patch file to
.teamcity/patches
in the repository.
For TeamCity and Azure Pipelines, the generated configuration takes advantage of the target dependency model. That means that for every target, a separate build configuration (TeamCity) or job (Azure Pipelines) is created. This provides a better overview for individual target behavior:
Artifacts
Supported for TeamCity, Azure Pipelines, AppVeyor, GitHub Actions.
Usually, builds are supposed to publish some kind of artifacts, like NuGet packages or test results. Using the Produces
call, artifact paths can be defined per target:
Target Pack => _ => _
.Produces(OutputDirectory / "*.nupkg")
.Executes(() =>
{
DotNetPack(s => s
.SetProject(Solution)
.SetOutputDirectory(OutputDirectory));
});
Defining artifact paths with absolute paths is the recommended approach. In the resulting configuration files, they are automatically converted to relative paths.
For multi-staged builds with TeamCity, a target can consume the artifacts from another target by using Produces
and Consumes
in combination:
Target Restore => _ => _
.Produces(SourceDirectory / "*/obj/**/*")
.Executes(() =>
{
});
Target Compile => _ => _
.Consumes(Restore)
.Executes(() =>
{
});
Partitioning
Supported for TeamCity, Azure Pipelines.
Many targets are well-suited to be split into multiple partitions. For instance, think of a target that executes tests for several test assemblies. NUKE introduces an easy way to run those tests in parallel on different agents:
[Partition(2)] readonly Partition TestPartition;
Target Test => _ => _
.DependsOn(Compile)
.Partition(() => TestPartition)
.Executes(() =>
{
var projects = Solution.GetProjects("*.Tests");
var relevantProjects = TestPartition.GetCurrent(projects);
DotNetTest(s => s
.SetConfiguration(Configuration)
.CombineWith(
relevantProjects, (cs, v) => cs
.SetProjectFile(v)));
});
Adding the Partition
attribute on the TestPartition
field will automatically split the execution in to the specified amount of partitions. A partition can be associated with a target via Partition(() => Partition)
. Calling TestPartition.GetCurrent(enumerable)
inside the target implementation returns only the relevant items for the current partition. In terms of configuration files, this is implemented by adding the --test-partition n
parameter. For local executions, the TestPartition
has a size of 1
.
In TeamCity, the resulting build chain would look like this:
Parameters
Supported for TeamCity.
All properties and fields having the ParameterAttribute
applied, will automatically be exposed to the Run Build Type dialog.
Required parameters are marked with red asterisks. Default values are read from the initializers. Enumeration parameters can be picked from a drop-down.
Serialization
Work in progress. This will allow state to be shared when targets are executed on different agents.