Fix studio push for native reprint-pulled sites#3994
Conversation
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
| 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 ); | ||
| } |
There was a problem hiding this comment.
Could we if/else here?
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
📊 Performance Test ResultsComparing 832f740 vs trunk app-size
site-editor
site-startup
Results are median values from multiple test runs. Legend: 🟢 Improvement (faster) | 🔴 Regression (slower) | ⚪ No change (<50ms diff) |
…ity-works-the-same-with
fredrikekelund
left a comment
There was a problem hiding this comment.
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
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
fredrikekelund
left a comment
There was a problem hiding this comment.
Clean fix 👍 Works great. I'll take a look at #4038 next
| // 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 ); | ||
| } | ||
|
|
There was a problem hiding this comment.
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
…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.
|
After all changes, the following tests have been done successfully:
|
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 pushwork for sites created bystudio pull-reprinton 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 PHPauto_prepend_file; these sites have nowp-content/db.phpdrop-in. The server reaches the database, but standalone WP-CLI — which push uses forwp plugin list,wp theme list, andwp sqlite export— never loadsruntime.php. That produced two separate failures:wp plugin list/theme listfell back to MySQL → "Error establishing a database connection".wp sqlite exportadditionally needs the SQLite integration plugin discoverable inwp-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.phpdrop-in; native imported sites never did.The fix is two coordinated changes:
runtime.phpasauto_prepend_filefor imported sites, restoring the database connection for general WP-CLI.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'swp-contentso the command can find it.Safe on both ends:
runtime.phptakes precedence over the drop-in on the running server (require_wp_db()returns early when$wpdbis set, so the drop-in is inert), and the exporter already excludesdb.phpandsqlite-database-integrationfrom the upload, so neither reaches the MySQL remote.Testing Instructions
npm run cli:buildSTUDIO_ENABLE_PULL_REPRINT=true node apps/cli/dist/cli/main.mjs pull-reprint --path <path-to-Studio-site>topulla 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 completioncd <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 pushPushcomplete successfully