Skip to content

Add an updater-first script for 2.x → 3.x Compose upgrades - #1224

Merged
cursor[bot] merged 2 commits into
masterfrom
cursor/upgrade-paired-release-88e0
Sep 12, 2026
Merged

cursor[bot] merged 2 commits into
masterfrom
cursor/upgrade-paired-release-88e0

Conversation

@frahlg

@frahlg frahlg commented Sep 12, 2026

Copy link
Copy Markdown
Member

Problem and result

Orange Update is not a safe 2.x → 3.x path. It recreates Core only; the sidecar replaces itself after Core is healthy. The first DuckDB hop needs the new updater already running (docs/self-update.md, #1164, #1223).

People who want 3.x had SSH runbook fragments and no one-liner. This adds scripts/upgrade-paired-release.sh and docs/upgrade-paired-release.md: verified .ftwbak, pin ftw-updater to a published tag, require GET /capabilities, then move Core to the same tag.

Until this merges, the raw script URL is the branch, not master.

Scope and safety

  • Linux Compose installs that already use ghcr.io/srcfl/ftw and FTW_*_IMAGE_TAG. Older frahlg/ layouts stay on upgrade-from-legacy.md.
  • Refuses latest / beta / v3.2.0-beta.1.
  • Does not start Core until the new updater advertises protocol 1 and preserve_core_on_readiness_failure.
  • If Core exits with update ftw-updater first before it can have opened data, previous Core is restored and the new updater stays. A long DuckDB wait does not image-rollback.
  • Does not implement the Update Center gate in feat(update-center): guard large Core hops until updater capabilities are ready #1223. That cannot retrofit the 2.14 button.

No overlapping open PRs on these files.

Verification

  • bash scripts/test-upgrade-paired-release.sh — refuses aliases and v3.2.0-beta.1; updater pull/recreate happens before Core; missing /capabilities does not pull Core; .env comments and unrelated keys survive.
  • bash .github/scripts/test-change-classifier.sh

Not run on a physical 2.14 box in this PR. Hardware: SSH to a 2.14 site, USB --backup-dir, --tag of a published v3.2.1-beta.1+ release, then docker compose images / /api/health / /api/status.

Checklist

  • The change follows VISION.md and one selected scope.
  • I checked overlapping PRs and coordinated shared files/contracts.
  • Relevant checks cover the changed behaviour and failure paths.
  • A human reviewed changed UI in a browser, or no UI changed.
  • A Changeset is included, or the change is exempt.
  • Every commit has a DCO sign-off.
Open in Web Open in Cursor 

Orange Update recreates Core before the sidecar, which is unsafe for the
first DuckDB hop. Give operators a curl-able script that backs up, pins
ftw-updater to a published tag, checks /capabilities, then moves Core.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>
@frahlg
frahlg marked this pull request as ready for review September 12, 2026 16:53
@cursor

cursor Bot commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_056bcd2a-bfb7-4943-b0bd-de3807651197)

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 12, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-12T16:56:54.078418Z 42da9f2 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

brand-cleanup treats new forty-two-watts copy as unclassified. Migrated
installs may still use that service name, and the script must detect it
without guessing when both names exist.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>
@cursor

cursor Bot commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_75f02a41-1f94-4a3d-8ab6-d77f92b152f0)

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 42da9f2d8c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +549 to +550
else
core_may_have_opened_data=true

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Mark data as opened immediately after recreating Core

If the script is interrupted or another command fails during the first 120 seconds after compose up succeeds, core_may_have_opened_data is still false and the EXIT trap recreates the old 2.x Core. The new Core can open and migrate persistent state within seconds, well before /api/status becomes ready, so this rollback can run the old binary against already-migrated data—the exact image/data mismatch this script is intended to prevent. Treat data as potentially opened immediately after a successful recreation, and only permit rollback after conclusively detecting the preflight refusal that occurs before state is opened.

Useful? React with 👍 / 👎.

Comment on lines +361 to +363
[ "$data_mount_type" = bind ] || die "the /app/data mount must be a host bind"
[ -d "$data_mount_source" ] || die "the /app/data source does not exist: $data_mount_source"
expected_data_source="$(cd "$data_mount_source" && pwd -P)"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Verify the running Core's data bind before backing it up

When the current Compose configuration no longer matches the running container—for example after moving the installation directory, changing an override, or supplying the wrong --dir—this path is derived only from docker compose config. The script then backs up that possibly inactive directory and force-recreates the existing project against it, making the site appear to lose its real configuration and history while claiming the backup is valid. Inspect the running Core's /app/data mount and require it to equal this resolved source before changing either container.

Useful? React with 👍 / 👎.

@cursor
cursor Bot merged commit dc7b724 into master Sep 12, 2026
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants