Skip to content

Add repository, tag, ID and created columns to image list output#40043

Merged
beena352 merged 9 commits intomicrosoft:feature/wsl-for-appsfrom
beena352:user/beenachauhan/improve-image-list
Apr 1, 2026
Merged

Add repository, tag, ID and created columns to image list output#40043
beena352 merged 9 commits intomicrosoft:feature/wsl-for-appsfrom
beena352:user/beenachauhan/improve-image-list

Conversation

@beena352
Copy link
Copy Markdown

@beena352 beena352 commented Mar 30, 2026

Summary of the Pull Request

Enhance wslc image ls output to display REPOSITORY, TAG, IMAGE ID, CREATED, SIZE.
image
image

PR Checklist

  • Closes: Link to issue #xxx
  • [ x] Communication: I've discussed this with core contributors already. If work hasn't been agreed, this work might be rejected
  • [x ] Tests: Added/updated if needed and all pass
  • Localization: All end user facing strings can be localized
  • Dev docs: Added/updated if needed
  • Documentation updated: If checked, please file a pull request on our docs repo and link it here: #xxx

Detailed Description of the Pull Request / Additional comments

  • Extended ImageInformation with new fields: Repository, Tag, Id, and Created
  • Updated ImageService::List() to use the existing ParseImage() helper and populate fields that were previously ignored
  • Truncated image ID to 12 characters and reused ContainerService::FormatRelativeTime() for consistency
  • Adjusted E2E tests and helpers to handle separate repository and tag columns

Validation Steps Performed

@beena352 beena352 requested a review from a team as a code owner March 30, 2026 21:26
Copilot AI review requested due to automatic review settings March 30, 2026 21:26
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR enhances the wslc image ls/list output to surface more Docker-like image metadata (repository, tag, image ID, created time, size) across table, quiet, and JSON formats, and updates E2E tests accordingly.

Changes:

  • Extends ImageInformation to include Repository, Tag, Id, and Created and updates JSON serialization accordingly.
  • Updates wslc image list table/quiet output formatting (new columns, short ID rendering, relative “CREATED” time).
  • Adjusts E2E tests/helpers to work with the new output format and validates the new table header columns.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
test/windows/wslc/e2e/WSLCE2EImageListTests.cpp Updates image list assertions; adds a header/columns check for table output.
test/windows/wslc/e2e/WSLCE2EHelpers.cpp Adjusts image existence checks used by E2E setup/cleanup.
src/windows/wslc/tasks/ImageTasks.cpp Updates CLI formatting for image list (quiet + table) and adds created/ID formatting.
src/windows/wslc/services/ImageService.cpp Populates the expanded ImageInformation fields using ParseImage() and WSLC image metadata.
src/windows/wslc/services/ImageModel.h Expands the image model and updates nlohmann JSON mapping.
Comments suppressed due to low confidence (1)

test/windows/wslc/e2e/WSLCE2EHelpers.cpp:214

  • EnsureImageIsDeleted() now checks image list output with a substring match on image.Name. This can trigger cleanup logic even when the specific NameAndTag() image isn't present (e.g., another repo containing the substring), leading to an attempted delete of image.NameAndTag() and a potential cleanup failure.

