Skip to content

[Blueprints] Export and import all site files except Playground runtime files - #4141

Merged
adamziel merged 4 commits into
trunkfrom
adamziel/separate-runtime-wp-content-paths
Jul 21, 2026
Merged

[Blueprints] Export and import all site files except Playground runtime files#4141
adamziel merged 4 commits into
trunkfrom
adamziel/separate-runtime-wp-content-paths

Conversation

@adamziel

@adamziel adamziel commented Jul 21, 2026

Copy link
Copy Markdown
Collaborator

Make new ZIP exports preserve the site’s plugins, themes, uploads, and database exactly. Make imports remove any pre-bundled Playground's runtime files (such as 0-playground.php mu-plugin) and lean on their latest versions shipped in the /internal directory.

Backwards compatibility

Playground's ZIP export format evolved over time. Here's how each version is handled after this PR:

ZIP Site files in wp-content Playground runtime artifacts If a theme or plugin is missing
Before this PR Custom plugins, themes, and uploads. Default themes/twenty* directories were included only by the self-contained export. database/ may be absent. Some January–May 2024 ZIPs contain the old SQLite MU plugin. Backfill well-known paths from the site loaded right before the import: Akismet, Hello Dolly, WordPress Importer, default themes, and database/. This is a best-effort heuristic. We can't distinguish a deleted theme from a missing theme.
formatVersion: 2 after this PR Every site path then on disk: plugins, themes, uploads, database/, and a custom db.php if the user specifically created one. None. Leave it missing.

On every import, archived Playground files are removed. The new Playground supplies them.

Playground runtime files

These four old paths are always treated as Playground-provided runtime files:

  • mu-plugins/sqlite-database-integration
  • mu-plugins/playground-includes
  • mu-plugins/0-playground.php
  • mu-plugins/0-sqlite.php

From January 29 through May 8, 2024, the self-contained exporter included mu-plugins/sqlite-database-integration. It also included mu-plugins/0-sqlite.php when present. It already omitted mu-plugins/0-playground.php and mu-plugins/playground-includes; those entries handle stale sites, GitHub trees, and hand-built ZIPs.

db.php needs a separate rule because it can be a custom WordPress drop-in. During legacy WordPress boot, writeLegacyDbPhp() creates Playground's copy through generateDbPhpContent(). That function writes @playground-managed into the file header. Only a db.php with that marker is treated as a Playground file. An unmarked db.php stays with the site.

Before January 29, 2024, SQLite used plugins/sqlite-database-integration. This PR leaves that path as site content because it is also a valid user-installed plugin path.

Breaking change: wpContentFilesExcludedFromExport is no longer public. getLegacyPlaygroundRuntimeWpContentPaths() exposes the smaller runtime rule.

Testing

Tests cover a modified Twenty Twenty-Five theme, a deleted v2 theme, a theme omitted by a pre-v2 ZIP, archived runtime files, marked and custom db.php files, failed runtime staging, and archives without wp-content. The full stack passes 488 Blueprint tests, 347 website tests, package lint and typecheck, and 10 Chromium ZIP-import scenarios.

Stack

  1. #4139 — Export complete versioned Playground ZIP snapshots — merged
  2. #4141 — Exclude legacy runtime artifacts from site snapshots — includes [Blueprints] Import versioned ZIP user content while retaining legacy defaults #4130
  3. #4131 — Import ZIP contents before initial browser persistence
  4. #4132 — Keep ZIP preparation visible until the imported site is ready
  5. #4121 — Accept ZIP drops across the page
adamziel added a commit that referenced this pull request Jul 21, 2026
Playground ZIP exports now contain every file under `wp-content`, plus
`wp-config.php`. The manifest records `formatVersion: 2` so the importer
work in #4130 can distinguish these archives from pre-versioned partial
exports.

This removes the `selfContained` option from the public `zipWpContent()`
API. Every caller now receives a complete archive.

## Testing

Export a Playground with a custom file inside a default theme. Inspect
the ZIP and confirm it contains that file, `wp-config.php`, and a
`playground-export.json` manifest with `formatVersion: 2`.


## Stack

1. [#4139 — Export complete versioned Playground ZIP
snapshots](#4139)
2. [#4141 — Separate runtime-managed paths from legacy ZIP
omissions](#4141)
3. [#4130 — Import versioned ZIP content while retaining legacy
defaults](#4130)
4. [#4131 — Import ZIP contents before initial browser
persistence](#4131)
5. [#4132 — Keep ZIP preparation visible until the imported site is
ready](#4132)
6. [#4121 — Accept ZIP drops across the
page](#4121)
Base automatically changed from adamziel/complete-versioned-zip-exports to trunk July 21, 2026 10:59
@adamziel
adamziel requested review from a team and ashfame July 21, 2026 10:59
@adamziel
adamziel force-pushed the adamziel/separate-runtime-wp-content-paths branch 3 times, most recently from 4b71fa1 to 4235938 Compare July 21, 2026 12:20
Copilot AI review requested due to automatic review settings July 21, 2026 12:20
@adamziel adamziel changed the title [Blueprints] Separate runtime-managed paths from legacy ZIP omissions Jul 21, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

This PR separates legacy ZIP export omissions from runtime-managed wp-content artifacts so that GitHub exports/imports only exclude/override Playground-managed paths while ZIP importer compatibility remains supported for older archives.

Changes:

  • Replace the old public exclusion list with runtime-path detection (getLegacyPlaygroundRuntimeWpContentPaths) for GitHub export/import and ZIP snapshot creation.
  • Introduce a legacy omission list for pre-v2 ZIP compatibility (legacyUserWpContentPathsExcludedFromExport) and apply it during ZIP imports.
  • Regenerate blueprint schema artifacts and adjust relevant tests/mocks.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/playground/website/src/github/import-from-github.ts Updates GitHub import to preserve current runtime-managed paths and remove legacy runtime artifacts from imported content.
packages/playground/website/src/github/github-export-form/form.tsx Updates GitHub export to dynamically exclude only runtime-managed wp-content paths.
packages/playground/website/src/github/github-export-form/form.spec.tsx Updates mocks to reflect the new runtime-path API.
packages/playground/blueprints/src/tests/steps/import-wordpress-files.spec.ts Adds coverage for omitting legacy runtime artifacts and preserving custom db.php, plus precedence rules on import.
packages/playground/blueprints/src/lib/utils/wp-content-files-excluded-from-exports.ts Removes the old combined exclusion list.
packages/playground/blueprints/src/lib/utils/legacy-wp-content-paths-excluded-from-exports.ts Adds legacy omission list for restoring paths missing from old ZIP archives.
packages/playground/blueprints/src/lib/utils/legacy-playground-runtime-wp-content-paths.ts Adds detection of legacy runtime artifacts (including marker-based db.php).
packages/playground/blueprints/src/lib/steps/zip-wp-content.ts Excludes legacy runtime-managed artifacts when generating ZIP snapshots.
packages/playground/blueprints/src/lib/steps/index.ts Removes re-export of the old exclusion list and minor type formatting update.
packages/playground/blueprints/src/lib/steps/import-wordpress-files.ts Updates ZIP import logic to drop archived runtime artifacts and retain runtime/current legacy user paths.
packages/playground/blueprints/src/index.ts Updates public exports to expose the new runtime-path helper instead of the old exclusion list.
packages/playground/blueprints/public/blueprint-v2-schema-validator.js Regenerated schema validator output.
packages/playground/blueprints/public/blueprint-schema.json Regenerated schema JSON output.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/playground/blueprints/src/index.ts
Comment thread packages/playground/website/src/github/import-from-github.ts
Comment thread packages/playground/blueprints/src/lib/steps/import-wordpress-files.ts Outdated
@adamziel
adamziel force-pushed the adamziel/separate-runtime-wp-content-paths branch from 4235938 to f1277cf Compare July 21, 2026 12:28
@adamziel
adamziel force-pushed the adamziel/separate-runtime-wp-content-paths branch from 8c47bf3 to 274fb50 Compare July 21, 2026 12:50
adamziel added a commit that referenced this pull request Jul 21, 2026
… defaults (#4130)

A version-2 Playground ZIP now defines user-owned `wp-content`: archived
files replace the boot defaults, and a missing user file means it was
deleted. Legacy runtime artifacts remain owned by the importing
Playground through #4141.

Pre-versioned exports remain partial. When one omits a stock plugin,
theme, or database directory, import retains the fresh installation's
copy. An archived copy still wins when present.

This preserves customized default themes such as BrewCommerce's purple
Twenty Twenty-Five background through export, import, and reload without
treating stock themes as runtime files.

## Testing

Browser coverage imports a pre-versioned partial export, then separately
customizes Twenty Twenty-Five, exports it, imports it into a new
Playground, reloads, and checks both the theme file and rendered
background. The full stack passes 488 Blueprint tests, 347 website
tests, both packages' lint and typecheck, and 10 Chromium ZIP-import
scenarios.

## Stack

1. [#4139 — Export complete versioned Playground ZIP
snapshots](#4139)
2. [#4141 — Exclude legacy runtime artifacts from site
snapshots](#4141)
3. [#4130 — Import versioned ZIP user content while retaining legacy
defaults](#4130)
4. [#4131 — Import ZIP contents before initial browser
persistence](#4131)
5. [#4132 — Keep ZIP preparation visible until the imported site is
ready](#4132)
6. [#4121 — Accept ZIP drops across the
page](#4121)
@adamziel adamziel changed the title [Blueprints] Exclude legacy runtime artifacts from site snapshots Jul 21, 2026
adamziel added 4 commits July 21, 2026 21:13
… defaults (#4130)

A version-2 Playground ZIP now defines user-owned `wp-content`: archived
files replace the boot defaults, and a missing user file means it was
deleted. Legacy runtime artifacts remain owned by the importing
Playground through #4141.

Pre-versioned exports remain partial. When one omits a stock plugin,
theme, or database directory, import retains the fresh installation's
copy. An archived copy still wins when present.

This preserves customized default themes such as BrewCommerce's purple
Twenty Twenty-Five background through export, import, and reload without
treating stock themes as runtime files.

## Testing

Browser coverage imports a pre-versioned partial export, then separately
customizes Twenty Twenty-Five, exports it, imports it into a new
Playground, reloads, and checks both the theme file and rendered
background. The full stack passes 488 Blueprint tests, 347 website
tests, both packages' lint and typecheck, and 10 Chromium ZIP-import
scenarios.

## Stack

1. [#4139 — Export complete versioned Playground ZIP
snapshots](#4139)
2. [#4141 — Exclude legacy runtime artifacts from site
snapshots](#4141)
3. [#4130 — Import versioned ZIP user content while retaining legacy
defaults](#4130)
4. [#4131 — Import ZIP contents before initial browser
persistence](#4131)
5. [#4132 — Keep ZIP preparation visible until the imported site is
ready](#4132)
6. [#4121 — Accept ZIP drops across the
page](#4121)
@adamziel
adamziel force-pushed the adamziel/separate-runtime-wp-content-paths branch from 04e635b to aad47fb Compare July 21, 2026 19:13
@adamziel
adamziel merged commit 28db845 into trunk Jul 21, 2026
53 checks passed
@adamziel
adamziel deleted the adamziel/separate-runtime-wp-content-paths branch July 21, 2026 19:34
adamziel added a commit that referenced this pull request Jul 21, 2026
ZIP imports used to persist a fresh WordPress installation before
applying the
archive. The archive then rewrote that stored filesystem:

1. Boot fresh WordPress in MEMFS.
2. Copy the fresh site to browser storage.
3. Apply the ZIP to the running site.
4. Flush the rewritten site to browser storage again.

This PR applies the ZIP during the new site's first boot, before its
initial
browser-storage copy:

1. Boot fresh WordPress in MEMFS.
2. Apply the ZIP in MEMFS.
3. Copy the finished filesystem to browser storage once.

`createNewSiteFromZip()` registers the import as first-boot work. The
boot path
runs that work before the initial MEMFS-to-OPFS copy, and the call
reports
success only after that copy finishes.

If ZIP initialization or the first OPFS copy fails, the newly created
stored
site is removed and the previously active Playground is selected again.
When
OPFS is unavailable, the import uses a fresh temporary Playground. Its
new slug
forces React to boot a new iframe instead of reusing the previous
runtime.

The ZIP picker now delegates this lifecycle to `createNewSiteFromZip()`
instead
of coordinating site creation, client boot, import, and persistence
through
component effects.

This PR does not change which files a ZIP contains or how versioned and
legacy
ZIP contents are interpreted. Those rules are handled by #4141 and
#4130. This
PR changes when the imported filesystem is written to browser storage.

## Testing

1. Import a ZIP from both temporary and saved Playgrounds and confirm
the new
   site persists after reload.
2. Import a malformed ZIP and confirm no incomplete stored site remains.
3. Confirm the previously active Playground remains selected after a
failed
   stored-site import.

Unit coverage checks that ZIP initialization runs before the initial
OPFS copy
and that failed-import cleanup selects the requested previous site once.
Browser
coverage checks that a failed import leaves the stored-site list
unchanged,
including after reload.

## Stack

1. [#4139 — Export complete versioned Playground ZIP
snapshots](#4139)
— merged
2. [#4141 — Export and import all site files except Playground runtime
files](#4141) —
merged
3. [#4130 — Import versioned ZIP user content while retaining legacy
defaults](#4130) —
merged
4. [#4131 — Import ZIP contents before initial browser
persistence](#4131)
5. [#4132 — Keep ZIP preparation visible until the imported site is
ready](#4132)
6. [#4121 — Accept ZIP drops across the
page](#4121)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment