Files
intotheeast-com/docs/working/specs/2026-07-04-grav-2.0.4-upgrade-design.md
m038andClaude Opus 4.8 3085cede28 docs: correct upgrade spec channel + CLI commands after container verification
- GPM channel is system.yaml gpm.releases (testing->stable), not GRAV_CHANNEL
- core upgrade is 'bin/gpm self-upgrade -y'; existing remote-upgrade-grav
  target ('bin/grav upgrade') is broken and must be fixed
- add server content-pull + cache-clear + preflight steps to Phase 2

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-04 14:58:27 +02:00

210 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Grav 2.0.4 Upgrade + GPM-Manage admin2/api/flex-objects — Design
**Date:** 2026-07-04
**Status:** Design approved — pending implementation plan
## Goal
Perform one coordinated upgrade of the intotheeast stack:
1. Bump Grav core from `2.0.0-rc.10``2.0.4` (stable).
2. Promote `admin2`, `api`, and `flex-objects` from bundle-extracted plugins to
**GPM-managed** plugins (this is "option B").
These two changes are **not separable**. The stable plugins hard-require the
stable core, so GPM enforces an atomic upgrade of the whole chain.
## Background / findings
### Version gaps
The project has been frozen on the final release candidate since the original
Grav 2.0 upgrade. Grav went stable on 2026-06-21; latest patch is `2.0.4`
(2026-06-29). No breaking changes exist within the 2.0.x line — the
2.0.12.0.4 releases are security hardening (XSS re-checks on editor Twig,
ZIP-bomb limits, `.htaccess` case-insensitive bypass fix) plus bugfixes.
Installed vs. bundled-in-2.0.4 versions:
| Plugin | Installed | 2.0.4 stable |
|---|---|---|
| core (grav) | 2.0.0-rc.10 | 2.0.4 |
| admin2 | 2.0.0-rc.15 | 2.0.9 |
| api | 1.0.0-rc.15 | 1.0.6 |
| flex-objects | 1.4.0-rc.7 | 1.4.3 |
| login | 3.8.9 | 3.8.11 |
| form | 9.1.6 | 9.1.8 |
| shortcode-core | 6.0.0 | 6.2.1 |
### Dependency chain (why it's atomic)
From the stable plugin blueprints:
- `api` 1.0.6 requires `grav >= 2.0.4` **and** `login >= 3.8.11`
- `admin2` 2.0.9 requires `api >= 1.0.6`
- `flex-objects` 1.4.3 requires `form >= 6.0.0`, `api >= 1.0.0`
So stable admin2/api cannot run on the rc.10 core — GPM would refuse. This is
the core reason option B is the right approach: `gpm` resolves and enforces the
entire chain automatically, which the previous manual-extract approach never
did.
### Three plugin management categories
The upgrade must account for the fact that plugins reached the servers three
different ways:
| Category | Plugins | In `plugins.txt`? | How installed | Upgrade mechanism |
|---|---|---|---|---|
| GPM-managed | email, error, form, login, problems, add-page-by-form, shortcode-gallery-plusplus | yes | `gpm install` | `gpm update` |
| Manually-placed → GPM (option B) | admin2, api, flex-objects | **will add** | hand-extracted from grav-admin zip | `plugins.txt` for fresh installs; `gpm update` on existing test env |
| Remote-only | git-sync | **no** (config gitignored, holds encrypted token) | installed directly on the server | documented separately; carried by `gpm update`; **disabled during upgrade** |
### git-sync compatibility
git-sync is version 3.4.4 with an explicit `compatibility: 2.0` flag and is one
of Grav's own reference plugins for the Admin Next / API. It is safe to carry
through the upgrade. Note the documented folders-YAML quirk
(`docs/working/git-sync-notes.md`): its config must list `folders` as an array,
never the UI-written comma-string.
### Local vs. server upgrade mechanisms differ
- **Local** bakes the core into the Docker image (`Dockerfile`) → upgrade by
rebuilding the image.
- **Server** is a native webroot install → core upgrades via
`bin/grav upgrade`, plugins via `bin/gpm update`.
The plan therefore has distinct local and remote steps.
## Decisions
- **Option B (GPM management)** for admin2/api/flex-objects. Add them to
`plugins.txt` so future fresh installs pull them via GPM.
- **Rollout order:** local → test → prod.
- **Prod is currently empty** → the prod phase is written as a *documented
fresh-install runbook only* and is **not executed** in this effort. Fresh prod
install uses the option-B-modified `server-install.sh` with
`GRAV_VERSION=2.0.4`.
- **Rollback = git.** All relevant data (`pages/`, `config/`, `accounts/`,
`themes/`) is committed. No separate backup step. Rollback is `git revert` of
this branch plus a rebuild/redeploy.
- **Upgrade verb on existing installs is `gpm update` (update-all)**, not
`gpm install <plugins.txt>`. `install` skips already-installed plugins and
never touches git-sync (which is not in the list); `update` upgrades every
installed plugin regardless of how it was placed, catching the manual and
remote-only categories in one shot.
- **git-sync stays out of `plugins.txt`** (that list is shared with local; git-sync
is remote-only with a manual encrypted token). Documented as separately
managed.
- **git-sync is disabled before the test upgrade and left disabled**, so the
upgrade cannot auto-commit reformatted/server-specific config back into the
shared Gitea `user` repo. The user validates first, then re-enables it as a
separate deliberate step.
## File changes (Phase 0)
| File | Change |
|---|---|
| `Dockerfile` | grav-admin zip URL `2.0.0-rc.10/grav-admin-v2.0.0-rc.10.zip``2.0.4/grav-admin-v2.0.4.zip`. Verified: the 2.0.4 zip still extracts to a `grav-admin/` folder, so the existing `cp` block is unchanged. |
| `plugins.txt` | add `api`, `admin2`, `flex-objects` (`form`, `login` already present as their deps) |
| `user/config/system.yaml` | **`gpm.releases: testing → stable`** — this is the authoritative GPM channel. `testing` is what has been serving RC/pre-release versions. Tracked in the `user` repo, so it applies to both local and server once pushed. |
| `docker-compose.yml` | `GRAV_CHANNEL=beta``production` for consistency only. This env drives the base image's `docker-entrypoint.sh`, **not** `bin/gpm`'s channel — `gpm.releases` above is what governs updates. |
| `scripts/server-install.sh` | remove the admin2/api stash+restore special-casing (lines 2526 and 4345); they now install via `gpm install` from `PLUGINS` |
| `Makefile` | **fix broken `remote-upgrade-grav`:** `php bin/grav upgrade` is not a real command — change to `php bin/gpm self-upgrade -y`. Add the new remote targets (below) to `REMOTE_TARGETS` so each gets `-test`/`-prod` variants. |
| `CLAUDE.md`, `docs/reference/architecture.md`, memory | update stack versions; document the three-category plugin model and the channel change |
### New Makefile targets
Added to the `REMOTE_TARGETS` list (Makefile:2224) so the env-suffix macro
(Makefile:3134) auto-generates `-test` / `-prod` variants:
- `remote-update-plugins``cd $(WEBROOT) && php bin/gpm update -y`
- `remote-git-sync-disable` → set `enabled: false` in
`$(WEBROOT)/user/config/plugins/git-sync.yaml` (touch only the `enabled` key;
never rewrite `folders`)
- `remote-git-sync-enable` → set `enabled: true` in the same file
`remote-upgrade-grav` exists but its command is **broken** (`php bin/grav
upgrade` is not a Grav CLI command) — it is fixed to `php bin/gpm self-upgrade
-y` as part of Phase 0. Core self-upgrade respects the `gpm.releases` channel.
**Verified CLI command names** (against the running rc.10 container):
`php bin/gpm self-upgrade -y` (core), `php bin/gpm update -y` (all plugins),
`php bin/grav cache` (clear cache; aliases `clearcache`/`cache-clear`).
> The exact idempotent shell used to toggle the `enabled` key is finalized in the
> implementation plan; it must not disturb the `folders` array or the encrypted
> token in `git-sync.yaml`.
## Phases
### Phase 0 — branch + edits
New branch off `main`. Apply all file changes above.
### Phase 1 — local
1. Remove the stale manually-extracted `admin2`, `api`, `flex-objects` folders
from `user/plugins/` so GPM does a clean install.
2. `make build` (core → 2.0.4)
3. `make start`
4. Install the newly-listed plugins **and** update the already-installed ones
to their 2.0.4-compatible versions via GPM. Note: `gpm install` skips plugins
that are already present, so `login` (3.8.9 → ≥3.8.11, required by `api`) and
`form` need `gpm update`, not `install`. The exact `gpm update` + `gpm install`
sequencing (run inside the container via `docker exec`) is pinned in the plan.
5. Assert versions: admin2 2.0.9, api 1.0.6, flex-objects 1.4.3, login ≥ 3.8.11.
6. **Smoke test:** admin2 login; submit `/post` → entry appears in the active
trip's dailies; `/gpx-manager` list + upload + delete; a trip page and a
story render; maps load.
Prerequisite: the Phase 0 config changes (esp. `system.yaml`
`gpm.releases: stable`) are committed and pushed to Gitea, or GPM on the server
will still resolve the `testing` channel and pull RCs.
1. `make remote-git-sync-disable-test`
2. `make remote-fetch-content-test` — pull latest `user/` content to the test
server so `system.yaml` `gpm.releases: stable` is in place before any GPM
operation.
3. `make remote-upgrade-grav-test` (core self-upgrade → 2.0.4)
4. `make remote-update-plugins-test` (`gpm update -y` — all plugins incl.
admin2/api/flex/git-sync/login/form)
5. Clear cache on the server (`php bin/grav cache`).
6. Review `git status` in the server's `user/` for unexpected config diffs;
handle any deliberately (do not blind-commit).
7. Smoke test on the test URL (same checklist as Phase 1).
8. **Leave git-sync disabled and notify the user.** After the user validates,
re-enable as a separate deliberate step: `make remote-git-sync-enable-test`,
then a `content-push` round-trip to confirm sync still works.
### Phase 3 — prod (DOCUMENTED, NOT EXECUTED)
Prod is empty, so this is a fresh install, not an upgrade. Documented as a
runbook:
- Run the option-B-modified `server-install.sh` with `GRAV_VERSION=2.0.4`
(`make remote-install-prod`).
- admin2/api/flex-objects now install via GPM from `plugins.txt` — no manual
extraction.
- Set up git-sync manually afterward: install, add the encrypted token, apply
the folders-YAML array fix (`docs/working/git-sync-notes.md`).
## Rollback
`git revert` the branch (Dockerfile + plugins.txt + docker-compose +
server-install.sh + Makefile) and rebuild/redeploy. Content, config, and
accounts are already in git, so no data restore is needed.
## Risks
- **git-sync auto-commit during upgrade** — mitigated by disabling git-sync
before the test upgrade and reviewing `git status` before re-enabling.
- **admin2/api behavioral changes across RC→stable** — these back the `/post`
form and `/gpx-manager`; covered by the smoke tests, which are the
highest-weight validation in this effort.
- **GPM channel** — `gpm.releases` must be `stable` on the server *before* any
`gpm update`/`self-upgrade`, or GPM pulls RCs. Enforced by pushing the
`system.yaml` change and running `remote-fetch-content` first (Phase 2 step 2).
- **`bin/gpm self-upgrade` on shared hosting** — Grav 2.0.3 fixed self-upgrade
failures on shared-folder setups. On the native server this can still be
fragile; run `php bin/gpm preflight` first and use `-o/--overwrite` if a retry
is needed.