Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .nuke/build.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
"CleanProjects",
"PackBinaries",
"PreRelease",
"PreReleaseContainer",
"PublishBinaries",
"PublishContainer",
"Release",
Expand Down
3 changes: 2 additions & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="HLabs.Containers" Version="1.0.0-preview.1" />
<PackageVersion Include="HLabs.ImageReferences" Version="1.0.0-preview.2" />
<PackageVersion Include="HLabs.ImageReferences.Extensions.Nuke" Version="1.0.0-preview.2" />
<PackageVersion Include="Humanizer" Version="3.0.1" />
<PackageVersion Include="IPNetwork2" Version="3.4.853" />
<PackageVersion Include="JsonSchema.Net" Version="9.0.0" />
Expand Down
3 changes: 2 additions & 1 deletion build-utils/Build.Utilities/Build.Utilities.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">

<ItemGroup>
<PackageReference Include="HLabs.Containers" />
<PackageReference Include="HLabs.ImageReferences" />
<PackageReference Include="HLabs.ImageReferences.Extensions.Nuke" />
<PackageReference Include="Humanizer" />
<PackageReference Include="Semver" />
<PackageReference Include="Nuke.Common" />
Expand Down
26 changes: 0 additions & 26 deletions build-utils/Build.Utilities/ContainerImage/NukeExtensions.cs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using HLabs.Containers;
using HLabs.ImageReferences;
using Semver;

namespace Drift.Build.Utilities.Versioning.Abstractions;
Expand All @@ -16,5 +16,5 @@ public interface IReleaseInfo {

Task<string> GetGitTagAsync();

Task<ICollection<ImageReference>> GetImageReferences();
Task<ICollection<QualifiedImageRef>> GetImageReferences();
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using Drift.Build.Utilities.Versioning.Abstractions;
using HLabs.Containers;
using HLabs.ImageReferences;
using JetBrains.Annotations;
using Nuke.Common;
using Nuke.Common.Git;
Expand Down Expand Up @@ -40,7 +40,7 @@
}
}

[CanBeNull] public IReleaseInfo Release => this;

Check warning on line 43 in build-utils/Build.Utilities/Versioning/ReleaseVersioningBase.cs

View workflow job for this annotation

GitHub Actions / Test

Each attribute should be placed on its own line of code. (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1134.md)

Check warning on line 43 in build-utils/Build.Utilities/Versioning/ReleaseVersioningBase.cs

View workflow job for this annotation

GitHub Actions / Pre-release

Each attribute should be placed on its own line of code. (https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1134.md)

public abstract Task<SemVersion> GetVersionAsync();

Expand All @@ -51,9 +51,9 @@
return _cachedGitTag;
}

