Skip to content

feat(cli): vers github install + mint-token (with VERS_LANDING_URL)#187

Draft
nsluss wants to merge 3 commits intomainfrom
feat/vers-github-commands
Draft

feat(cli): vers github install + mint-token (with VERS_LANDING_URL)#187
nsluss wants to merge 3 commits intomainfrom
feat/vers-github-commands

Conversation

@nsluss
Copy link
Copy Markdown

@nsluss nsluss commented Apr 20, 2026

Summary

Adds two new subcommands under vers github:

  • vers github install — drives the GitHub App install flow via the vers-landing API (/api/github/install-url + /api/github/status), optionally opens the browser, polls until the install completes.
  • vers github mint-token — mints a short-lived GitHub App installation access token scoped to the caller's org, prints it to stdout for piping into git clone / gh / curl.

Also adds a VERS_LANDING_URL env var + DEFAULT_VERS_LANDING_URL_STR constant (parallel to VERS_URL / DEFAULT_VERS_URL_STR) via a new auth.GetVersLandingURL() helper. Replaces a prior host-munging helper (deriveLandingURL()) that inferred api.vers.sh → vers.sh heuristically; the landing app is a separate deployment and should be configurable independently.

Verification

Full end-to-end verified against prod:

$ vers github install --timeout 300
https://github.com/apps/vers-landing-github-prod/installations/new?state=92c0f153-...
Waiting for GitHub App installation (timeout 5m0s)...
✓ GitHub App installed successfully (installation 125660596)

$ vers github mint-token
ghs_bOwLPf7djzfichRloBQMuoUQ28y3vM2X0sqK

Paired server-side work

Route handlers (/api/github/install-url, /api/github/status) + the installation_id bigint→number cast were deployed separately:

  • hdresearch/vers-landing#572 — routes + middleware whitelist
  • hdresearch/vers-landing noah/cli-backend-routes — installation-token bigint fix

Noah (fleet agent) and others added 2 commits April 20, 2026 17:53
Add two new subcommands under vers github:

- vers github install: Gets the GitHub App install URL, opens browser,
  polls for installation confirmation with configurable timeout.
- vers github mint-token: Mints short-lived GitHub App installation
  access tokens via vers-landing API. Outputs raw token for piping
  or JSON with --format json.

Files added:
  cmd/github.go            - parent command
  cmd/github_install.go    - install subcommand
  cmd/github_mint_token.go - mint-token subcommand
Adds a dedicated VERS_LANDING_URL env + DEFAULT_VERS_LANDING_URL_STR
constant (parallel to VERS_URL / DEFAULT_VERS_URL_STR) via a new
auth.GetVersLandingURL() helper.

Replaces deriveLandingURL() — which was host-munging the API URL
('api.vers.sh' -> 'vers.sh') — with an explicit configuration point.
The landing deployment is independent from the API and should not be
inferred from it.

Refactors cmd/github_install.go to:
  - Resolve the landing base via auth.GetVersLandingURL() instead of
    going through application.Client (which targets api.vers.sh)
  - Call the correct landing paths: /api/github/install-url and
    /api/github/status (no bogus /v1/ prefix)
  - Use a local landingGetJSON() helper that does Bearer-authed GET
    against the landing app directly

cmd/github_mint_token.go drops the host-munging helper and uses the
same auth.GetVersLandingURL() for the installation-token endpoint.

The end-to-end flow was exercised against a local vers-landing dev
server (see companion vers-landing commits for the matching route
handlers and middleware whitelist).
@nsluss nsluss force-pushed the feat/vers-github-commands branch from 65c435f to c5fe564 Compare April 20, 2026 22:00
Coverage matches the existing repo style:
  - handler-level tests via httptest.NewServer that assert wire-format
    (path, method, Bearer header, request body shape, response decoding)
  - table-driven pure-function tests modeled on TestGetVMDomain

Additions:

  internal/auth/auth_test.go (extended):
    - TestGetVersLandingURL — table-driven, 7 cases covering the default,
      empty/whitespace env fallback, staging + localhost overrides, and
      error paths for missing/unsupported schemes
    - TestGetVersLandingURL_IndependentOfVersURL — regression guard that
      the landing URL is NOT derived from VERS_URL (the old host-munging
      heuristic should not sneak back)

  cmd/github_install_test.go:
    - TestLandingGetJSON_Success — path, GET method, Bearer header,
      Accept header, JSON decoding of the response
    - TestLandingGetJSON_NoAPIKey — clean error before any HTTP fires;
      isolates HOME to a tempdir so LoadConfig() can't pick up the
      developer's real ~/.versrc
    - TestLandingGetJSON_ServerError — 403 surfaces with status + body
    - TestLandingGetJSON_NumericInstallationID — installation_id decodes
      cleanly as int64 (locks in the post-fix wire format from
      vers-landing)
    - TestLandingGetJSON_ContextCancel — cancellation propagates

  cmd/github_mint_token_test.go:
    - TestDoMintToken_Success — wire format (path, POST, Bearer,
      Content-Type), request body (repositories + permissions),
      response decoding
    - TestDoMintToken_NoAPIKey — clean error, no HTTP fires
    - TestDoMintToken_ErrorMapping — 6-case table: 401/403 → auth failed,
      404 → 'run vers github install first', 503 → not configured,
      generic 4xx/5xx → HTTP-coded passthrough
    - TestDoMintToken_EmptyToken — 200 with empty token still errors
    - TestDoMintToken_UsesLandingURL — regression guard: VERS_LANDING_URL
      drives the endpoint host, not vers.sh
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