Skip to content

Replace cli/cli api dependency with go-gh - #72

Open
williammartin wants to merge 1 commit into
mdb:mainfrom
williammartin:williammartin-remove-cli-cli-dependency
Open

williammartin wants to merge 1 commit into
mdb:mainfrom
williammartin:williammartin-remove-cli-cli-dependency

Conversation

@williammartin

@williammartin williammartin commented Oct 2, 2026 •

Copy link
Copy Markdown

Description

Hihi, thanks for creating an extension for the GitHub CLI. I'm a maintainer for gh. We were doing some work on short lived tokens and I noticed you are depending on the api package from the cli/cli module. Historically, the maintainers did a bad job of setting expectations around importing packages from this module. I'm strongly considering biting the bullet and moving packages into internal to reduce our ongoing maintenance burden, but I'd prefer not to just break everyone.

This PR removes the dependency on github.com/cli/cli/v2/api (and pkg/httpmock) in favour of github.com/cli/go-gh/v2's api.RESTClient, which we do expect to follow semantic versioning.

pkg/iostreams and pkg/cmdutil are still imported from cli/cli. Replacing iostreams means copying in a lot of terminal handling code, so I've left it out to keep this PR small. If anything, it indicates an opportunity to create new abstractions in go-gh.

Run/workflow types

The upstream run/shared fetch helpers (GetRun, GetJobs, GetAnnotations, etc.) all take the cli/cli api.Client, so they're replaced with small go-gh equivalents in runs.go.

I also redefined the handful of types and render helpers this extension uses instead of importing them from run/shared and workflow/shared: Run, Job, Step, Annotation, RenderJobs, RenderAnnotations and Symbol. Upstream shared.Run keeps the workflow name in an unexported field that only cli/cli's own GetRun can populate. Reusing it would render an empty workflow name in the run header.

Behaviour change: per-host auth

Previously the HTTP client was built for the default host (GH_HOST, the sole logged-in host, or github.com), while the request URL was derived from the --repo host. go-gh only attaches the Authorization header when the request host matches the client's host, so -R ghes.example.com/o/r was sent unauthenticated.

The client is now built with Host: repo.RepoHost(), so the target host's token is used. I haven't exercised this against a GHES instance.

Scenario (default = github.com) Before After
-R o/r / -R github.com/o/r github.com token same
-R ghes.example.com/o/r, logged in to GHES unauthenticated GHES token ✅
-R ghes.example.com/o/r, not logged in to GHES unauthenticated error: authentication token not found for host ghes.example.com

Relatedly, the current user's login (used to find the dispatched run) now comes from REST GET /user instead of GraphQL.

Test Change

Since I wanted to drop httpmock usage, I swapped it for the httptest package. A smaller change would have been a simple replacement transport stubber but honestly, I think httptest is just a better black box approach. Can back it out if you feel differently! The expected output in the tests is unchanged.

Caveat

Copilot did most of the work here so I can't say I've given it extreme scrutiny but I did guide it along the way and it looks generally correct to me.

Demo

These GIFs were recorded on github.com with a build from this PR, against a scratch repo containing copies of this repo's Hello and Goodbye workflows. I also recorded the failure scenario with a build of main, and its output matched, including exit code 1.

gh dispatch workflow, success:

gh dispatch workflow dispatches the Goodbye workflow with force_fail false, watches the run and reports it completed with success

gh dispatch repository, success:

gh dispatch repository sends a hello repository_dispatch event, watches the Hello run and reports it completed with success

gh dispatch workflow, failure:

gh dispatch workflow dispatches the Goodbye workflow with force_fail true, watches the failing run, reports it completed with failure and exits with status 1

Two things in these recordings are pre-existing on main and unchanged here:

  • Annotations don't show up in the watch view, because jobs that are still queued get cached with no annotations.
  • Failed runs print Error: SilentError.

Replace cli/cli's api.Client and the run/workflow shared packages with
local types and helpers built on go-gh's RESTClient. Only cli/cli's
iostreams and cmdutil are still used. Tests run against an httptest
server instead of httpmock.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@williammartin williammartin changed the title Use go-gh REST client instead of cli/cli api Replace cli/cli api dependency with go-gh Oct 2, 2026
@williammartin
williammartin marked this pull request as ready for review October 2, 2026 12:33

This branch has not been deployed

No deployments
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