Upgrade Jetrepo
Back up, build, migrate, reconstruct history, verify, and choose a safe return path.
Upgrade between trusted revisions through docker-compose.prod.yaml. Database migrations move forward; Jetrepo does not provide an automatic database downgrade.
Access
You need host, deployment-secret, database, storage, backup, and change administration.
Prepare the release
- Review target changes and release notes when available.
- Record the current and target source revisions, resolved image IDs/digests, non-secret configuration, and baseline smoke-test results.
- Prove an isolated restore of the recovery point you will use.
- Stage the exact release pair with representative restored data.
- Keep the prior recovery set immutable until the upgrade and return-path verification finish.
If your shell exports DATABASE_URL, Compose uses it instead of the internal Postgres default. Unset it unless the override is intentional and points at the database being upgraded.
Build the target
From the trusted target checkout, validate interpolation without printing resolved secrets and build every production target:
unset DATABASE_URL # omit this only for an intentional external database
docker compose -f docker-compose.prod.yaml config --quiet
docker compose -f docker-compose.prod.yaml build
The production Node images are pinned to the repository’s required runtime. Record the resolved base and application image digests; the Image service and object-client tags can otherwise change independently of a Jetrepo source revision.
Freeze writes and back up
Follow Back up and restore. Stop Admin, Core API, Delivery API, Worker, and the Image service; then capture Postgres, object storage, the chosen Redis state, image identities, configuration inventory, and checksums from one maintenance point.
Do not reopen ingress after taking the backup.
Migrate and reconstruct authority
Set the Core API service key from the production Compose definition:
CORE_SERVICE=<core-api-service-key>
COMPOSE='docker compose -f docker-compose.prod.yaml'
Start only the stateful dependencies, run the migration one-shot, then reconstruct immutable Resource History before starting request or background writers:
$COMPOSE up -d postgres redis minio minio-setup
$COMPOSE run --rm migrate
$COMPOSE run --rm --no-deps "$CORE_SERVICE" \
jetrepo-resource-history-bootstrap
The bootstrap creates missing Draft, Published, and Release manifests from the pre-upgrade authoritative state. It is deterministic and idempotent. Run it a second time and require every Backend to report that no perspectives were created:
$COMPOSE run --rm --no-deps "$CORE_SERVICE" \
jetrepo-resource-history-bootstrap
Stop on a migration or bootstrap failure. Preserve logs and the pre-upgrade recovery set; do not force dependent services past the gate.
Start and verify
$COMPOSE up -d
$COMPOSE ps -a
$COMPOSE logs --tail=200 migrate minio-setup
Migration and object setup must exit 0. Postgres, Redis, Core API, Delivery API, Admin, and Docs must become healthy. Worker starts only after Core API is healthy.
Before reopening ingress, verify:
- sign-in, Organization membership, and role/scope enforcement;
- the representative Backend, main Environment, locale, and Data Type retained their exact identities and values;
- Draft, Published, and Release heads exist for pre-history Backends;
- a safe Candidate/Operation completes with audit and outbox evidence;
- exact Published manifest/value parity through REST and Context MCP;
- upload, Worker metadata, public original download, and a signed image transform;
- no unexpected errors in Core API, Delivery API, or Worker logs;
- the repeated history bootstrap creates nothing.
The project upgrade drill started from a retained pre-agent-native schema containing an Organization, Backend, main Environment, locale, and Data Type. The current migration chain preserved those identifiers/values, added the new authority tables, reconstructed all three perspectives, and started every production service healthy. A restored multi-Backend data set independently proved idempotent reconstruction and exact Published delivery.
Choose the return path
- Migration did not run: return to the prior trusted checkout, image identities, and coherent configuration; then recreate and verify the prior stack.
- Schema migrated: restore Postgres, objects, and the selected Redis state from the complete pre-upgrade recovery set before starting prior applications.
- Restore fails in isolation: do not cut over. Preserve the known recovery set and diagnose the failed target.
The drill restored the pre-upgrade Postgres set into a separate database, verified the old migration boundary and representative data, and did not start an incompatible prior application against the migrated schema. A live production cutover and release-specific backward compatibility remain deployment decisions.