Skip to content

Create and push syndicated tags during builds - #2239

Merged
lbussell merged 2 commits into
mainfrom
lbussell/pipeline-3076999-investigation
Sep 17, 2026
Merged

lbussell merged 2 commits into
mainfrom
lbussell/pipeline-3076999-investigation

Conversation

@lbussell

@lbussell lbussell commented Sep 17, 2026 •

Copy link
Copy Markdown
Member

Aspire Dashboard images will be syndicated for a period of time. When attempting to publish syndicated aspire dashboard images, the post-build stage failed with:

Failed to execute docker manifest create --amend
  msdotnetcontainersstaging.azurecr.io/build-staging/3076999/dotnet/nightly/aspire-dashboard:13.6.0 
  msdotnetcontainersstaging.azurecr.io/build-staging/3076999/dotnet/nightly/aspire-dashboard:13.6.0-amd64
  msdotnetcontainersstaging.azurecr.io/build-staging/3076999/dotnet/nightly/aspire-dashboard:13.6.0-arm64v8
    
  no such manifest: msdotnetcontainersstaging.azurecr.io/build-staging/3076999/dotnet/nightly/aspire-dashboard:13.6.0-amd64

In this instance, dotnet/nightly/aspire-dashboard is the syndicated version of the image.

The manifest list creation task attempts to create the syndicated manifest lists, but since the syndicated platform-specific tags haven't been created yet, it fails.

Historically, here is how syndication worked:

Prior to #2030 (aka the last time we had working syndication):

  • Build stage:
    • builds images
    • tags built images with primary platform-specific tags
    • tags built images with primary multi-platform tags
  • Post-build stage:
    • does nothing with tags or syndication
  • Publish stage:
    • creates and publishes manifest lists
    • creates all syndicated tags and manifest lists

After #2030:

  • Build stage:
    • builds images
    • tags built images with primary platform-specific tags
    • tags built images with primary multi-platform tags
  • Post-build stage:
    • creates manifest lists
    • creates syndicated manifest lists (this is what is breaking today)
  • Publish stage:
    • copies all tags (primary + syndicated) to publish destination

With the changes from this PR:

  • Build stage:
    • builds images
    • tags built images with all platform-specific tags
    • tags built images with all multi-platform tags
  • Post-build stage:
    • creates manifest lists
    • creates syndicated manifest lists (will now succeed)
  • Publish stage:
    • copies all tags (primary + syndicated) to publish destination

You may be wondering, "Why not have the Build/Post-Build stages operate only on primary tags, and just create syndicated tags as part of publishing?"

This approach is appealing, but the current manifest/syndication model is on a tag-specific basis. This means that platforms may participate selectively in syndication.

If an image has platforms [A, B, C], but only platforms [A, B] are syndicated with shared syndicated tags, then that necessitates a new manifest list [A, B] be created. Thus, we must create it during Build/Post-Build and not during Publishing (so that it can get signed, etc.).

I would like to simplify the syndication model to image-level instead of tag-level, but I will leave that as follow-up work. This PR is required to unblock syndication of Aspire Dashboard images.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: ef3e1f6f-f17d-4cc9-8466-aa0b5e21dbdf
@lbussell
lbussell requested a review from a team as a code owner September 17, 2026 16:11

@mthalman mthalman left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about signing? ImageSigningService calls GetAllDigests:

But that implementation does not handle syndication:

public static List<string> GetAllDigests(this ImageData imageData)
{
// Platform specific digests
IEnumerable<string> digests = imageData.Platforms.Select(platform => platform.Digest);
// Include manifest list digest if it exists
if (imageData.Manifest is not null)
{
digests = [ ..digests, imageData.Manifest.Digest ];
}
return digests.ToList();
}

That means that digests addressed by aspire/dashboard would be signed but not digests at dotnet/aspire-dashboard.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: ef3e1f6f-f17d-4cc9-8466-aa0b5e21dbdf
@lbussell

Copy link
Copy Markdown
Member Author

@mthalman fixed in 45a5657 by:

  • Making ImageInfoHelper.GetAllDigests includes SyndicatedDigests.
  • Ensuring that SyndicatedDigests have proper registry overrides (to account for build staging registries, etc.)
  • Copying signatures to syndicated repos.

@lbussell
lbussell requested a review from mthalman September 17, 2026 20:55
@lbussell
lbussell enabled auto-merge (squash) September 17, 2026 21:27
@lbussell
lbussell merged commit 876c8de into main Sep 17, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants