Skip to content

feat: export git workspace diff and patch - #146

Merged
delete-cloud merged 2 commits into
mainfrom
feat/git-workspace-diff-patch
May 13, 2026
Merged

delete-cloud merged 2 commits into
mainfrom
feat/git-workspace-diff-patch

Conversation

@delete-cloud

@delete-cloud delete-cloud commented May 13, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • add provider-level workspace diff and patch result contracts
  • implement Docker provider Git-backed diff metadata and unified patch export
  • wire GET /sessions/{session_id}/workspace/diff and /workspace/patch to provider operations

Validation

  • uv run pytest tests/coding_agent/environment/test_docker_workspace_provider.py tests/coding_agent/environment/test_docker_workspace_provider_transfer.py tests/ui/test_http_server.py tests/ui/test_http_server_workspace_transfer.py tests/cli/test_remote_client.py -k "git_workspace or workspace_source or workspace_diff or workspace_patch or docker_workspace or workspace_transfer or remote_run or RemoteResultPublicationContract" -q
  • uv run basedpyright --level error src/coding_agent/environment/workspace_provider.py src/coding_agent/environment/init.py src/coding_agent/environment/docker_workspace_provider.py src/coding_agent/ui/http_server.py src/coding_agent/ui/schemas.py tests/coding_agent/environment/test_docker_workspace_provider.py tests/ui/test_http_server.py
  • uv run ruff format --check src/coding_agent/environment/workspace_provider.py src/coding_agent/environment/init.py src/coding_agent/environment/docker_workspace_provider.py src/coding_agent/ui/http_server.py src/coding_agent/ui/schemas.py tests/coding_agent/environment/test_docker_workspace_provider.py tests/ui/test_http_server.py
  • git diff --check

Summary by CodeRabbit

  • New Features

    • Workspace diff endpoint returns detailed per-file change info (status, old/new paths, additions/deletions, binary flags) and totals
    • Workspace patch endpoint returns git-format unified patches with format metadata
  • Behavior Changes

    • Diff/patch endpoints now return real provider-derived payloads instead of "not implemented"
  • Errors

    • Improved error mappings for diff/patch requests (404/400/409 where appropriate)
  • Tests

    • Added end-to-end tests covering diff and patch behavior and access controls

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 13, 2026 •

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: bd3fddd2-415e-42be-bf1c-20a94cc6c73e

📥 Commits

Reviewing files that changed from the base of the PR and between c480940 and 280cc86.

📒 Files selected for processing (2)
  • coding-agent/src/coding_agent/ui/http_server.py
  • coding-agent/tests/ui/test_http_server.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • coding-agent/tests/ui/test_http_server.py
  • coding-agent/src/coding_agent/ui/http_server.py

📝 Walkthrough

Walkthrough

Adds git-based workspace diff/patch: domain types and wrappers, Docker provider git implementations, HTTP endpoint wiring, and corresponding tests.

Changes

Workspace Diff and Patch Export via Git

Layer / File(s) Summary
Domain types and provider protocol
coding-agent/src/coding_agent/environment/workspace_provider.py
Introduces WorkspaceDiffStatus type alias and dataclasses (WorkspaceDiffFile, WorkspaceDiff, WorkspacePatch) and adds workspace_diff/workspace_patch methods plus workspace_diff_from_config/workspace_patch_from_config wrappers.
Docker provider git implementation
coding-agent/src/coding_agent/environment/docker_workspace_provider.py
Implements workspace_diff and workspace_patch overrides that validate git-capable workspace roots and run git commands. Adds helpers: _git_workspace_root_for_operation, _run_git_workspace_command, _parse_git_name_status, _workspace_diff_status_from_git_status, and _parse_git_numstat.
Public API re-exports
coding-agent/src/coding_agent/environment/__init__.py
Re-exports WorkspaceDiff, WorkspaceDiffFile, WorkspacePatch and workspace_diff_from_config, workspace_patch_from_config via the environment package.
HTTP endpoint implementation
coding-agent/src/coding_agent/ui/http_server.py
Implements /sessions/{session_id}/workspace/diff and /sessions/{session_id}/workspace/patch endpoints to call provider wrappers, convert results to UI schemas, and translate common errors to HTTP statuses.
Docker provider test coverage
coding-agent/tests/coding_agent/environment/test_docker_workspace_provider.py
Adds tests that monkeypatch git subprocesses to validate diff parsing (name-status + numstat), patch export command/return, and error on missing .git.
HTTP endpoint test coverage
coding-agent/tests/ui/test_http_server.py
Adds contract tests asserting provider-derived payloads for /workspace/diff and /workspace/patch, session ownership hiding, and /publish still returns 501.

Sequence Diagram

sequenceDiagram
  participant Client
  participant HTTPEndpoint
  participant ConfigWrapper
  participant DockerProvider
  participant GitCmd

  Client->>HTTPEndpoint: GET /sessions/{session_id}/workspace/diff
  HTTPEndpoint->>ConfigWrapper: workspace_diff_from_config(config, workspace_id)
  ConfigWrapper->>DockerProvider: workspace_diff(config, workspace_id)
  DockerProvider->>GitCmd: git diff --name-status -z
  GitCmd-->>DockerProvider: name-status output
  DockerProvider->>GitCmd: git diff --numstat
  GitCmd-->>DockerProvider: numstat output
  DockerProvider-->>ConfigWrapper: WorkspaceDiff
  ConfigWrapper-->>HTTPEndpoint: WorkspaceDiff
  HTTPEndpoint-->>Client: WorkspaceDiffResponse (files, totals)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 In Docker's den the branches play,
