Skip to content

feat: publish remote results as GitHub PRs - #151

Merged
delete-cloud merged 2 commits into
mainfrom
feat/remote-result-pr-publication
May 13, 2026
Merged

delete-cloud merged 2 commits into
mainfrom
feat/remote-result-pr-publication

Conversation

@delete-cloud

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

Copy link
Copy Markdown
Owner

Summary

  • implement publish mode=pr by first publishing a branch, then creating a GitHub PR via the Pulls API
  • return branch metadata for unsupported/missing GitHub config and failed PR creation after branch push
  • add CLI support for remote publish --pr and document GitHub publication config

Validation

  • uv run pytest tests/ui/test_http_server.py tests/cli/test_remote_client.py tests/coding_agent/environment/test_docker_workspace_provider.py -k "publish or workspace_diff or workspace_patch or remote_run" -q
  • uv run basedpyright --level error src/coding_agent/ui/schemas.py src/coding_agent/ui/http_server.py src/coding_agent/remote/client.py src/coding_agent/main.py src/coding_agent/environment/workspace_provider.py src/coding_agent/environment/docker_workspace_provider.py tests/ui/test_http_server.py tests/cli/test_remote_client.py tests/coding_agent/environment/test_docker_workspace_provider.py
  • uv run ruff format --check src/coding_agent/ui/http_server.py src/coding_agent/remote/client.py src/coding_agent/main.py tests/ui/test_http_server.py tests/cli/test_remote_client.py
  • git diff --check

Summary by CodeRabbit

  • New Features

    • Added GitHub pull request publication mode to the remote publish flow via --pr (branch-only remains default with --branch-only)
    • Branch name is now optional and auto-generated when omitted
    • CLI output now shows PR URL (when created), pushed ref, commit SHA, and remote URL; reports publication status
  • Documentation

    • Updated production config examples with GitHub remote publication settings and PR publication workflow
  • Tests

    • Added CLI and server tests covering successful PR creation and failure/unsupported scenarios

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: 0a9b0509-7258-41d3-a107-a8de38f27f75

📥 Commits

Reviewing files that changed from the base of the PR and between 0d6e11c and a23495b.

📒 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/src/coding_agent/ui/http_server.py
  • coding-agent/tests/ui/test_http_server.py

📝 Walkthrough

Walkthrough

Adds GitHub PR publication to session publishing: a mode-aware publish API and client, server-side GitHub REST PR creation with config/URL parsing and mapped statuses, CLI --pr/--branch-only support, tests for success/failure, and documentation updates.

Changes

GitHub PR Publication

