Repository navigation
✨ Added Ghost updates within a major version (S7) - #386
Merged
Merged
Conversation
ref https://linear.app/ghost/issue/PLA-485/s7-host-driven-ghost-upgrades-ghost-docker-update Ghost could only change by editing GHOST_IMAGE_REF by hand, with no backup before its migrations ran. `./ghost-docker update [version|latest]` moves a site within its Ghost major: it pulls the target while the site runs, pauses the writers, takes a checked backup, writes the pin and the metadata together, then starts and verifies. latest is the site's floating major tag, so no registry API is needed. Once startup is attempted, the new Ghost may have migrated the data. The update then stops the services and keeps the new pin, unlike self-update, which puts its files back: switching Ghost back does not undo its migrations. The operator restores the named backup or fixes the cause and starts it. Self-update and update now share one executor that returns its outcome (done, restored, needs-operator), so the S8 supervisor can run the same code and record the result instead of re-implementing recovery. A site may still follow Ghost's tag with Compose alone. Restore now pins such a backup to the digest Ghost ran, so after the tag has moved the data never starts on a newer Ghost than wrote it. - manager/src/update.ts: the shared update executor and its outcomes. - manager/src/commands/update.ts: the update command, its refusals, --check, and how its failures read. - manager/src/commands/self-update.ts: runs on the shared executor, with its messages unchanged. - manager/src/restore.ts: pin a floating-tag backup to the Ghost it ran. - manager/src/ghost.ts: tags of a site's own variant. - manager/src/cli.ts, help, README.md: the command. - manager/test/update.test.ts, backup.test.ts, site.ts, cli.test.ts: update's decisions and recovery, the floating restore, per-tag digests. - tests/e2e/ghost-update.sh, .github/workflows/test.yml: a real update across Ghost's migrations, one that fails after startup and is restored, and a refused downgrade, as a required job. - docs/install.md, architecture.md, configuration.md: the command, the executor and recovery boundary, and sites that follow the tag. - docs/ghost-cli-replacement.md: S7 keeps only its analytics acceptance.
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
Ghost refuses a password containing "ghost" as insecure, so setting up the owner failed before the update was exercised.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
ref https://linear.app/ghost/issue/PLA-485/s7-host-driven-ghost-upgrades-ghost-docker-update
./ghost-docker update [--check] [<version> | latest]moves a site's Ghost within its major version, with a checked backup taken before Ghost's migrations run.What it does
latest(the default) pulls the site's floating major tag,<major>-<variant>(e.g.6-next-alpine), so no registry API is needed. A named version maps to<version>-<variant>, and the image must report exactly that version.GHOST_IMAGE_REFthat is not the one the metadata records, a held lock, and a leftover update snapshot..env+ metadata → pause Ghost/ActivityPub → checked backup → write the pin and metadata together → resolve and validate → start and verify. Works for image installs and clones (only.envand metadata change).Recovery
restored).self-update, it does not put the old pin back, because switching Ghost back does not undo its migrations. The operator restores the named backup, or fixes the cause and runsdocker compose up -d.Shared executor for S8
The snapshot / pause / backup / startup-boundary / recovery logic moved out of
self-updateintomanager/src/update.ts, which returns a structured outcome (done,restored,needs-operator) instead of printing.self-updateruns on it with its messages unchanged (all 40 of its tests pass as before); the S8 supervisor can run the same code and record the outcome as a job state.src/legacy.tsstill has its own copy and is left alone here.Sites that follow Ghost's tag
A site can still leave
GHOST_IMAGE_REFempty and upgrade with Compose alone (backup,docker compose pull ghost,up -d). Before this, restoring such a backup was refused once the tag had moved. Restore now pinsGHOST_IMAGE_REF(and the metadata) to the registry digest Ghost ran, so restored data never starts on a newer Ghost than wrote it. Pinned sites are unchanged. If Ghost wasn't running when the backup was taken, there is no digest to pin and restore behaves as before.Remaining for S7
Acceptance on a site with analytics (Tinybird sync rerun from the new image, deploy succeeds) needs a Tinybird login, so it is run by hand; the roadmap keeps only that.
Testing
test/update.test.ts(16): each refusal,--check, nothing to do, backup and validation failures restored, a failed start after a migration (data and pin kept, then the leftover-snapshot refusal), services that cannot be stopped, a clone.backup.test.ts: floating-tag restore after the tag moves, and a pinned restore unchanged.tests/e2e/ghost-update.sh): installs Ghost 6.61.0 with an owner, a post and an image; an override healthy only on 6.61.0 makes the newest 6.x migrate and fail, checked to leave migrations and pin in place, then the named backup is restored; without it, a real update across the migrations keeps the post, image, sign-in andcheck; a downgrade is refused. Not run locally, so this PR is its first run.🤖 Generated with Claude Code