Skip to content

Talk to GitHub through its API instead of the gh CLI (#1528) - #1550

Merged
currentbits merged 1 commit into
mainfrom
coder/talk-to-github-through-its-api-instead-o-04dd2a
Oct 9, 2026
Merged

currentbits merged 1 commit into
mainfrom
coder/talk-to-github-through-its-api-instead-o-04dd2a

Conversation

@currentbits

Copy link
Copy Markdown
Owner

Closes #1528, closes #1533, closes #1534.

What changed

  • electron/github.js: a REST/GraphQL transport. It gets a token per host in this order: a token saved in Settings, then gh auth token --hostname <host> [--user <account>] (cached per host and account), then gh's active account. Existing gh users don't need to change anything. GHE works through https://<host>/api/graphql and /api/v3.
  • Background refresher (worktrees-pr.js): one GraphQL query per repo instead of one gh pr view per thread on every 5-minute tick. Threads with PR watch (Workflow round: review, PR loop, composer, compaction, real terminal #1493) keep the per-thread gh path, because they need gh's watch fields.
  • Interactive PR and issue actions go through ghApiTryAsync, which tries the API first and falls back to gh. A write that times out is not retried through gh, so nothing gets posted twice. PR create, edit and comment still run the outbound secret scan before sending. gh pr checkout stays on gh because it does the git plumbing.
  • Settings › Source control: pick the account per host (logins come from gh auth status --json hosts), save a token, and "Add host" for GHE. Tokens are sealed the same way as linearApiKey and never sent to the renderer: settings come back as {host, account, hasToken}, and saving a row without a token key keeps the stored token.

Testing

  • Typecheck: no new errors. src/mermaidEngine.ts(72) TS2345 already fails the same way on main with the same node_modules.
  • vite build succeeds.
  • Renderer tests: 2916 pass, 0 fail.
  • Electron tests: 4407 pass, 0 fail, run with a CI-style env (no inherited CODER_*, minimal PATH).
  • Live read-only check against this repo: 3 PRs in one GraphQL request, 508 ms.
  • A join test confirms that a token saved in Settings authenticates an interactive pr view.

Not in this PR

  • Issue comments and creates have never been secret-scanned (that's not new here). Left as a suggested follow-up.

🤖 Generated with Claude Code

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-09T12:50:57.899656Z 87b4f31 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 87b4f31c87

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread electron/github.js
try {
const u = new URL(s);
if (!/^(https?|ssh|git):$/.test(u.protocol)) return null;
host = u.hostname;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve custom ports when parsing GitHub remotes

For a GitHub Enterprise remote such as https://ghe.example:8443/org/repo.git, URL.hostname drops :8443. The resulting target therefore neither matches the saved githubHosts row (whose validator explicitly permits ports) nor sends API requests to the configured port, so token-backed PR operations silently fall back or fail against the wrong endpoint. Use the URL host, including its port, when constructing the API target.

Useful? React with 👍 / 👎.

Comment thread electron/github.js
Comment on lines +415 to +416
if (sub === "merge" && number != null && args.includes("--squash") && args.length === 4) {
await rest({ ...req, method: "PUT", path: `${repoPath}/pulls/${number}/merge`, body: { merge_method: "squash" } });

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Support configured merge modes on GitHub Enterprise

On a GitHub Enterprise remote, this condition translates only an exact four-argument squash merge. Existing callers also pass --merge, --rebase, --auto, or an optional squash --body; those forms throw Unsupported, and ghApiTryAsync explicitly refuses the normal gh fallback for non-githubproxy.fjygbaifeng.eu.org origins. Consequently those user-visible merge choices always fail on the newly supported Enterprise hosts, even when gh is available; translate the supported flags or permit the GHES fallback.

Useful? React with 👍 / 👎.

- electron/github.js: REST/GraphQL transport. Token per host: saved token
  from Settings, else `gh auth token --hostname h [--user <account>]`
  (cached host|account), so existing gh users change nothing. GHE via
  https://<host>/api/graphql and /api/v3.
- Background refresher: one GraphQL query per repo instead of one
  `gh pr view` per thread; watched threads (#1493) keep the gh path.
- Interactive PR and issue ops go through ghApiTryAsync: API first, gh as
  fallback; a timed-out write is not retried via gh. PR create/edit/comment
  keep the outbound secret scan. `gh pr checkout` stays on gh.
- Settings › Source control: account per host, saved token (never sent
  to the renderer), Add host for GHE (#1533).

Closes #1528, #1533, #1534.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@currentbits
currentbits force-pushed the coder/talk-to-github-through-its-api-instead-o-04dd2a branch from 87b4f31 to 85b4f7b Compare October 9, 2026 13:25
@currentbits
currentbits merged commit 62ea068 into main Oct 9, 2026
6 checks passed
currentbits pushed a commit that referenced this pull request Oct 9, 2026
#1550 moved PR/issue ops to the GitHub API behind isGitHubPrRemote.
Keep that at every call site and feed it the gh-host/ssh-alias aware
isGitHubRemoteAsync (#1523), so GHE works through the API or gh. Planboard
(issues.js) and revertPr.js also use the async check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
currentbits pushed a commit that referenced this pull request Oct 19, 2026
#1550 moved PR/issue ops to the GitHub API behind isGitHubPrRemote.
Keep that at every call site and feed it the gh-host/ssh-alias aware
isGitHubRemoteAsync (#1523), so GHE works through the API or gh. Planboard
(issues.js) and revertPr.js also use the async check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants