134 lines
4.2 KiB
Markdown
134 lines
4.2 KiB
Markdown
|
|
# Keeping up with WordPress
|
||
|
|
|
||
|
|
WordPress ships security releases, and a fork that cannot take them quickly is
|
||
|
|
a liability rather than a project. This page is how Sirius Press takes them.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## The arrangement
|
||
|
|
|
||
|
|
WordPress is not in this repository. Instead:
|
||
|
|
|
||
|
|
- `tools/wordpress.lock` pins an exact version, its download URL and its
|
||
|
|
SHA-256.
|
||
|
|
- `patches/` holds the fork's core diff as a patch series.
|
||
|
|
- `tools/build.sh` and the Docker image each download the pinned tarball,
|
||
|
|
verify the hash, and apply the series.
|
||
|
|
|
||
|
|
The entire core diff is currently **one file, 75 lines**: the setup wizard, at
|
||
|
|
`wp-admin/install.php`. Everything else the fork does is plugins and hooks.
|
||
|
|
|
||
|
|
### Why not a vendored subtree
|
||
|
|
|
||
|
|
The original plan was to vendor core as a `git subtree`, which is the standard
|
||
|
|
way to run a fork with a substantial diff. Two numbers argued against it.
|
||
|
|
|
||
|
|
WordPress 7.1.1 is **149 MB and 5,008 files**. The fork's core diff is **75
|
||
|
|
lines**. Carrying the first to express the second means every clone, every
|
||
|
|
`git status`, every `git subtree split` in the parent monorepo pays for a patch
|
||
|
|
you can read in a minute — and it buries that patch in a haystack where nobody
|
||
|
|
will ever review it again.
|
||
|
|
|
||
|
|
A patch series makes the opposite trade. The core change is a file you can read
|
||
|
|
in one sitting, review in a pull request, and re-read whenever it stops
|
||
|
|
applying. The cost is that upstream merges are `patch` rather than a three-way
|
||
|
|
git merge — which, for 75 lines in one file, is not much of a cost.
|
||
|
|
|
||
|
|
This holds as long as the diff stays small. If the fork ever needs to change
|
||
|
|
core substantially, vendor it properly: see "Switching to a subtree" below.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Taking a new release
|
||
|
|
|
||
|
|
```bash
|
||
|
|
tools/update-wordpress.sh 7.1.2
|
||
|
|
```
|
||
|
|
|
||
|
|
It fetches the release, verifies its SHA-1 against what wordpress.org
|
||
|
|
publishes, records a SHA-256, applies the patch series to the new tree, and
|
||
|
|
reports what happened.
|
||
|
|
|
||
|
|
Three possible outcomes:
|
||
|
|
|
||
|
|
**Clean.** The series applied. `tools/wordpress.lock` is updated, the tests
|
||
|
|
run, and you commit the lock change. Usually thirty seconds of work.
|
||
|
|
|
||
|
|
**Applied with fuzz.** Upstream moved code near a hunk but not the hunk itself.
|
||
|
|
The script says which hunk and by how many lines. Look at the result, then
|
||
|
|
refresh the series so the next release starts from a clean base:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
tools/update-wordpress.sh 7.1.2 --refresh
|
||
|
|
```
|
||
|
|
|
||
|
|
**Failed.** Upstream rewrote the code the patch touches. This is the case that
|
||
|
|
needs a person: open the new `wp-admin/install.php`, redo the change by hand,
|
||
|
|
and regenerate the patch. The script leaves the unpacked tree in
|
||
|
|
`dist/.upstream/` so there is something to work in.
|
||
|
|
|
||
|
|
In every case the fork is **not broken while you work** — the lock file still
|
||
|
|
points at the last known-good version, and builds keep producing that until you
|
||
|
|
change it.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Reviewing a release before taking it
|
||
|
|
|
||
|
|
Security releases are usually small, and it is worth knowing what changed near
|
||
|
|
the code the fork patches:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
tools/update-wordpress.sh 7.1.2 --diff wp-admin/install.php
|
||
|
|
```
|
||
|
|
|
||
|
|
prints upstream's own diff for that file between the pinned version and the new
|
||
|
|
one. If it is empty — which it usually is — the patch will apply and there is
|
||
|
|
nothing to think about.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## After any bump
|
||
|
|
|
||
|
|
```bash
|
||
|
|
tests/run.sh
|
||
|
|
```
|
||
|
|
|
||
|
|
The suite does not test core, but it does test every assumption the fork makes
|
||
|
|
about it. Then build and try an actual install:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
tools/build.sh
|
||
|
|
cd docker && docker compose build && docker compose up -d
|
||
|
|
```
|
||
|
|
|
||
|
|
and walk through `wp-admin/install.php` once. The setup wizard is the only
|
||
|
|
patched file, so it is the only thing an upstream change can break in a way
|
||
|
|
the tests would miss.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Switching to a subtree
|
||
|
|
|
||
|
|
If the diff ever grows past what a patch series is comfortable with, the
|
||
|
|
mechanics are:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
git remote add wordpress https://github.com/WordPress/WordPress.git
|
||
|
|
git fetch --depth=1 wordpress 7.1.1
|
||
|
|
git subtree add --prefix=wordpress FETCH_HEAD --squash
|
||
|
|
```
|
||
|
|
|
||
|
|
and then, per release:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
git fetch --depth=1 wordpress 7.1.2
|
||
|
|
git subtree merge --prefix=wordpress FETCH_HEAD --squash
|
||
|
|
```
|
||
|
|
|
||
|
|
with `patches/` becoming the record of what was changed rather than the
|
||
|
|
mechanism that changes it. The build script would then copy `wordpress/`
|
||
|
|
instead of downloading and patching.
|
||
|
|
|
||
|
|
Worth doing when the core diff reaches, say, a dozen files. Not before.
|