Skip to content

Support separate web root and WordPress core directory#217

Open
adamziel wants to merge 3 commits intotrunkfrom
support-split-wp-core-webroot
Open

Support separate web root and WordPress core directory#217
adamziel wants to merge 3 commits intotrunkfrom
support-split-wp-core-webroot

Conversation

@adamziel
Copy link
Collaborator

Summary

On WP Cloud sites, the web root and WordPress core directory are separate paths:

  • Web root: /srv/htdocs (contains wp-content/)
  • WP root: /srv/htdocs/__wp__/ (contains wp-load.php, wp-includes/, wp-admin/)

The blueprint runner previously assumed these were always the same directory. All subprocess scripts used DOCROOT to find both wp-content/ and wp-load.php, which breaks on split layouts.

This PR introduces a WP_CORE_DIR environment variable that points to where WordPress core files live, independent of DOCROOT (the web root). On standard installs they're identical; on WP Cloud they differ.

The ExistingSiteResolver auto-detects the core directory by scanning immediate subdirectories for wp-load.php, so existing blueprints work without changes. A --wp-core-path CLI flag is also available for explicit configuration.

Test plan

  • New unit tests for detect_wordpress_core_dir() (standard layout, __wp__/ subdirectory, custom subdirectory, no WP found, deeply nested, nonexistent path)
  • New unit tests for RunnerConfiguration (default fallback, explicit override, reset to null)
  • Verify existing CI tests still pass (the change is backwards-compatible since WP_CORE_DIR defaults to DOCROOT)
  • Test on a WP Cloud site with split web/core roots

On WP Cloud sites, the web root (/srv/htdocs with wp-content/) and the
WordPress core directory (/srv/htdocs/__wp__/ with wp-load.php, wp-admin,
wp-includes) can be separate paths. Previously the runner assumed they
were always the same directory.

This introduces a WP_CORE_DIR env var alongside DOCROOT so subprocess
scripts can find WordPress core files independently of the web root.
The ExistingSiteResolver auto-detects the core directory by scanning
immediate subdirectories for wp-load.php, and a --wp-core-path CLI
flag allows explicit configuration.
Keep the language generic since this is a package for all hosts.
@adamziel adamziel force-pushed the support-split-wp-core-webroot branch from 3292d9b to c1ecdbe Compare February 13, 2026 14:32
@mdbitz
Copy link

mdbitz commented Feb 24, 2026

I circled back to this doing some testing and am still unable to get the blueprint runner to execute on the WP Cloud environment.

To test I checked out this project locally and built the phar that I uploaded to my test site. I tested using the following command and blueprint.json file.

php blueprints.phar exec blueprints.json --mode apply-to-existing-site --site-url "https://anonymous-hedgehog.jurassic.ninja" --site-path "/srv/htdocs" --db-user 151688099 --db-pass "REDACTED" --db-name 151688099 --wp-core-path=/srv/htdocs/__wp__/


[>                                                 ] 0.0% -   Site URL:  https://anonymous-hedgehog.Error: Failed to load WordPress installation: The target site exists but WordPress is not properly installed or configured

The built phar has the new code as it accepts wp-core-path as a known option.

blueprints.json testing with.

{
  "$schema": "https://playground.wordpress.net/blueprint-schema.json",
  "steps": [
    {
      "step": "installPlugin",
      "pluginData": {
        "resource": "wordpress.org/plugins",
        "slug": "gutenberg"
      },
      "options": {
        "activate": true
      }
    }
  ]
}

I was looking over this change in more detail and on the WP Cloud environments we have a symlink at /srv/htdocs/wp-load.php that points to /srv/htdocs/__wp__/wp-load.php and so supplying the core path doesn't change the execution.

The issue is stemming from the following test executed in $runtime->eval_php_code_in_subprocess of class-existingsiteresolver.php when i pull the code out directly into a test.php file it runs without issue.

<?php
				require_once( "/srv/htdocs/" . "/wp-load.php");
				$is_installed = function_exists("is_blog_installed") && is_blog_installed() ? "true" : "false";
				echo "WordPress is installed: " . $is_installed;

@adamziel
Copy link
Collaborator Author

adamziel commented Mar 4, 2026

@mdbitz thank you for reviewing! I'll revisit this and ping you

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.

2 participants