mirror of
https://github.com/nocobase/nocobase.git
synced 2026-10-13 16:19:28 +08:00
* feat(hub-installer): install a Hub from the published template Add @nocobase/hub-installer for servers that run an unmodified Hub. `install <dir>` resolves the template version, generates and builds the Hub in `.build/<version>/` with create-app, unpacks only the deployment archive into `releases/<version>/hub`, writes `hub.env` and `config.yml` outside the release, applies the migrations with the release's own CLI, switches `current`, and starts the Hub with pm2 until `/hub/api/healthz` answers. A failure before the switch removes everything it wrote. `status` reports the current version, health, pm2 process, releases, Node compatibility and whether the registry has a newer version. The pm2 configuration runs `node` itself with the entry file as its argument, because pm2's fork mode loads a script through a wrapper where `import.meta.main` is false and the Hub never starts. A smoke test installs the published template on Debian bookworm with Node 24 on pull requests that touch the package, and daily, since the template ships no lockfile and a new dependency release can break it. * feat(hub-installer): upgrade and roll back a Hub `upgrade` builds the new release beside the running one, or reuses a release already on disk, and checks it with its own `config check` and `db apply --dry-run` before any downtime. It then stops the Hub, copies the SQLite database, config.yml and hub.env to backups/, switches `current`, migrates and starts the new release behind a health check. A failure after the switch rolls back automatically, restoring the database when the new release may have migrated it: exit 3 when the previous release is healthy again, 4 when it is not. Releases beyond `--keep` are pruned. `rollback` returns to the release the last upgrade came from and restores the pre-upgrade database only when that upgrade migrated. An operation interrupted during the downtime is recorded in installer.json: status reports it, upgrade refuses to stack on it, and rollback recovers by undoing an interrupted upgrade or finishing an interrupted rollback. Both commands confirm first or take `--yes`, and a non-SQLite database requires `--backup-done`. The smoke test now upgrades from a copy of the installed release and rolls back, exercising the downtime path without a second build. * feat(scripts): add unreleased:hub-smoke for the Hub installer `pnpm unreleased:hub-smoke` installs a Hub with the snapshot's hub-installer from the local registry, checks it, upgrades from a copy registered as an older release, rolls back and checks again. It runs pm2 under a short temporary PM2_HOME, stops it afterwards, and keeps the Hub and its logs outside the repository. The CI smoke test can only see changes to the installer itself: it installs the published template. This covers changes to the Hub template, app-cli, app-host and create-app before they are released. Both run scripts/smoke-hub-installer.mjs, which replaces the inline checks the workflow carried, so the local and CI checks cannot drift. * fix(hub-installer): address the install review - Refuse a pm2 name that is already registered: `pm2 start` on a taken name restarts that process with this install's environment instead of starting a new one, and START_FAILED then deleted it. - Check before the first write that the port binds, that every `--set-from-env` variable is set, and bound `--port` and `--health-timeout`; a regular file at the target is a precheck error. - SIGINT/SIGTERM stop the running step and let the failure handling clean up; a second signal exits. Children run in their own process group, so a timeout or interrupt stops what pnpm started, and the promise settles only once the group has exited. - Write the pm2 config and installer.json before switching `current`, so the switch is the last write before starting; remove parents the install created; keep `.build/` on failure under `--keep-source`. - Fail fast when pm2 reports the new process as crashed, instead of waiting out the health timeout. - `status` no longer starts the pm2 daemon; the lock is linked into place with its pid already written; dist-tags use `hasOwn`; `install --help` prints help; `config set` values are masked in output; an unsupported Node exits 2. - The smoke test builds the package and runs dist/, and also runs on lockfile and workspace changes. - Tests drive `install()` through a fake of every child process it starts, and runCommand through real process groups. * fix(hub-installer): address the upgrade and rollback review rollback: - Restore only from a backup that holds a database. An external database is never in one, so a Hub on PostgreSQL or MySQL used to stop, fail to restore, and stay down. - Keep installer.json in step with the `current` link: `current` is written only after the link moves. A failed stop changes nothing and exits 1; a target that does not start stays pending, and running rollback again retries it, restore included. - Recover an interrupted upgrade by what it actually did: before the switch nothing was migrated, so the old release is just started; an interrupted rollback keeps its backup and restores it again. upgrade: - Record the backup in `pending` only once it is complete, and mark the switch before the link moves; remove a half-written backup on abort. - Move the switch inside the rollback's error handling. - Write the successful result before pruning, then prune. - Never prune the release upgraded from; `--keep` is at least 2. - Keep the new release, and the pending state, when the automatic rollback fails too, so `rollback` can finish or return to it. - Refuse a downgrade; reuse a recorded release only when it was built for this machine, otherwise rebuild it and replace its record. - Check that the pm2 process belongs to this root and that the port is free once the Hub is stopped; wait for health failing fast on a crashed process; read the state under the lock; UTC backup names. Flow tests drive both commands through the fake world: exit 3 and 4, recovery after each, external databases, stop failures, interrupted upgrades, rebuilds, ownership and pruning. The smoke test pins the upgrade target to the installed version. * test(scripts): cover the restore and automatic rollback paths in the Hub smoke test The smoke test upgraded to a copy of the same release, which applies no migrations, so the rollback never restored the database and no upgrade ever failed. It now also rolls back an upgrade recorded as migrating and checks that a table written after it is gone, and upgrades to a release whose server entry throws, expecting exit 3 with UPGRADE_ROLLED_BACK and the previous release healthy again. Both scripts refuse port 13010, where the Hub's App Host listens; a Hub on it failed its health check with no clear reason. * feat(hub-installer): start through a launcher, report endpoints, and make suggestions runnable pm2 now runs launcher.mjs in the Hub root. On every start it reads hub.env and resolves `current`, then becomes the Hub through process.execve, keeping the pid pm2 watches and passing node flags on. A plain `pm2 restart` therefore applies an edited hub.env or a switched release; ecosystem.config.cjs no longer captures either. - status reports `endpoints`: the public URL and origin, and the host and port the Hub listens on. - install reports `initialAdmin` (username, email, and whether the password is still the template default, never the password), and takes --dir like the other commands. - Every suggested command and --help example runs as printed: npx with the registry named, pinned to this installer's version, paths quoted. Suggestions that were not commands, and the release CLI's own commands, become messages. - pm2 4.3 or later is required, the first release that reads ecosystem.config.cjs as a configuration. - Under --json, an unsupported Node.js prints the error envelope. - The README documents every error code, changing the origin or port, and the launcher. The smoke test switches releases with `pm2 restart` and checks that the pm2 process runs the expected release's server entry. * fix(hub-installer): address the launcher review - bin/run.js waits for stdout and stderr to flush before exiting, so a --json document on a slow pipe arrives whole; a plain process.exit cut a 2 MB write to 64 KB. - endpointsOf drops a trailing slash from a hand-edited origin and reports a port that is not one as null, with a warning from status; healthUrl reads host and port from it instead of repeating defaults. - install reports `endpoints` like status, and --version --json prints the same envelope as every other command. - pm2's version is the line of `pm2 --version` that is one, and a version that cannot be read is reported as such rather than as a pm2 older than 4.3. - A failed automatic rollback that did not restore the database says where the pre-upgrade database is and where it belongs again. - The launcher comment and the README state what pm2 actually does: it gives the launcher an IPC channel that execve drops, and ignores node_args for interpreter 'none', so node flags go in `args` or in NODE_OPTIONS. - A folded application CLI command no longer starts with a space when the suggestion had no message.