Repository navigation
Conversation
The GitHub counterpart of phabricator.submit_patch. The agent records the submission during the run; when it is applied, hackbot-api pushes a branch carrying the run's commits to the source repository and opens a draft pull request against its default branch. hackbot-api has no git checkout to apply the run's patch in, so publish_changes also captures each commit (message, author and changed files) as changes/github_commits.json, from the published base. The handler recreates those commits through GitHub's Git Data API on a hackbot/<run_id> branch, using the GitHub App with a token narrowed to that repository. Retrying reuses the branch and any pull request already open from it. github.submit_patch counts as a patch action in hackbot-api, so a run that leaves changes without one is still reported, and the run page previews the pull request's title and body. Fixes mozilla#7057
Drop the trailing NUL explicitly and pair headers with paths using itertools.batched(strict=True), so output that doesn't hold one path per entry raises instead of being silently mispaired. Handle a commit that changes no files, where diff-tree prints nothing.
There was a problem hiding this comment.
🟡 Changes recommended
The agent-writable artifact controls both the target repository and credential installation, allowing a compromised run to create branches and PRs in other repositories where the App is installed.
2 open issues
What changed in this PR
Adds github.submit_patch, the GitHub equivalent of Hackbot’s Phabricator submission action, addressing #7057. Agents record a submission during a run; hackbot-api later recreates the commits and opens a draft pull request.
Changes:
- Adds the recording tool and GitHub-specific commit artifact generation.
- Registers an apply-side handler that creates commits, manages the run’s branch, and reuses an existing PR on retries.
- Adds runtime and API tests, action documentation, and a UI preview.
| File | Description |
|---|---|
services/hackbot-ui/components/RunDetail.tsx |
Previews the PR title and body. |
services/hackbot-api/tests/test_github_handler.py |
Tests GitHub API calls, retries, and failures. |
services/hackbot-api/app/action_handlers/registry.py |
Registers the handler and patch action type. |
services/hackbot-api/app/action_handlers/github_handler.py |
Recreates commits and opens draft PRs. |
libs/hackbot-runtime/tests/test_github_actions.py |
Tests action recording and tool exposure. |
libs/hackbot-runtime/tests/test_context.py |
Tests artifact publishing and commit naming. |
libs/hackbot-runtime/tests/test_changes.py |
Tests commit serialization and file changes. |
libs/hackbot-runtime/hackbot_runtime/context.py |
Publishes GitHub artifacts for recorded submissions. |
libs/hackbot-runtime/hackbot_runtime/changes.py |
Builds the GitHub commit payload. |
libs/hackbot-runtime/hackbot_runtime/actions/github.py |
Defines the submission recording tool. |
libs/hackbot-runtime/hackbot_runtime/actions/claude_sdk.py |
Exposes the tool through the Claude SDK integration. |
libs/hackbot-runtime/hackbot_runtime/actions/__init__.py |
Exports GitHub actions. |
docs/hackbot/actions.md |
Documents the action and submission flow. |
Review effort: Balanced
Comment on lines
+210
to
+211
| repo_url = submission["repo_url"] | ||
| parsed = parse_repo_url(repo_url) |
| installation = await app_client.rest.apps.async_get_repo_installation(owner, repo) | ||
| return github_app.as_installation( | ||
| installation.json()["id"], | ||
| permissions=READ_WRITE_PERMISSIONS, |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Fixes #7057.
Adds
github.submit_patch, the GitHub equivalent ofphabricator.submit_patch. The agent records the action during the run. When it is applied, hackbot-api pushes the run's commits to ahackbot/<run_id>branch of the agent's source repository and opens a draft PR against its default branch. The PR'surlgoes in the action result, so later actions can reference it.How it works
hackbot-api has no checkout or git binary, so it can't
git push. This follows the Phabricator diff and the try push: the git work happens in the agent's container, and hackbot-api only calls the service's API.publish_changeswriteschanges/github_commits.jsonwhen agithub.submit_patchis recorded, next to the existing changes artifacts.build_github_commitsinchanges.pybuilds it from the commits since the published base. It includes uncommitted work, through the same WIP commit the other artifacts use, and records for each commit its message, author and changed files.github_handler.SubmitPatchHandlerreplays those commits through GitHub's Git Data API (blobs, trees, commits, then a branch ref) and opens the draft PR. Commits keep their original author, and the GitHub App commits and signs them. The installation token is narrowed to the one repository, withcontents: writeandpull_requests: write.github.submit_patchis added to hackbot-api'sPATCH_ACTION_TYPES, so a run that leaves changes without submitting them is still flagged. The runtime gets its own GitHubPATCH_ACTION_TYPES, kept separate from the Phabricator one so that a GitHub submission doesn't also build a Phabricator diff.docs/hackbot/actions.md, and a pull request preview (title and body) on the run page.Tests
pytest tests/passes (524). The newtest_github_handler.pydrives githubkit against a fake api.github.com built onhttpx.MockTransport. It covers the full flow, an empty body, a retry that reuses the branch and PR, a non-GitHub repository, a missing artifact, GitHub rejecting a call, and the App not being configured.pytest tests/passes (349). It covers the tool,build_github_commitsagainst real git repos (multiple commits, uncommitted work, deletions, file modes, binaries, renames, no changes) andpublish_changesgating.This hasn't been run against a real GitHub repository yet.
Risks and follow-ups
[source].repo_urlinside the agent-built artifact. That's the same trust model aschanges.json, and the token only works where the App is installed. A server-side allowlist of repositories could be added later.bug-fixwould also need prompt changes before using it.