Native PHP runtime: blueprint execution via blueprints.phar#3271
Merged
fredrikekelund merged 21 commits intotrunkfrom Apr 30, 2026
Merged
Native PHP runtime: blueprint execution via blueprints.phar#3271fredrikekelund merged 21 commits intotrunkfrom
fredrikekelund merged 21 commits intotrunkfrom
Conversation
…emove redundant result assignment
Collaborator
📊 Performance Test ResultsComparing 24e019e 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) |
- Handle parallelism for `run-blueprint` messages - Harden `config.blueprint` types to avoid non-null assertion - Remove `runProcessToCompletion` in favor of `runPhpCommand`
fredrikekelund
approved these changes
Apr 29, 2026
Contributor
fredrikekelund
left a comment
There was a problem hiding this comment.
Fundamentally, this works incredibly well 👍
I took the liberty of making a few changes to address things I identified while reviewing:
- Type-safe and reusable GitHub release fetching in
scripts/download-wp-server-files.ts. - Use a queue for
run-blueprintmessages. - Hardened
config.blueprinttypes to avoid non-null assertion. - Removed
runProcessToCompletionin favor ofrunPhpCommand. - Write the blueprint JSON file to the original blueprint directory so
blueprint.pharcan read local assets correctly. - Use
fs.rmto remove thesqlite-database-integrationsymlink (Claude says Windows will throw when unlinking junctions). For extra safety, this is backed up by verifying the inode before deleting.
We should investigate how blueprint.phar handles remote resources more closely. Right now, php-server-child.ts errors if blueprint.uri is an HTTP URL. We can work around that by fetching the URL before handing it to blueprint.phar, but that only work if there are no additional gotchas related to how blueprint.phar handles HTTP fetching compared to the Playground implementation.
…layground-server-child
- `wordpress-server-manager.ts` got stuck waiting for a response to the `start-server` message because zod parsing failed on the response. That's because JSON serialization drops keys where the value is undefined. It's unclear why we haven't seen this error for `playground-server-child.ts`. The fix was to change the `childMessageResult` schema. - Pass environment variables from the CLI through the process manager daemon when spawning a process so that `getPhpBinaryPath` returns the same result as in the CLI process when running E2E tests.
1 task
fredrikekelund
added a commit
that referenced
this pull request
May 5, 2026
## Related issues <!-- Link a related issue to this PR. If the PR does not immediately resolve the issue, for example, it requires a separate deployment to production, avoid using the "Fixes" keyword and use "Related to" instead. --> - Fixes RSM-1725 ## How AI was used in this PR <!-- Help reviewers understand what to look for and verify that you've reviewed the code yourself. --> Primarily to help me debug the problem. I alternated between Claude and Codex. ## Proposed Changes While working on #3271, @bcotrim discovered that the E2E tests were failing when run with `STUDIO_RUNTIME=native-php`. This PR fixes that by implementing the following fixes: - When Studio clones a site, explicitly update the site URL. Playground can handle this internally, but the native PHP runtime obviously cannot. - On Posix platforms, spawn process daemon children with `detached: true` to assign them to a new process group. This is so we can pass a negative PID to `process.kill` to terminate the entire process group (the Node.js process and the associated PHP process). This approach isn't bulletproof, but it's alright, and it works for the purpose of the E2E tests. - Favor SIGTERM over SIGKILL when killing child processes to give them a chance to clean up. ## Testing Instructions <!-- Add as many details as possible to help others reproduce the issue and test the fix. "Before / After" screenshots can also be very helpful when the change is visual. --> Run the E2E tests locally on macOS by following these steps: 1. `npm run package` 2. `STUDIO_RUNTIME=native-php npm run e2e` 3. Ensure that they pass successfully ## Pre-merge Checklist <!-- Complete applicable items on this checklist **before** merging into trunk. Inapplicable items can be left unchecked. Both the PR author and reviewer are responsible for ensuring the checklist is completed. --> - [ ] Have you checked for TypeScript, React or other console errors?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Related issues
How AI was used in this PR
This PR was largely AI-assisted. I reviewed all changes and tested end-to-end locally.
Proposed Changes
Implements blueprint execution for the native PHP runtime (
php-server-child.ts), which previously threw"not supported"for therun-blueprintIPC message.scripts/download-wp-server-files.ts: addsblueprints-phardownload entry — fetches the latestblueprints.pharfrom WordPress/php-toolkit GitHub releases and lands it atwp-files/blueprints/blueprints.phar, which Vite auto-copies intodist/cli/wp-files/at build timeapps/cli/lib/dependency-management/paths.ts: addsgetBlueprintsPharPath()following the existing phar path helper patternapps/cli/php-server-child.ts:runProcessToCompletion()— spawns a process, streams stdout/stderr, sends{ topic: 'activity' }IPC pings on each chunk to keep the parent alive during long installsrunBlueprint()— writes blueprint JSON to a temp file, callsphp blueprints.phar exec --mode=apply-to-existing-site, cleans up on exitrunBlueprint()intostartServer()so blueprints are applied automatically after WordPress is installedrun-blueprintIPC case to callrunBlueprint()directly (used by the--no-startpath)SQLite workaround:
blueprints.phardetects SQLite by checkingwp-content/plugins/sqlite-database-integration/load.php, but Studio installs it inmu-plugins/. A temporary symlinkplugins/ → mu-plugins/is created before the PHAR runs and removed after. Moving SQLite frommu-pluginstopluginsis a broader conversation for later.Testing Instructions
Example blueprint
{ "steps": [ { "step": "setSiteOptions", "options": { "blogname": "Blueprint worked!" } } ] }npm run download:wp-server-files(ornpm install) — confirmwp-files/blueprints/blueprints.pharappearsnpm run cli:buildPre-merge Checklist