Autorun migrations in community edition (#5141)

* fix: autorun migrations in community edition

* re-run tests

* refactor

* fix: review

* fix: double error
This commit is contained in:
Apoorv Mishra
2023-04-19 09:27:50 +05:30
committed by GitHub
parent f4206f888c
commit dadba3f3af
3 changed files with 57 additions and 37 deletions

View File

@@ -1,7 +1,6 @@
up: up:
docker-compose up -d redis postgres s3 docker-compose up -d redis postgres s3
yarn install --pure-lockfile yarn install --pure-lockfile
yarn sequelize db:migrate
yarn dev:watch yarn dev:watch
build: build:

View File

@@ -18,11 +18,7 @@ import services from "./services";
import { getArg } from "./utils/args"; import { getArg } from "./utils/args";
import { getSSLOptions } from "./utils/ssl"; import { getSSLOptions } from "./utils/ssl";
import { defaultRateLimiter } from "@server/middlewares/rateLimiter"; import { defaultRateLimiter } from "@server/middlewares/rateLimiter";
import { import { checkEnv, checkPendingMigrations } from "./utils/startup";
checkEnv,
checkMigrations,
checkPendingMigrations,
} from "./utils/startup";
import { checkUpdates } from "./utils/updates"; import { checkUpdates } from "./utils/updates";
import onerror from "./onerror"; import onerror from "./onerror";
import ShutdownHelper, { ShutdownOrder } from "./utils/ShutdownHelper"; import ShutdownHelper, { ShutdownOrder } from "./utils/ShutdownHelper";
@@ -53,8 +49,7 @@ if (serviceNames.includes("collaboration")) {
// This function will only be called once in the original process // This function will only be called once in the original process
async function master() { async function master() {
await checkEnv(); await checkEnv();
checkPendingMigrations(); await checkPendingMigrations();
await checkMigrations();
if (env.TELEMETRY && env.ENVIRONMENT === "production") { if (env.TELEMETRY && env.ENVIRONMENT === "production") {
checkUpdates(); checkUpdates();

View File

@@ -1,51 +1,76 @@
import { execSync } from "child_process"; import { execSync } from "child_process";
import chalk from "chalk"; import chalk from "chalk";
import { isEmpty } from "lodash";
import env from "@server/env"; import env from "@server/env";
import Logger from "@server/logging/Logger"; import Logger from "@server/logging/Logger";
import AuthenticationProvider from "@server/models/AuthenticationProvider"; import AuthenticationProvider from "@server/models/AuthenticationProvider";
import Team from "@server/models/Team"; import Team from "@server/models/Team";
export function checkPendingMigrations() { function getPendingMigrations() {
const commandResult = execSync(
`yarn sequelize db:migrate:status${
env.PGSSLMODE === "disable" ? " --env=production-ssl-disabled" : ""
}`
);
const commandResultArray = Buffer.from(commandResult)
.toString("utf-8")
.split("\n");
const pendingMigrations = commandResultArray.filter((line) =>
line.startsWith("down")
);
return pendingMigrations;
}
function runMigrations() {
Logger.info("database", "Running migrations...");
const cmdResult = execSync(
`yarn db:migrate${
env.PGSSLMODE === "disable" ? " --env=production-ssl-disabled" : ""
}`
);
const cmdOutput = Buffer.from(cmdResult).toString("utf-8");
Logger.info("database", cmdOutput);
Logger.info("database", "Done.");
}
function logMigrations(migrations: string[]) {
Logger.warn("You have pending migrations");
Logger.warn(
migrations
.map((line, i) => `${i + 1}. ${line.replace("down ", "")}`)
.join("\n")
);
}
export async function checkPendingMigrations() {
try { try {
const commandResult = execSync( const pending = getPendingMigrations();
`yarn sequelize db:migrate:status${ if (!isEmpty(pending)) {
env.PGSSLMODE === "disable" ? " --env=production-ssl-disabled" : "" if (env.isCloudHosted()) {
}` logMigrations(pending);
); process.exit(1);
const commandResultArray = Buffer.from(commandResult) } else {
.toString("utf-8") runMigrations();
.split("\n"); }
const pendingMigrations = commandResultArray.filter((line) =>
line.startsWith("down")
);
if (pendingMigrations.length) {
Logger.warn("You have pending migrations");
Logger.warn(
pendingMigrations
.map((line, i) => `${i + 1}. ${line.replace("down ", "")}`)
.join("\n")
);
Logger.warn(
"Please run `yarn db:migrate` or `yarn db:migrate --env production-ssl-disabled` to run all pending migrations"
);
process.exit(1);
} }
await checkDataMigrations();
} catch (err) { } catch (err) {
if (err.message.includes("ECONNREFUSED")) { if (err.message.includes("ECONNREFUSED")) {
Logger.warn( Logger.warn(
`Could not connect to the database. Please check your connection settings.` chalk.red(
`Could not connect to the database. Please check your connection settings.`
)
); );
} else { } else {
Logger.warn(err.message); Logger.warn(chalk.red(err.message));
} }
process.exit(1); process.exit(1);
} }
} }
export async function checkMigrations() { export async function checkDataMigrations() {
if (env.isCloudHosted()) { if (env.isCloudHosted()) {
return; return;
} }
@@ -58,6 +83,7 @@ export async function checkMigrations() {
Logger.warn(` Logger.warn(`
This version of Outline cannot start until a data migration is complete. This version of Outline cannot start until a data migration is complete.
Backup your database, run the database migrations and the following script: Backup your database, run the database migrations and the following script:
(Note: script run needed only when upgrading to any version between 0.54.0 and 0.61.1, including both)
$ node ./build/server/scripts/20210226232041-migrate-authentication.js $ node ./build/server/scripts/20210226232041-migrate-authentication.js
`); `);