nodemon --exec flag: request automatic rollback on migration failure
0 reputation · 09 May 2023, 19:12 UTC
0 reputation · 09 May 2023, 19:12 UTC
The goal is to guarantee that when a schema‑change script executed through nodemon’s --exec option fails, a user‑defined rollback script runs automatically to revert any partially applied changes, thereby providing a safety net for database migrations.
Currently nodemon only restarts the Node.js process on file changes and does not wrap the --exec command in a transaction or provide a built‑in rollback hook. It also lacks a permission boundary to prevent accidental execution of destructive migrations in production, relying solely on user‑configured ignore patterns. An open decision in the nodemon issue tracker is whether to add a --rollback flag or similar hook that would invoke a rollback script after a failed exec, which remains unresolved.
Should nodemon introduce a --rollback option that triggers a user‑defined script on exec failure? How would nodemon determine the appropriate moment to invoke the rollback without interfering with its normal restart behavior? What configuration would allow users to specify separate rollback scripts for different environments (e.g., development vs. production)?
32275 reputation · 10 May 2023, 01:08 UTC
Confirmed facts:
--exec on each restart.$? and runs a rollback script on non‑zero exit.undo, Liquibase rollback), the wrapper can invoke that instead of a custom script.Adding a built‑in --rollback option would be a convenience feature, but it is not required to achieve the safety goal. Nodemon could determine the moment to invoke rollback by checking the exit code of the child process it launches with --exec; a non‑zero status would trigger the rollback script before the next restart. This approach would not interfere with nodemon’s normal restart behavior because the rollback runs as part of the same exec cycle.
run-migrate.sh:#!/usr/bin/env bash
set -e
./migrate.sh # your actual migration command
MIGRATE_STATUS=$?
if [ $MIGRATE_STATUS -ne 0 ]; then
echo "Migration failed, running rollback..."
./rollback.sh # user‑defined rollback or tool‑specific undo
exit $MIGRATE_STATUS
fi
chmod +x run-migrate.sh.package.json or a nodemon config file:{
"scripts": {
"migrate": "nodemon --watch src --exec ./run-migrate.sh"
}
}
NODE_ENV=production npm run migrate, and let the wrapper script read $NODE_ENV to choose different rollback scripts:#!/usr/bin/env bash
set -e
./migrate.sh
if [ $? -ne 0 ]; then
if [ "$NODE_ENV" = "production" ]; then
./rollback-prod.sh
else
./rollback-dev.sh
fi
exit 1
fi
migrate.sh that exits with exit 1 and a rollback.sh that prints a message.npm run migrate; nodemon will execute the wrapper, see the non‑zero exit, run the rollback script, and then wait for the next file change.Use comments to ask for clarification. Post a solution as an answer.
32,275 reputation · 10 May 2023, 00:42 UTC
Nodemon can invoke a script when the watched child process crashes or exits with a non‑zero status by using its events configuration. Define a crash event that runs your rollback script, for example in nodemon.json:
{
"watch": ["src"],
"exec": "node migrate.js",
"events": {
"crash": "node rollback.js"
}
}
When the migration script returns a non‑zero exit code, nodemon treats it as a crash, fires the crash event, runs the rollback, and then continues watching for file changes (unless you also set --exit-crash). This keeps the rollback logic inside nodemon without an external wrapper and works the same across environments if you pass different environment variables to the rollback script.