Skip redundant container uploads for existing manifests - #55690
Merged
baronfel merged 2 commits intoAug 18, 2026
Conversation
|
Azure Pipelines: Successfully started running 1 pipeline(s). 2 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
|
Azure Pipelines: Successfully started running 1 pipeline(s). 2 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
Contributor
There was a problem hiding this comment.
Pull request overview
Adds an opt-in ContainerSkipPushIfAlreadyPresent property to optimize remote container publishes by checking (via manifest HEAD) whether a locally computed manifest digest already exists in the destination repository, and when present skipping layer/config uploads while still updating tags.
Changes:
- Introduces manifest-existence probing via
IManifestOperations.ExistsAsyncand wires it intoRegistry.PushAsyncto conditionally skip blob uploads. - Threads the new opt-in through the MSBuild targets and
CreateNewImage→ImagePublisherpublish path. - Adds unit test coverage for manifest existence behavior and the “skip uploads but still tag” push flow, plus a localized log message for manifest reuse.
Reviewed changes
Copilot reviewed 24 out of 25 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| test/Microsoft.NET.Build.Containers.UnitTests/RegistryTests.cs | Adds unit tests for manifest HEAD existence checks and push skip behavior. |
| test/Microsoft.NET.Build.Containers.IntegrationTests/EndToEndTests.cs | Updates call site for ImagePublisher.PublishImageAsync signature change. |
| src/Containers/packaging/build/Microsoft.NET.Build.Containers.targets | Adds and flows ContainerSkipPushIfAlreadyPresent MSBuild property into tasks/logging. |
| src/Containers/Microsoft.NET.Build.Containers/Tasks/CreateNewImage.Interface.cs | Adds new task parameter SkipPushIfAlreadyPresent. |
| src/Containers/Microsoft.NET.Build.Containers/Tasks/CreateNewImage.cs | Passes the new opt-in to ImagePublisher.PublishImageAsync. |
| src/Containers/Microsoft.NET.Build.Containers/Resources/xlf/Strings.*.xlf | Adds localization entries for the new “manifest already exists” message. |
| src/Containers/Microsoft.NET.Build.Containers/Resources/Strings.resx | Adds the Registry_ManifestExists resource string. |
| src/Containers/Microsoft.NET.Build.Containers/Resources/Strings.Designer.cs | Regenerates designer to include Registry_ManifestExists. |
| src/Containers/Microsoft.NET.Build.Containers/Registry/Registry.cs | Implements the skip behavior (manifest HEAD check + conditional blob uploads) and logs reuse. |
| src/Containers/Microsoft.NET.Build.Containers/Registry/IManifestOperations.cs | Extends manifest operations abstraction with ExistsAsync. |
| src/Containers/Microsoft.NET.Build.Containers/Registry/DefaultManifestOperations.cs | Implements ExistsAsync using HEAD with manifest accept headers and 5xx propagation. |
| src/Containers/Microsoft.NET.Build.Containers/PublicAPI/net11.0/PublicAPI.Unshipped.txt | Adds the new CreateNewImage.SkipPushIfAlreadyPresent API surface. |
| src/Containers/Microsoft.NET.Build.Containers/ImagePublisher.cs | Threads the new opt-in into the remote push delegate for single-arch images. |
Files not reviewed (1)
- src/Containers/Microsoft.NET.Build.Containers/Resources/Strings.Designer.cs: Generated file
lbussell
reviewed
Aug 10, 2026
baronfel
approved these changes
Aug 12, 2026
baronfel
had a problem deploying
to
copilot-pat-pool
August 18, 2026 17:23 — with
GitHub Actions
Failure
Member
|
/backport to release/11.0.1xx-rc1 |
Member
|
/backport to release/11.0.1xx |
Contributor
|
Started backporting to |
Contributor
|
Started backporting to |
This was referenced Aug 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Add an opt-in
ContainerSkipPushIfAlreadyPresentproperty for remote registry publishes.When enabled, the SDK checks whether the locally computed manifest digest already exists in the destination repository. If it does, the publish skips layer and configuration blob uploads while still applying every requested image tag to the existing manifest. If it does not, publishing follows the existing upload path.
The property defaults to
false, so existing behavior is unchanged.Details
HEADsupport throughIManifestOperations.ExistsAsyncCreateNewImage,ImagePublisher, and the container targetsThis intentionally does not skip the local image build. The SDK must still build the image locally to compute
BuiltImage.ManifestDigest. The optimization avoids redundant registry blob transfer.Dependency
The common unchanged-build case depends on deterministic image output. #55689 implements the deterministic timestamps, layer ordering, and PAX normalization needed for independently built identical inputs to produce the same digest.
Verification
RegistryTests: 32 passed, 5 skippedMicrosoft.NET.Build.Containers.UnitTests: 322 passed, 6 skipped, with one unrelated environment-specific failure inDockerDaemonTests.Can_detect_when_no_daemon_is_running; the isolated rerun reproduced because a runtime is available at the test's supposedly unused endpointreusedtag, and kept both tags on digestsha256:1754b379…stableandreused, emitted one skip per single manifest or two skips for multi-platform inner manifests, performed zero repeated layer/config uploads, and reported the expected manifest/index media type; all four temporary repositories were deleted afterwardFixes #54038