Skip to content

Migrate to new Stacks REST API#177

Merged
skarim merged 4 commits into
skarim/sync-remote-new-branchesfrom
skarim/rest-api-migration
Jul 15, 2026
Merged

Migrate to new Stacks REST API#177
skarim merged 4 commits into
skarim/sync-remote-new-branchesfrom
skarim/rest-api-migration

Conversation

@skarim

@skarim skarim commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator

With the upcoming release of the public REST API for stacked pull requests (/repos/{owner}/{repo}/stacks), this will replace the temporary cli_internal endpoints that gh-stack had previously been using. This moves every stack operation onto it. Because the API is public, it also lifts the auth restriction added in #113: anyone authenticated with the GitHub CLI can run stack operations once the feature is enabled for their repo — the OAuth-only limitation is gone.

What the new API gives us

  • List (GET /stacks) with a server-side ?pull_request=N filter to find the stack a PR belongs to.
  • Detail (GET /stacks/{number}) — fetch a single stack by its number.
  • Create (POST /stacks) — returns the created stack, including its number.
  • Add (POST /stacks/{number}/add) — append PRs to the top of a stack (delta only; we no longer resend the full PR list).
  • Unstack (POST /stacks/{number}/unstack) — the server decides which PRs can be removed.

Behavior changes worth noting

  • Discovery uses the ?pull_request= filter instead of listing every stack and scanning client-side.
  • Updates are append-only. There is no full-replace endpoint, so submit and link compute the delta and append it. A desired change that isn't a clean append onto the remote stack — a reorder, or a removal such as merged PRs leaving the stack — is left untouched rather than force-rewritten.
  • unstack is now server-driven. The old client-side eligibility pre-check is gone. The server removes the unlocked PRs and returns 204 when the stack is fully dissolved, 200 when some PRs (queued for merge or with auto-merge enabled) remain, or 422 when nothing can be removed. unstack keeps local tracking when PRs remain on the stack.

Changes

Add stack Number field to local model and schema

  • internal/stack/stack.go, schema.json — add the Number field to the Stack model and document it. Additive only; nothing populates it yet.

