-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBuild.cs
178 lines (150 loc) · 5.51 KB
/
Build.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
using JetBrains.Annotations;
using Nuke.Common;
using Nuke.Common.Git;
using Nuke.Common.IO;
using Nuke.Common.ProjectModel;
using Nuke.Common.Tooling;
using Nuke.Common.Tools.Docker;
using Nuke.Common.Tools.DotNet;
using Nuke.Common.Tools.GitVersion;
using Polly;
using Serilog;
using System;
using static Nuke.Common.Tools.Docker.DockerTasks;
using static Nuke.Common.Tools.DotNet.DotNetTasks;
using static Nuke.Common.Tools.Git.GitTasks;
using static Nuke.Common.Tools.GitHub.GitHubTasks;
class Build : NukeBuild
{
const string ApiAssemblyName = "MagicEightBall.API";
const string ContainerRegistry = "ghcr.io";
const string Image = "magic-8-ball-api";
const string BuiltInImageTag = Image + ":built-in";
const string DockerfileImageTag = Image + ":dockerfile";
public static int Main() => Execute<Build>(b => b.Compile);
[GitRepository]
readonly GitRepository GitRepository;
[GitVersion(UpdateBuildNumber = true)]
readonly GitVersion GitVersion;
[Parameter("Configuration to build - Default is 'Debug' (local) or 'Release' (server)")]
readonly Configuration Configuration = IsLocalBuild ? Configuration.Debug : Configuration.Release;
[Parameter("The PAT used in order to push the Docker image to the container registry")]
readonly string ContainerRegistryPAT;
[Parameter("The GitHub user account that will be used to push the Docker image to the container registry")]
readonly string ContainerRegistryUsername;
[Parameter("The git author username, used for tagging release commits.")]
readonly string GitAuthorUsername;
[Parameter("The git author email, used for tagging release commits.")]
readonly string GitAuthorEmail;
readonly AbsolutePath ApiProject = RootDirectory / "src" / ApiAssemblyName;
Target Clean => _ => _
.Before(Restore)
.Executes(() => DotNetClean(c => c.SetProject(ApiProject)));
Target Restore => _ => _
.Executes(() => DotNetRestore(s => s.SetProjectFile(ApiProject)));
Target Compile => _ => _
.DependsOn(Clean, Restore)
.Executes(() =>
{
DotNetBuild(s => s
.SetProjectFile(ApiProject)
.SetConfiguration(Configuration)
.SetAssemblyVersion(GitVersion.AssemblySemVer)
.SetFileVersion(GitVersion.AssemblySemFileVer)
.SetInformationalVersion(GitVersion.InformationalVersion)
.EnableNoRestore());
Log.Information("Current semver: {@Version}", GitVersion.FullSemVer);
});
[UsedImplicitly]
Target BuildApiImageWithBuiltInContainerSupport => _ => _
.Description("Builds the API image with the built-in container support from dotnet.")
.DependsOn(Compile)
.Executes(() =>
{
DotNetPublish(c => c
.SetProject(ApiProject)
.SetOperatingSystem("linux")
.SetArchitecture("x64")
.SetConfiguration("Debug")
.SetPublishProfile("DefaultContainer"));
});
[UsedImplicitly]
Target BuildApiImageWithDockerfile => _ => _
.Description("Builds the API image with a multi-stage build through a Dockerfile.")
.DependsOn(Compile)
.Executes(() =>
{
DockerBuild(s => s
.SetProcessEnvironmentVariable("DOCKER_BUILDKIT", "1")
.SetProcessWorkingDirectory(RootDirectory)
.SetFile(ApiProject / "Dockerfile")
.SetPath(".")
.SetTag(DockerfileImageTag));
});
[UsedImplicitly]
Target PushImagesToContainerRegistry => _ => _
.Description("Pushes built OCI images to a container registry.")
.WhenSkipped(DependencyBehavior.Skip)
.DependsOn(BuildApiImageWithBuiltInContainerSupport, BuildApiImageWithDockerfile)
.OnlyWhenDynamic(() => GitRepository.IsOnMainOrMasterBranch())
.Triggers(TagReleaseCommit)
.Requires(
() => ContainerRegistryPAT,
() => ContainerRegistryUsername)
.Executes(() =>
{
PublishImage(DockerfileImageTag);
PublishImage(BuiltInImageTag);
});
Target TagReleaseCommit => _ => _
.Description("Creates a git tag with the current semantic version.")
.OnlyWhenDynamic(() => GitRepository.IsOnMainOrMasterBranch())
.Requires(
() => GitAuthorEmail,
() => GitAuthorUsername)
.Executes(() =>
{
Git($"config user.email \"{GitAuthorEmail}\"");
Git($"config user.name \"{GitAuthorUsername}\"");
Git($"tag -a {GitVersion.FullSemVer} -m \"Release: '{GitVersion.FullSemVer}'\"");
Git("push --follow-tags");
});
/// <summary>
/// Publishes an OCI image to a given container registry.
/// </summary>
/// <param name="imageName">The image tag, that needs to be pushed.</param>
private void PublishImage(string imageName)
{
ArgumentNullException.ThrowIfNullOrWhiteSpace(imageName);
Policy
.Handle<Exception>()
.WaitAndRetry(5,
retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
(ex, _, retryCount, _) =>
{
Log.Warning(ex, "Docker login was unsuccessful");
Log.Information("Attempting to login into GitHub Docker image registry. Try #{RetryCount}", retryCount);
})
.Execute(() => DockerLogin(s => s
.SetServer(ContainerRegistry)
.SetUsername(ContainerRegistryUsername)
.SetPassword(ContainerRegistryPAT)
.DisableProcessOutputLogging()));
var repositoryOwner = GitRepository.GetGitHubOwner();
var repositoryName = GitRepository.GetGitHubName();
var targetImageName =
$"{ContainerRegistry}/{repositoryOwner.ToLowerInvariant()}/{repositoryName}/{imageName}";
var tagWithSemver = targetImageName + '-' + GitVersion.FullSemVer;
DockerTag(s => s
.SetSourceImage(imageName)
.SetTargetImage(tagWithSemver));
DockerPush(s => s.SetName(tagWithSemver));
if (GitRepository.IsOnMainOrMasterBranch())
{
DockerTag(s => s
.SetSourceImage(imageName)
.SetTargetImage(targetImageName));
DockerPush(s => s.SetName(targetImageName));
}
}
}