Skip to content

Fix studio push for native reprint-pulled sites#3994

Merged
epeicher merged 13 commits into
trunkfrom
stu-1950-verify-that-studio-push-functionality-works-the-same-with
Jul 2, 2026
Merged

Fix studio push for native reprint-pulled sites#3994
epeicher merged 13 commits into
trunkfrom
stu-1950-verify-that-studio-push-functionality-works-the-same-with

Conversation

@epeicher

@epeicher epeicher commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Related issues

How AI was used in this PR

Claude Code was used throughout: to reproduce and diagnose the failure, to discover that there were two distinct blockers (a DB-connection error and a separate "could not locate the SQLite integration plugin" error), to validate the fix design with controlled experiments against a real reprint-pulled site, to implement the changes, and to verify the full push end-to-end. All generated code was reviewed.

Proposed Changes

Makes studio push work for sites created by studio pull-reprint on the native-php runtime. The export step previously failed — first with "Error establishing a database connection", then "Database export failed". The same WP-CLI path backs the desktop "get theme details" / "get site icon" features, which failed identically for these sites and are fixed too.

Why it failed: a reprint pull wires SQLite only through a generated runtime.php, which the web server applies as a PHP auto_prepend_file; these sites have no wp-content/db.php drop-in. The server reaches the database, but standalone WP-CLI — which push uses for wp plugin list, wp theme list, and wp sqlite export — never loads runtime.php. That produced two separate failures:

  1. wp plugin list / theme list fell back to MySQL → "Error establishing a database connection".
  2. wp sqlite export additionally needs the SQLite integration plugin discoverable in wp-content, which reprint sites don't have → "Could not locate the SQLite integration plugin".

WASM/Playground imported sites were never affected because their pull installs a real db.php drop-in; native imported sites never did.

The fix is two coordinated changes:

  • The native WP-CLI runner loads the site's runtime.php as auto_prepend_file for imported sites, restoring the database connection for general WP-CLI.
  • The sqlite-command (wp sqlite export/tables) is the exception: it loads its own integration copy and reads the database file directly, so it runs without the prepend, and push installs the SQLite integration into the imported site's wp-content so the command can find it.

Safe on both ends: runtime.php takes precedence over the drop-in on the running server (require_wp_db() returns early when $wpdb is set, so the drop-in is inert), and the exporter already excludes db.php and sqlite-database-integration from the upload, so neither reaches the MySQL remote.

Testing Instructions

  1. Apply the changes on this branch and run npm run cli:build
  2. Create a Studio site or use an existing Studio site
  3. Run STUDIO_ENABLE_PULL_REPRINT=true node apps/cli/dist/cli/main.mjs pull-reprint --path <path-to-Studio-site> to pull a remote site using Reprint, e.g. STUDIO_ENABLE_PULL_REPRINT=true node apps/cli/dist/cli/main.mjs pull-reprint --path ~/Studio/my-shiny-website. Select the remote site to pull and wait for completion
  4. Open Studio and connect to the remote site selected in previous step, or use the following CLI command on the Studio folder cd <path-to-Studio-site> && node ~/github/studio/apps/cli/dist/cli/main.mjs push, e.g. cd ~/Studio/my-shiny-website && node ~/github/studio/apps/cli/dist/cli/main.mjs push
  5. Verify that the Push complete successfully

Sites created by `studio pull-reprint` on the native-php runtime wire SQLite
only through a generated runtime.php (applied by the server as
auto_prepend_file) and ship no wp-content/db.php drop-in. Standalone WP-CLI
never loaded runtime.php, so `studio push` failed two ways: `wp plugin list`
and `wp theme list` (meta.json) hit "Error establishing a database
connection", and `wp sqlite export` (the DB dump) reported "Could not locate
the SQLite integration plugin".

The native WP-CLI runner now loads the site's runtime.php as auto_prepend_file
for imported sites, restoring the database connection for general WP-CLI. This
also fixes the desktop get-theme-details / get-site-icon errors.

The sqlite-command (wp sqlite export/tables) is the exception: it loads its own
SQLite integration copy and reads the database file directly, so prepending
runtime.php loads a second integration copy and fatals. It runs without the
prepend, and push installs the SQLite integration into the imported site's
wp-content so the command can find it. This is safe: runtime.php takes
precedence over the drop-in on the running server (require_wp_db returns early
when $wpdb is set), and the exporter already excludes db.php and the
integration from the upload, so neither the local server nor the MySQL remote
is affected.

Claude-Session: https://claude.ai/code/session_015EADJrWvjTQrmdgpFZre6j
Comment thread apps/cli/commands/push.ts Outdated
Comment on lines +59 to +71
await keepSqliteIntegrationUpdated( siteFolder );
// Reprint-pulled (imported) sites wire SQLite through runtime.php and ship no db.php
// drop-in, so the step above skips them. The database export below uses `wp sqlite
// export`, which requires the SQLite integration to be discoverable in wp-content.
// Install it for imported sites; the exporter excludes db.php and the integration from
// the upload, so it never reaches the remote.
if ( site.runtimeBlueprintPath && ! ( await isSqliteIntegrationInstalled( siteFolder ) ) ) {
await installSqliteIntegration( siteFolder );
}

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.

Could we if/else here?

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.

Done as part of 1ce73b2

epeicher added 2 commits July 1, 2026 12:01
Addresses review feedback on #3994: move keepSqliteIntegrationUpdated into
the else branch so the imported-site install and the normal-site update are
mutually exclusive, instead of always calling keepSqliteIntegrationUpdated
and then conditionally installing. Behavior-preserving.

Claude-Session: https://claude.ai/code/session_015EADJrWvjTQrmdgpFZre6j
…rify-that-studio-push-functionality-works-the-same-with
@epeicher epeicher marked this pull request as ready for review July 1, 2026 11:01
@epeicher epeicher requested a review from a team July 1, 2026 11:03
@wpmobilebot

wpmobilebot commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

📊 Performance Test Results

Comparing 832f740 vs trunk

app-size

Metric trunk 832f740 Diff Change
App Size (Mac) 1316.93 MB 1316.83 MB 0.10 MB ⚪ 0.0%

site-editor

Metric trunk 832f740 Diff Change
load 746 ms 1073 ms +327 ms 🔴 43.8%

site-startup

Metric trunk 832f740 Diff Change
siteCreation 6508 ms 6539 ms +31 ms ⚪ 0.0%
siteStartup 1862 ms 1866 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.

Nice and targeted fix 👍 Looks good overall, although it'd be nice to address the SQLite integration issue in the export command here, too. Let me know your thoughts there, @epeicher

Comment thread apps/cli/lib/run-wp-cli-command.ts Outdated
Comment thread apps/cli/lib/pull/runtime-start-options.ts Outdated
Comment thread apps/cli/lib/pull/runtime-start-options.ts
Comment thread apps/cli/commands/push.ts Outdated
epeicher added 5 commits July 1, 2026 16:58
The parameter was widened to the full SiteData type, but the tests still passed partial objects, which broke tsc. Route the calls through a minimal SiteData factory. Also reword the getImportedSiteAutoPrependFile docblock and the auto_prepend_file comment in runNativeWpCliCommand.
runNativeWpCliCommand and spawnPhpProcess each built the '-d auto_prepend_file=...' arg themselves. getDefaultPhpArgs now emits it, and its optional params move into an options object so callers no longer pass meaningless positional placeholders. Behavior-preserving.
Reprint-pulled sites wire SQLite through runtime.php and ship no db.php drop-in, so 'wp sqlite export' could not locate the integration and the database step failed ('Could not locate the SQLite integration plugin'). This hit the standalone 'export' command, which — unlike push — had no imported-site setup. Move the install from push.ts into the exporter's addDatabase so both push and export get it. The integration is excluded from the archive, so it never reaches the backup or the remote.
…-studio-push-functionality-works-the-same-with
@epeicher epeicher requested a review from fredrikekelund July 2, 2026 07:46

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

Clean fix 👍 Works great. I'll take a look at #4038 next

Comment on lines +286 to +297
// Reprint-pulled (imported) sites wire SQLite through runtime.php and ship no
// db.php drop-in, so keepSqliteIntegrationUpdated skips them. The `wp sqlite export`
// below requires the SQLite integration to be discoverable in wp-content, so install
// it for imported sites. It's excluded from the archive (see isExactPathExcluded),
// so it never reaches the backup or the remote.
if (
this.options.site.runtimeBlueprintPath &&
! ( await isSqliteIntegrationInstalled( this.options.site.path ) )
) {
await installSqliteIntegration( this.options.site.path );
}

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.

It'd be nice to defer this "is this a reprint site" check to the lower-level API here eventually. We can tackle that in another PR, though

Comment thread apps/cli/lib/pull/runtime-start-options.ts
Comment thread apps/cli/lib/run-wp-cli-command.ts Outdated
epeicher added 3 commits July 2, 2026 15:53
…onsNative

Both functions resolved the same runtime.php for a native imported site. Merge them into a single loadImportedRuntimeStartOptionsNative that takes the imported-site fields (satisfied by SiteData and the pull metadata alike) and returns undefined instead of throwing; the pull-reprint caller keeps its actionable error. Addresses review feedback on #3994.
The exporter checked runtimeBlueprintPath and installed the integration itself. Encapsulate that in ensureSqliteIntegrationForImportedSite so callers don't need to know how imported sites are detected. Addresses review feedback on #3994.
@epeicher

epeicher commented Jul 2, 2026

Copy link
Copy Markdown
Contributor Author

After all changes, the following tests have been done successfully:

  • Create a site
  • Pull a remote by using pull-reprint
  • Stop/start the site - Verified it works fine
  • Pull again so it is an incremental pull
  • Stop/start the site - Verified it works fine
  • Push the site - Verified the remote site works fine
  • Exported the site

@epeicher epeicher enabled auto-merge (squash) July 2, 2026 14:31
@epeicher epeicher merged commit 3de31c3 into trunk Jul 2, 2026
13 checks passed
@epeicher epeicher deleted the stu-1950-verify-that-studio-push-functionality-works-the-same-with branch July 2, 2026 14:37
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