Skip to content

Upgrading

Theodor Dimitriou edited this page Sep 24, 2026 · 2 revisions

How to move an AstroBaaS install, or a project that uses the astrobaas npm package, to a newer version: the upgrade procedure, how schema migrations behave, what the project does and does not promise about stability, how the alpha npm tag works, and how to read the changelog and upgrade notes. It is for operators and for plugin, theme and SDK authors.

AstroBaaS is pre-1.0 and pre-alpha. Expect behaviour changes between releases, and read the notes before every upgrade.

Where changes are documented

File What it tells you
CHANGELOG.md Every notable change per release, newest first, with an [Unreleased] section at the top. Format inspired by Keep a Changelog; strict semver is not followed yet.
UPGRADE.md Behaviour changes an existing deployment has to know about, each with an id (U-1 to U-21 so far), who it affects and what to do. Newest first.
STABILITY.md What counts as public API and what the project promises about it.
PUBLISHING.md How releases are cut and published to npm, and the dist-tags.

Reading the changelog

  • Each release is a ## [x.y.z] — date heading; each change is a ### heading written as the observable result ("Pagination on the admin's products, posts and pages lists"), followed by why it changed.
  • A change that breaks existing behaviour is marked BREAKING in its heading, with the reason and a migration note.
  • Entries that need action on a running install point to an UPGRADE.md id, for example "See UPGRADE.md U-20". Read that entry; it has the steps.
  • Look at [Unreleased] too if you run from main rather than a tag.

Reading UPGRADE.md

Start with the section "Headless storefronts — the short version" if a separate frontend reads your API: it summarises which public endpoints and fields changed. Then read every U- entry newer than the version you are running. Entries marked ACTION REQUIRED need steps before or after the deploy, for example:

Entry Summary
U-21 SMTP now retries transient failures by default, uses a new EHLO name, and supports Reply-To. SMTP_RETRIES=0 and SMTP_HELO_NAME restore the old behaviour.
U-20 Checkout and payment hardening. Before deploying, set Settings → Site URL to the storefront's address, or buyers returning from a payment provider land on a 404.
U-19 One scheduler per database via a lease; off-site backup state survives restarts; new optional variables.
U-18 Deploy and ops hardening (ACTION REQUIRED for self-hosted nginx, systemd or Docker): copy the nginx zones file again, add new unit keys, check where form attachments are stored.
U-16, U-17 Request limits, sign-in hardening, bounded and cacheable public reads.
U-12 Custom content types are private unless they declare visibility: 'public' (BREAKING for storefronts reading them anonymously).
U-6 Production refuses the seeded admin password.
U-6b The admin's Site URL setting now wins over the build-time SITE_URL.

U-13 and U-14 apply only to installs that ran the separately distributed eyewear module. The full list is in UPGRADE.md.

Upgrading a running install

Upgrading in place is: get the new code, build it, and restart. Pending schema migrations run automatically at startup.

1. Before you start

  1. Read the CHANGELOG and every UPGRADE.md entry between your version and the target.
  2. Take a backup you can restore: the admin export, the off-site backup, or a consistent copy of the data directory (for SQLite, VACUUM INTO or .backup, never a plain copy beside a live -wal file). Back up .env too. See Backups and storage.
  3. Try the upgrade on a staging copy first if you can. See Staging and maintenance.
  4. Check the Node version: the project requires Node 22.12 or newer.

2. From a git checkout

Releases are tagged vX.Y.Z (for example v0.1.3).

git fetch --tags
git checkout v0.1.3        # or: git pull on main
npm ci
npm run build
# restart however you run it, for example:
sudo systemctl restart cms-example-com

Remember that build-time variables (SITE_URL, CSP_*, ANALYTICS_PROVIDERS) must be set in the environment where npm run build runs.

3. With deploy.sh

Update your checkout to the new version, refresh .deploy/node_modules if package.json dependencies changed (a production npm install --omit=dev made on Linux), then run your deploy as usual. deploy/remote-activate.sh restarts the service and waits for /readyz, so the deploy fails visibly if the new release never becomes ready. See Deployment.

When an UPGRADE.md entry changes the reference configs (nginx, Caddy, systemd), apply those changes to your server's copies; the deploy scripts do not touch them. If you keep a private deploy.local.sh, it should only set variables and call deploy.sh, so it picks up fixes automatically.

4. With Docker

Rebuild the image from the new version and recreate the container. The data volume at /app/data carries over.

git pull
docker compose up -d --build

5. After the restart

