Skip to content

[eas-cli] Add eas billing:subscribe and billing:manage commands - #4007

Draft
jonsamp wants to merge 11 commits into
mainfrom
jon/eng-24459-eas-subscribe-command
Draft

[eas-cli] Add eas billing:subscribe and billing:manage commands#4007
jonsamp wants to merge 11 commits into
mainfrom
jon/eng-24459-eas-subscribe-command

Conversation

@jonsamp

@jonsamp jonsamp commented Jul 12, 2026

Copy link
Copy Markdown
Member

Why

Implements the CLI half of ENG-24459: let users subscribe to an EAS plan and get a Stripe checkout link from the terminal (e.g. eas billing:subscribe starter), plus manage/cancel an existing subscription.

The www-side half is ENG-24461 (jon/eng-24461-add-stripe-link-support-to-www), which makes the stripe-auth/checkout endpoint accept plan slugs and return session.url. This PR depends on that shipping first.

How

New billing topic:

  • eas billing:subscribe <plan> (starter, agent, production-plus, enterprise) — resolves the account (-a/--account, single account, or interactive picker), POSTs stripe-auth/checkout with the plan slug, and opens/prints the returned Stripe checkout URL. If the account already has a paid subscription it does not create a second one; it points the user at billing:manage (Stripe's portal handles plan changes with proration).
  • eas billing:manage — POSTs stripe-auth/customer-portal and opens/prints the portal URL (change plan, update payment method, cancel).

Implementation notes:

  • Plan slug → server PlanType mapping lives in the CLI; the env-specific Stripe price ids stay server-side.
  • Reuses ApiV2Client; unwraps the apiv2 { data } response envelope (eas-cli's ApiV2Client returns the raw body, unlike the website client).
  • Opens URLs with open instead of better-opn: better-opn runs the URL through encodeURI, which double-encodes Stripe's already-percent-encoded checkout fragment (%2F%252F) and breaks the link. The URL is always printed as a clickable fallback.
  • Added AccountQuery.getSubscriptionAsync for the already-subscribed check.

Test Plan

  • Unit tests: billingClient (envelope unwrapping), subscribe (plan mapping, already-subscribed guard, free-plan handling, non-interactive/JSON output, missing-URL error), manage (portal open, verbatim URL). yarn test src/billing src/commands/billing → 10/10 pass.
  • yarn typecheck, yarn lint, yarn fmt:check clean.
  • Manual: ran the built CLI against a local www with the ENG-24461 changes:
    EXPO_LOCAL=true easc papeete billing:subscribe starter --account jonexpo
    
    Returns a real https://checkout.stripe.com/... URL with the fragment intact.

Note: end-to-end against staging/prod requires ENG-24461 to be deployed first; until then the endpoint returns only { id } and subscribe reports that no URL was returned.

@linear-code

linear-code Bot commented Jul 12, 2026

Copy link
Copy Markdown

ENG-24459

@codecov

codecov Bot commented Jul 12, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 86.48649% with 30 lines in your changes missing coverage. Please review.
✅ Project coverage is 62.59%. Comparing base (01829a2) to head (7f26f4a).
⚠️ Report is 27 commits behind head on main.

Files with missing lines Patch % Lines
packages/eas-cli/src/billing/resolveAccount.ts 80.00% 12 Missing and 4 partials ⚠️
packages/eas-cli/src/commands/billing/subscribe.ts 91.53% 4 Missing and 1 partial ⚠️
packages/eas-cli/src/billing/openUrl.ts 84.22% 3 Missing ⚠️
...ckages/eas-cli/src/graphql/queries/AccountQuery.ts 0.00% 3 Missing ⚠️
packages/eas-cli/src/commands/billing/manage.ts 93.75% 2 Missing ⚠️
packages/eas-cli/src/build/build.ts 90.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4007      +/-   ##
==========================================
+ Coverage   62.47%   62.59%   +0.12%     
==========================================
  Files         995     1014      +19     
  Lines       44954    45997    +1043     
  Branches     9447     9685     +238     
==========================================
+ Hits        28080    28786     +706     
- Misses      15427    15745     +318     
- Partials     1447     1466      +19     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

jonsamp added 3 commits July 18, 2026 16:42
Adds a billing topic with:
- billing:subscribe <plan> - creates a Stripe checkout session for an EAS
  plan and returns/opens the checkout URL. Guards against double-subscribing
  by routing already-subscribed accounts to billing:manage.
- billing:manage - opens the Stripe customer portal (change plan, update
  payment method, cancel).

Calls the stripe-auth apiv2 endpoints, unwrapping the { data } envelope, and
uses open (not better-opn) so the pre-encoded Stripe checkout fragment is not
double-encoded. Depends on the www-side change (ENG-24461) that makes the
checkout endpoint return session.url and accept planTypes.
@jonsamp
jonsamp force-pushed the jon/eng-24459-eas-subscribe-command branch from e4f2824 to 1930122 Compare July 18, 2026 21:43
@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown

✅ Thank you for adding the changelog entry!

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