mix encryptor.ecto.migrate (Encryptor.Ecto v0.2.0)

Copy Markdown View Source

Runs a migration plan, in exactly one of the two modes.

mix encryptor.ecto.migrate PLAN --mode dry-run|write
                                [--batch-size N] [--resume] [--no-resume]
                                [--prefix PREFIX] [--no-checkpoint]
                                [--only Schema:field,Schema:field]
                                [--only-tenant ID] [--except-tenant ID]
                                [--on-error halt|continue]

PLAN is the plan module - the one that use Encryptor.Ecto.Migration - positional and required. The plan is the unit of work (ADR-0002 decision 2): no flag names a schema, a field or a repo instead of it.

This task is a thin parser over Encryptor.Ecto.Migrator.run/2, and the library function is the real interface. A production host runs releases and a release has no Mix, so the same pass runs there as:

bin/my_app eval 'Encryptor.Ecto.Migrator.run(MyApp.Encryption.CloakMigration, mode: :dry_run)'

Every flag below maps one-to-one onto an option of run/2. The task adds no capability the library function lacks (ADR-0004 decision 6), which is what keeps the release path a first-class one rather than a degraded one.

Flags

Flagrun/2 option
--mode dry-run|write:modeRequired, no default. dry-run performs every read, probe, decrypt and encrypt and discards the write
--batch-size N:batch_sizeRows per transaction; 500 by default
--resume / --no-resume:resumeStart after the recorded checkpoint cursor. Off by default
--prefix PREFIX:prefixThe one schema prefix to visit; the repo's default when absent. No mode enumerates prefixes - a host with several loops the command over its own list
--no-checkpoint:checkpoint:none, the documented degraded mode for a host that will not add the checkpoint table: every run is a full scan, which probe-first idempotence makes correct rather than merely tolerable
--only Schema:field,Schema:field:onlyNarrow the plan to these fields, in the plan's own order
--only-tenant ID:only_tenantsRepeatable. Visit only these tenants
--except-tenant ID:except_tenantsRepeatable. Visit every tenant but these
--on-error halt|continue:on_errorcontinue records the failure and finishes the pass. halt by default

--resume with --no-checkpoint is a usage error: resuming from a checkpoint that was never written is a request with no meaning.

There is deliberately no flag for run/2's :checkpoint_table or :progress. The grammar is fixed by ADR-0004 decision 6 and widening it is an amendment to that record, not a convenience: a host that renamed the checkpoint table passes checkpoint_table: to run/2 from an eval.

Exit codes

0The pass completed and recorded no failures
1The pass ran and found something: failures recorded under --on-error continue, or rows an operator has to decide about. A dry run that finds :undecryptable rows exits 1, because "the rehearsal found a problem" is not success
2Usage error, a plan that will not compile, no mode given, or a run that could not start at all - a missing checkpoint table, a tenant filter against a rewrite with no tenant column

What it prints

The report: one line per class of Encryptor.Ecto.Migrator.Report, the concurrent-write count, the failure count, and one line per recorded failure naming the schema, the field, the primary key and the reason. Never a plaintext, never ciphertext bytes, never key material.