mirror of
https://github.com/cupcakearmy/firemorph.git
synced 2024-12-22 08:16:33 +00:00
single and dry run
This commit is contained in:
parent
f92e983fe5
commit
a2ebb6f839
@ -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)
|
||||||
|
45
src/index.ts
45
src/index.ts
@ -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>) {
|
||||||
const merged: Options = Object.assign(defaults, options)
|
try {
|
||||||
const migrations = await gather(merged)
|
const merged: Options = Object.assign(defaults, options)
|
||||||
await runMigrations(migrations, merged)
|
let migrations = await gather(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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user