Route container image save reference list to stderr in stdout mode - #1804
Conversation
jglogan
left a comment
There was a problem hiding this comment.
@costajohnt Thank you for the fix! Please see the one suggested change.
| // saved-reference list goes to stderr. Printing it to stdout | ||
| // appends non-archive bytes after the tar EOF and corrupts | ||
| // the stream for redirection and pipelines (#1801). | ||
| FileHandle.standardError.write(Data("\(reference)\n".utf8)) |
There was a problem hiding this comment.
Also, could you rebase your change onto the latest main and push it again? We needed to disable a CI test that was flaky, so rebase and push will allow us to build this change without fear of an unrelated test failing.
c4f18a1 to
d9f888a
Compare
|
@costajohnt The fix looks good now, but one more thing - we need you to submit signed commits to merge the change. See https://github.com/apple/containerization/blob/main/CONTRIBUTING.md#pull-requests for details. |
d9f888a to
2137bea
Compare
When `container image save` runs without `--output`, stdout carries the OCI tar archive. The command wrote the archive bytes to stdout and then printed each saved image reference to stdout, appending non-archive text after the tar EOF marker and corrupting the stream for strict tar/OCI consumers (the existing round-trip test passed only because `image load` tolerates the trailing data). Emit the saved-reference list via the logger (`log.info`, which the StderrLogHandler routes to stderr) when stdout is carrying the archive; keep printing to stdout when saving to a file (`--output`), where stdout is free. Add a regression test asserting the stdout archive ends at the tar EOF marker (1024 zero bytes) with the reference surfaced on stderr. Fixes #1801 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016vEx9M9Bkph3CdvqmMj392
2137bea to
0d7eaa6
Compare
Code Coverage
|
jglogan
left a comment
There was a problem hiding this comment.
@costajohnt Thank you for the fix and the test!
|
@costajohnt The point of using the logger is that by default it's like a |
…pple#1804) - Fixes apple#1801. - When `container image save` runs without `--output`, stdout carries the OCI tar archive. The command writes the archive bytes to stdout and then `print(reference)`s each saved image reference to stdout afterward, appending non-archive text after the tar EOF marker, which will cause strict tar/OCI consumers to fail. - This routes the saved-reference list to stderr in the no-`--output` branch, so stdout contains only archive bytes. When saving to a file via `--output`, stdout is free, so the references continue to print to stdout exactly as before. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…pple#1804) - Fixes apple#1801. - When `container image save` runs without `--output`, stdout carries the OCI tar archive. The command writes the archive bytes to stdout and then `print(reference)`s each saved image reference to stdout afterward, appending non-archive text after the tar EOF marker, which will cause strict tar/OCI consumers to fail. - This routes the saved-reference list to stderr in the no-`--output` branch, so stdout contains only archive bytes. When saving to a file via `--output`, stdout is free, so the references continue to print to stdout exactly as before. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Type of Change
Motivation and Context
Fixes #1801.
When
container image saveruns without--output, stdout carries the OCI tar archive. The command writes the archive bytes to stdout and thenprint(reference)s each saved image reference to stdout afterward, appending non-archive text after the tar EOF marker. That corrupts the stream for strict tar/OCI consumers, so a command like:container image save alpine:latest > alpine.tarproduces an archive with trailing non-archive bytes. The existing round-trip test passes only because
container image loadtolerates the trailing data, while other tooling rejects or warns about it.This routes the saved-reference list to stderr in the no-
--outputbranch, so stdout contains only archive bytes. When saving to a file via--output, stdout is free, so the references continue to print to stdout exactly as before.I used a raw
FileHandle.standardError.write(...)to match the existing stderr writes in this codebase (e.g.Application.swift) and to keep the reference list as plain text rather than formatted log lines. Happy to route it through the logger instead if you'd prefer.Testing
Added
testImageSaveToStdoutProducesCleanArchive: it saves an image to stdout and asserts that the captured stdout ends at the tar EOF marker (1024 zero bytes), with the saved reference surfaced on stderr. With the bug, the trailing bytes are reference text and the assertion fails.swift buildandswift formatare clean. I was not able to run the CLI integration suite locally (it needs the running container runtime), so I left "Tested locally" unchecked. The new test sits alongside the existingimage save/loadintegration tests and is written to run in CI.