Skip to content

Bring the interactive site selector to pull-reprint - #3729

Merged
epeicher merged 14 commits into
trunkfrom
studio-10-bring-the-interactive-site-selector-to-pull-reprint
Jun 15, 2026
Merged

Bring the interactive site selector to pull-reprint#3729
epeicher merged 14 commits into
trunkfrom
studio-10-bring-the-interactive-site-selector-to-pull-reprint

Conversation

@epeicher

@epeicher epeicher commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Related issues

Selector compared with previous one

CleanShot 2026-06-09 at 18 16 32@2x

How AI was used in this PR

Claude Code adapted the existing pull site selector (pickSyncSite) into a trimmed pull-reprint variant per the issue's guidance to copy rather than abstract (since pull is being deprecated), added unit tests for both the picker and the source-resolution flow, and verified the change — cli:build, typecheck, and the new test suites all pass. I reviewed the diff against the reference implementation and confirmed there are no behavior changes on the non-interactive paths.

Proposed Changes

When you run pull-reprint without --url and have more than one connected WordPress.com site, the command previously printed the list and aborted, forcing you to re-run with an explicit --url. Now, in an interactive terminal, it opens a searchable site picker (type to filter by name or hostname, arrow keys to navigate, Enter to select) — the same friendly selection experience already offered by pull. Cancelling with Esc or Ctrl-C is treated as a clean no-op: nothing is downloaded and no local state is created.

Existing behavior is preserved everywhere else: a single connected site is still auto-selected, the zero-site and --url/--secret paths are unchanged, and non-interactive callers (CI, the Desktop app driving the CLI) keep the original print-list-and-abort behavior so scripted usage is unaffected.

Testing Instructions

  1. Authenticate with a WordPress.com account that has two or more connected sites (studio auth login).
  2. From an interactive terminal, run:
    STUDIO_ENABLE_PULL_REPRINT=true node apps/cli/dist/cli/main.mjs pull-reprint --verbose
    
    (run npm run cli:build first)
  3. Confirm the interactive picker appears. Type to filter, select a site, and verify the pull proceeds against the chosen site.
  4. Re-run and press Esc (or Ctrl-C) at the picker — confirm it exits cleanly with no site created under ~/Studio/ and no state under ~/.studio/pulls/.
  5. Regression checks: with a single connected site it should auto-select without prompting; piping to a non-TTY (e.g. ... pull-reprint | cat) should fall back to printing the list and aborting.

Pre-merge Checklist

  • Have you checked for TypeScript, React or other console errors?
epeicher added 2 commits June 9, 2026 18:09
…interactive-site-selector-to-pull-reprint

# Conflicts:
#	apps/cli/commands/tests/pull-reprint.test.ts
@epeicher
epeicher marked this pull request as ready for review June 9, 2026 16:20
…ring-the-interactive-site-selector-to-pull-reprint
@epeicher
epeicher requested a review from fredrikekelund June 9, 2026 16:21
@wpmobilebot

wpmobilebot commented Jun 9, 2026

Copy link
Copy Markdown
Collaborator

📊 Performance Test Results

Comparing d43d5bd vs trunk

app-size

Metric trunk d43d5bd Diff Change
App Size (Mac) 1328.22 MB 1328.22 MB +0.00 MB ⚪ 0.0%

site-editor

Metric trunk d43d5bd Diff Change
load 1647 ms 1621 ms 26 ms ⚪ 0.0%

site-startup

Metric trunk d43d5bd Diff Change
siteCreation 8036 ms 8028 ms 8 ms ⚪ 0.0%
siteStartup 3917 ms 3913 ms 4 ms ⚪ 0.0%

Results are median values from multiple test runs.

Legend: 🟢 Improvement (faster) | 🔴 Regression (slower) | ⚪ No change (<50ms diff)

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

The control works well, but we need to look into the site list fetching. Right now, non-Atomic sites are displayed in the list, but selecting them leads to an error like this for me:

