Warn on Missing Migrations (#6580)

* added warn when migrations have not all been run

* fixed imports

* added better error handling

* Update api/src/database/index.ts

Co-authored-by: Rijk van Zanten <rijkvanzanten@me.com>

* migration is its own file

* added custom migrations path

* Handle non-existing custom migrations folder

Co-authored-by: jaycammarano <jaycammarano@gmail.com>
Co-authored-by: Rijk van Zanten <rijkvanzanten@me.com>
This commit is contained in:
Jay Cammarano
2021-08-02 15:52:10 -04:00
committed by GitHub
parent 1881139188
commit 0b17fdcf81
7 changed files with 230 additions and 100 deletions

View File

@@ -24,7 +24,7 @@ import settingsRouter from './controllers/settings';
import usersRouter from './controllers/users';
import utilsRouter from './controllers/utils';
import webhooksRouter from './controllers/webhooks';
import { isInstalled, validateDBConnection } from './database';
import { isInstalled, validateDBConnection, validateMigrations } from './database';
import { emitAsyncSafe } from './emitter';
import env from './env';
import { InvalidPayloadException } from './exceptions';
@@ -60,6 +60,10 @@ export default async function createApp(): Promise<express.Application> {
process.exit(1);
}
if ((await validateMigrations()) === false) {
logger.warn(`Database migrations have not all been run`);
}
await initializeExtensions();
registerExtensionHooks();

View File

@@ -5,6 +5,8 @@ import env from '../env';
import logger from '../logger';
import { getConfigFromEnv } from '../utils/get-config-from-env';
import { validateEnv } from '../utils/validate-env';
import fse from 'fs-extra';
import path from 'path';
let database: Knex | null = null;
let inspector: ReturnType<typeof SchemaInspector> | null = null;
@@ -134,3 +136,35 @@ export async function isInstalled(): Promise<boolean> {
// exists when using the installer CLI.
return await inspector.hasTable('directus_collections');
}
export async function validateMigrations(): Promise<boolean> {
const database = getDatabase();
try {
let migrationFiles = await fse.readdir(path.join(__dirname, 'migrations'));
const customMigrationsPath = path.resolve(env.EXTENSIONS_PATH, 'migrations');
let customMigrationFiles =
((await fse.pathExists(customMigrationsPath)) && (await fse.readdir(customMigrationsPath))) || [];
migrationFiles = migrationFiles.filter(
(file: string) => file.startsWith('run') === false && file.endsWith('.d.ts') === false
);
customMigrationFiles = customMigrationFiles.filter((file: string) => file.endsWith('.js'));
migrationFiles.push(...customMigrationFiles);
const requiredVersions = migrationFiles.map((filePath) => filePath.split('-')[0]);
const completedVersions = (await database.select('version').from('directus_migrations')).map(
({ version }) => version
);
return requiredVersions.every((version) => completedVersions.includes(version));
} catch (error) {
logger.error(`Database migrations cannot be found`);
logger.error(error);
throw process.exit(1);
}
}

View File

@@ -5,12 +5,7 @@ import fse from 'fs-extra';
import { Knex } from 'knex';
import path from 'path';
import env from '../../env';
type Migration = {
version: string;
name: string;
timestamp: Date;
};
import { Migration } from '../../types';
export default async function run(database: Knex, direction: 'up' | 'down' | 'latest'): Promise<void> {
let migrationFiles = await fse.readdir(__dirname);

View File

@@ -8,6 +8,7 @@ export * from './files';
export * from './graphql';
export * from './items';
export * from './meta';
export * from './migration';
export * from './permissions';
export * from './query';
export * from './relation';

View File

@@ -0,0 +1,5 @@
export type Migration = {
version: string;
name: string;
timestamp: Date;
};