public virtual async Task<ICollection<ImageReference>> GetImageReferences() {
public virtual async Task<ICollection<QualifiedImageRef>> GetImageReferences() {
return [
ImageReference.DockerIo( "hojmark", "drift", await GetVersionAsync() )
"hojmark/drift".Image().Qualify( await GetVersionAsync() )
];
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System.Globalization;
using Drift.Build.Utilities.Versioning.Abstractions;
using HLabs.Containers;
using HLabs.ImageReferences;
using Nuke.Common.Git;
using Nuke.Common.Tools.GitHub;
using Octokit;
Expand All @@ -15,7 +15,7 @@
string? customVersion,
GitRepository repository,
IGitHubClient gitHubClient
) : ReleaseVersioningBase( build, configuration, repository, gitHubClient ) {

Check warning on line 18 in build-utils/Build.Utilities/Versioning/Strategies/ReleaseVersioning.cs

View workflow job for this annotation

GitHub Actions / Test

Parameter 'IGitHubClient gitHubClient' is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well.

Check warning on line 18 in build-utils/Build.Utilities/Versioning/Strategies/ReleaseVersioning.cs

View workflow job for this annotation

GitHub Actions / Test

Parameter 'GitRepository repository' is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well.

Check warning on line 18 in build-utils/Build.Utilities/Versioning/Strategies/ReleaseVersioning.cs

View workflow job for this annotation

GitHub Actions / Pre-release

Parameter 'IGitHubClient gitHubClient' is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well.

Check warning on line 18 in build-utils/Build.Utilities/Versioning/Strategies/ReleaseVersioning.cs

View workflow job for this annotation

GitHub Actions / Pre-release

Parameter 'GitRepository repository' is captured into the state of the enclosing type and its value is also passed to the base constructor. The value might be captured by the base class as well.
private SemVersion? _cachedVersion;

public override async Task<SemVersion> GetVersionAsync() {
Expand Down Expand Up @@ -51,9 +51,9 @@
return CreateReleaseName( await GetVersionAsync(), includeMetadata: false );
}

public override async Task<ICollection<ImageReference>> GetImageReferences() {
public override async Task<ICollection<QualifiedImageRef>> GetImageReferences() {
return [
ImageReference.DockerIo( "hojmark", "drift", Tag.Latest ),
"hojmark/drift".Image().Qualify( Tag.Latest ),
..await base.GetImageReferences()
];
}
Expand Down
88 changes: 46 additions & 42 deletions build/NukeBuild.Container.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
using System;
using System.Linq;
using Drift.Build.Utilities;
using Drift.Build.Utilities.ContainerImage;
using HLabs.Containers;
using HLabs.ImageReferences;
using HLabs.ImageReferences.Extensions.Nuke;
using JetBrains.Annotations;
using Nuke.Common;
using Nuke.Common.Tools.Docker;
using Serilog;
using Versioning;

// ReSharper disable VariableHidesOuterVariable
// ReSharper disable AllUnderscoreLocalParameterName
Expand All @@ -23,23 +26,28 @@ partial class NukeBuild {
[Parameter( "DockerHubPassword - Required for releasing container images to Docker Hub" )]
public readonly string DockerHubPassword;

private static readonly PartialImageRef DriftImage = new("drift");
private static readonly PartialImageRef LocalDriftImage = DriftImage.With( Registry.Localhost );
private static readonly PartialImageRef DockerHubDriftImage = DriftImage.With( Registry.DockerHub, "hojmark" );
[CanBeNull] private QualifiedImageRef _driftImageRef;

Target PublishContainer => _ => _
.DependsOn( PublishBinaries, CleanArtifacts )
.Requires( () => Commit )
.Executes( async () => {
using var _ = new OperationTimer( nameof(PublishContainer) );

// TODO use GetContainerImageReferences (.WithRepo(repo))
var version = await Versioning.Value.GetVersionAsync();
var localTagVersion = ImageReference.Localhost( "drift", version );

// var created = DateTime.UtcNow.ToString( "o", CultureInfo.InvariantCulture ); // o = round-trip format / ISO 8601
var tag = new Tag( Guid.NewGuid().ToString( "N" ) );
_driftImageRef = LocalDriftImage.Qualify( tag );

Log.Information( "Building container image {Tag}", localTagVersion );
Log.Information( "Building container image..." );
// var created = DateTime.UtcNow.ToString( "o", CultureInfo.InvariantCulture ); // o = round-trip format / ISO 8601
DockerTasks.DockerBuild( s => s
.SetPath( RootDirectory )
.SetTag( _driftImageRef )
.SetFile( "Containerfile" )
.SetTag( localTagVersion )
.SetLabel(
// Timestamping prevents the build from being idempotent
// $"\"org.opencontainers.image.created={created}\"",
Expand All @@ -48,12 +56,14 @@ partial class NukeBuild {
)
);

// For convenience, tag the image with dev as well
var localTagDev = localTagVersion.WithTag( Tag.Dev );
Log.Information( "Re-tagging {LocalTagVersion} -> {LocalTagDev}", localTagVersion, localTagDev );
Log.Information( "Built image: {ImageRef}", _driftImageRef );

Log.Information( "Tagging image..." );
// For convenience, tag the image with dev
var devTag = LocalDriftImage.Qualify( Tag.Dev );
DockerTasks.DockerTag( s => s
.SetSourceImage( localTagVersion )
.SetTargetImage( localTagDev )
.SetSourceImage( _driftImageRef )
.SetTargetImage( devTag )
);
}
);
Expand All @@ -67,20 +77,18 @@ partial class NukeBuild {
.Executes( async () => {
using var _ = new OperationTimer( nameof(ReleaseContainer) );

var version = await Versioning.Value.GetVersionAsync();
var local = ImageReference.Localhost( "drift", version );
var @public = ( await Versioning.Value.Release!.GetImageReferences() )
var publicReferences = ( await Versioning.Value.Release!.GetImageReferences() )
.OrderBy( LatestLast ) // Pushing 'latest' last will make sure it appears as the most recent tag on Docker Hub
.ToArray();

Push( local, @public.ToArray() );
Push( _driftImageRef, publicReferences.ToArray() );

var repos = @public.Select( r => r.Host ).Distinct();
var registries = publicReferences.Select( r => r.Registry ).Distinct();

Log.Information( "🐋 Released to {Repositories}!", string.Join( " and ", repos ) );
Log.Information( "🐋 Released to {Registries}!", string.Join( " and ", registries ) );
}
);

/*
/// <summary>
/// Releases container image to public Docker Hub!
/// </summary>
Expand All @@ -90,45 +98,45 @@ partial class NukeBuild {
.Executes( async () => {
using var _ = new OperationTimer( nameof(PreReleaseContainer) );

var version = await Versioning.Value.GetVersionAsync();
var local = ImageReference.Localhost( "drift", version );
var publicc = await Versioning.Value.Release!.GetImageReferences();
var publicReferences = await Versioning.Value.Release!.GetImageReferences();

Push( local, publicc.ToArray() );
Push( ImageIdDrift, publicReferences.ToArray() );

var repos = publicc.DistinctBy( r => r.Repository );
var registries = publicReferences.DistinctBy( r => r.Registry );

Log.Information( "🐋 Released to {Repositories}!", string.Join( " and ", repos ) );
Log.Information( "🐋 Released to {Registries}!", string.Join( " and ", registries ) );
}
);
);*/

private static int LatestLast( ImageReference r ) {
return r.Tag is LatestTag ? 1 : 0;
private static int LatestLast( ImageRef r ) {
return r.Tag == Tag.Latest ? 1 : 0;
}

private void Push( ImageReference source, params ImageReference[] targets ) {
ImageReference[] allReferences = [source, ..targets];
var loginToDockerHub = allReferences.Any( reference => reference.Host == DockerIoRegistry.Instance );
private void Push( QualifiedImageRef source, params QualifiedImageRef[] targets ) {
var logInToDockerHub = targets.Any( r => r.Registry == Registry.DockerHub );

try {
if ( loginToDockerHub ) {
if ( logInToDockerHub ) {
DockerHubLogin();
}

Log.Debug(
"Pushing {SourceTag} to: {TargetTags}",
"Pushing {Source} to: {Targets}",
source,
string.Join( ", ", targets.Select( t => t.ToString() ) )
);

foreach ( var target in targets ) {
Log.Debug( "Re-tagging {SourceTag} -> {TargetTag}", source, target );
// Unfortunately, Docker (unlike Podman) does not support pushing an image selected by image ID directly to a
// registry tag (image ID → registry:tag). A local tag must be created first, which prevents this from being a
// single, atomic operation.
Log.Debug( "Tagging {Source} with {Target}", source, target );
DockerTasks.DockerTag( s => s
.SetSourceImage( source )
.SetTargetImage( target )
);

Log.Information( "Pushing {TargetTag}", target );
Log.Information( "Pushing {Target}", target );
DockerTasks.DockerPush( s => s
.SetName( target )
);
Expand All @@ -137,27 +145,23 @@ private void Push( ImageReference source, params ImageReference[] targets ) {
}
}
finally {
if ( loginToDockerHub ) {
if ( logInToDockerHub ) {
DockerHubLogout();
}
}
}

private void DockerHubLogin() {
Log.Debug( "Logging in to Docker Hub" );

DockerTasks.DockerLogin( s => s
.SetServer( Registry.DockerHub )
.SetUsername( DockerHubUsername )
.SetPassword( DockerHubPassword )
.SetServer( DockerIoRegistry.Instance )
);
}

private static void DockerHubLogout() {
Log.Debug( "Logging out of Docker Hub" );

DockerTasks.DockerLogout( s => s
.SetServer( "docker.io" )
);
DockerTasks.DockerLogout( s => s.SetServer( Registry.DockerHub ) );
}
}
2 changes: 1 addition & 1 deletion build/NukeBuild.Release.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ internal partial class NukeBuild {
);

public Target PreRelease => _ => _
.DependsOn( PackBinaries, PreReleaseContainer, Test )
.DependsOn( PackBinaries, ReleaseContainer, Test )
.Executes( async () => {
using var _ = new OperationTimer( nameof(PreRelease) );

Expand Down
10 changes: 4 additions & 6 deletions build/NukeBuild.Test.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System.Threading.Tasks;
using Drift.Build.Utilities;
using Drift.Build.Utilities.MsBuild;
using HLabs.Containers;
using JetBrains.Annotations;
using Nuke.Common;
using Nuke.Common.Tooling;
Expand Down Expand Up @@ -71,17 +70,16 @@ sealed partial class NukeBuild {
.Executes( async () => {
using var _ = new OperationTimer( nameof(TestE2E) );

var version = await Versioning.Value.GetVersionAsync();
var imageRef = _driftImageRef ?? throw new ArgumentNullException( nameof(_driftImageRef) );
Log.Information( "Using image {ImageRef}", imageRef );

foreach ( var runtime in SupportedRuntimes ) {
var driftBinary = Paths.PublishDirectoryForRuntime( runtime ) / "drift";

var envVars = new Dictionary<string, string> {
// { nameof(EnvVar.DRIFT_BINARY_PATH), driftBinary },
{ "DRIFT_BINARY_PATH", driftBinary },
// TODO use this!
// { "DRIFT_CONTAINER_IMAGE_REF", ImageReference.Localhost( "drift", version ).ToString() }
{ "DRIFT_CONTAINER_IMAGE_REF", ImageReference.Localhost( "drift", version ).ToString() }
{ "DRIFT_BINARY_PATH", driftBinary }, //
{ "DRIFT_CONTAINER_IMAGE_REF", imageRef.ToString() }
};

var alternateDockerHost = await FindAlternateDockerHostAsync();
Expand Down
4 changes: 3 additions & 1 deletion build/Versioning/SemVersionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
namespace Versioning;

internal static class SemVersionExtensions {
/*
* NUKE build extensions
*/
internal static DotNetBuildSettings SetVersionProperties(
this DotNetBuildSettings settings,
SemVersion version
Expand All @@ -27,7 +30,6 @@ SemVersion version
/*
* Below methods skips metadata because .NET add the commit hash by itself (somewhere?)
*/

internal static string ToDotNetAssemblyVersion( this SemVersion version ) {
// Takes major.minor.patch and optional build number
return version.WithoutPrereleaseOrMetadata().ToString();
Expand Down
9 changes: 9 additions & 0 deletions build/Versioning/TagExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using HLabs.ImageReferences;

namespace Versioning;

internal static class TagExtensions {
extension( Tag ) {
public static Tag Dev => new("dev");
}
}
2 changes: 1 addition & 1 deletion build/_build.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="HLabs.Containers" />
<PackageReference Include="HLabs.ImageReferences" />
<PackageReference Include="Octokit" />
<PackageReference Include="Semver" />
<PackageReference Include="Nuke.Common" />
Expand Down
2 changes: 1 addition & 1 deletion src/Cli.E2ETests/Cli.E2ETests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="HLabs.Containers" />
<PackageReference Include="HLabs.ImageReferences" />
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="Nuke.Common" />
<PackageReference Include="NUnit" />
Expand Down
Loading
Loading