Skip to content

Fix OCI prune cleanup of broken tag symlinks - #1312

Open
mikemikimike wants to merge 12 commits into
openai:mainfrom
mikemikimike:fix/prune-oci-broken-symlinks
Open

Fix OCI prune cleanup of broken tag symlinks#1312
mikemikimike wants to merge 12 commits into
openai:mainfrom
mikemikimike:fix/prune-oci-broken-symlinks

Conversation

@mikemikimike

Copy link
Copy Markdown

Related issue

Closes #1293

Background

tart prune can remove a digest-addressed OCI cache entry while leaving tag symlinks pointing to the deleted directory. The cache then contains broken links until a separate garbage-collection run.

Changes

Run VMStorageOCI.gc() after OCI cache pruning completes. This covers both age-based and space-budget pruning, including invocations that also pass --gc.

Compatibility

No CLI or storage format changes. Healthy tag symlinks and local VM pruning are unaffected.

Verification

  • git diff --check — passed
  • swift test --filter HumanReadableByteCountTests — not run: Swift is not installed in the current Windows environment
  • Full build, lint, and CI checks — not run locally for the same reason

The change is intentionally small and relies on the existing OCI garbage collector.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 33c49e5f81

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread Sources/tart/Commands/Prune.swift Outdated
fkorotkov-oai
fkorotkov-oai previously approved these changes Aug 17, 2026
Comment thread Sources/tart/Commands/Prune.swift Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4626d57bf7

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread Sources/tart/VMStorageOCI.swift Outdated
@yzhuang-oai

Copy link
Copy Markdown
Contributor

@mikemikimike just need to fix the unit test /Users/runner/work/tart/tart/Sources/tart/ContentStore.swift:187: error: -[TartTests.VMStorageOCITests testPruningCachedImageRemovesOnlyItsTagSymlink] : failed: caught error: "invalidContentDigest("sha256:retained")" - rest lgtm

@yzhuang-oai

Copy link
Copy Markdown
Contributor

@mikemikimike test still failing

/Users/runner/work/tart/tart/Sources/tart/ContentStore.swift:187: error: -[TartTests.VMStorageOCITests testPruningCachedImageRemovesOnlyItsTagSymlink] : failed: caught error: "invalidContentDigest("sha256:overlay")"

@mikemikimike
mikemikimike force-pushed the fix/prune-oci-broken-symlinks branch from df3a16a to 01c822a Compare August 23, 2026 16:01
@mikemikimike

Copy link
Copy Markdown
Author

Thanks @yzhuang-oai. I addressed both reported invalidContentDigest failures in the latest commit 892ce7b03016fa86b731e5107f2620d74b061232: the tag-symlink pruning fixtures now use 64-character lowercase hexadecimal content digests instead of the invalid sha256:retained/sha256:overlay placeholders. The failing test no longer passes those invalid values into ContentStore validation.

I could not run the Swift XCTest suite on this Windows host because Swift/Xcode is unavailable here. Please rerun the macOS CI job to confirm the updated fixtures in the project environment.

Use the existing OCI garbage collector after deleting a cached image so broken tag symlinks are removed for both prune criteria. Fix the regression fixture to measure the VM directory through its Prunable implementation.\n\nCloses openai#1293\n\nGenerated-by: Codex

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d6c9bde8ad

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread Sources/tart/VMStorageOCI.swift Outdated
@mikemikimike

Copy link
Copy Markdown
Author

Pushed commit 5238e0a to address the requested cleanup scope. Cached-image pruning now removes only tag symlinks targeting the deleted digest, then runs content-only GC; it no longer invokes full record GC and cannot delete unrelated prune candidates. The Windows environment cannot run the repository's macOS/Xcode test suite locally. The new CI run is currently awaiting fork workflow approval (action_required, no jobs); please approve and run it so the regression tests can execute.

@yzhuang-oai

Copy link
Copy Markdown
Contributor

@mikemikimike CI still failing with unit test failures

@mikemikimike

Copy link
Copy Markdown
Author

Fixed the CI regression in commit 63ab43a114e592216094935aa062762d00560170. The two pruning tests were incorrectly asserting that destinationOfSymbolicLink throws for a broken symlink; that API returns the stored destination even when the target is missing. They now assert that the pruned tag path no longer exists, while retaining the checks that the retained record and tag remain. git diff --check passes. Swift/XCTest could not be run on this Windows host; please rerun the macOS CI.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 63ab43a114

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread Sources/tart/VMStorageOCI.swift Outdated
fileURLWithPath: destination,
relativeTo: foundURL.deletingLastPathComponent()
).standardizedFileURL
if destinationURL == standardizedTargetURL {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Compare symlink targets without directory URL hints

When pruning a digest record that has a tag, vmDir.delete() removes the target directory before this comparison runs. Constructing destinationURL after that removal produces a file URL without a directory marker, while targetURL came from the directory enumerator and retains its trailing-slash directory hint; Foundation treats those URLs as unequal, so the branch is skipped and the broken tag symlink remains. The new tests do not catch this because fileExists(atPath:) follows a dangling symlink and returns false even when the link itself still exists; compare normalized path strings or otherwise inspect the symlink itself.

Useful? React with 👍 / 👎.

@mikemikimike

Copy link
Copy Markdown
Author

Addressed the review feedback in commit eea3f0010df1f4e630808d9e2623478437823b6c. The tag cleanup now compares normalized filesystem paths, avoiding the trailing-slash directory URL mismatch after the digest directory is deleted. The regression tests now inspect the symlink resource itself, so a dangling symlink cannot make the test pass. git diff --check passes; macOS XCTest remains unavailable on this Windows host.

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.

tart prune leaves broken OCI tag symlinks after deleting their digest

3 participants