Skip to content

Add support for installing WordPress from an arbitrary ZIP archive - #351

Merged
swissspidy merged 2 commits into
mainfrom
claude/wordpress-core-testing-automation-yrlybg
Aug 7, 2026
Merged

Add support for installing WordPress from an arbitrary ZIP archive#351
swissspidy merged 2 commits into
mainfrom
claude/wordpress-core-testing-automation-yrlybg

Conversation

@swissspidy

@swissspidy swissspidy commented Aug 7, 2026

Copy link
Copy Markdown
Member

Behat suites can now install WordPress from a ZIP archive instead of
downloading it from WordPress.org, by pointing the new
WP_CLI_TEST_CORE_ZIP environment variable at either a local file or an
HTTP(S) URL.

This makes it possible to run the functional tests against a WordPress
build that has not been released, such as the wordpress.zip and
develop.zip artifacts produced by the WordPress core build process.

The archive may contain WordPress at its root or wrapped in a single
folder, so that both the wordpress/ layout used by WordPress.org
releases and the build/ layout used by some core build artifacts work.
Archives are extracted once and cached, keyed by their contents.

WP_VERSION keeps governing which version-specific tags are filtered
out, as the version of a development build cannot be compared
meaningfully, and defaults to trunk when an archive is configured.
Steps requesting an explicit version, such as Given a WP 6.4.2 installation, continue to download that version and ignore the archive.

Co-Authored-By: Claude Opus 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01CE81GsxUY597AdaMP1NXzk

Summary by CodeRabbit

  • New Features

    • Added support for running Behat tests with WordPress core supplied as a local ZIP file or HTTP(S) archive.
    • Supports multiple archive layouts, validation, content-based caching, and replacement of existing installations.
    • Defaults WP_VERSION to trunk when using a configured archive without an explicit version.
  • Documentation

    • Added setup instructions covering archive formats, caching behavior, version filtering, and download fallback.

Behat suites can now install WordPress from a ZIP archive instead of
downloading it from WordPress.org, by pointing the new
`WP_CLI_TEST_CORE_ZIP` environment variable at either a local file or an
HTTP(S) URL.

This makes it possible to run the functional tests against a WordPress
build that has not been released, such as the `wordpress.zip` and
`develop.zip` artifacts produced by the WordPress core build process.

The archive may contain WordPress at its root or wrapped in a single
folder, so that both the `wordpress/` layout used by WordPress.org
releases and the `build/` layout used by some core build artifacts work.
Archives are extracted once and cached, keyed by their contents.

`WP_VERSION` keeps governing which version-specific tags are filtered
out, as the version of a development build cannot be compared
meaningfully, and defaults to `trunk` when an archive is configured.
Steps requesting an explicit version, such as `Given a WP 6.4.2
installation`, continue to download that version and ignore the archive.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CE81GsxUY597AdaMP1NXzk
@swissspidy
swissspidy requested a review from a team as a code owner August 7, 2026 07:18
Copilot AI lite review requested due to automatic review settings August 7, 2026 07:18
@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@swissspidy, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 26 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 81e9bfc4-d588-421a-af13-0ace7e6fbaa5

📥 Commits

Reviewing files that changed from the base of the PR and between bb979f4 and e7f616e.

📒 Files selected for processing (2)
  • src/Context/FeatureContext.php
  • tests/tests/TestCoreZip.php
📝 Walkthrough

Walkthrough

The test runner now accepts local or remote WordPress core ZIP archives. FeatureContext resolves, validates, extracts, and caches these archives by version or content hash. Documentation and PHPUnit tests cover configuration, supported layouts, cache behavior, and error handling.

Changes

WordPress core ZIP support

Layer / File(s) Summary
Archive resolution and cache selection
bin/run-behat-tests, src/Context/FeatureContext.php
Archive-based runs default WP_VERSION to trunk. Local and HTTP(S) archives resolve once and use version-based or content-hash cache paths.
Archive extraction and installation
src/Context/FeatureContext.php
The context extracts supported ZIP layouts, validates the WordPress root, replaces invalid destinations, populates the cache, and skips wp core download when an archive is configured.
Extraction and cache validation
tests/tests/TestCoreZip.php
Tests cover archive layouts, replacement behavior, invalid archives, unreadable archives, cache derivation, version precedence, and missing archives.
Archive usage documentation
.readme-partials/USING.md, README.md
Documentation describes archive sources, layouts, caching, WP_VERSION behavior, and version-specific scenario filtering.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant TestRunner
  participant FeatureContext
  participant WordPressArchive
  participant CoreCache
  TestRunner->>FeatureContext: configure WP_CLI_TEST_CORE_ZIP
  FeatureContext->>WordPressArchive: resolve local or remote archive
  WordPressArchive-->>FeatureContext: validate readable archive
  FeatureContext->>WordPressArchive: extract WordPress files
  WordPressArchive-->>CoreCache: provide extracted installation
  FeatureContext->>CoreCache: use archive-based cache
Loading

Suggested labels: scope:testing

Suggested reviewers: copilot, schlessera

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: installing WordPress from arbitrary ZIP archives.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/wordpress-core-testing-automation-yrlybg

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Aug 7, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 65.88235% with 29 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/Context/FeatureContext.php 65.88% 29 Missing ⚠️

📢 Thoughts on this report? Let us know!

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@README.md`:
- Line 133: Resolve the MD003 warning for the “WordPress Archive” heading by
either updating the Markdown lint configuration to permit the existing ATX
heading hierarchy or changing the heading to the repository-approved
setext-compatible form; preserve the document’s heading structure and ensure
markdownlint-cli2 passes.

In `@src/Context/FeatureContext.php`:
- Around line 821-825: Update the rename fallback in the directory move flow to
create $dest_dir before calling self::copy_dir( $source_dir, $dest_dir ).
Preserve the existing rename path, and ensure the destination directory exists
when rename() fails so root-level files can be copied successfully.

In `@tests/tests/TestCoreZip.php`:
- Around line 18-30: Update TestCoreZip::set_up() to capture the original
WP_CLI_TEST_CORE_ZIP value, then have tear_down() restore that value after
cleanup instead of only clearing it. Reset FeatureContext::$core_zip after
restoration so later tests retain the original archive configuration.
- Around line 172-185: In get_core_cache_dir() and reset_core_zip(), guard each
ReflectionMethod/ReflectionProperty::setAccessible() call with a PHP_VERSION_ID
check for runtimes below 8.1, and update composer.json’s minimum PHP requirement
to >=8.1 so the supported runtime matches the reflection behavior.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 7d00e01c-302a-49d2-8b04-63c3bb6a6faf

📥 Commits

Reviewing files that changed from the base of the PR and between 9c4782b and bb979f4.

📒 Files selected for processing (5)
  • .readme-partials/USING.md
  • README.md
  • bin/run-behat-tests
  • src/Context/FeatureContext.php
  • tests/tests/TestCoreZip.php

Comment thread README.md
Comment thread src/Context/FeatureContext.php
Comment thread tests/tests/TestCoreZip.php
Comment thread tests/tests/TestCoreZip.php Outdated

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

This PR extends the WP-CLI Behat test framework to allow installing WordPress core from an arbitrary ZIP archive (local path or HTTP(S) URL) via the new WP_CLI_TEST_CORE_ZIP environment variable, enabling functional tests against unreleased WordPress build artifacts while preserving existing version-driven behavior.

Changes:

  • Add ZIP resolution (local/remote), extraction, and cache-directory derivation keyed by archive contents in the Behat FeatureContext.
  • Add PHPUnit coverage for archive layouts (wordpress/, build/, flat), destination replacement, and cache-dir derivation rules.
  • Document the new environment variable and default WP_VERSION behavior; default WP_VERSION=trunk when an archive is configured.

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/Context/FeatureContext.php Implements archive resolution/download, content-hash cache keying, and extraction logic used by the Behat install workflow.
tests/tests/TestCoreZip.php Adds unit tests for ZIP extraction behavior and cache directory derivation when an archive is configured.
README.md Documents WP_CLI_TEST_CORE_ZIP usage and interaction with WP_VERSION.
.readme-partials/USING.md Mirrors the README “WordPress Archive” documentation in the generated partials.
bin/run-behat-tests Defaults WP_VERSION to trunk when WP_CLI_TEST_CORE_ZIP is set and WP_VERSION is not.
Suppressed comments (1)

src/Context/FeatureContext.php:825

  • If the fast-path rename() fails, the fallback copy_dir() is called with a destination that may not exist. copy_dir()'s own docblock says the destination directory must exist, and copy() will fail when the extracted WordPress root contains files at its top level (e.g. wp-load.php). Ensure $dest_dir is created before calling copy_dir().
			// Both directories live in the system temp folder, so a rename is
			// normally possible and avoids copying thousands of files.
			if ( ! @rename( $source_dir, $dest_dir ) ) {
				self::copy_dir( $source_dir, $dest_dir );
			}

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

Comment thread src/Context/FeatureContext.php Outdated
Comment thread tests/tests/TestCoreZip.php
Fixes the unit test failure on PHP < 8.0, where calling
`ZipArchive::getStatusString()` on an archive that failed to open errors
out with "Invalid or uninitialized Zip object". The error code returned
by `ZipArchive::open()` is now used instead.

Creates the destination directory before falling back to `copy_dir()`,
which copies into an existing directory and would otherwise fail to copy
the files at the root of the archive.

Rejects archives holding entries that point outside of the directory
they are extracted into. `ZipArchive::extractTo()` normalizes such
entries rather than following them, but an archive containing them is
malformed for our purposes on any PHP version.

Drops the reflection from the tests, which called
`Reflection*::setAccessible()`, deprecated as of PHP 8.5. The cache
directory is now derived through a public method, and the resolved
archive is memoized against the environment variable it came from, so a
change of that variable is picked up rather than served from the
memoized value.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CE81GsxUY597AdaMP1NXzk
@swissspidy swissspidy added this to the 5.2.3 milestone Aug 7, 2026
@swissspidy
swissspidy merged commit cc7e495 into main Aug 7, 2026
80 checks passed
@swissspidy
swissspidy deleted the claude/wordpress-core-testing-automation-yrlybg branch August 7, 2026 08:30
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.

3 participants