sirius-press/docs/upstream-merges.md
Silent Mode a65556726e docs(sirius-press): say that the forge repo is a mirror, and what that costs
Someone who clones from code.silentmode.st and starts working will otherwise
find out the hard way: push-split.sh force-pushes master, so their branch
does not survive the next mirror push. Better to say it on the page that
tells people how to take an upstream release, since that is exactly the work
that would be lost.
2026-09-21 03:23:14 +02:00

156 lines
5.4 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 lives in this repository, at `wordpress/`, as a **git subtree**. The
fork's own change sits on top of it as an ordinary commit.
Three pieces make that work:
| | |
|---|---|
| `wordpress/` | The vendored tree, patched. This is what gets built and shipped. |
| `sirius-press/wordpress-upstream` | A branch holding **pristine** upstream releases, one commit each, never edited. The other side of the merge. |
| `patches/` | A readable record of what the fork changes in core. Generated, not maintained. |
The entire core diff is **one file, 75 lines**: `wp-admin/install.php`, the
setup wizard. Everything else Sirius Press does is plugins and hooks.
### Why a subtree and not a patch series
Because a three-way merge understands something a patch does not. When
upstream edits lines near the fork's change, `git subtree merge` merges them
and moves on; `patch` either applies with fuzz and hopes, or fails and hands
you the job of re-deriving the change by hand. A conflict from the merge is
resolved once, in the file, and stays resolved — the next release merges
against the resolution.
The cost is repository size: WordPress is about 149 MB and 3,800 files. That
is the price of a fork that can take a security release in a minute, and it is
the right trade for a project whose whole argument is that it should outlive
its maintainers' attention.
---
## Taking a new release
```bash
tools/update-wordpress.sh 7.1.2
```
It downloads the release, checks it against the SHA-1 wordpress.org publishes,
imports the pristine tree onto `sirius-press/wordpress-upstream`, and merges
that branch into `wordpress/`. Then it updates `tools/wordpress.lock` and
regenerates `patches/`.
Two outcomes.
**Clean.** The merge went through. Run the tests, build, commit. Usually a
minute of work.
**Conflicted.** Upstream changed the same lines the fork changes — in
practice, `wp-admin/install.php`. Git leaves the conflict in the file:
```bash
git status
$EDITOR wordpress/wp-admin/install.php
git add wordpress/wp-admin/install.php
git commit
tools/refresh-patches.sh
```
Then set `WP_VERSION`, `WP_URL`, `WP_SHA256` and `WP_SHA1` in
`tools/wordpress.lock` by hand, since the script stopped before it got there.
Either way the fork is **not broken while you work**: the merge is in your
working tree, and until you commit it, `wordpress/` still holds the last
version that worked.
---
## After any bump
```bash
tests/run.sh
tools/build.sh
```
The suite does not test core, but it tests every assumption the fork makes
about it. Then walk through `wp-admin/install.php` once in a browser — 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.
[testing.md](testing.md) has a recipe for a throwaway instance that needs no
database server.
---
## Keeping `patches/` honest
`patches/` is documentation. It answers the question anyone auditing this fork
asks first — *what exactly did you change inside WordPress?* — in a minute,
which `git log wordpress/` cannot, because that log is mostly upstream
imports.
It is generated from the tree, never edited:
```bash
tools/refresh-patches.sh # rewrite it
tools/refresh-patches.sh --check # fail if it has drifted (for CI)
```
Generated documentation stays true. A hand-maintained record of a fork's core
diff drifts, and a stale one is worse than none, because people trust it.
---
## Changing core yourself
Edit the file under `wordpress/` and commit it like any other change. The next
upstream merge will three-way it.
Before you do: check whether a plugin hook can carry the change instead. Every
line added to `wordpress/` is a line that can conflict with upstream forever,
and the reason this fork's merges are cheap is that there are only 75 of them.
The registration form, the password-reset page and the mail pipeline were all
replaced from plugins precisely so they would never appear in this directory.
---
## Where this repository lives
`code.silentmode.st/silentmode/sirius-press` is a **mirror**. Sirius Press is
developed inside the Silent Mode monorepo and split out with
`scripts/push-split.sh`, which force-pushes `master` each time. History on the
forge is real — file blame points at the actual commits — but it is rewritten
on every push, so a pull request against it will not survive.
What that means in practice:
- **Silent Mode takes upstream releases in the monorepo**, where the subtree's
merge history is intact, and the result is mirrored here.
- **A downstream fork** that clones from the forge and wants to bump WordPress
itself should treat its clone as the source of truth from that point on and
stop pulling the mirror, because the next mirror push will not merge with
its work.
Patches and bug reports are welcome as issues; code is easiest to take as a
diff rather than as a branch.
---
## If the upstream branch is missing
A clone made with `--single-branch` will not have
`sirius-press/wordpress-upstream`, and `tools/update-wordpress.sh` will say so
rather than guessing. Fetch it:
```bash
git fetch origin sirius-press/wordpress-upstream:sirius-press/wordpress-upstream
```
Building and running do not need it — only taking a new upstream release does.