Files
shopdb-flask/docs/UPGRADE.md
cproudlock 741dda5be7
Some checks failed
CI / backend (push) Failing after 8s
CI / naming (push) Successful in 2s
CI / frontend (push) Successful in 9s
CI / migrations-mysql (push) Failing after 7s
Document buildings and levels where the old single-map model was still taught
The 0.11.0 release changed what a map position means and six documents still
described the model it replaced. Each of these could have caused a real mistake
rather than being merely out of date:

- IMPORT-API mapped legacy mapleft/maptop to mapx/mapy with no mention of the
  level, so a scripted import - including the classic-ASP one still to run
  against production - would have produced markers the map shows as "level
  unknown". It now maps levelid too and says how to resolve the default level.
- API-REFERENCE enumerates the unauthenticated surface in full, because that is
  what a deploy reviewer reads, and the three public /api/maplevels reads were
  missing from it. Also records why the write split is asymmetric: repositioning
  needs assets.edit, creating a level needs admin, since a level's dimensions are
  the coordinate space every marker on it is expressed in.
- CONFIG still presented the four map_* settings as live, telling the reader to
  re-upload a blueprint in a settings page that no longer drives the map. They
  are marked superseded and kept for downgrade.
- UPGRADE gained a 0.11.0 section: nothing moves on screen, and replacing a
  blueprint with one of different dimensions moves every marker on that level, so
  recalibrate from landmarks rather than editing width and height.
- PLUGIN-HOOKS now states that a map overlay keys on assetid and must not return
  coordinates or a level - a second copy of a position is one that can disagree.

Adds FLOOR-MAP.md, the operator's page: loading a plan, placing markers, and
what to do when the plan changes, with the reasoning left in ADR-017. START-HERE
routes to it from the new-site path, and specifically as the page to read BEFORE
a floor plan changes.
2026-08-17 13:35:57 -04:00

6.1 KiB

Upgrading an existing site

This is the procedure for moving a running shopdb-flask instance to a newer version. For a first-time install use DEPLOY.md instead.

Each site is single-tenant (ADR-004), so an upgrade touches only that site's own stack. Read the ADRs added since your last update (docs/adr/) and the CHANGELOG.md before starting; a breaking ADR may require coordinated work.

Step 0: Back up first

Never upgrade without a fresh backup you have tested. Take a full database dump and copy the instance/ directory. See BACKUP-RESTORE.md.

# Docker:
docker compose exec -T db mysqldump -u root -p"${MYSQL_ROOT_PASSWORD}" shopdb_flask | gzip > pre-upgrade-$(date +%F).sql.gz
cp -a instance/ instance-backup-$(date +%F)/

Step 1: Get the new code / image

git pull origin main

The application is distributed through the internal GE Aerospace git server; pull from there. There is no external image registry.

Step 2: Rebuild

The Docker image builds the Vue frontend in-image, so a container rebuild picks up frontend changes automatically:

docker compose build api
docker compose up -d api

Bare-metal / venv install: rebuild the frontend by hand and refresh Python dependencies:

source venv/bin/activate
pip install -r requirements.txt
cd frontend && npm ci && npm run build && cd ..

Step 3: Apply migrations

# Docker:
docker compose exec api flask db upgrade
docker compose exec api flask plugin upgrade-all
# venv:
flask db upgrade
flask plugin upgrade-all

flask db upgrade applies any new migrations in the core Alembic chain. flask plugin upgrade-all then applies any new per-plugin migrations (each bundled plugin owns its schema going forward - see ADR-008). Both are idempotent; running them when already at head is a no-op.

Step 4: Re-seed permissions and settings

New versions may add RBAC permissions or default Settings keys. Both seeders are idempotent - they add anything missing and leave existing rows untouched, so your site's customized values are preserved.

# Docker:
docker compose exec api flask seed permissions
docker compose exec api flask seed settings
# venv:
flask seed permissions
flask seed settings

Step 5: Restart

docker compose restart api
# venv: restart your process manager, e.g. pm2 restart shopdb-flask-api shopdb-flask-ui

Confirm the app is healthy (login page renders, /api/auth/login returns a VALIDATION_ERROR for an empty body rather than a 500).

Version-specific notes

Upgrading to v0.11.0: the floor map became buildings and levels

Nothing to do, and nothing moves on screen. Run both migration steps as always:

flask db upgrade
flask plugin upgrade-all

7d33_buildings_and_levels creates one building ("Main") and one default level ("Ground floor") carrying the blueprint paths and dimensions from your map_* settings, then assigns every already-placed asset and location to that level. Unplaced things stay unplaced. The old settings rows are deliberately left in place, so a downgrade still finds the blueprint.

Two things to know afterwards:

  • A second floor or building is a Settings task, not a migration: add it under Settings > Buildings and levels, upload its blueprint, then move the markers that belong on it. POST /api/mappositions/transform moves a whole level's markers onto a redrawn plan from landmark pairs, dry run by default.
  • Replacing a blueprint with one of DIFFERENT dimensions moves every marker on that level, because the coordinates are pixels of the old size. Upload it, then recalibrate with landmarks rather than editing the level's width and height by hand. The API refuses to adopt a new size on a level that already has markers, for this reason.

If you wrote a plugin that stores map positions, see CONTRACT-STABILITY.md: the contract is 0.20.0 and a position must now carry its levelid.

Upgrading to v0.5.0 or later: bundled the reference site floor plan removed

Versions before 0.5 shipped the the reference site facility floor-plan PNGs as the map default (/static/images/sitemap2025-light.png and -dark.png). v0.5+ removes those bundled PNGs and ships a generic placeholder SVG instead.

If your instance's map_blueprint_light / map_blueprint_dark Settings still point at /static/images/sitemap2025-*, the map will 404 those images after the upgrade. Re-upload your own floor plan in Settings > Floor Map. Uploaded floor plans are stored under instance/ and survive upgrades, so a site that already uploaded its own plan is unaffected. Only instances still using the old bundled default need to act.

To check what your instance points at:

docker compose exec -T api flask shell <<'PY'
from shopdb.core.models.setting import Setting
print(Setting.query.filter(Setting.key.like('map_blueprint%')).all())
PY

Windows sites (installer-built)

Run a newer installer .exe over the existing install. That is the whole procedure - none of the manual steps above apply.

UPDATES-WINDOWS.md is the operator-facing version of this: downtime, what is and is not touched, security updates, and the effect on other sites sharing the same IIS server.

It backs the database up first and verifies the dump, applies the core and plugin migrations, restores from that backup if a migration fails, and refuses to install an older build over a newer one. Your .env, your data and your web.config are kept.

Before the first upgrade, confirm mysqldump is available (.\shopdb-admin.ps1 check). Without it the pre-upgrade backup is skipped, which is the one you would want if a migration went wrong.

Afterwards:

.\shopdb-admin.ps1 status
.\shopdb-admin.ps1 verify

See OPERATE-WINDOWS.md.

See also