Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support publishing of multi-architecture OCI container images #43085

Open
wants to merge 111 commits into
base: release/8.0.4xx
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
111 commits
Select commit Hold shift + click to select a range
b389d3d
teeny tiny amount of work to show an example
baronfel Aug 4, 2024
bf66471
implement CreateImageIndex task
surayya-MS Aug 29, 2024
7324ae3
fix
surayya-MS Aug 29, 2024
9b35f4d
rename
surayya-MS Aug 29, 2024
8c5a3fd
remove comment
surayya-MS Aug 29, 2024
7f9bf21
fix
surayya-MS Aug 29, 2024
d46637c
remove usings
surayya-MS Aug 30, 2024
ec4c94f
fix
surayya-MS Aug 30, 2024
7521fa2
fix
surayya-MS Aug 30, 2024
29ccc1a
fix
surayya-MS Aug 30, 2024
e7d7deb
Revert "fix"
surayya-MS Aug 30, 2024
dd188fc
Revert "fix"
surayya-MS Aug 30, 2024
d9a342f
fix
surayya-MS Aug 30, 2024
6e1af9d
Merge branch 'release/8.0.4xx' into multi-arch-containers
surayya-MS Aug 30, 2024
3fc3c4d
fix init Registry in CreateImageIndex
surayya-MS Aug 30, 2024
8550fb7
fix condition for calling _PublishMultiArchContainers or _PublishSing…
surayya-MS Aug 30, 2024
71765a3
small fix
surayya-MS Aug 30, 2024
905039d
fix condition for including rids in _PublishMultiArchContainers
surayya-MS Aug 30, 2024
852c0c9
Revert "fix condition for including rids in _PublishMultiArchContainers"
surayya-MS Sep 2, 2024
2695e53
optimize targets order
surayya-MS Sep 3, 2024
6fc398c
Merge branch 'release/8.0.4xx' into multi-arch-containers
surayya-MS Sep 3, 2024
64b816c
create each image and skip image index when no container registry is …
surayya-MS Sep 11, 2024
44909ac
Merge branch 'release/8.0.4xx' into multi-arch-containers
surayya-MS Sep 19, 2024
b52a15f
call ComputeContainerImageTag target once for all containers
surayya-MS Sep 20, 2024
d9a3969
Revert "call ComputeContainerImageTag target once for all containers"
surayya-MS Sep 20, 2024
727cb17
Reapply "call ComputeContainerImageTag target once for all containers"
surayya-MS Sep 23, 2024
69bd62b
call ComputeContainerBaseImage and ComputeContainerConfig targets onc…
surayya-MS Sep 23, 2024
02a837e
fix _SkipCreateImageIndex condition
surayya-MS Sep 23, 2024
82c57dc
support ContainerImageTags for image index
surayya-MS Sep 24, 2024
eed384f
improved logging for CreateImageIndex
surayya-MS Sep 24, 2024
ee59377
support posting tarballs to ArchiveRegistry for multi-arch scenario
surayya-MS Sep 26, 2024
d7d673a
small fix
surayya-MS Sep 26, 2024
014e0c4
set _ContainersTargetsDir to point to the containers package path
surayya-MS Sep 30, 2024
8875c40
add code to containers check to allow users to silence it
baronfel Aug 1, 2024
613f2fb
import containers targets only when the package was not referenced
surayya-MS Sep 30, 2024
bbbfe36
rename a property
surayya-MS Sep 30, 2024
4762014
fix e2e tests
surayya-MS Sep 30, 2024
5fc9d6f
1. group outputs of CreateNewImage task into GeneratedContainers
surayya-MS Oct 3, 2024
7236be4
Merge branch 'release/8.0.4xx' into multi-arch-containers
surayya-MS Oct 21, 2024
7387b05
set image index mediaType accurately
surayya-MS Oct 22, 2024
a196718
refactor CreateImageIndex
surayya-MS Oct 22, 2024
5c2b717
change ManifestV2.MediaType to optional
surayya-MS Oct 28, 2024
d482adb
initial oci tarball fix
surayya-MS Oct 29, 2024
420b2be
set image name and tag for oci tarball publishing
surayya-MS Oct 30, 2024
8cb6888
Revert "change ManifestV2.MediaType to optional"
surayya-MS Oct 30, 2024
6f6be5a
make Manifesr.MediaType optional
surayya-MS Oct 30, 2024
30f47a5
small fix
surayya-MS Oct 30, 2024
8e0469e
add annotations to ImageIndexV1 entries; fix oci tarball publishing
surayya-MS Oct 30, 2024
2ea2599
refactor WriteDockerImageToStreamAsync and WriteOciImageToStreamAsync
surayya-MS Oct 31, 2024
e27d5d0
fix CreateImageIndex because of added annotations to oci image index …
surayya-MS Oct 31, 2024
b000b37
small fix
surayya-MS Oct 31, 2024
5b167f6
log error when trying to create tarball for oci image with multiple tags
surayya-MS Oct 31, 2024
0f91db6
improve CreateImageIndex
surayya-MS Oct 31, 2024
8876c83
remove usings
surayya-MS Oct 31, 2024
0f3468a
BugFix: UseAppHost is the property that controls if a project should …
baronfel Nov 1, 2024
df5a123
Bugfix: Ensure that per-RID publishing occurs so that the per-RID ass…
baronfel Nov 1, 2024
a5db173
small fix
surayya-MS Nov 5, 2024
eadbcd4
refactor CreateImageIndex
surayya-MS Nov 5, 2024
1e40d65
small fix
surayya-MS Nov 5, 2024
e283e44
small fix
surayya-MS Nov 5, 2024
b499d62
change error messages
surayya-MS Nov 5, 2024
6f40046
add ImageIndexGeneratorTests
surayya-MS Nov 5, 2024
42fef99
remove usings
surayya-MS Nov 5, 2024
59f0cb2
revert "make Manifesr.MediaType optional"
surayya-MS Nov 6, 2024
1a4ab0c
merge main
surayya-MS Nov 6, 2024
7a1d1f8
fix
surayya-MS Nov 6, 2024
d5dae3d
validate images items metadata in CreateImageIndex; rename field
surayya-MS Nov 6, 2024
2c2651f
fix
surayya-MS Nov 6, 2024
5a69397
remove not used properties
surayya-MS Nov 6, 2024
2b7e624
add output GeneratedContainerMediaType to CreateNewImage; use it in C…
surayya-MS Nov 6, 2024
b705957
add tests that check docker and oci tarball correct structure
surayya-MS Nov 6, 2024
5983b40
fix tests
surayya-MS Nov 6, 2024
9b742b9
fix tests
surayya-MS Nov 6, 2024
5478d79
fix oci tarball tests
surayya-MS Nov 7, 2024
41ef743
add validation for TargetRuntimeIdentifiers in ComputeDotnetBaseImage…
surayya-MS Nov 7, 2024
d182cfa
fix per image publish when rid is linux-musl
surayya-MS Nov 7, 2024
8a0dc7b
Revert "fix per image publish when rid is linux-musl"
surayya-MS Nov 7, 2024
c2a29c4
Reapply "fix per image publish when rid is linux-musl"
surayya-MS Nov 7, 2024
4418153
fix setting RuntimeIdentifier without musl
surayya-MS Nov 8, 2024
123f1ea
Revert "fix setting RuntimeIdentifier without musl"
surayya-MS Nov 8, 2024
603e0f2
Revert "Reapply "fix per image publish when rid is linux-musl""
surayya-MS Nov 8, 2024
1ed7163
use BuiltImage.ManifestMediaType to create tarballs
surayya-MS Nov 8, 2024
9d1ea06
add tests for multiple rids in ComputeDotnetBaseImageAndTag.TargetRun…
surayya-MS Nov 8, 2024
406981c
add CreateImageIndex baseline test
surayya-MS Nov 10, 2024
136d7d7
small fix
surayya-MS Nov 10, 2024
90a4e2c
fix type and comment
surayya-MS Nov 10, 2024
50b2845
add e2e tests for multi-arch scenario
surayya-MS Nov 10, 2024
4fe139c
fixed passing ContainerEnvironmentVariables in _PublishMultiArchConta…
surayya-MS Nov 10, 2024
8aca252
added test for env vars for multi-arch
surayya-MS Nov 10, 2024
58d7a56
fix by adding a condition
surayya-MS Nov 10, 2024
8ef679d
Merge branch 'release/8.0.4xx' into multi-arch-containers
surayya-MS Nov 10, 2024
d6d4070
fixed passing ContainerPort
surayya-MS Nov 11, 2024
3b991b3
add test for ports
surayya-MS Nov 11, 2024
5bcba3b
improve env var e2e test
surayya-MS Nov 11, 2024
a8824e3
improve ports test
surayya-MS Nov 11, 2024
699e200
improve e2e muclti-arch tests
surayya-MS Nov 11, 2024
741ea4e
fixed passing labels for multi-arch
surayya-MS Nov 11, 2024
dee4455
added test for labels
surayya-MS Nov 11, 2024
073a29f
simplify passing env vars, ports and labels
surayya-MS Nov 11, 2024
4fdbea6
set --platform option in docker command in e2e tests
surayya-MS Nov 11, 2024
a76a407
merge from main
surayya-MS Nov 11, 2024
db442c2
remove usings
surayya-MS Nov 11, 2024
04b02bf
remove line
surayya-MS Nov 11, 2024
ece7ee2
try fixing tests
surayya-MS Nov 11, 2024
25b16a8
Revert "try fixing tests"
surayya-MS Nov 11, 2024
9cf14e0
fix tests
surayya-MS Nov 11, 2024
d6bbaee
fix BuildingImageIndex message
surayya-MS Nov 12, 2024
983a279
move target position in the file
surayya-MS Nov 13, 2024
eef2abf
change order of msbuild task targets in _PublishMultiArchContainers t…
surayya-MS Nov 13, 2024
0b694ea
better name for target _ParseItemsForPublishingSingleContainer
surayya-MS Nov 13, 2024
c6b0008
change env vars and ports e2e tests to be multi-rid
surayya-MS Nov 13, 2024
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
6 changes: 6 additions & 0 deletions src/Containers/Microsoft.NET.Build.Containers/ImageBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,12 @@ static string[] Split(string input)
}
}

// For tests
internal string GetManifestConfigDigest()
{
return _manifest.Config.digest;
}

internal static class EnvironmentVariables
{
public static readonly string APP_UID = nameof(APP_UID);
Expand Down
128 changes: 128 additions & 0 deletions src/Containers/Microsoft.NET.Build.Containers/ImageIndexGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Text.Json;
using System.Text.Json.Nodes;
using Microsoft.NET.Build.Containers.Resources;
using Microsoft.NET.Build.Containers.Tasks;

namespace Microsoft.NET.Build.Containers;

internal struct ImageInfo
{
internal string Config { get; init; }
internal string ManifestDigest { get; init; }
internal string Manifest { get; init; }
internal string ManifestMediaType { get; init; }
}

internal static class ImageIndexGenerator
{
/// <summary>
/// Generates an image index from the given images.
/// </summary>
/// <param name="imageInfos"></param>
/// <returns>Returns json string of image index and image index mediaType.</returns>
/// <exception cref="ArgumentException"></exception>
/// <exception cref="NotSupportedException"></exception>
internal static (string, string) GenerateImageIndex(ImageInfo[] imageInfos)
{
if (imageInfos.Length == 0)
{
throw new ArgumentException(string.Format(Strings.ImagesEmpty));
}

string firstManifestMediaType = imageInfos[0].ManifestMediaType;

if (firstManifestMediaType == SchemaTypes.DockerManifestV2)
{
return GenerateDockerManifestList(imageInfos, firstManifestMediaType);
}
else if (firstManifestMediaType == SchemaTypes.OciManifestV1)
{
return GenerateOciImageIndex(imageInfos, firstManifestMediaType);
}
else
{
throw new NotSupportedException(string.Format(Strings.UnsupportedMediaType, firstManifestMediaType));
}
}

private static (string, string) GenerateDockerManifestList(ImageInfo[] images, string firstManifestMediaType)
{
var manifests = new PlatformSpecificManifest[images.Length];
for (int i = 0; i < images.Length; i++)
{
var image = images[i];

if (i > 0 && image.ManifestMediaType != firstManifestMediaType)
{
throw new ArgumentException(Strings.MixedMediaTypes);
}

var manifest = new PlatformSpecificManifest
{
mediaType = firstManifestMediaType,
size = image.Manifest.Length,
digest = image.ManifestDigest,
platform = GetArchitectureAndOsFromConfig(image)
};
manifests[i] = manifest;
}

var dockerManifestList = new ManifestListV2
{
schemaVersion = 2,
mediaType = SchemaTypes.DockerManifestListV2,
manifests = manifests
};

return (JsonSerializer.SerializeToNode(dockerManifestList)?.ToJsonString() ?? "", dockerManifestList.mediaType);
}

private static (string, string) GenerateOciImageIndex(ImageInfo[] images, string firstManifestMediaType)
{
var manifests = new PlatformSpecificOciManifest[images.Length];
for (int i = 0; i < images.Length; i++)
{
var image = images[i];

if (i > 0 && image.ManifestMediaType != firstManifestMediaType)
{
throw new ArgumentException(Strings.MixedMediaTypes);
}

var manifest = new PlatformSpecificOciManifest
{
mediaType = firstManifestMediaType,
size = image.Manifest.Length,
digest = image.ManifestDigest,
platform = GetArchitectureAndOsFromConfig(image)
};
manifests[i] = manifest;
}

var ociImageIndex = new ImageIndexV1
{
schemaVersion = 2,
mediaType = SchemaTypes.OciImageIndexV1,
manifests = manifests
};

return (JsonSerializer.SerializeToNode(ociImageIndex)?.ToJsonString() ?? "", ociImageIndex.mediaType);
}

private static PlatformInformation GetArchitectureAndOsFromConfig(ImageInfo image)
{
var configJson = JsonNode.Parse(image.Config) as JsonObject ??
throw new ArgumentException($"{nameof(image.Config)} should be a JSON object.", nameof(image.Config));

var architecture = configJson["architecture"]?.ToString() ??
throw new ArgumentException($"{nameof(image.Config)} should contain 'architecture'.", nameof(image.Config));

var os = configJson["os"]?.ToString() ??
throw new ArgumentException($"{nameof(image.Config)} should contain 'os'.", nameof(image.Config));

return new PlatformInformation { architecture = architecture, os = os };
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GeneratedContainerDigest.get
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GeneratedContainerDigest.set -> void
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GeneratedArchiveOutputPath.get -> string!
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GeneratedArchiveOutputPath.set -> void
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GeneratedContainerMediaType.get -> string!
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GeneratedContainerMediaType.set -> void
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.Repository.get -> string!
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.Repository.set -> void
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.ImageTags.get -> string![]!
Expand Down Expand Up @@ -123,8 +125,8 @@ Microsoft.NET.Build.Containers.Tasks.ComputeDotnetBaseImageAndTag.IsTrimmed.get
Microsoft.NET.Build.Containers.Tasks.ComputeDotnetBaseImageAndTag.IsTrimmed.set -> void
Microsoft.NET.Build.Containers.Tasks.ComputeDotnetBaseImageAndTag.IsSelfContained.get -> bool
Microsoft.NET.Build.Containers.Tasks.ComputeDotnetBaseImageAndTag.IsSelfContained.set -> void
Microsoft.NET.Build.Containers.Tasks.ComputeDotnetBaseImageAndTag.TargetRuntimeIdentifier.get -> string!
Microsoft.NET.Build.Containers.Tasks.ComputeDotnetBaseImageAndTag.TargetRuntimeIdentifier.set -> void
Microsoft.NET.Build.Containers.Tasks.ComputeDotnetBaseImageAndTag.TargetRuntimeIdentifiers.get -> string![]!
Microsoft.NET.Build.Containers.Tasks.ComputeDotnetBaseImageAndTag.TargetRuntimeIdentifiers.set -> void
Microsoft.NET.Build.Containers.Tasks.ComputeDotnetBaseImageAndTag.UsesInvariantGlobalization.get -> bool
Microsoft.NET.Build.Containers.Tasks.ComputeDotnetBaseImageAndTag.UsesInvariantGlobalization.set -> void
Microsoft.NET.Build.Containers.Tasks.ComputeDotnetBaseImageAndTag
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,27 @@ Microsoft.NET.Build.Containers.Tasks.ComputeDotnetBaseImageAndTag.IsTrimmed.get
Microsoft.NET.Build.Containers.Tasks.ComputeDotnetBaseImageAndTag.IsTrimmed.set -> void
Microsoft.NET.Build.Containers.Tasks.ComputeDotnetBaseImageAndTag.IsSelfContained.get -> bool
Microsoft.NET.Build.Containers.Tasks.ComputeDotnetBaseImageAndTag.IsSelfContained.set -> void
Microsoft.NET.Build.Containers.Tasks.ComputeDotnetBaseImageAndTag.TargetRuntimeIdentifier.get -> string!
Microsoft.NET.Build.Containers.Tasks.ComputeDotnetBaseImageAndTag.TargetRuntimeIdentifier.set -> void
Microsoft.NET.Build.Containers.Tasks.ComputeDotnetBaseImageAndTag.TargetRuntimeIdentifiers.get -> string![]!
Microsoft.NET.Build.Containers.Tasks.ComputeDotnetBaseImageAndTag.TargetRuntimeIdentifiers.set -> void
Microsoft.NET.Build.Containers.Tasks.ComputeDotnetBaseImageAndTag.UserBaseImage.get -> string?
Microsoft.NET.Build.Containers.Tasks.ComputeDotnetBaseImageAndTag.UserBaseImage.set -> void
Microsoft.NET.Build.Containers.Tasks.ComputeDotnetBaseImageAndTag.UsesInvariantGlobalization.get -> bool
Microsoft.NET.Build.Containers.Tasks.ComputeDotnetBaseImageAndTag.UsesInvariantGlobalization.set -> void
Microsoft.NET.Build.Containers.Tasks.CreateImageIndex
Microsoft.NET.Build.Containers.Tasks.CreateImageIndex.Cancel() -> void
Microsoft.NET.Build.Containers.Tasks.CreateImageIndex.CreateImageIndex() -> void
Microsoft.NET.Build.Containers.Tasks.CreateImageIndex.Dispose() -> void
Microsoft.NET.Build.Containers.Tasks.CreateImageIndex.GeneratedImageIndex.get -> string!
Microsoft.NET.Build.Containers.Tasks.CreateImageIndex.GeneratedImageIndex.set -> void
Microsoft.NET.Build.Containers.Tasks.CreateImageIndex.ImageTags.get -> string![]!
Microsoft.NET.Build.Containers.Tasks.CreateImageIndex.ImageTags.set -> void
Microsoft.NET.Build.Containers.Tasks.CreateImageIndex.GeneratedContainers.get -> Microsoft.Build.Framework.ITaskItem![]!
Microsoft.NET.Build.Containers.Tasks.CreateImageIndex.GeneratedContainers.set -> void
Microsoft.NET.Build.Containers.Tasks.CreateImageIndex.OutputRegistry.get -> string!
Microsoft.NET.Build.Containers.Tasks.CreateImageIndex.OutputRegistry.set -> void
Microsoft.NET.Build.Containers.Tasks.CreateImageIndex.Repository.get -> string!
Microsoft.NET.Build.Containers.Tasks.CreateImageIndex.Repository.set -> void
override Microsoft.NET.Build.Containers.Tasks.CreateImageIndex.Execute() -> bool
static readonly Microsoft.NET.Build.Containers.Constants.Version -> string!
Microsoft.NET.Build.Containers.ContainerHelpers
Microsoft.NET.Build.Containers.ContainerHelpers.ParsePortError
Expand Down Expand Up @@ -196,6 +211,8 @@ Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GeneratedContainerDigest.get
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GeneratedContainerDigest.set -> void
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GeneratedArchiveOutputPath.get -> string!
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GeneratedArchiveOutputPath.set -> void
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GeneratedContainerMediaType.get -> string!
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GeneratedContainerMediaType.set -> void
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.Repository.get -> string!
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.Repository.set -> void
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.ImageTags.get -> string![]!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,13 @@ public async Task<HttpResponseMessage> GetAsync(string repositoryName, string re
public async Task PutAsync(string repositoryName, string reference, ManifestV2 manifest, string mediaType, CancellationToken cancellationToken)
{
string jsonString = JsonSerializer.SerializeToNode(manifest)?.ToJsonString() ?? "";
HttpContent manifestUploadContent = new StringContent(jsonString);

await PutAsync(repositoryName, reference, jsonString, mediaType, cancellationToken).ConfigureAwait(false);
}

public async Task PutAsync(string repositoryName, string reference, string manifestJson, string mediaType, CancellationToken cancellationToken)
{
HttpContent manifestUploadContent = new StringContent(manifestJson);
manifestUploadContent.Headers.ContentType = new MediaTypeHeaderValue(mediaType);

HttpResponseMessage putResponse = await _client.PutAsync(new Uri(_baseUri, $"/v2/{repositoryName}/manifests/{reference}"), manifestUploadContent, cancellationToken).ConfigureAwait(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@ internal interface IManifestOperations
public Task<HttpResponseMessage> GetAsync(string repositoryName, string reference, CancellationToken cancellationToken);

public Task PutAsync(string repositoryName, string reference, ManifestV2 manifest, string mediaType, CancellationToken cancellationToken);

public Task PutAsync(string repositoryName, string reference, string manifestListJson, string mediaType, CancellationToken cancellationToken);
}
13 changes: 11 additions & 2 deletions src/Containers/Microsoft.NET.Build.Containers/Registry/Registry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@
using NuGet.RuntimeModel;
using System.Diagnostics;
using System.Net.Http.Json;
using System.Text.Json;
using System.Text.Json.Nodes;
using System.Text.RegularExpressions;

namespace Microsoft.NET.Build.Containers;

Expand Down Expand Up @@ -527,6 +525,17 @@ private async Task UploadBlobAsync(string repository, string digest, Stream cont

}

public async Task PushManifestListAsync(string repositoryName, string[] tags, string manifestListJson, string mediaType, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
foreach (var tag in tags)
{
_logger.LogInformation(Strings.Registry_TagUploadStarted, tag, RegistryName);
await _registryAPI.Manifest.PutAsync(repositoryName, tag, manifestListJson, mediaType, cancellationToken).ConfigureAwait(false);
_logger.LogInformation(Strings.Registry_TagUploaded, tag, RegistryName);
}
}

public Task PushAsync(BuiltImage builtImage, SourceImageReference source, DestinationImageReference destination, CancellationToken cancellationToken)
=> PushAsync(builtImage, source, destination, pushTags: true, cancellationToken);

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading