diff --git a/docs/generated/cli/migrate.md b/docs/generated/cli/migrate.md index 509edb14ac..7807d46e96 100644 --- a/docs/generated/cli/migrate.md +++ b/docs/generated/cli/migrate.md @@ -3,7 +3,7 @@ title: 'migrate - CLI command' description: 'Creates a migrations file or runs migrations from the migrations file. - Migrate packages and create migrations.json (e.g., nx migrate @nrwl/workspace@latest) - - Run migrations (e.g., nx migrate --run-migrations=migrations.json)' + - Run migrations (e.g., nx migrate --run-migrations=migrations.json). Use flag --if-exists to run migrations only if the migrations file exists.' --- # migrate @@ -11,7 +11,7 @@ description: Creates a migrations file or runs migrations from the migrations file. - Migrate packages and create migrations.json (e.g., nx migrate @nrwl/workspace@latest) -- Run migrations (e.g., nx migrate --run-migrations=migrations.json) +- Run migrations (e.g., nx migrate --run-migrations=migrations.json). Use flag --if-exists to run migrations only if the migrations file exists. ## Usage @@ -115,6 +115,14 @@ Type: `boolean` Show help +### ifExists + +Type: `boolean` + +Default: `false` + +Run migrations only if the migrations file exists, if not continues successfully + ### interactive Type: `boolean` diff --git a/docs/generated/packages/nx/documents/migrate.md b/docs/generated/packages/nx/documents/migrate.md index 509edb14ac..7807d46e96 100644 --- a/docs/generated/packages/nx/documents/migrate.md +++ b/docs/generated/packages/nx/documents/migrate.md @@ -3,7 +3,7 @@ title: 'migrate - CLI command' description: 'Creates a migrations file or runs migrations from the migrations file. - Migrate packages and create migrations.json (e.g., nx migrate @nrwl/workspace@latest) - - Run migrations (e.g., nx migrate --run-migrations=migrations.json)' + - Run migrations (e.g., nx migrate --run-migrations=migrations.json). Use flag --if-exists to run migrations only if the migrations file exists.' --- # migrate @@ -11,7 +11,7 @@ description: Creates a migrations file or runs migrations from the migrations file. - Migrate packages and create migrations.json (e.g., nx migrate @nrwl/workspace@latest) -- Run migrations (e.g., nx migrate --run-migrations=migrations.json) +- Run migrations (e.g., nx migrate --run-migrations=migrations.json). Use flag --if-exists to run migrations only if the migrations file exists. ## Usage @@ -115,6 +115,14 @@ Type: `boolean` Show help +### ifExists + +Type: `boolean` + +Default: `false` + +Run migrations only if the migrations file exists, if not continues successfully + ### interactive Type: `boolean` diff --git a/e2e/nx-misc/src/misc.test.ts b/e2e/nx-misc/src/misc.test.ts index aaee7f884c..22de465b18 100644 --- a/e2e/nx-misc/src/misc.test.ts +++ b/e2e/nx-misc/src/misc.test.ts @@ -6,6 +6,7 @@ import { newProject, readFile, readJson, + removeFile, runCLI, runCLIAsync, runCommand, @@ -532,4 +533,38 @@ describe('migrate', () => { `Error: Providing a custom commit prefix requires --create-commits to be enabled` ); }); + + it('should fail if no migrations are present', () => { + removeFile(`./migrations.json`); + + // Invalid: runs migrations with a custom commit-prefix but without enabling --create-commits + const output = runCLI(`migrate --run-migrations`, { + env: { + ...process.env, + NX_MIGRATE_SKIP_INSTALL: 'true', + NX_MIGRATE_USE_LOCAL: 'true', + }, + silenceError: true, + }); + + expect(output).toContain( + `File 'migrations.json' doesn't exist, can't run migrations. Use flag --if-exists to run migrations only if the file exists` + ); + }); + + it('should not run migrations if no migrations are present and flag --if-exists is used', () => { + removeFile(`./migrations.json`); + + // Invalid: runs migrations with a custom commit-prefix but without enabling --create-commits + const output = runCLI(`migrate --run-migrations --if-exists`, { + env: { + ...process.env, + NX_MIGRATE_SKIP_INSTALL: 'true', + NX_MIGRATE_USE_LOCAL: 'true', + }, + silenceError: true, + }); + + expect(output).toContain(`Migrations file 'migrations.json' doesn't exist`); + }); }); diff --git a/packages/nx/src/command-line/migrate.spec.ts b/packages/nx/src/command-line/migrate.spec.ts index d8704b3980..fdb893c45b 100644 --- a/packages/nx/src/command-line/migrate.spec.ts +++ b/packages/nx/src/command-line/migrate.spec.ts @@ -1493,7 +1493,7 @@ describe('Migration', () => { }); describe('parseMigrationsOptions', () => { - it('should work', () => { + it('should work for generating migrations', () => { const r = parseMigrationsOptions({ packageAndVersion: '8.12.0', from: '@myscope/a@12.3,@myscope/b@1.1.1', @@ -1513,6 +1513,18 @@ describe('Migration', () => { }); }); + it('should work for running migrations', () => { + const r = parseMigrationsOptions({ + runMigrations: '', + ifExists: true, + }); + expect(r).toEqual({ + type: 'runMigrations', + runMigrations: 'migrations.json', + ifExists: true, + }); + }); + it('should handle different variations of the target package', () => { expect( parseMigrationsOptions({ packageAndVersion: '@angular/core' }) diff --git a/packages/nx/src/command-line/migrate.ts b/packages/nx/src/command-line/migrate.ts index 002f6e1d03..7fc1bcfdab 100644 --- a/packages/nx/src/command-line/migrate.ts +++ b/packages/nx/src/command-line/migrate.ts @@ -24,6 +24,7 @@ import { NxJsonConfiguration } from '../config/nx-json'; import { flushChanges, FsTree, printChanges } from '../generators/tree'; import { extractFileFromTarball, + fileExists, JsonReadOptions, readJsonFile, writeJsonFile, @@ -660,7 +661,11 @@ type GenerateMigrations = { excludeAppliedMigrations?: boolean; }; -type RunMigrations = { type: 'runMigrations'; runMigrations: string }; +type RunMigrations = { + type: 'runMigrations'; + runMigrations: string; + ifExists: boolean; +}; export function parseMigrationsOptions(options: { [k: string]: any; @@ -690,6 +695,7 @@ export function parseMigrationsOptions(options: { return { type: 'runMigrations', runMigrations: options.runMigrations as string, + ifExists: options.ifExists as boolean, }; } } @@ -1304,7 +1310,7 @@ export async function executeMigrations( async function runMigrations( root: string, - opts: { runMigrations: string }, + opts: { runMigrations: string; ifExists: boolean }, isVerbose: boolean, shouldCreateCommits = false, commitPrefix: string @@ -1313,6 +1319,19 @@ async function runMigrations( runInstall(); } + const migrationsExists: boolean = fileExists(opts.runMigrations); + + if (opts.ifExists && !migrationsExists) { + output.log({ + title: `Migrations file '${opts.runMigrations}' doesn't exist`, + }); + return; + } else if (!opts.ifExists && !migrationsExists) { + throw new Error( + `File '${opts.runMigrations}' doesn't exist, can't run migrations. Use flag --if-exists to run migrations only if the file exists` + ); + } + output.log({ title: `Running migrations from '${opts.runMigrations}'` + diff --git a/packages/nx/src/command-line/nx-commands.ts b/packages/nx/src/command-line/nx-commands.ts index 23fc5264b9..c7817e60e4 100644 --- a/packages/nx/src/command-line/nx-commands.ts +++ b/packages/nx/src/command-line/nx-commands.ts @@ -282,7 +282,7 @@ export const commandsObject = yargs command: 'migrate [packageAndVersion]', describe: `Creates a migrations file or runs migrations from the migrations file. - Migrate packages and create migrations.json (e.g., nx migrate @nrwl/workspace@latest) - - Run migrations (e.g., nx migrate --run-migrations=migrations.json)`, + - Run migrations (e.g., nx migrate --run-migrations=migrations.json). Use flag --if-exists to run migrations only if the migrations file exists.`, builder: (yargs) => linkToNxDevAndExamples(withMigrationOptions(yargs), 'migrate'), handler: () => { @@ -944,6 +944,11 @@ function withMigrationOptions(yargs: yargs.Argv) { describe: `Execute migrations from a file (when the file isn't provided, execute migrations from migrations.json)`, type: 'string', }) + .option('ifExists', { + describe: `Run migrations only if the migrations file exists, if not continues successfully`, + type: 'boolean', + default: false, + }) .option('from', { describe: 'Use the provided versions for packages instead of the ones installed in node_modules (e.g., --from="@nrwl/react@12.0.0,@nrwl/js@12.0.0")',