I nibble diffs and patch away,
Renames, binaries, added lines,
I hop through git's small signs.
Now endpoints sing the workspace tune!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main feature: adding git workspace diff and patch export functionality across the provider interface, Docker implementation, and HTTP endpoints.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/git-workspace-diff-patch

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 and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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)
coding-agent/src/coding_agent/ui/http_server.py (1)

1739-1744: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Enforce session visibility checks before exporting diff/patch

Line 1742 and Line 1791 inject auth_context, but these handlers never validate caller visibility (unlike endpoints using _get_visible_session). This can expose another user’s workspace metadata/content.

Suggested fix
 async def get_session_workspace_diff(
     request: Request,
     session_id: str,
     auth_context: AuthContext | None = Depends(auth_context_from_headers),
 ) -> WorkspaceDiffResponse:
     del request
+    _ = await _get_visible_session(session_id, auth_context)
     try:
         diff = await session_manager.export_workspace_archive(
             session_id,
             lambda binding: workspace_diff_from_config(
                 _load_cloud_workspace_config(),
                 binding.workspace_id,
             ),
         )
 async def get_session_workspace_patch(
     request: Request,
     session_id: str,
     auth_context: AuthContext | None = Depends(auth_context_from_headers),
 ) -> WorkspacePatchResponse:
     del request
+    _ = await _get_visible_session(session_id, auth_context)
     try:
         patch = await session_manager.export_workspace_archive(
             session_id,
             lambda binding: workspace_patch_from_config(
                 _load_cloud_workspace_config(),
                 binding.workspace_id,
             ),
         )

Also applies to: 1788-1793

🤖 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 `@coding-agent/src/coding_agent/ui/http_server.py` around lines 1739 - 1744,
The handler get_session_workspace_diff (and the similar endpoint around lines
1788-1793) currently accept auth_context but skip visibility checks; update both
to call the existing _get_visible_session(session_id, auth_context) (or
equivalent visibility helper) at the start, use the returned session for any
workspace access, and return the appropriate error (403/404) if the session is
not visible to the caller; remove the placeholder "del request" and ensure all
exported diff/patch logic uses the verified session object so no other user's
workspace metadata/content can be leaked.
🧹 Nitpick comments (1)
coding-agent/tests/ui/test_http_server.py (1)

3472-3579: ⚡ Quick win

Add owner-isolation tests for /workspace/diff and /workspace/patch

These new tests cover happy paths well, but they don’t assert cross-user access is hidden (404) like existing session/result tests do. Adding one non-owner case per endpoint would guard the auth boundary.

🤖 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 `@coding-agent/tests/ui/test_http_server.py` around lines 3472 - 3579, Add
owner-isolation assertions to the two tests
(test_workspace_diff_returns_provider_result and
test_workspace_patch_returns_provider_result) by creating a second client or
simulating a different user and calling the same endpoints
(/sessions/{session_id}/workspace/diff and
/sessions/{session_id}/workspace/patch) as a non-owner, then assert the response
status_code is 404; keep the existing monkeypatch setup for
workspace_diff_from_config/workspace_patch_from_config and
_load_cloud_workspace_config and reuse the created session_id but perform the
GET as the non-owner to ensure cross-user access is hidden.
🤖 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 `@coding-agent/src/coding_agent/ui/http_server.py`:
- Around line 1739-1744: The handler get_session_workspace_diff (and the similar
endpoint around lines 1788-1793) currently accept auth_context but skip
visibility checks; update both to call the existing
_get_visible_session(session_id, auth_context) (or equivalent visibility helper)
at the start, use the returned session for any workspace access, and return the
appropriate error (403/404) if the session is not visible to the caller; remove
the placeholder "del request" and ensure all exported diff/patch logic uses the
verified session object so no other user's workspace metadata/content can be
leaked.

---

Nitpick comments:
In `@coding-agent/tests/ui/test_http_server.py`:
- Around line 3472-3579: Add owner-isolation assertions to the two tests
(test_workspace_diff_returns_provider_result and
test_workspace_patch_returns_provider_result) by creating a second client or
simulating a different user and calling the same endpoints
(/sessions/{session_id}/workspace/diff and
/sessions/{session_id}/workspace/patch) as a non-owner, then assert the response
status_code is 404; keep the existing monkeypatch setup for
workspace_diff_from_config/workspace_patch_from_config and
_load_cloud_workspace_config and reuse the created session_id but perform the
GET as the non-owner to ensure cross-user access is hidden.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 62a06a92-48a7-46a4-b659-25526a2c3fb3

📥 Commits

Reviewing files that changed from the base of the PR and between 9dde89f and c480940.

📒 Files selected for processing (6)
  • coding-agent/src/coding_agent/environment/__init__.py
  • coding-agent/src/coding_agent/environment/docker_workspace_provider.py
  • coding-agent/src/coding_agent/environment/workspace_provider.py
  • coding-agent/src/coding_agent/ui/http_server.py
  • coding-agent/tests/coding_agent/environment/test_docker_workspace_provider.py
  • coding-agent/tests/ui/test_http_server.py

@delete-cloud
delete-cloud merged commit 26f8eea into main May 13, 2026
1 check passed
@delete-cloud
delete-cloud deleted the feat/git-workspace-diff-patch branch May 13, 2026 07:15
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