Read bundled CLI dependencies directly from wp-files#3125
Conversation
📊 Performance Test ResultsComparing e6ed07e 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) |
|
Given the changes we made in #3086, could we not read WP-CLI and sqlite-command directly from the wp-files directory, too? |
|
WDYT about adding a migration to clean up the paths in |
9ad5546 to
7334eb1
Compare
9849ca2 to
ce3716f
Compare
|
@bcotrim, did you close this PR intentionally? |
|
Can we remove |
9315a88 to
77648f0
Compare
016f988 to
a9a9f94
Compare
23e990c to
406cbbb
Compare
…guages/" This reverts commit 79da74f.
…te-dependency-handling # Conflicts: # apps/cli/lib/dependency-management/setup.ts
fredrikekelund
left a comment
There was a problem hiding this comment.
Nice and clean change 👍 Tests well. I left a few minor comments
| } | ||
|
|
||
| protected getSqlitePluginSourcePath(): string { | ||
| return path.join( 'server-files', SQLITE_DIRNAME ); |
There was a problem hiding this comment.
| return path.join( 'server-files', SQLITE_DIRNAME ); | |
| return path.join( 'wp-files', SQLITE_DIRNAME ); |
Might as well swap this to not mislead anyone.
There was a problem hiding this comment.
Noting that #3129 removes this file. We shouldn't make any changes here now, but we'll need to reconcile the changes between the PRs, depending on which one we land first.
There was a problem hiding this comment.
Let's also remove apps/studio/src/lib/sqlite-command-release.ts
There was a problem hiding this comment.
I advise renaming this file. We can call it something like apps/cli/lib/dependency-management/paths.ts
## Related issues - Closes STU-1537 (completes the part deferred from #3125) ## How AI was used in this PR Claude Code reconstructed the April context (#3125's deferred section, this PR's original debug instrumentation, and the language-pack copy races later documented in #3492), re-applied the bundle-read change cleanly on top of current trunk. ## Proposed Changes Language packs were the last site dependency still copied from the read-only CLI bundle into the writable `~/.studio/server-files/` cache on every CLI invocation. The copy was pure overhead: language packs are only ever read at site creation, to copy the matching locale's files into the new site's `wp-content/languages/`, and they only change when the app ships a new bundle. This PR has site creation read language packs directly from the bundled `wp-files/latest/languages/`, and drops the per-invocation copy step — shaving the remaining recursive dir-walk (~1,400 files) off CLI startup. Side benefits: - The copy step needed lockfile serialization (#3492) because concurrent CLI invocations raced on the shared cache (transient `ENOENT` warnings). With no copy and no writable cache, that bug class is gone by construction. - Site creation now skips the language-pack directory scans entirely for locales we don't bundle translations for (`WP_LOCALES`). - The existing `04-cleanup-obsolete-server-files` migration also removes the now-unused `~/.studio/server-files/language-packs/` (and its lockfile) on first run after upgrade. **On the April E2E failures that deferred this:** they never reproduced locally — neither at the CLI level (3/3 ja-locale sites healthy, WPLANG=ja, wp-admin 200) nor with the packaged-app Playwright suites that failed in CI back then. The Playground worker-spawn stack has been rewritten since (#3602), and the failure was never root-caused, so CI on this PR is the deciding signal. If mac E2E reds again, this time it fails on a clean branch with inspectable artifacts. ## Testing Instructions 1. `npm run download-language-packs` (plain `npm install` does not populate `wp-files/latest/languages`), then `npm run cli:build`. 2. Set a non-English locale (e.g. `"locale": "ja"` in `~/.studio/shared.json` or via Studio Settings) and create a site. 3. Verify the site's `wp-content/languages/` contains the locale's files (core + `plugins/` + `themes/`), wp-admin loads in that language, and Settings → General shows the locale selected under Site Language. 4. Verify `~/.studio/server-files/language-packs/` is deleted on first CLI run after upgrade and is not recreated. 5. Covered by e2e `localization.test.ts` (locale site creation + WPLANG) and `blueprints.test.ts` (blueprint provisioning). Verified locally on macOS arm64: typecheck, eslint, full unit suite (1963 tests), packaged-app e2e `localization.test.ts` 4/4 (twice) and `blueprints.test.ts` 6/6. ## Pre-merge Checklist - [x] Have you checked for TypeScript, React or other console errors?
Related issues
How AI was used in this PR
Claude Code explored the
setupServerFiles()call graph, identified which bundled deps safely work read-only from the CLI bundle vs. those that need a writable cache, then applied the refactor incrementally — one dep per commit, each validated on CI before moving on. A previous attempt had tried moving multiple deps at once and hit a wp-admin 500 failure; this time each dep was isolated and the real culprit (language packs) got narrowed down cleanly.Proposed Changes
setupServerFiles()used to run on every CLI invocation and copy every bundled dependency from the read-onlywp-files/(shipped with the CLI) to the writable~/.studio/server-files/. Almost none of those copies were needed — only WordPress is genuinely updated at runtime. The copy logic added ~60ms of overhead per CLI invocation.This PR has consumers read read-only deps directly from bundled
wp-files/and drops the corresponding copy steps.Kept writable (still copied into
~/.studio/server-files/):wordpress-versions/latest) — genuinely updated at runtime viaupdateLatestWordPressVersion()/downloadWordPress().language-packs/) — see Deferred below.Now read directly from
wp-files/(no copy):skills/) — CLI and desktop both repointedavailable-site-translations.jsonsqlite-database-integration/)wp-cli.phar) — mounted into PHP-wasm VFSsqlite-command/) — mounted into PHP-wasm VFSphpmyadmin/) — mounted into PHP-wasm VFSConsumer changes:
server-files.ts,site-language.ts,sqlite-integration.ts,dependency-management/setup.tslib/server-files-paths.ts(AI instructions repointed, newgetBundledSqlitePluginPathexport),lib/sqlite-versions.tstools/common/lib/sqlite-integration.ts— replaced the misleadingly-namedgetServerFilesPath()abstract method with agetSqlitePluginSourcePath()override, so subclasses can point anywhere.Cleanup:
04-cleanup-obsolete-server-filesdeletes the now-unused entries from~/.studio/server-files/on first CLI run after upgrade:skills/,sqlite-database-integration/,sqlite-command/,phpmyadmin/,wp-cli.phar, andwordpress-versions/latest/available-site-translations.json.apps/studio/src/lib/sqlite-command-versions.ts(nothing imports it).copySourceDirectoryIfNewerOrMissinghelper fromsetup.tsafter all its callers were dropped.Deferred
Language packs were initially in scope but consistently failed E2E (
localization.test.ts) in CI when moved to bundle-read — 2 failures, 2 passes on the equivalent commit-1-only state, so the failure is specific to reading language packs from the bundled location. Working theory: thereaddirover the ~1,300-entry bundledlatest/languages/dir inside the packaged.appmisbehaves in CI under a code path we haven't traced yet. Reverted to preserve the other wins; will revisit in a follow-up once we can grab a Playwright trace from a failing run.Testing Instructions
Automated
npm run typecheckpassesnpx eslint --fixon modified files — cleannpm test— all tests passManual
~/.studio/server-files/→ run CLI (studio site list) → verify onlywordpress-versions/andlanguage-packs/get created. No moreskills/,sqlite-database-integration/,sqlite-command/,phpmyadmin/,wp-cli.phar, oravailable-site-translations.json.~/.studio/server-files/with all the old entries, then upgrade to this build. On first CLI run the migration should delete the six obsolete entries;wordpress-versions/andlanguage-packs/are untouched.blueprints.test.tsandimport.test.ts.overview-customize-links.test.ts.STUDIO.mdin a site and restart the server — should be refreshed from bundledwp-files/skills/. (No direct E2E coverage — manual smoke.)WPLANG=jain wp-admin (language packs still go through the copy step, so behaviour should be identical to trunk). Covered by e2elocalization.test.ts.time node apps/cli/dist/cli/main.mjs site listbefore vs after on trunk; expect a measurable drop from dropping six copy steps at startup.Pre-merge Checklist