Layer / File(s) Summary
PR Publication Contract & Status Handling
coding-agent/src/coding_agent/remote/client.py
publish_remote_result posts /sessions/{session_id}/publish with mode and branch_name, validates status in `published
CLI PR Publication Command
coding-agent/src/coding_agent/__main__.py
remote publish gains --pr and --branch-only options; branch_name is optional (defaults to coding-agent/session-<session_id>). Uses publish_remote_result, prints PR URL when present, branch/ref/commit/remote metadata, and raises on PR-mode failure.
Server-side GitHub PR Creation
coding-agent/src/coding_agent/ui/http_server.py
Adds urlsplit/httpx imports, GitHub API constants, PR-specific exception types, and helpers: _create_github_pull_request (validates config/token/base_branch, calls GitHub REST POST, returns html_url), _github_repo_from_remote_url (parses owner/repo from HTTP(S) or SCP remotes), and _publish_session_pr_response (maps outcomes to PublishSessionResponse). Integrates PR routing into publish_session_result.
PR Publication Tests
coding-agent/tests/cli/test_remote_client.py, coding-agent/tests/ui/test_http_server.py
CLI tests verify successful PR output (PR URL, metadata) and failure handling (non-zero exit, error message while showing branch metadata). HTTP server tests verify GitHub POST call and responses for success, unsupported config, and API failure.
Configuration & Usage Documentation
coding-agent/docs/remote-sandbox-production.md
Adds [remote_publication.github] example block (enabled, token_env, base_branch) and documents --pr behavior, required config, supported remotes, token usage, and status outcomes (unsupported, failed, published).

Sequence Diagram

sequenceDiagram
  participant CLI
  participant Server as publish_session_result
  participant BranchPub as publish_workspace_branch_from_config
  participant GitHub as GitHub API
  CLI->>Server: POST /sessions/{id}/publish {mode: "pr", branch_name}
  Server->>BranchPub: publish branch (config)
  BranchPub-->>Server: WorkspaceBranchPublication (remote_url, ref, commit)
  alt mode == "pr"
    Server->>_create_github_pull_request: create PR with publication & config
    _create_github_pull_request->>_github_repo_from_remote_url: parse owner/repo
    _create_github_pull_request->>GitHub: POST /repos/{owner}/{repo}/pulls (Authorization)
    GitHub-->>_create_github_pull_request: 201 + html_url or error
    _create_github_pull_request-->>Server: PR URL or raise GitHubPrPublicationError
    Server->>Server: _publish_session_pr_response -> status (published/failed/unsupported)
  end
  Server-->>CLI: PublishSessionResponse {status, pr_url?, branch_ref, remote_url, commit}
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

🐰 A branch hops out into the light,
Then dons a PR cape to take its flight,
The CLI whispers --pr with gentle cheer,
Servers nudge GitHub to open the door,
A rabbit claps — the merge link appears!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 2.17% 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 and concisely summarizes the main change: adding GitHub PR publication support to the remote publish feature.
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/remote-result-pr-publication

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.

Actionable comments posted: 3

🤖 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.

Inline comments:
In `@coding-agent/src/coding_agent/__main__.py`:
- Around line 1202-1265: The change to the CLI entrypoint remote_publish
(function remote_publish) alters publish behavior and must be validated by
running the full CLI test suite; run the entire tests/cli/ suite (e.g. pytest
tests/cli) and fix any failures that surface by adjusting either the
implementation around publish_remote_result handling (checks for
published_branch, commit_sha, remote_url, pr_url, status, pushed_ref and the
publish_mode == "pr" vs branch flows) or the tests to reflect intended behavior,
ensuring error messages, click.ClickException conditions and click.echo outputs
match expected tests; re-run tests/cli/ until all pass before merge.

In `@coding-agent/src/coding_agent/ui/http_server.py`:
- Around line 1876-1881: The PR path is making blocking httpx.post calls from an
async request handler; change _publish_session_pr_response and
_create_github_pull_request to async functions, replace synchronous httpx.post
calls with awaits against an httpx.AsyncClient (use either an async context
manager or a shared AsyncClient instance), update any caller
(publish_session_result) to await _publish_session_pr_response, and adjust
timeout/exception handling to work with async awaits and client.aclose()/context
management to avoid resource leaks; ensure all import references to httpx are
compatible with AsyncClient and update any synchronous helper usage accordingly.
- Around line 2010-2026: _github_repo_from_remote_url currently fails for
SCP-style remotes like "git@github.com:owner/repo.git" because urlsplit doesn't
set hostname; update the function to first detect SCP-style SSH remotes (e.g.
patterns like "git@github.com:owner/repo.git" or
"ssh://git@github.com/owner/repo.git") using a small regex or string parsing,
extract owner and repo (strip a trailing ".git"), and return them; if no
SCP-style match, continue to use urlsplit as before and keep the same
GitHubPrUnsupportedError checks and messages when hostname != "github.com" or
owner/repo can’t be derived.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0c02bb09-143a-4dee-83fb-b5c425f776d0

📥 Commits

Reviewing files that changed from the base of the PR and between 7ac2d26 and 0d6e11c.

📒 Files selected for processing (6)
  • coding-agent/docs/remote-sandbox-production.md
  • coding-agent/src/coding_agent/__main__.py
  • coding-agent/src/coding_agent/remote/client.py
  • coding-agent/src/coding_agent/ui/http_server.py
  • coding-agent/tests/cli/test_remote_client.py
  • coding-agent/tests/ui/test_http_server.py

Comment on lines +1202 to +1265
@click.option(
"--pr",
"publish_mode",
flag_value="pr",
help="Create a GitHub pull request after publishing the branch.",
)
@click.option(
"--branch-only",
"publish_mode",
flag_value="branch",
default="branch",
help="Publish the remote session changes as a Git branch only.",
)
def remote_publish(
name: str,
session_id: str,
branch_name: str | None,
publish_mode: str,
) -> None:
"""Publish remote session results as a Git branch or PR."""
from coding_agent.remote.client import get_remote, publish_remote_result

endpoint = get_remote(name)
publication = publish_remote_branch(endpoint, session_id, branch_name)
if branch_name is None:
branch_name = f"coding-agent/session-{session_id}"
publication = publish_remote_result(
endpoint,
session_id,
mode=publish_mode,
branch_name=branch_name,
)
published_branch = publication.get("branch_name")
pushed_ref = publication.get("pushed_ref")
commit_sha = publication.get("commit_sha")
remote_url = publication.get("remote_url")
pr_url = publication.get("pr_url")
status = publication.get("status")
if not isinstance(published_branch, str) or not published_branch:
raise click.ClickException("Remote publish response missing branch_name")
if not isinstance(commit_sha, str) or not commit_sha:
raise click.ClickException("Remote publish response missing commit_sha")
if not isinstance(remote_url, str) or not remote_url:
raise click.ClickException("Remote publish response missing remote_url")
click.echo(f"Published branch {published_branch}")
if publish_mode == "pr":
if isinstance(pr_url, str) and pr_url:
click.echo(f"Published PR {pr_url}")
click.echo(f"Branch: {published_branch}")
elif status in {"unsupported", "failed"}:
error = publication.get("error")
if isinstance(error, str) and error:
click.echo(error)
click.echo(f"Branch: {published_branch}")
else:
raise click.ClickException("Remote PR publication did not complete")
else:
if status != "published":
raise click.ClickException("Remote branch publication did not complete")
click.echo(f"Published branch {published_branch}")
if isinstance(pushed_ref, str) and pushed_ref:
click.echo(f"Ref: {pushed_ref}")
click.echo(f"Commit: {commit_sha}")
click.echo(f"Remote: {remote_url}")
if publish_mode == "pr" and status == "failed":
raise click.ClickException("Remote PR publication did not complete")

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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Run the full CLI test suite for this entrypoint change.

remote publish behavior changed materially, but the listed validation only covers a targeted CLI test file. Please run the full tests/cli/ suite before merge.

As per coding guidelines, "When changing CLI/entrypoint behavior, run tests/cli/ test suite".

🤖 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/__main__.py` around lines 1202 - 1265, The
change to the CLI entrypoint remote_publish (function remote_publish) alters
publish behavior and must be validated by running the full CLI test suite; run
the entire tests/cli/ suite (e.g. pytest tests/cli) and fix any failures that
surface by adjusting either the implementation around publish_remote_result
handling (checks for published_branch, commit_sha, remote_url, pr_url, status,
pushed_ref and the publish_mode == "pr" vs branch flows) or the tests to reflect
intended behavior, ensuring error messages, click.ClickException conditions and
click.echo outputs match expected tests; re-run tests/cli/ until all pass before
merge.

Comment thread coding-agent/src/coding_agent/ui/http_server.py
Comment thread coding-agent/src/coding_agent/ui/http_server.py
@delete-cloud
delete-cloud merged commit e99f92e into main May 13, 2026
1 check passed
@delete-cloud
delete-cloud deleted the feat/remote-result-pr-publication branch June 1, 2026 14: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