single and dry run

This commit is contained in:
cupcakearmy 2021-03-26 17:20:34 +01:00
parent f92e983fe5
commit a2ebb6f839
No known key found for this signature in database
GPG Key ID: 81C683415BBD86B0
2 changed files with 42 additions and 10 deletions

View File

@ -10,11 +10,12 @@ program.version(spec.version).name(spec.name)
program program
.command('migrate') .command('migrate')
.description('run migrations') .description('run migrations')
// .option('--dry-run', 'run simulation without committing changes') .option('--dry-run', 'run simulation without committing changes')
.option('-m, --migrations <glob>', 'migration files', './migrations/*.js') .option('-m, --migrations <glob>', 'migration files', './migrations/*.js')
.option('--force', 'ignore remote state and rerun migrations') .option('--only <version...>', 'only run specific migration')
.option('-f, --force', 'ignore remote state and rerun migrations')
.action(async (args) => { .action(async (args) => {
await migrate({ directory: args.migrations, ignoreRemote: args.force }) await migrate({ directory: args.migrations, ignoreRemote: args.force, single: args.only, dryRun: args.dryRun })
}) })
program.parse(process.argv) program.parse(process.argv)

View File

@ -32,16 +32,23 @@ export type Options = {
directory: string directory: string
delimiter: string delimiter: string
ignoreRemote: boolean ignoreRemote: boolean
single?: string[]
dryRun: boolean
} }
const defaults: Options = { const defaults: Options = {
directory: './migrations', directory: './migrations',
delimiter: '__', delimiter: '__',
ignoreRemote: false, ignoreRemote: false,
dryRun: false,
} }
const extension = /\..*$/ const extension = /\..*$/
function sortMigrationFiles(arr: MigrationFile[]): MigrationFile[] {
return arr.sort((a, b) => (semver.gt(a.version, b.version) ? 1 : -1))
}
async function gather(options: Options): Promise<MigrationFile[]> { async function gather(options: Options): Promise<MigrationFile[]> {
const files = glob const files = glob
.sync(path.join(options.directory, '*.js')) .sync(path.join(options.directory, '*.js'))
@ -68,11 +75,11 @@ async function gather(options: Options): Promise<MigrationFile[]> {
}) })
) )
const sorted = contents.sort((a, b) => (semver.gt(a.version, b.version) ? 1 : -1)) const asMigrationFile = contents.map(({ version, ...rest }) => ({
return sorted.map(({ version, ...rest }) => ({
...rest, ...rest,
version: version.version, version: version.version,
})) }))
return sortMigrationFiles(asMigrationFile)
} }
function getIdFromMigration(migration: MigrationFile): string { function getIdFromMigration(migration: MigrationFile): string {
@ -93,6 +100,11 @@ async function runMigrations(migrations: MigrationFile[], options: Options) {
continue continue
} }
if (options.dryRun) {
printMigration(migration, 'Skip due to dry-run.')
return
}
const start = process.hrtime.bigint() const start = process.hrtime.bigint()
let error = false let error = false
try { try {
@ -115,15 +127,34 @@ async function runMigrations(migrations: MigrationFile[], options: Options) {
await remoteDoc.ref.set(result) await remoteDoc.ref.set(result)
if (error) { if (error) {
console.log('⚠️ Skipping next migrations') throw new Error('⚠️ Skipping next migrations')
break
} }
} }
} }
} }
export async function migrate(options?: Partial<Options>) { export async function migrate(options?: Partial<Options>) {
try {
const merged: Options = Object.assign(defaults, options) const merged: Options = Object.assign(defaults, options)
const migrations = await gather(merged) let migrations = await gather(merged)
await runMigrations(migrations, merged) console.log(`Found ${chalk.bold(migrations.length)} migrations.`)
if (options?.single) {
const singleVersions = options.single.map((v) => {
const parsed = semver.coerce(v)
if (!parsed) throw new Error(`Invalid version specified: "${v}". Could not parse.`)
return parsed.version
})
const filtered = singleVersions.map((v) => {
const selected = migrations.find((m) => m.version === v)
if (!selected) throw new Error(`Version "${v}" specified in --only does not exist in as migration.`)
return selected
})
migrations = sortMigrationFiles(filtered)
console.log(`Only running specified versions: ${singleVersions.join(', ')}`)
}
await runMigrations(migrations, merged)
} catch (e) {
console.error(chalk.red(e.message))
process.exit(1)
}
} }