WordPress/wordpress-playground

Boot protocol

adamziel opened this issue · 3 comments

Playground needs a boot function with this signature: bootWordPress :: Configuration -> Promise<PHPRequestHandler>. It would be a single point of entry for all Playground-based applications on all platforms to get WordPress up and running. See the discussion for more context.

Related resources

What will that unlock?

  • Reliable Playground CLI that can run any WordPress project
  • Reliable OPFS („browser storage”) that doesn’t break whenever db.php changes
  • Reliable and fast native fs integration that only stores wp-content locally without the rest of WP core (writing all the WordPress core files is super slow)
  • Migrating wp-now and the VS Code extension to a Playground CLI backend and solving most issues it suffers from
  • Groundwork for zip exports and imports.
  • Simpler, more consistent codebase
  • Inform Blueprints v2 development

Related issues this will solve:

Version 1 scope

A bootWordPress function

There are tactical guidelines all over the discussion, for example this comment about conflicts between mount options and installing WordPress options. Refer to the discussion frequently when working on this.

  • Boot PHP
    • Configuration would include a runtime-specific PHP factory function to create a PHPRequestHandler, setup runtime rotation, and use the right PHP version.
    • Set the default php.ini path
    • Set php.ini overrides
    • Set sub-process spawn handler
  • Boot PHPRequestHandler
    • Setup PHP process factory
    • Accept a site URL
  • Setup VFS
    • Create the right /internal directory structure to preload mu-plugins etc. from
    • Mount any resources (NODEFS, OPFS, Native FS handle, ZIP etc.)
    • Recursive copy files from given resources (NODEFS, OPFS, Native FS handle, extract ZIPs etc.)
    • Mounting and copying could happen at one of three stages: before setting up WordPress, before setting up the database, after setting up the database
    • Proxy /tmp, /internal/shared, and documentRoot to the primary PHP instance of the PHPRequestHandler
  • Setup WordPress files
    • Create any custom mu-plugins in /internal/shared/preload
    • Put ca certs in /internal/shared/ca.certs (if provided)
    • Unzip a "base snapshot" at /wordpress if needed. It could be an official WordPress release, a minified build, or a "complete Playground export" with wp-admin etc, but it can't be a "partial Playground export" with just wp-content.
    • Create docroot/../wp-config.php if docroot/wp-config.php is missing. If docroot is not in /wordpress, e.g. when mapping all local paths to vfs, then create wp-config.php in docroot
    • Set SITE_URL, HOME_URL
    • Generate secrets constants if needed
    • Assert WordPress core files are in place
  • Setup the database
    • Configuration specifies SQLite, MySQL, or "custom"
    • Boot function either preloads the SQLite plugin, expects MySQL connection details already provided in wp-config.php, or expects to find a custom db.php file
    • If SQLite, source the database either from wp-content, if we’re allowed to modify local files, or from /internal/shared/.ht.sqlite if we’re not allowed to.
    • Assert DB is accessible
  • Installs WordPress
    • checks is_blog_installed()
    • If yes, upgrade the database and we're done
    • Otherwise run the WordPress installation wizard
    • Run database upgrade
    • Assert is_blog_installed()

Platform-level enhancements

  • Migrate Playground CLI, Playground web, and Blueprints unit tests to this new boot function.
  • Generate the minified playground.wordpress.net build using Playground CLI. Remove the SQLite integration plugin from it. Still ship a pre-installed .ht.sqlite database. On web boot install the sqlite plugin in /internal. Ensure that previous ZIP exports and NativeFS mounts continue to work on playground.wordpress.net, ditto for new ZIP exports and NativeFS mounts.
  • #1407 + an in-browser counterpart
  • Get rid of wpContentFilesExcludedFromExport
  • A utility function similar to withPhpIniValues(callback) to disable networking for the WordPress installation request
  • Decide how to handle the configureErrorLogging platform-level mu-plugin – it creates debug.log file in wp-content which means it potentially modifies a local mount.
  • Align GitHub import/export handlers with zip import/export handlers and boot handlers. Remove a lot of special casing and excluding „core files” from different types of exports (zip, GitHub, native fs, local directories), reuse GitHub import/export path mapping logic in all these scenarios
  • #1399 to simplify the Configuration shape
  • Remove the importWordPressFiles and runWpInstallationWizard Blueprint steps as all these operations will be handled by the boot flow. Leave a no-op fallback in place and log a warning when it's used.

Related PRs:

Remaining work:

Nice to haves

  • Update the default php.ini values baked into WebAssembly PHP to something more useful for all runtimes, e.g. don't disable_functions, allow network calls, set the memory limit to 256M etc. Basically compile with the same default values we're setting in runtime now.
  • Replace the entire WordPress PR previewer Blueprint with a single artifact URL since the Boot flow would handle the installation, SQLite setup, db upgrades etc. cc @dmsnell

Assumptions

  • The behavior is low-level and explicit. We might use sensible default to ease the setup, but the boot function should avoid implicit, magic behaviors.
  • Error early when mutually incompatible options are used (example). This could be a runtime check, a type-level check, or both.
  • fetch() requests to get the Base Snapshot, SQLite plugin etc. may be started before the bootWordPress() call so the configuration should accept deferred resources.
  • Running the Blueprint is not a part of boot. The Blueprint runner assumes the filesystem already exists.
  • Boot avoids modifying the mounted files as much as possible. Two exceptions could be:
    • Writing to .ht.sqlite database – unless we'd offer a way of moving it to /internal/shared
    • Copying wp-config-sample.php to wp-config.php

Out of scope for v1 (future work)

  • Migrating wp-now
  • OverlayFS
  • Other mounting modes
    • One-way mounts (local changes are copied to Playground but not the other way around
    • Read-only modes (error on write attempt)
    • Timer/watcher for syncing local files to VFS
  • Site transfer protocol
  • Importing data from data.sql and rewrite stale URLs on the fly. V1 would only accept input data in form of a .ht.sqlite database.

The only two files Playground modifies during the boot sequence now are:

  • `wp-config.php‘, only when it’s originally missing. It could be also moved one level above the document root and WordPress would still pick it up.
  • .ht.sqlite, to install WordPress. It could be sourced from /internal if needed.

We still need to address this one: #1486

Well, actually let's close this one as a project and treat #1486 as a bug.