Skip to content

Commit 5fe16eb

Browse files
Fix --tag parameter to properly publish versioned tags
Motivation: The `--tag` parameter was accepted but never used when publishing images. The manifest and index were always pushed using `destinationImage.reference` (defaulting to 'latest'), ignoring the user-specified tag entirely. Modifications: - Collect both the `--tag` value and the repository reference into a list - Push the manifest and index to each tag in the list - Skip duplicates when `--tag` matches the repository reference - Return the `--tag` as the primary reference in the result Result: Running `swift package build-container-image --repository ghcr.io/org/app --tag v1.0.0` now correctly pushes to both `v1.0.0` and `latest` tags. Test Plan: Tested with attendix-backend by building and pushing to ghcr.io. Verified both tags appear in the registry after a single build command.
1 parent 1ea1608 commit 5fe16eb

File tree

1 file changed

+43
-41
lines changed

1 file changed

+43
-41
lines changed

Sources/containertool/Extensions/RegistryClient+publish.swift

Lines changed: 43 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -135,56 +135,58 @@ func publishContainerImage<Source: ImageSource, Destination: ImageDestination>(
135135
)
136136
}
137137

138-
// MARK: Upload application manifest
139-
140-
let manifestDescriptor = try await destination.putManifest(
141-
repository: destinationImage.repository,
142-
reference: destinationImage.reference,
143-
manifest: manifest
144-
)
145-
146-
if verbose {
147-
log("manifest: \(manifestDescriptor.digest) (\(manifestDescriptor.size) bytes)")
138+
// Determine the tags to push. Always include the reference from --repository (defaults to 'latest').
139+
// If --tag is provided and differs from the repository reference, push to both.
140+
var tagsToPublish: [any ImageReference.Reference] = [destinationImage.reference]
141+
if let tag {
142+
let tagReference = try ImageReference.Tag(tag)
143+
// Avoid duplicates if --tag matches the reference already in --repository
144+
if "\(tagReference)" != "\(destinationImage.reference)" {
145+
tagsToPublish.insert(tagReference, at: 0)
146+
}
148147
}
149148

150-
// MARK: Create application index
149+
// MARK: Upload application manifest and index for each tag
151150

152-
let index = ImageIndex(
153-
schemaVersion: 2,
154-
mediaType: "application/vnd.oci.image.index.v1+json",
155-
manifests: [
156-
ContentDescriptor(
157-
mediaType: manifestDescriptor.mediaType,
158-
digest: manifestDescriptor.digest,
159-
size: Int64(manifestDescriptor.size),
160-
platform: .init(architecture: architecture, os: os)
161-
)
162-
]
163-
)
151+
for tagReference in tagsToPublish {
152+
let manifestDescriptor = try await destination.putManifest(
153+
repository: destinationImage.repository,
154+
reference: tagReference,
155+
manifest: manifest
156+
)
164157

165-
// MARK: Upload application manifest
158+
if verbose {
159+
log("manifest (\(tagReference)): \(manifestDescriptor.digest) (\(manifestDescriptor.size) bytes)")
160+
}
166161

167-
let indexDescriptor = try await destination.putIndex(
168-
repository: destinationImage.repository,
169-
reference: destinationImage.reference,
170-
index: index
171-
)
162+
let index = ImageIndex(
163+
schemaVersion: 2,
164+
mediaType: "application/vnd.oci.image.index.v1+json",
165+
manifests: [
166+
ContentDescriptor(
167+
mediaType: manifestDescriptor.mediaType,
168+
digest: manifestDescriptor.digest,
169+
size: Int64(manifestDescriptor.size),
170+
platform: .init(architecture: architecture, os: os)
171+
)
172+
]
173+
)
172174

173-
if verbose {
174-
log("index: \(indexDescriptor.digest) (\(indexDescriptor.size) bytes)")
175-
}
175+
let indexDescriptor = try await destination.putIndex(
176+
repository: destinationImage.repository,
177+
reference: tagReference,
178+
index: index
179+
)
176180

177-
// Use the index digest if the user did not provide a human-readable tag
178-
// To support multiarch images, we should also create an an index pointing to
179-
// this manifest.
180-
let reference: ImageReference.Reference
181-
if let tag {
182-
reference = try ImageReference.Tag(tag)
183-
} else {
184-
reference = try ImageReference.Digest(indexDescriptor.digest)
181+
if verbose {
182+
log("index (\(tagReference)): \(indexDescriptor.digest) (\(indexDescriptor.size) bytes)")
183+
}
185184
}
186185

186+
// Return the primary tag (--tag if provided, otherwise the repository reference)
187187
var result = destinationImage
188-
result.reference = reference
188+
if let tag {
189+
result.reference = try ImageReference.Tag(tag)
190+
}
189191
return result
190192
}

0 commit comments

Comments
 (0)