Skip to content

fix(box): attempts on a repository GitHub doesn't host finish with the pick, and a pull request that doesn't open can be retried - #151

Merged
sean-brydon merged 2 commits into
mainfrom
fix/pr-step-non-github
Oct 18, 2026
Merged

sean-brydon merged 2 commits into
mainfrom
fix/pr-step-non-github

Conversation

@sean-brydon

Copy link
Copy Markdown
Collaborator

Fixes #138.

Before

The pr step pushed and then ran gh pr create on any remote. On Gitea, gh failed ("none of the git remotes … point to a known GitHub host"), and the step failed with it. The attempts template's cleanup runs only after success, so the whole run failed, cleanup was skipped and every worktree stayed behind. A finished run has no way to retry a step.

What changed

Checking the host first (internal/box/prhost.go):

  • The step reads origin's host. An SSH alias is resolved with ssh -G --, which reads the config and connects to nothing.
  • gh is used only for github.com, or for a host where gh auth status --hostname H succeeds (GitHub Enterprise).
  • On any other host (Gitea, Forgejo, GitLab, or a folder), the step still pushes the branch, then ends as skipped with a plain message. If the forge printed an "open a pull request" link on push (Gitea, Forgejo, GitLab and Bitbucket do), the message includes it, with any credentials removed.
  • The run goes on: the pick is kept, the other attempts are archived, and the run succeeds.

A pull request that fails on GitHub no longer fails the run:

  • The pr step opens a gate, "The pull request didn't open". It quotes gh's words and says the agents' work and the pick are kept.
  • Retry publishing runs the step again. Finish without a pull request ends it as skipped and the run goes on. Both work through the existing decide API (berth run approve / berth run reject).
  • The choice is journaled, so after a berthd restart the run asks the same question again instead of re-running gh.

Elsewhere:

  • Gate gets approve_label and reject_label, so the buttons in the app and the CLI say what they do.
  • /v1/review includes the pr step.
  • Review's Compare and the runs timeline show the note and its two buttons.
  • Credentials are stripped from URLs in push and gh output.

Gitea API pull requests: not added. The box has no Gitea credential (gh's token is GitHub-only), and tea can't be assumed to be installed. Pushing the branch and passing on the forge's own compare link is the safe step now.

Behaviour change: in your own flows, a pr step that fails now waits at the gate instead of failing the run. A step with when: "failure" after a pr step won't run, because choosing "Finish without a pull request" counts as skipped, not failed.

Proof

A pull request that didn't open (mock):

An attempts run on a Gitea repository, finished with its branch pushed:

The runs timeline:

Tests

The box tests use real git: a bare repository with a Gitea-style post-receive hook, and a fake gh that logs its calls.

--- PASS: TestThePRStepOnGiteaPushesAndSkips          # gh only asked "auth status --hostname gitea.acme.test"; branch pushed
--- PASS: TestThePRStepOnGitHubFailsWithGhsWords      # and the credential in the remote is stripped
--- PASS: TestThePRStepOpensOnASignedInEnterpriseHost
--- PASS: TestRemoteHostsAndPushLinks
--- PASS: TestAttemptsPRSkippedOnAnotherForgeStillCleansUp
--- PASS: TestAttemptsPRFailureWaitsThenRetries       # through a restart: gh isn't re-run, then the retry succeeds
--- PASS: TestAttemptsPRFailureFinishesWithoutOne
  • app/e2e/publish-failed.spec.ts (3 tests) passes.
  • typecheck, check:titles, check:csp, check:themes, pnpm test, build, tsc -p e2e, cargo check and the docs build pass.
  • Locally TestAttachPassesShiftEnter fails against tmux 3.7c, the same way on a clean origin/main.

🤖 Generated with Claude Code

…e pick, and a pull request that doesn't open can be retried

The pr step ran gh pr create on any remote. On Gitea (#138) gh failed,
the run failed at pr → open, cleanup was skipped and every worktree was
left behind.

- On a host gh can't open pull requests on (Gitea, Forgejo, GitLab, a
  folder; anything but github.com or a GitHub Enterprise host gh is
  signed in to), the step pushes the branch, says why it opened nothing,
  passes on the link the forge printed on push, and ends as skipped. A
  skipped leaf goes on like a success, so the run archives the other
  attempts and succeeds with the pick kept.
- A pr step that fails is a publishing failure, not the agents' work:
  the run waits at a gate, "The pull request didn't open", with gh's
  words, the pick recorded and nothing archived. Retry publishing
  (approve) tries again; Finish without a pull request (reject) makes the
  step a skip and the run goes on. A restart asks the same question
  without running gh again.
- Gates can name their two ways on (approve_label, reject_label); the
  app's run timeline and Review's Compare show them, Compare says what
  became of the pull request, and the CLI prints them.
- URLs in push and gh output lose any user and password before they are
  kept.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vercel

vercel Bot commented Oct 18, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
berth Ready Ready Preview Oct 18, 2026 5:25pm UTC
berth-docs Ready Ready Preview Oct 18, 2026 5:25pm UTC

Request Review

@sean-brydon
sean-brydon merged commit df58611 into main Oct 18, 2026
8 checks passed
@linear-code

linear-code Bot commented Oct 18, 2026

Copy link
Copy Markdown

ENG-6405

@daniil616

Copy link
Copy Markdown

thank you

This branch was successfully deployed

2 active deployments
Preview – berth-docs — e398ff06 Deployed Oct 18, 2026 by vercel[bot]
Preview – berth — e398ff06 Deployed Oct 18, 2026 by vercel[bot]
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.

Attempts workflow invokes GitHub PR creation for a repository hosted on Gitea

2 participants