Consider switching the existence check to wslc image list --quiet (exact match) or --format json and match repository+tag explicitly.

    auto outputLines = result.GetStdoutLines();
    for (const auto& line : outputLines)
    {
        if (line.find(image.Name) != std::wstring::npos)
        {
            EnsureImageContainersAreDeleted(image);
            auto deleteResult = RunWslc(std::format(L"image delete --force {}", image.NameAndTag()));
            deleteResult.Verify({.Stderr = L"", .ExitCode = 0});

Copilot AI review requested due to automatic review settings March 30, 2026 22:47
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (2)

test/windows/wslc/e2e/WSLCE2EImageListTests.cpp:61

  • WSLCE2E_Image_List_DisplayLoadedImage now only checks for DebianImage.Name as a substring in the table output. This can yield false positives (e.g., if a different tag of the same repository, or another repository containing the substring, is present) and allow the test to pass even when the expected Name:Tag isn’t listed. Prefer asserting on the exact NameAndTag() by using image list --quiet (line equality) or by parsing --format json and matching both Repository and Tag.
            if (line.find(DebianImage.Name) != std::wstring::npos)
            {
                return;
            }
        }

test/windows/wslc/e2e/WSLCE2EHelpers.cpp:214

  • EnsureImageIsDeleted() matches image.Name as a substring in image list output. This is prone to false matches (e.g., another tag for the same repo, or another repo containing the substring), which can cause the helper to attempt deleting image.NameAndTag() even when that specific tag isn’t present (leading to flaky failures) or to skip deletion when the exact tag still exists. Use image list --quiet and compare exact lines to NameAndTag(), or use --format json and match both Repository and Tag.
    for (const auto& line : outputLines)
    {
        if (line.find(image.Name) != std::wstring::npos)
        {
            EnsureImageContainersAreDeleted(image);
            auto deleteResult = RunWslc(std::format(L"image delete --force {}", image.NameAndTag()));
            deleteResult.Verify({.Stderr = L"", .ExitCode = 0});

@beena352 beena352 marked this pull request as draft March 30, 2026 22:59
Copilot AI review requested due to automatic review settings March 31, 2026 00:00
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (2)

test/windows/wslc/e2e/WSLCE2EHelpers.cpp:324

  • EnsureImageIsLoaded() declares auto result twice in the same scope (image list -q and then listCommand), which will not compile. Remove the first declaration or rename one of them, and make sure the chosen call is the one actually used for the presence check.
    auto result = RunWslc(L"image list -q");
    std::wstring listCommand = L"image list";
    if (!sessionName.empty())
    {
        listCommand = std::format(L"image list --session \"{}\"", sessionName);
    }

    auto result = RunWslc(listCommand);
    result.Verify({.Stderr = L"", .ExitCode = 0});

test/windows/wslc/e2e/WSLCE2EHelpers.cpp:333

  • EnsureImageIsLoaded() searches image list (table) output for repo:tag, but the table output now prints repository and tag in separate columns, so the substring repo:tag likely won’t appear and this will always treat the image as missing. Use image list -q (or --format json) for the existence check so the comparison matches TestImage::NameAndTag() reliably.
    std::wstring listCommand = L"image list";
    if (!sessionName.empty())
    {
        listCommand = std::format(L"image list --session \"{}\"", sessionName);
    }

    auto result = RunWslc(listCommand);
    result.Verify({.Stderr = L"", .ExitCode = 0});

    auto outputLines = result.GetStdoutLines();
    for (const auto& line : outputLines)
    {
        if (line.find(image.NameAndTag()) != std::wstring::npos)
        {
            return;
        }
    }

@beena352 beena352 marked this pull request as ready for review April 1, 2026 17:16
Copilot AI review requested due to automatic review settings April 1, 2026 17:16
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Comment on lines +19 to +25
std::string Repository;
std::string Tag;
std::string Id;
LONGLONG Created{};
ULONGLONG Size{};

NLOHMANN_DEFINE_TYPE_INTRUSIVE(ImageInformation, Name, Size);
NLOHMANN_DEFINE_TYPE_INTRUSIVE(ImageInformation, Repository, Tag, Id, Created, Size);
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

Replacing Name with {Repository, Tag, Id, Created} changes the JSON shape produced/consumed via NLOHMANN_DEFINE_TYPE_INTRUSIVE, which is a breaking change for any existing image list JSON consumers expecting a Name field. If backward compatibility matters, consider keeping Name (populated as Repository + ":" + Tag) and including it in serialization, or implement a custom to_json/from_json that continues to emit Name while adding the new fields.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator

@OneBlue OneBlue left a comment

Choose a reason for hiding this comment

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

Change looks good, two minor comments

Copilot AI review requested due to automatic review settings April 1, 2026 20:44
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

MultiByteToWide(image.Repository.value_or("<untagged>")),
MultiByteToWide(image.Tag.value_or("<untagged>")),
MultiByteToWide(TruncateId(image.Id, trunc)),
ContainerService::FormatRelativeTime(image.Created > 0 ? static_cast<ULONGLONG>(image.Created) : 0),
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

ContainerService::FormatRelativeTime(0) will format relative time from the Unix epoch, producing a huge "N days ago" value. If image.Created can be 0/unknown, consider outputting an empty/"-" value (or a dedicated "unknown" string) instead of calling FormatRelativeTime with 0.

Suggested change
ContainerService::FormatRelativeTime(image.Created > 0 ? static_cast<ULONGLONG>(image.Created) : 0),
image.Created > 0
? ContainerService::FormatRelativeTime(static_cast<ULONGLONG>(image.Created))
: std::wstring(L"-"),

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I guess this isn't supposed to happen ? Probably not a huge deal

Comment on lines +149 to +156
// Parse the image reference — dangling images have no repo/tag
std::string imageRef = image.Image;
if (imageRef != "<none>:<none>")
{
auto parsed = wsl::windows::common::wslutil::ParseImage(imageRef);
info.Repository = parsed.first;
info.Tag = parsed.second;
}
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

For dangling images, ImageService::List() leaves Repository/Tag unset (when Image == "<none>:<none>"), which then causes the CLI to synthesize placeholders like <untagged> in both table and --quiet output. That placeholder string is not the actual image reference returned by the service and is unlikely to be usable as an identifier in follow-up commands. Consider preserving the service’s sentinel by setting Repository="<none>" and Tag="<none>" (or storing the raw reference separately) so image list output stays consistent and scriptable even with dangling images present.

Copilot uses AI. Check for mistakes.
@beena352 beena352 merged commit 801b145 into microsoft:feature/wsl-for-apps Apr 1, 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.

6 participants