Cut over stack operations to the public Stacks REST API

  • internal/github/github.go — the core of the change. Point the client at the new /stacks endpoints and rework RemoteStack to carry the stack's id, number, base, open state, and PR list. Adds FindStackForPR (the ?pull_request= lookup), GetStack, AddToStack (delta append), and a Unstack that distinguishes the 204 (dissolved) from 200 (PRs remain) responses. client_interface.go and mock_client.go follow the new method set.
  • cmd/submit.go, cmd/link.go — reconcile against the remote stack via the ?pull_request= lookup and express updates as delta appends rather than resending the full list.
  • cmd/checkout.go — discover a PR's stack through FindStackForPR instead of scanning every stack.
  • cmd/unstack.go — drop the client-side eligibility pre-check and react to the server's 204/200/422 result, keeping local tracking when PRs remain.
  • cmd/utils.go — shared helpers for the sync reconcile path and for resolving a stack's number from its id.
  • cmd/*_test.go — command tests updated for the new client surface and mock.

Remove the personal access token (PAT) limitation

  • Delete internal/config/auth.go and auth_test.go, and the TokenForHostFn test hook in config.go.
  • cmd/submit.go drops the PAT pre-flight; cmd/utils.go renames warnStacksUnavailableOrPATwarnStacksUnavailable, and checkout.go / link.go drop the PAT-specific messaging. A 404 now simply means stacked PRs aren't enabled for the repo.

Testing

  • Updated the affected command tests for the new client surface and the server-driven unstack semantics.
  • Verified the create → add → unstack round-trip against the live API on a test repo, including the delta-append and 204/200/422 paths.
  • go test -race ./..., go vet ./..., and gofmt are clean, and each of the three commits builds and passes tests independently.

Stack created with GitHub Stacks CLIGive Feedback 💬

skarim added 3 commits July 14, 2026 06:01
The new Stacks REST API exposes a human-facing stack number (shown in the
github.com UI) alongside the internal stack id. Add a Number field to the
stack.Stack model and document it in schema.json so it can be persisted in
the .git/gh-stack file. Purely additive; behavior is unchanged until callers
populate it.

Copilot-Session: 03673c26-a245-42da-93ed-dfcebc92a740
Replace the private cli_internal stack endpoints with the new public
Stacks REST API (/repos/{owner}/{repo}/stacks):
- ListStacks / FindStackForPR (?pull_request= filter) / GetStack for reads
- CreateStack, which now returns the created stack including its number
- AddToStack for delta-only appends (there is no full-replace endpoint)
- Unstack for server-driven removal (204 dissolved / 200 partial / 422)

Migrate all callers (checkout, submit, link, sync, unstack, utils) and
drop the client-side unstack eligibility pre-check — the server now
decides which PRs can be unstacked. checkout discovers stacks via the
pull_request filter; submit/link express updates as append-only deltas;
unstack adopts partial-unstack semantics, keeping local tracking when
PRs remain stacked on GitHub.

RemoteStack now carries the stack number, and stack updates resolve a
stack's number from its internal id for stack files that predate the
Number field.

Copilot-Session: 03673c26-a245-42da-93ed-dfcebc92a740
The new Stacks REST API is public, so any user authenticated with the
GitHub CLI (including via a PAT with repo scope) can perform stack
operations once the feature is enabled for their repository. Remove the
PAT detection and the private-preview gating:

- Delete Config.WarnIfPAT / IsPersonalAccessToken and the TokenForHostFn
  test hook (internal/config/auth.go is no longer needed).
- Drop the submit pre-flight that aborted on a PAT.
- Rename warnStacksUnavailableOrPAT to warnStacksUnavailable and simplify
  it to the "stacked PRs not enabled" message.

Copilot-Session: 03673c26-a245-42da-93ed-dfcebc92a740
Copilot AI review requested due to automatic review settings July 14, 2026 11:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Migrates stack operations from temporary internal endpoints to the public Stacks REST API.

Changes:

  • Adds stack numbers and public REST API client methods.
  • Updates submit, link, checkout, sync, and unstack workflows.
  • Removes PAT-specific restrictions and updates tests.
Show a summary per file
File Description
internal/stack/stack.go Adds stack number storage.
internal/stack/stack_test.go Tests number persistence.
internal/stack/schema.json Documents the number field.
internal/github/mock_client.go Updates stack API mocks.
internal/github/github.go Implements public REST stack operations.
internal/github/client_interface.go Updates the client interface.
internal/config/config.go Removes the token test hook.
internal/config/auth.go Removes PAT detection.
internal/config/auth_test.go Removes PAT tests.
cmd/utils.go Adds number resolution and reconciliation support.
cmd/utils_test.go Updates warning tests.
cmd/unstack.go Adopts server-driven unstacking.
cmd/unstack_test.go Tests new unstack semantics.
cmd/sync_test.go Updates sync API mocks and expectations.
cmd/submit.go Implements append-only stack reconciliation.
cmd/submit_test.go Updates submit and modify-recovery tests.
cmd/link.go Uses delta-based stack additions.
cmd/link_test.go Tests additive linking behavior.
cmd/checkout.go Uses filtered discovery and stack numbers.
cmd/checkout_test.go Updates remote checkout tests.

Review details

  • Files reviewed: 20/20 changed files
  • Comments generated: 7
  • Review effort level: Medium

Comment thread cmd/utils.go
Comment thread cmd/utils.go
Comment thread cmd/submit.go
Comment thread cmd/submit.go
Comment thread cmd/checkout.go
Comment thread cmd/checkout.go Outdated
Comment thread internal/github/github.go

@talum talum 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.

👍🏼

@skarim skarim merged commit a82dc3e into main Jul 15, 2026
7 checks passed
@skarim skarim deleted the skarim/rest-api-migration branch July 15, 2026 16:08
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.

3 participants