✖ Invalid API response format: Zod validation failed: [
  {
    "expected": "string",
    "code": "invalid_type",
    "path": [
      "body",
      "data",
      "secret"
    ],
    "message": "Invalid input: expected string, received undefined"
  }
]. Raw response: {"code":404,"headers":[{"name":"Content-Type","value":"application/json"}],"body":{"error":"rest_no_route","message":"No route was found matching the URL and request method.","data":{"status":404}}}
Comment thread apps/cli/lib/wpcom-site-picker.ts Outdated
Comment on lines +24 to +37
/**
* Interactive, searchable WordPress.com site picker.
*
* A trimmed clone of `pickSyncSite` (`apps/cli/lib/sync-site-picker.ts`)
* for the `pull-reprint` source-selection flow. It keeps the
* `[staging]` badge but, because `WpComSiteInfo` has no `syncSupport`,
* drops the disabled-entry and sync-support logic — every site is
* selectable.
*
* Type-to-filter matches on the site name and normalized hostname. Esc
* cancels the prompt (TTY only, via an `AbortController` wired to the
* raw escape byte) and resolves to `undefined`, as does Ctrl-C — so the
* caller can treat a cancellation as a clean no-op rather than an error.
*/

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.

In my testing, it doesn't appear that Reprint can sync non-Atomic sites. I would think this should be theoretically possible with how the Reprint exporter is deployed through wpcomsh, but I'm not familiar enough with wpcomsh to say for sure.

In any case, we need to adjust this implementation:

  1. We should only display syncable sites in the list. The simple solution to this problem is to change the site fetching to use the same implementation as apps/cli/commands/pull.ts
  2. If we do this, then there's not really a need for separate implementations between the pull and pull-reprint commands, as I understand it. Yes, the Jetpack-powered pull command is going away soon enough, so this isn't very important, but it'd be a nice touch.
  3. We should talk to Adam about whether Reprint is intended to work for simple sites, too, and what adjustments we might need to make that work.

@fredrikekelund fredrikekelund Jun 11, 2026

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.

separate implementations

I guess I explicitly said not to worry about this in the Linear issue 😅 Let's ignore this unless the implementation end up 1:1

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Well spotted! I didn't have any simple sites so when comparing with the pull command I was obtaining the same results, I will work on that.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed as part of a5ea784

Comment on lines +1182 to +1193
// In a real terminal, let the user pick interactively. Outside a
// TTY (CI, Desktop driving the command), keep the original
// print-list-and-abort behavior so scripted callers are
// unaffected.
if ( ! process.stdin.isTTY ) {
console.log( __( 'Connected WordPress.com sites:' ) );
console.log( formatWpComSitesList( sites ) );
console.log( '' );
throw new LoggerError(
__( 'Multiple WordPress.com sites are available. Re-run with `--url <site-url>`.' )
);
}

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.

If no --url option was provided and this isn't a TTY, I think it's fine to just exit with an error. Realistically, the main case in which this command would be triggered in a non-TTY context is when it is spawned as a child command of Studio.

If we follow this suggestion, then let's also remove the formatWpComSitesList function.

I could also see us moving the if ( ! process.stdin.isTTY ) into the pickWpComSite implementation, but I'll leave that to you, @epeicher

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed as part of fc3d1fa, with regards to moving the condition, I prefer the TTY gate at the call site: "are we allowed to prompt, and what do we do if not?" and keep the picker focused on "given a list, return a choice or a cancel."

@epeicher

Copy link
Copy Markdown
Contributor Author

Hi @fredrikekelund, after our conversation, I have checked the conditions to pull sites and I've decided to unify them so pull and pull-reprint use the same logic. The jetpack and is_wpcom_atomic conditions are basically the same, I have not been able to simulate an atomic non-jetpack site so I don't think we need to worry about that.

The logic is greatly simplified, can you have a look at it and let me know any issues?

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

Looks good! 👍 There's more we can do to streamline and simplify site fetching and preflight logic, but we can do that in follow-up PRs

@epeicher
epeicher merged commit 6116d4c into trunk Jun 15, 2026
12 checks passed
@epeicher
epeicher deleted the studio-10-bring-the-interactive-site-selector-to-pull-reprint branch June 15, 2026 10:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

3 participants