Summary
Agent release publishing shells out to the gh CLI for pure platform (API) operations. Move these to the github.com/google/go-github/v89 client, which is already a direct dependency (go.mod:22, used read-only today in cmd/agents/versions.go). This is the highest-value migration because it removes the runtime requirement that the gh binary be installed and authenticated on release hosts.
What uses gh today
In cmd/publish/agent_release.go:
createAndUploadRelease (:291) → gh release create + gh release upload --clobber (:301-306) — creates the GitHub release and uploads loader archives + SBOM assets.releaseExists (:319) → gh release view.- Preflight
exec.LookPath("gh") (:51) — the whole flow hard-requires the binary.
These are all GitHub REST API calls wrapped in a subprocess — not git operations.
Proposed change
Replace with go-github calls:
- Release exists check →
client.Repositories.GetReleaseByTag - Create release →
client.Repositories.CreateRelease - Upload assets →
client.Repositories.UploadReleaseAsset (loop over archives + SBOM; delete-then-upload to replicate --clobber) - Drop the
exec.LookPath("gh") preflight.
Reuse the existing client/token plumbing from cmd/agents/versions.go:
newGitHubClient (:488) → github.NewClient(github.WithAuthToken(token))githubToken() (:500) reads GITHUB_TOKEN / GH_TOKEN, then falls back to gh auth token (:507). Keep that fallback so local dev still works without exporting a token, but the gh dependency becomes optional (credential-only) instead of required.
Consider lifting newGitHubClient / githubToken into a small shared pkg/github (or similar) helper so agent-release, versions listing, and the GitOps/issue flows can share one client + token path.
Acceptance
Out of scope
- Content push / tagging that is a genuine git operation (release tags via
git tag/git push in cmd/publish/release.go) — keep git for those.
Part of #460.
Summary
Agent release publishing shells out to the
ghCLI for pure platform (API) operations. Move these to thegithub.com/google/go-github/v89client, which is already a direct dependency (go.mod:22, used read-only today incmd/agents/versions.go). This is the highest-value migration because it removes the runtime requirement that theghbinary be installed and authenticated on release hosts.What uses
ghtodayIn
cmd/publish/agent_release.go:createAndUploadRelease(:291) →gh release create+gh release upload --clobber(:301-306) — creates the GitHub release and uploads loader archives + SBOM assets.releaseExists(:319) →gh release view.exec.LookPath("gh")(:51) — the whole flow hard-requires the binary.These are all GitHub REST API calls wrapped in a subprocess — not git operations.
Proposed change
Replace with go-github calls:
client.Repositories.GetReleaseByTagclient.Repositories.CreateReleaseclient.Repositories.UploadReleaseAsset(loop over archives + SBOM; delete-then-upload to replicate--clobber)exec.LookPath("gh")preflight.Reuse the existing client/token plumbing from
cmd/agents/versions.go:newGitHubClient(:488) →github.NewClient(github.WithAuthToken(token))githubToken()(:500) readsGITHUB_TOKEN/GH_TOKEN, then falls back togh auth token(:507). Keep that fallback so local dev still works without exporting a token, but theghdependency becomes optional (credential-only) instead of required.Consider lifting
newGitHubClient/githubTokeninto a small sharedpkg/github(or similar) helper so agent-release, versions listing, and the GitOps/issue flows can share one client + token path.Acceptance
gh release *shell-outs.--clobbersemantics preserved (re-uploading an existing asset replaces it).ghbinary is no longer required for a release when a token is present via env.Out of scope
git tag/git pushincmd/publish/release.go) — keep git for those.Part of #460.