Skip to content

fix(snapshot): fail closed when git check-ignore errors#8

Merged
CreatorGhost merged 2 commits into
devfrom
snapshot-fail-closed
Jul 12, 2026
Merged

fix(snapshot): fail closed when git check-ignore errors#8
CreatorGhost merged 2 commits into
devfrom
snapshot-fail-closed

Conversation

@CreatorGhost

@CreatorGhost CreatorGhost commented Jul 11, 2026

Copy link
Copy Markdown
Owner

Port of upstream anomalyco/opencode#36357.

When git check-ignore exits with a code other than 0/1 (repo corruption, permission errors), the snapshot ignore-check now treats all candidate files as ignored instead of returning an empty set, preventing sensitive ignored files from being swept into snapshots on git failure.

Verified: bun test test/snapshot/ (55 pass, 1 pre-existing skip) and bun typecheck from packages/opencode. Applied cleanly.

Summary by CodeRabbit

  • Bug Fixes
    • Improved snapshot handling when ignore checks encounter an unexpected failure.
    • Files are now conservatively treated as ignored instead of potentially being included incorrectly.

@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@CreatorGhost, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 47 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 089e467f-2b70-4a21-98ce-d5d1aa08c686

📥 Commits

Reviewing files that changed from the base of the PR and between 2cf324e and bafe8dd.

📒 Files selected for processing (1)
  • packages/opencode/src/snapshot/index.ts
📝 Walkthrough

Walkthrough

The snapshot ignore logic now warns on unexpected git check-ignore exit codes and treats all candidate files as ignored instead of returning an empty set.

Changes

Snapshot ignore handling

Layer / File(s) Summary
Unexpected ignore-command failures
packages/opencode/src/snapshot/index.ts
Unexpected git check-ignore exit codes now emit a warning and return the full candidate set as ignored.

Estimated code review effort: 2 (Simple) | ~10 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description covers the fix and verification, but it misses required template sections like the issue reference, type of change, and checklist. Add the missing template sections, including 'Closes #', type of change, and checklist, while keeping the existing implementation and verification details.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title concisely matches the main change: snapshot now fails closed when git check-ignore errors.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch snapshot-fail-closed

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@CreatorGhost

Copy link
Copy Markdown
Owner Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.


Your plan includes PR reviews subject to rate limits. More reviews will be available in 47 minutes.

@CreatorGhost

Copy link
Copy Markdown
Owner Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown
✅ Action performed

Full review finished.

@coderabbitai coderabbitai 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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/opencode/src/snapshot/index.ts (1)

93-99: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

git() should not mask spawn failures as exit code 1. ignore() treats 1 as a normal “none ignored” result, so a failed appProcess.run still falls through as an empty ignored set and bypasses the new fail-closed path. Surface the error or use a distinct sentinel for execution failures.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/opencode/src/snapshot/index.ts` around lines 93 - 99, Update the
error handling in git() so failures from appProcess.run are not represented by
ChildProcessSpawner.ExitCode(1), which ignore() interprets as a successful empty
result. Surface the spawn error or return a distinct execution-failure sentinel,
while preserving normal exit-code handling for actual git results.
🧹 Nitpick comments (2)
packages/opencode/src/snapshot/index.ts (2)

126-132: 🩺 Stability & Availability | 🔵 Trivial

Consider the blast radius of fail-closed across add/patch/diffFull.

Since ignore() is shared by add(), patch(), and diffFull(), a persistent unexpected check-ignore exit code won't just hide ignored files — add() will stop staging any candidates and patch()/diffFull() will silently show empty output, with only a warning-level log as a signal. Worth ensuring this warning is surfaced/alerted on in production observability so a persistently failing check-ignore (e.g., misconfigured git binary) doesn't look like "nothing changed" to users.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/opencode/src/snapshot/index.ts` around lines 126 - 132, Update the
unexpected check-ignore failure handling in ignore() so the warning is surfaced
through production observability, not only a warning-level log. Ensure failures
affecting add(), patch(), and diffFull() are clearly identifiable as
check-ignore errors rather than appearing as empty or unchanged results.

126-132: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a test for the new fail-closed branch.

None of the provided snapshot tests exercise a non-0/1 check-ignore exit code. Given this is a security-motivated change (preventing ignored-file leakage on git errors), a test that mocks/stubs an unexpected exit code and asserts all candidates end up in the returned set would directly protect this path from regression.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/opencode/src/snapshot/index.ts` around lines 126 - 132, Add a
snapshot test covering the `check.code !== 0 && check.code !== 1` branch in the
snapshot filtering flow: stub `git check-ignore` to return an unexpected non-0/1
exit code, invoke the relevant snapshot function, and assert the returned set
contains every candidate file.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@packages/opencode/src/snapshot/index.ts`:
- Around line 93-99: Update the error handling in git() so failures from
appProcess.run are not represented by ChildProcessSpawner.ExitCode(1), which
ignore() interprets as a successful empty result. Surface the spawn error or
return a distinct execution-failure sentinel, while preserving normal exit-code
handling for actual git results.

---

Nitpick comments:
In `@packages/opencode/src/snapshot/index.ts`:
- Around line 126-132: Update the unexpected check-ignore failure handling in
ignore() so the warning is surfaced through production observability, not only a
warning-level log. Ensure failures affecting add(), patch(), and diffFull() are
clearly identifiable as check-ignore errors rather than appearing as empty or
unchanged results.
- Around line 126-132: Add a snapshot test covering the `check.code !== 0 &&
check.code !== 1` branch in the snapshot filtering flow: stub `git check-ignore`
to return an unexpected non-0/1 exit code, invoke the relevant snapshot
function, and assert the returned set contains every candidate file.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b5c19cf6-f2ba-466c-b29f-6cd861cab533

📥 Commits

Reviewing files that changed from the base of the PR and between 67e2bd4 and 2cf324e.

📒 Files selected for processing (1)
  • packages/opencode/src/snapshot/index.ts

Addresses CodeRabbit Major finding on the anomalyco#36357 port: spawn failures no
longer masquerade as exit code 1, so check-ignore fail-closed cannot be
bypassed by a failed git invocation.
@CreatorGhost

Copy link
Copy Markdown
Owner Author

Addressed findings:

  • Major (git() masking spawn failures as code 1): fixed — spawn failures now return a -1 sentinel. All other callers in the file only test zero/non-zero, so their behavior is unchanged; only check-ignore's 0/1 distinction is affected, which is the point.
  • Nitpick (observability): skipped for now — this fork has no alerting pipeline beyond structured logs; the fail-closed branch logs at warning level with code+stderr, which is the strongest signal available here.
  • Nitpick (test for fail-closed branch): skipped with reason — ignore() is internal to the service and the repo's test guidelines discourage service mocks; forcing a non-0/1 check-ignore exit against a real repo requires corrupting the snapshot git dir mid-operation, which destabilizes the surrounding integration suite. The branch is 6 lines and directly readable; the new sentinel guarantees spawn failures reach it.

@CreatorGhost

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@CreatorGhost CreatorGhost merged commit d8a049a into dev Jul 12, 2026
5 of 7 checks passed
@CreatorGhost CreatorGhost deleted the snapshot-fail-closed branch July 12, 2026 02:31
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.

1 participant