Upgrades — bumping submodule pointers
Polaris Express is composed as a superproject of git submodules — web,
email-worker, ios, steve, and docs. Upgrading a self-hosted
deployment means advancing those submodule pointers to a newer commit on
their respective main branches, rebuilding the affected images, and
restarting the stack.
This runbook covers the manual upgrade path. If you mirror our
automation, you can also drive it from the Bump submodules GitHub
Action shipped with the superproject.
When to run this
Section titled “When to run this”- Routine cadence. Weekly or biweekly. The reference automation runs every Monday at 09:00 UTC.
- Security fixes. When an advisory affects any component.
- Feature pulls. When you want a specific change from upstream.
Procedure
Section titled “Procedure”-
Take a backup.
Snapshot the Postgres volume used by
weband the MariaDB volume used bystevebefore doing anything else. If a migration fails, this is your only easy way back. -
Update the working tree.
From the superproject root:
Terminal window git fetch origingit checkout maingit pull --ff-only -
Pull the latest commit on each submodule’s tracking branch.
The
updatetarget wraps the two commands you want:Terminal window make updateWhich expands to:
Terminal window git submodule update --remote --mergegit diff --submodule=logThe
--submodule=logdiff shows you the per-submodule commit log between the old and new pointers. Read it. This is your changelog. -
Review the diff.
Look specifically for:
- Migration files under
web/drizzle/(Postgres schema for the web app). - Migration files under
steve/src/main/resources/db/migration/(MariaDB schema for SteVe). - Env-var additions in
web/.env.example. New required vars must be added to your deployment’s env file before you restart. - Compose changes in any submodule’s
docker-compose.yml.
- Migration files under
-
Commit the pointer bumps.
Terminal window git add web email-worker steve docs iosgit commit -m "chore: bump submodules $(date -u +%Y-%m-%d)" -
Rebuild and restart.
Terminal window make compose-buildmake downmake upOn first start after the bump, the
webcontainer will run any pending Drizzle migrations against Postgres, and SteVe will run any pending Flyway migrations against MariaDB. -
Tail the logs and watch for errors.
Terminal window docker compose logs -f web steveWait until both services log a steady-state ready message before moving on. Migration failures appear here and will keep the affected container in a restart loop.
Using the GitHub Action
Section titled “Using the GitHub Action”If your superproject lives on GitHub, the shipped
.github/workflows/bump-submodules.yml workflow does steps 1–5
automatically. It runs weekly (Monday 09:00 UTC) and on manual dispatch.
- It checks out the superproject with submodules.
- It runs
git checkout main && git pull origin maininside every submodule. - If anything changed, it opens a PR titled
chore: bump submoduleson a branch namedbump-submodules/<run-id>.
You still review the PR (especially the per-submodule diffs) and merge manually. Rebuild and restart are still your job — the workflow does not touch your deployment.
To run it on demand: Actions → Bump submodules → Run workflow.
Verify
Section titled “Verify”After restart, confirm each surface independently.
curl -fsS https://<your-web-host>/api/healthShould return 200 OK. Then log into the admin console and check that
the build SHA in the footer matches the commit you just bumped to.
curl -fsS https://<your-steve-host>/manager/homeShould return the SteVe manager page (auth-gated). Then confirm at
least one ChargeBox is Online in SteVe → Charge Points.
If you redeployed the email worker (it lives in email-worker/),
trigger a magic link send from the web app and confirm the email
arrives.
Audit and rollback
Section titled “Audit and rollback”The whole upgrade is one commit on the superproject. To roll back:
git revert <bump-commit-sha>git submodule update --init --recursivemake compose-buildmake downmake upFor destructive rollbacks:
- Stop the stack:
make down. - Restore the Postgres and MariaDB volumes from the pre-upgrade snapshot.
git revertthe bump commit andgit submodule update --init --recursive.make compose-build && make up.- Confirm health endpoints as above.
If something goes wrong
Section titled “If something goes wrong”- A submodule didn’t advance.
make updateuses--merge, which will fail noisily if your submodule working tree has local commits or uncommitted changes.cdinto the submodule, clean it (git status, thengit reset --hard origin/mainif you have no local work), and re-run. webcontainer restart loop after upgrade. Almost always a Drizzle migration error. Checkdocker compose logs webfor the failing SQL. If the migration is recoverable, fix the data and let it retry; if not, restore from backup.stevecontainer restart loop. Same pattern with Flyway against MariaDB. Logs will name the failing migration file.- New required env var.
webwill exit on boot with a clear message naming the missing variable. Add it to your env file andmake upagain. See the per-phase pages for which file owns which variable.
- Backups — take these before every upgrade.
- Monitoring — set this up so you find out about a failed migration before your users do.