add support for multiple --tag flags in build (#785)

- Closes #732.

## Type of Change
- [ ] Bug fix
- [x] New feature  
- [ ] Breaking change
- [ ] Documentation update

## Motivation and Context
Adds support for specifying multiple `-t` / `--tag` flags with the
`build` command. All specified tags will point to the same built image.

Example:
`container build -t myapp:latest -t myapp:v1.0.0 -t myapp:stable .`

## Testing
- [x] Tested locally
- [x] Added/updated tests
- [x] Added/updated docs
This commit is contained in:
Raj
2025-10-21 13:03:46 -07:00
committed by GitHub
parent d610a85703
commit ce40ffd33d
5 changed files with 75 additions and 18 deletions
@@ -83,7 +83,23 @@ class TestCLIBuildBase: CLITest {
otherArgs: [String] = []
) throws -> String {
try buildWithPaths(
tag: tag,
tags: [tag],
tempContext: tempDir,
tempDockerfileContext: tempDir,
buildArgs: buildArgs,
otherArgs: otherArgs
)
}
@discardableResult
func build(
tags: [String],
tempDir: URL,
buildArgs: [String] = [],
otherArgs: [String] = []
) throws -> String {
try buildWithPaths(
tags: tags,
tempContext: tempDir,
tempDockerfileContext: tempDir,
buildArgs: buildArgs,
@@ -95,7 +111,7 @@ class TestCLIBuildBase: CLITest {
// the dockerfile path. If both paths are the same, use `build` func above.
@discardableResult
func buildWithPaths(
tag: String,
tags: [String],
tempContext: URL,
tempDockerfileContext: URL,
buildArgs: [String] = [],
@@ -107,9 +123,11 @@ class TestCLIBuildBase: CLITest {
"build",
"-f",
tempDockerfileContext.appendingPathComponent("Dockerfile").path,
"-t",
tag,
]
for tag in tags {
args.append("-t")
args.append(tag)
}
for arg in buildArgs {
args.append("--build-arg")
args.append(arg)
@@ -390,7 +390,7 @@ extension TestCLIBuildBase {
let imageName = "registry.local/build-diff-context:\(UUID().uuidString)"
#expect(throws: Never.self) {
try self.buildWithPaths(tag: imageName, tempContext: buildContextDir, tempDockerfileContext: dockerfileCtxDir)
try self.buildWithPaths(tags: [imageName], tempContext: buildContextDir, tempDockerfileContext: dockerfileCtxDir)
}
#expect(try self.inspectImage(imageName) == imageName, "expected to have successfully built \(imageName)")
}
@@ -432,5 +432,29 @@ extension TestCLIBuildBase {
"expected platforms \(expected), got \(actual)"
)
}
@Test func testBuildMultipleTags() throws {
let tempDir: URL = try createTempDir()
let dockerfile: String =
"""
FROM scratch
ADD emptyFile /
"""
let context: [FileSystemEntry] = [.file("emptyFile", content: .zeroFilled(size: 1))]
try createContext(tempDir: tempDir, dockerfile: dockerfile, context: context)
let uuid = UUID().uuidString
let tag1 = "registry.local/multi-tag-test:\(uuid)"
let tag2 = "registry.local/multi-tag-test:latest"
let tag3 = "registry.local/multi-tag-test:v1.0.0"
try self.build(tags: [tag1, tag2, tag3], tempDir: tempDir)
// Verify all three tags exist and point to the same image
#expect(try self.inspectImage(tag1) == tag1, "expected to have successfully built \(tag1)")
#expect(try self.inspectImage(tag2) == tag2, "expected to have successfully built \(tag2)")
#expect(try self.inspectImage(tag3) == tag3, "expected to have successfully built \(tag3)")
}
}
}