curl -fsS http://127.0.0.1:<port>/readyz
curl -fsS -H "Authorization: Bearer $HEALTH_TOKEN" https://cms.example.com/api/health/deep
  • /readyz returns schema_version and expected_schema_version, and stays 503 until the database has been migrated to what the build expects.
  • The deep health check exercises the essentials and lists warnings introduced by new checks (for example a short HEALTH_TOKEN now reports warn).

Schema migrations

  • The database records a schema version. On startup, pending migrations run in ascending order, each stamped after it succeeds. A failure stops the run at the last successful step.
  • One migration definition upgrades all three storage drivers, because migrations go through the same Storage interface as the rest of the app.
  • A fresh install is created at the latest version; only an existing database has migrations applied.
  • With several processes on one database, migrations run under a migrations lease so they are not applied twice. A process that cannot take the lease waits MIGRATION_LOCK_WAIT_MS (default 2 minutes).
  • Migrations are forward-only: there are no down migrations. Shipped migrations are never edited; corrections are appended as new ones.

The migrations live in src/lib/migrations.ts.

Rolling back

Rolling back code is easy; rolling back a schema is not. If a release has already migrated the database, running the previous release against it is a judgement call: check the UPGRADE.md entry, and prefer restoring the backup you took before upgrading if the migration changed data the old code depends on.

With the reference deploy layout, the previous release stays on disk, and a failed deploy prints the exact ln -sfn ... current && systemctl restart ... command. See Deployment.

Stability promises

What is public API

The public API is everything exported from three import paths:

Import path Contents
astrobaas/core Domain and commerce types, the Storage contract, plugin and theme helpers, hook names (PLUGIN_HOOKS), content-type registration, manifest validation, sanitising and validation, webhook signing, email transport, audit logging and more.
astrobaas/plugins BUNDLED_PLUGINS, the registry of plugins that ship with AstroBaaS.
astrobaas/client The typed REST client (createClient), AstroBaasError, verifyWebhookSignature, and the SDK's input and output types.

STABILITY.md lists every covered export, and a few that are exported but explicitly not promised (for example the bundled-plugin loading internals). tests/stability.test.mjs fails the build if an export of those three barrels is neither documented nor excluded.

What is not covered

  • anything under src/lib/*, src/pages/*, src/components/* and src/middleware.ts;
  • the on-disk db.json format (go through Storage, never write it directly);
  • the admin UI's markup and DOM structure;
  • the internals of how bundled plugins are loaded.

Import only from the three public paths. Code that reaches into src/lib can break in any release without notice.

The policy while pre-1.0

  • Additive changes (new exports, optional fields, hooks) can land in any minor release.
  • Breaking changes to the public surface are allowed, but each is listed in the CHANGELOG as breaking, with the reason and a migration note.
  • Hook names in PLUGIN_HOOKS are not silently renamed or removed; a removed hook is a documented breaking change.
  • Declarative plugin manifests have their own version line, MANIFEST_API_VERSION. A manifest declares the major it targets; a mismatched major is refused rather than half-honoured.
  • Adding a new theme template slot is not breaking: themes that do not override it inherit the default.

From 1.0 the public surface follows semver: breaking changes only in major versions.

Note that these promises are about the programming interfaces. Behaviour changes that affect a running install (limits, defaults, which endpoints are public) are documented in UPGRADE.md.

The alpha npm tag

Two packages are published from this repository by CI when a v* tag is pushed, both with npm provenance:

Package Dist-tag Contents
astrobaas alpha The libraries (astrobaas/core, /client, /plugins) and the astrobaas CLI. Not the CMS itself.
astrobaas-mcp latest The MCP server alone, zero dependencies.

Pre-1.0 releases of astrobaas are published under alpha, so ask for it explicitly:

npm install astrobaas@alpha

The publish workflow never moves latest. npm points latest at a package's very first version whatever tag it was published with, so a bare npm install astrobaas still resolves to 0.1.0, not the newest alpha. Promoting a release to latest is a separate, deliberate step, planned to progress alpha → beta → latest.

To update the package in your own project:

npm install astrobaas@alpha        # newest alpha
npm view astrobaas dist-tags       # see what each tag points at

Pin an exact version in production projects, and read the CHANGELOG's breaking entries before moving. astrobaas-mcp is on latest because it is only an HTTP client of the REST API; npx -y astrobaas-mcp picks up the newest version.

The npm package never gives you a running CMS; upgrade the CMS itself as described above. See SDK, CLI and MCP.

See also

Clone this wiki locally