directus-deploy-cli 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +108 -2
- package/dist/cli.js.map +1 -1
- package/dist/lint.js +131 -0
- package/dist/lint.js.map +1 -0
- package/dist/reconcilers/migrations.js +204 -18
- package/dist/reconcilers/migrations.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -88,14 +88,50 @@ async function execute(mode, flags) {
|
|
|
88
88
|
process.stderr.write(`verify: drift detected (${report.counts.created} would-create, ${report.counts.updated} would-update)\n`);
|
|
89
89
|
return 1;
|
|
90
90
|
}
|
|
91
|
+
// Server-side gate: any `directus_fields.type = 'unknown'` row on the
|
|
92
|
+
// target means a raw-SQL column was added but never registered — either
|
|
93
|
+
// via `migrations/register/<table>.json` or by a Directus-native field
|
|
94
|
+
// definition. Fail fast so the miss surfaces here, not in a UI 500.
|
|
95
|
+
const unknowns = await fetchUnknownFields(client);
|
|
96
|
+
if (unknowns === null) {
|
|
97
|
+
process.stderr.write(`verify: could not query directus_fields for type=unknown (raw-query endpoint unavailable?) — skipping check\n`);
|
|
98
|
+
}
|
|
99
|
+
else if (unknowns.length > 0) {
|
|
100
|
+
process.stderr.write(`verify: ${unknowns.length} field(s) have type='unknown' on target — add a register manifest or Directus field definition:\n`);
|
|
101
|
+
for (const u of unknowns) {
|
|
102
|
+
process.stderr.write(` ${u.collection}.${u.field}\n`);
|
|
103
|
+
}
|
|
104
|
+
return 1;
|
|
105
|
+
}
|
|
91
106
|
}
|
|
92
107
|
return 0;
|
|
93
108
|
}
|
|
109
|
+
async function fetchUnknownFields(client) {
|
|
110
|
+
try {
|
|
111
|
+
const r = (await client.postRaw("/raw-query/execute", {
|
|
112
|
+
query: "SELECT collection, field FROM directus_fields WHERE type = 'unknown' ORDER BY collection, field",
|
|
113
|
+
}));
|
|
114
|
+
const inner = r?.results?.[0];
|
|
115
|
+
if (!r?.success || !inner?.success)
|
|
116
|
+
return null;
|
|
117
|
+
const out = [];
|
|
118
|
+
for (const row of inner.data ?? []) {
|
|
119
|
+
if (row && typeof row === "object" && "collection" in row && "field" in row) {
|
|
120
|
+
const rr = row;
|
|
121
|
+
out.push({ collection: String(rr.collection), field: String(rr.field) });
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return out;
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
94
130
|
const program = new Command();
|
|
95
131
|
program
|
|
96
132
|
.name("directus-deploy")
|
|
97
133
|
.description("Reconcile a Directus environment to the state described in directus_config/snapshot/. Per-entity, non-atomic.")
|
|
98
|
-
.version("0.
|
|
134
|
+
.version("0.3.0");
|
|
99
135
|
function attachCommon(cmd) {
|
|
100
136
|
return cmd
|
|
101
137
|
.option("--url <url>", "Directus base URL (env: DIRECTUS_URL)")
|
|
@@ -107,7 +143,7 @@ function attachCommon(cmd) {
|
|
|
107
143
|
.option("--config-dir <path>", "path to directus_config/collections (holds policies.json, permissions.json, roles.json, …)", "./directus_config/collections")
|
|
108
144
|
.option("--register-dir <path>", "path to migrations/register", "./migrations/register")
|
|
109
145
|
.option("--seed-dir <path>", "path to directus_config/seed (Tractr-style {collection, meta, data} files)", "./directus_config/seed")
|
|
110
|
-
.option("--migrations-dir <path>", "path to migrations/*.sql (raw SQL, tracked in
|
|
146
|
+
.option("--migrations-dir <path>", "path to migrations/*.sql (raw SQL, tracked in _directus_deploy_migrations)", "./migrations")
|
|
111
147
|
.option("--json", "emit JSON report instead of human-readable");
|
|
112
148
|
}
|
|
113
149
|
attachCommon(program.command("plan"))
|
|
@@ -125,6 +161,76 @@ attachCommon(program.command("verify"))
|
|
|
125
161
|
.action(async (_, cmd) => {
|
|
126
162
|
process.exit(await execute({ dryRun: true, strict: true }, cmd.optsWithGlobals()));
|
|
127
163
|
});
|
|
164
|
+
// migrations adopt: bootstrap the tracker on an env whose migrations were
|
|
165
|
+
// applied via some prior mechanism. Inserts (filename, sha256) rows without
|
|
166
|
+
// executing any SQL. Idempotent — re-adopting is a no-op when hashes match.
|
|
167
|
+
const migrationsGroup = program
|
|
168
|
+
.command("migrations")
|
|
169
|
+
.description("migration-specific commands");
|
|
170
|
+
migrationsGroup
|
|
171
|
+
.command("adopt")
|
|
172
|
+
.description("Insert current migrations/*.sql into the tracker WITHOUT running them. Use once per env when cutting over from a prior deploy mechanism.")
|
|
173
|
+
.option("--url <url>", "Directus base URL (env: DIRECTUS_URL)")
|
|
174
|
+
.option("--token <token>", "Directus admin token (env: DIRECTUS_TOKEN)")
|
|
175
|
+
.option("--target <label>", "friendly label for logs (default: URL hostname)")
|
|
176
|
+
.option("--migrations-dir <path>", "path to migrations/*.sql", "./migrations")
|
|
177
|
+
.option("--dry-run", "report what would be adopted, don't write")
|
|
178
|
+
.option("--json", "emit JSON report instead of human-readable")
|
|
179
|
+
.action(async (opts) => {
|
|
180
|
+
const url = opts.url ?? process.env.DIRECTUS_URL;
|
|
181
|
+
const token = opts.token ?? process.env.DIRECTUS_TOKEN;
|
|
182
|
+
if (!url)
|
|
183
|
+
throw new Error("--url or DIRECTUS_URL required");
|
|
184
|
+
if (!token)
|
|
185
|
+
throw new Error("--token or DIRECTUS_TOKEN required");
|
|
186
|
+
const target = opts.target ?? new URL(url).hostname;
|
|
187
|
+
const client = createDirectusClient({ baseUrl: url, token });
|
|
188
|
+
const { adoptMigrations } = await import("./reconcilers/migrations.js");
|
|
189
|
+
const results = await adoptMigrations({
|
|
190
|
+
migrationsDir: opts.migrationsDir,
|
|
191
|
+
client,
|
|
192
|
+
opts: { dryRun: Boolean(opts.dryRun) },
|
|
193
|
+
});
|
|
194
|
+
const counts = { created: 0, updated: 0, unchanged: 0, skipped: 0, failed: 0 };
|
|
195
|
+
for (const r of results)
|
|
196
|
+
counts[r.action] += 1;
|
|
197
|
+
const report = { target, results, counts };
|
|
198
|
+
if (opts.json) {
|
|
199
|
+
process.stdout.write(formatJson(report) + "\n");
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
process.stdout.write(formatHuman(report) + "\n");
|
|
203
|
+
}
|
|
204
|
+
process.exit(counts.failed > 0 ? 1 : 0);
|
|
205
|
+
});
|
|
206
|
+
migrationsGroup
|
|
207
|
+
.command("lint")
|
|
208
|
+
.description("Static check: every CREATE TABLE / ADD COLUMN in migrations/*.sql must be covered by a register manifest or a real (non-'unknown') snapshot field definition. No network calls.")
|
|
209
|
+
.option("--migrations-dir <path>", "path to migrations/*.sql", "./migrations")
|
|
210
|
+
.option("--register-dir <path>", "path to migrations/register", "./migrations/register")
|
|
211
|
+
.option("--snapshot-dir <path>", "path to directus_config/snapshot", "./directus_config/snapshot")
|
|
212
|
+
.option("--json", "emit JSON output")
|
|
213
|
+
.action(async (opts) => {
|
|
214
|
+
const { lintMigrations } = await import("./lint.js");
|
|
215
|
+
const { violations, scanned } = await lintMigrations({
|
|
216
|
+
migrationsDir: opts.migrationsDir,
|
|
217
|
+
registerDir: opts.registerDir,
|
|
218
|
+
snapshotDir: opts.snapshotDir,
|
|
219
|
+
});
|
|
220
|
+
if (opts.json) {
|
|
221
|
+
process.stdout.write(JSON.stringify({ scanned, violations }, null, 2) + "\n");
|
|
222
|
+
}
|
|
223
|
+
else if (violations.length === 0) {
|
|
224
|
+
process.stdout.write(`migrations lint: ${scanned} file(s) scanned, no violations.\n`);
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
process.stderr.write(`migrations lint: ${violations.length} violation(s) across ${scanned} file(s):\n`);
|
|
228
|
+
for (const v of violations) {
|
|
229
|
+
process.stderr.write(` ${v.file}: ${v.reason}\n`);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
process.exit(violations.length === 0 ? 0 : 1);
|
|
233
|
+
});
|
|
128
234
|
program.parseAsync(process.argv).catch((e) => {
|
|
129
235
|
process.stderr.write(`directus-deploy: ${e.message}\n`);
|
|
130
236
|
process.exit(2);
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
package/dist/lint.js
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { readdir, readFile } from "node:fs/promises";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
async function readManifests(dir) {
|
|
5
|
+
const map = new Map();
|
|
6
|
+
let entries;
|
|
7
|
+
try {
|
|
8
|
+
entries = await readdir(dir);
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return map;
|
|
12
|
+
}
|
|
13
|
+
for (const f of entries) {
|
|
14
|
+
if (!f.endsWith(".json"))
|
|
15
|
+
continue;
|
|
16
|
+
try {
|
|
17
|
+
const parsed = JSON.parse(await readFile(join(dir, f), "utf8"));
|
|
18
|
+
if (parsed?.table)
|
|
19
|
+
map.set(parsed.table, parsed);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
/* malformed manifest surfaces via other tooling */
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return map;
|
|
26
|
+
}
|
|
27
|
+
// Parse a SQL file for `CREATE TABLE (IF NOT EXISTS)? name`
|
|
28
|
+
// and `ALTER TABLE name ADD COLUMN (IF NOT EXISTS)? col`.
|
|
29
|
+
// Case-insensitive; multi-column ALTER TABLE ADD is handled by matching each
|
|
30
|
+
// ADD COLUMN clause independently.
|
|
31
|
+
function parseSql(sql) {
|
|
32
|
+
const createTables = [];
|
|
33
|
+
const addColumns = [];
|
|
34
|
+
// Strip block + line comments to simplify matching. We keep offsets rough —
|
|
35
|
+
// this is a lint, not a compiler.
|
|
36
|
+
const stripped = sql
|
|
37
|
+
.replace(/\/\*[\s\S]*?\*\//g, " ")
|
|
38
|
+
.replace(/--[^\n]*\n/g, "\n");
|
|
39
|
+
const createRe = /\bCREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?"?([a-z_][a-z0-9_]*)"?\s*\(/gi;
|
|
40
|
+
let m;
|
|
41
|
+
while ((m = createRe.exec(stripped)) !== null) {
|
|
42
|
+
createTables.push(m[1].toLowerCase());
|
|
43
|
+
}
|
|
44
|
+
// Find each `ALTER TABLE <t> …` block, then within that block find every
|
|
45
|
+
// `ADD COLUMN (IF NOT EXISTS)? <c>`. This handles the common
|
|
46
|
+
// ALTER TABLE t
|
|
47
|
+
// ADD COLUMN a int,
|
|
48
|
+
// ADD COLUMN b int;
|
|
49
|
+
// shape.
|
|
50
|
+
const alterRe = /\bALTER\s+TABLE\s+(?:ONLY\s+)?"?([a-z_][a-z0-9_]*)"?\s*([\s\S]*?);/gi;
|
|
51
|
+
while ((m = alterRe.exec(stripped)) !== null) {
|
|
52
|
+
const table = m[1].toLowerCase();
|
|
53
|
+
const body = m[2];
|
|
54
|
+
const colRe = /\bADD\s+COLUMN\s+(?:IF\s+NOT\s+EXISTS\s+)?"?([a-z_][a-z0-9_]*)"?/gi;
|
|
55
|
+
let cm;
|
|
56
|
+
while ((cm = colRe.exec(body)) !== null) {
|
|
57
|
+
addColumns.push({ table, column: cm[1].toLowerCase() });
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return { createTables, addColumns };
|
|
61
|
+
}
|
|
62
|
+
async function fieldSnapshotType(snapshotDir, table, column) {
|
|
63
|
+
const path = join(snapshotDir, "fields", table, `${column}.json`);
|
|
64
|
+
if (!existsSync(path))
|
|
65
|
+
return null;
|
|
66
|
+
try {
|
|
67
|
+
const parsed = JSON.parse(await readFile(path, "utf8"));
|
|
68
|
+
return typeof parsed.type === "string" ? parsed.type : null;
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function collectionSnapshotExists(snapshotDir, table) {
|
|
75
|
+
return existsSync(join(snapshotDir, "collections", `${table}.json`));
|
|
76
|
+
}
|
|
77
|
+
export async function lintMigrations(input) {
|
|
78
|
+
const violations = [];
|
|
79
|
+
let scanned = 0;
|
|
80
|
+
const manifests = await readManifests(input.registerDir);
|
|
81
|
+
let files;
|
|
82
|
+
try {
|
|
83
|
+
files = (await readdir(input.migrationsDir))
|
|
84
|
+
.filter((f) => f.endsWith(".sql") && !f.startsWith("_"))
|
|
85
|
+
.sort();
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
return { violations, scanned: 0 };
|
|
89
|
+
}
|
|
90
|
+
for (const f of files) {
|
|
91
|
+
const sql = await readFile(join(input.migrationsDir, f), "utf8");
|
|
92
|
+
const { createTables, addColumns } = parseSql(sql);
|
|
93
|
+
scanned += 1;
|
|
94
|
+
for (const table of createTables) {
|
|
95
|
+
const hasManifest = manifests.has(table);
|
|
96
|
+
const hasSnapshot = collectionSnapshotExists(input.snapshotDir, table);
|
|
97
|
+
if (!hasManifest && !hasSnapshot) {
|
|
98
|
+
violations.push({
|
|
99
|
+
kind: "table",
|
|
100
|
+
file: f,
|
|
101
|
+
table,
|
|
102
|
+
reason: `CREATE TABLE ${table} — needs migrations/register/${table}.json or directus_config/snapshot/collections/${table}.json`,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
for (const { table, column } of addColumns) {
|
|
107
|
+
// Manifest match: table is listed AND either fields[column] exists or
|
|
108
|
+
// fields is undefined (walk-all-unregistered mode).
|
|
109
|
+
const manifest = manifests.get(table);
|
|
110
|
+
const manifestCovers = !!manifest &&
|
|
111
|
+
(manifest.fields === undefined ||
|
|
112
|
+
Object.prototype.hasOwnProperty.call(manifest.fields, column));
|
|
113
|
+
if (manifestCovers)
|
|
114
|
+
continue;
|
|
115
|
+
const snapshotType = await fieldSnapshotType(input.snapshotDir, table, column);
|
|
116
|
+
if (snapshotType && snapshotType !== "unknown")
|
|
117
|
+
continue;
|
|
118
|
+
violations.push({
|
|
119
|
+
kind: "column",
|
|
120
|
+
file: f,
|
|
121
|
+
table,
|
|
122
|
+
column,
|
|
123
|
+
reason: snapshotType === "unknown"
|
|
124
|
+
? `${table}.${column} present in snapshot with type='unknown' — add migrations/register/${table}.json`
|
|
125
|
+
: `${table}.${column} — no manifest and no snapshot field definition`,
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return { violations, scanned };
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=lint.js.map
|
package/dist/lint.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lint.js","sourceRoot":"","sources":["../src/lint.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,37 @@
|
|
|
1
1
|
import { readdir, readFile } from "node:fs/promises";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
2
3
|
import { join, extname } from "node:path";
|
|
3
4
|
import { splitSql } from "../sql.js";
|
|
5
|
+
// Migration reconciler with a content-hash tracker table.
|
|
6
|
+
//
|
|
7
|
+
// Tracker shape:
|
|
8
|
+
//
|
|
9
|
+
// CREATE TABLE _directus_deploy_migrations (
|
|
10
|
+
// filename TEXT PRIMARY KEY,
|
|
11
|
+
// sha256 TEXT NOT NULL,
|
|
12
|
+
// applied_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
13
|
+
// )
|
|
14
|
+
//
|
|
15
|
+
// Per-file classification:
|
|
16
|
+
//
|
|
17
|
+
// filename absent from tracker → NEW (apply, then insert)
|
|
18
|
+
// filename present, hash matches → UNCHANGED (skip execution)
|
|
19
|
+
// filename present, hash differs → MUTATED (fail hard, don't touch DB)
|
|
20
|
+
//
|
|
21
|
+
// Bootstrap (see adoptMigrations): a fresh env whose migrations were applied
|
|
22
|
+
// via some prior mechanism needs a one-shot import that inserts each file's
|
|
23
|
+
// (name, hash) WITHOUT running the SQL. Prevents duplicate application.
|
|
24
|
+
//
|
|
25
|
+
// Uses Directus's /raw-query/execute endpoint. A missing endpoint yields a
|
|
26
|
+
// clean skip rather than N confusing errors.
|
|
27
|
+
const TRACKER_TABLE = "_directus_deploy_migrations";
|
|
28
|
+
const CREATE_TRACKER = `
|
|
29
|
+
CREATE TABLE IF NOT EXISTS ${TRACKER_TABLE} (
|
|
30
|
+
filename TEXT PRIMARY KEY,
|
|
31
|
+
sha256 TEXT NOT NULL,
|
|
32
|
+
applied_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
33
|
+
);
|
|
34
|
+
`;
|
|
4
35
|
async function rawQuery(client, sql) {
|
|
5
36
|
try {
|
|
6
37
|
const r = (await client.postRaw("/raw-query/execute", { query: sql }));
|
|
@@ -38,6 +69,59 @@ function stripLeadingComments(s) {
|
|
|
38
69
|
}
|
|
39
70
|
return s.slice(i);
|
|
40
71
|
}
|
|
72
|
+
function sha256(s) {
|
|
73
|
+
return createHash("sha256").update(s).digest("hex");
|
|
74
|
+
}
|
|
75
|
+
async function ensureTracker(client) {
|
|
76
|
+
const r = await rawQuery(client, CREATE_TRACKER);
|
|
77
|
+
return !!r?.success && !!r?.results?.[0]?.success;
|
|
78
|
+
}
|
|
79
|
+
async function fetchTracker(client) {
|
|
80
|
+
const r = await rawQuery(client, `SELECT filename, sha256 FROM ${TRACKER_TABLE}`);
|
|
81
|
+
if (r === null)
|
|
82
|
+
return null;
|
|
83
|
+
if (!r.success)
|
|
84
|
+
return null;
|
|
85
|
+
const first = r.results?.[0];
|
|
86
|
+
if (!first?.success)
|
|
87
|
+
return null;
|
|
88
|
+
const map = new Map();
|
|
89
|
+
for (const row of first.data ?? []) {
|
|
90
|
+
if (row && typeof row === "object" && "filename" in row && "sha256" in row) {
|
|
91
|
+
const rr = row;
|
|
92
|
+
map.set(String(rr.filename), String(rr.sha256));
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return map;
|
|
96
|
+
}
|
|
97
|
+
function sqlLiteral(s) {
|
|
98
|
+
return `'${s.replace(/'/g, "''")}'`;
|
|
99
|
+
}
|
|
100
|
+
async function insertTrackerRow(client, filename, hash) {
|
|
101
|
+
const r = await rawQuery(client, `INSERT INTO ${TRACKER_TABLE} (filename, sha256) VALUES (${sqlLiteral(filename)}, ${sqlLiteral(hash)}) ON CONFLICT (filename) DO NOTHING`);
|
|
102
|
+
const inner = r?.results?.[0];
|
|
103
|
+
if (!r?.success || !inner?.success) {
|
|
104
|
+
return { ok: false, reason: inner?.error ?? "tracker insert failed" };
|
|
105
|
+
}
|
|
106
|
+
return { ok: true };
|
|
107
|
+
}
|
|
108
|
+
async function readMigrationFiles(dir) {
|
|
109
|
+
let entries;
|
|
110
|
+
try {
|
|
111
|
+
entries = await readdir(dir);
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
return [];
|
|
115
|
+
}
|
|
116
|
+
const names = entries.filter((f) => extname(f) === ".sql" && !f.startsWith("_")).sort();
|
|
117
|
+
const out = [];
|
|
118
|
+
for (const filename of names) {
|
|
119
|
+
const path = join(dir, filename);
|
|
120
|
+
const raw = await readFile(path, "utf8");
|
|
121
|
+
out.push({ filename, path, raw, hash: sha256(raw) });
|
|
122
|
+
}
|
|
123
|
+
return out;
|
|
124
|
+
}
|
|
41
125
|
export async function reconcileMigrations(input) {
|
|
42
126
|
const results = [];
|
|
43
127
|
const probe = await rawQuery(input.client, "SELECT 1 AS ok");
|
|
@@ -50,28 +134,44 @@ export async function reconcileMigrations(input) {
|
|
|
50
134
|
});
|
|
51
135
|
return results;
|
|
52
136
|
}
|
|
53
|
-
|
|
54
|
-
try {
|
|
55
|
-
entries = await readdir(input.migrationsDir);
|
|
56
|
-
}
|
|
57
|
-
catch {
|
|
58
|
-
return results;
|
|
59
|
-
}
|
|
60
|
-
const files = entries.filter((f) => extname(f) === ".sql" && !f.startsWith("_")).sort();
|
|
137
|
+
const files = await readMigrationFiles(input.migrationsDir);
|
|
61
138
|
if (files.length === 0)
|
|
62
139
|
return results;
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
140
|
+
// Tracker create is a schema mutation → do it only outside dry-run. In
|
|
141
|
+
// dry-run, if the tracker is missing, treat everything as NEW (accurate).
|
|
142
|
+
if (!input.opts.dryRun) {
|
|
143
|
+
const ok = await ensureTracker(input.client);
|
|
144
|
+
if (!ok) {
|
|
145
|
+
results.push({
|
|
146
|
+
kind: "migrations",
|
|
147
|
+
label: `migrations/${TRACKER_TABLE}`,
|
|
148
|
+
action: "failed",
|
|
149
|
+
reason: "could not create tracker table",
|
|
150
|
+
});
|
|
151
|
+
return results;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
const tracker = (await fetchTracker(input.client)) ?? new Map();
|
|
155
|
+
for (const file of files) {
|
|
156
|
+
const label = `migrations/${file.filename}`;
|
|
157
|
+
const recordedHash = tracker.get(file.filename);
|
|
158
|
+
// UNCHANGED — already applied at this hash.
|
|
159
|
+
if (recordedHash === file.hash) {
|
|
160
|
+
results.push({ kind: "migrations", label, action: "unchanged" });
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
// MUTATED — recorded under a different hash. Never rewrite silently.
|
|
164
|
+
if (recordedHash !== undefined && recordedHash !== file.hash) {
|
|
165
|
+
results.push({
|
|
166
|
+
kind: "migrations",
|
|
167
|
+
label,
|
|
168
|
+
action: "failed",
|
|
169
|
+
reason: `content mismatch: tracker recorded sha256 ${recordedHash.slice(0, 12)}…, file now hashes to ${file.hash.slice(0, 12)}…. Migrations are immutable — add a new migration instead.`,
|
|
170
|
+
});
|
|
72
171
|
continue;
|
|
73
172
|
}
|
|
74
|
-
|
|
173
|
+
// NEW.
|
|
174
|
+
const statements = splitSql(file.raw).filter((s) => {
|
|
75
175
|
const stripped = stripLeadingComments(s.trim()).trim();
|
|
76
176
|
return stripped.length > 0 && stripped !== ";";
|
|
77
177
|
});
|
|
@@ -101,8 +201,94 @@ export async function reconcileMigrations(input) {
|
|
|
101
201
|
results.push({ kind: "migrations", label, action: "failed", reason: failedReason });
|
|
102
202
|
continue;
|
|
103
203
|
}
|
|
204
|
+
const rec = await insertTrackerRow(input.client, file.filename, file.hash);
|
|
205
|
+
if (!rec.ok) {
|
|
206
|
+
results.push({
|
|
207
|
+
kind: "migrations",
|
|
208
|
+
label,
|
|
209
|
+
action: "failed",
|
|
210
|
+
reason: `applied SQL but tracker insert failed: ${rec.reason}`,
|
|
211
|
+
});
|
|
212
|
+
continue;
|
|
213
|
+
}
|
|
104
214
|
results.push({ kind: "migrations", label, action: "created" });
|
|
105
215
|
}
|
|
106
216
|
return results;
|
|
107
217
|
}
|
|
218
|
+
// Bootstrap for envs whose migrations were applied via a prior mechanism.
|
|
219
|
+
// Inserts (filename, sha256) rows without executing any SQL. Idempotent:
|
|
220
|
+
// re-adopting is a no-op when hashes match. Fails on hash conflict, which
|
|
221
|
+
// tells the caller the file was edited since the target env applied it.
|
|
222
|
+
export async function adoptMigrations(input) {
|
|
223
|
+
const results = [];
|
|
224
|
+
const probe = await rawQuery(input.client, "SELECT 1 AS ok");
|
|
225
|
+
if (probe === null) {
|
|
226
|
+
results.push({
|
|
227
|
+
kind: "migrations",
|
|
228
|
+
label: "migrations",
|
|
229
|
+
action: "skipped",
|
|
230
|
+
reason: "/raw-query/execute not available on this target",
|
|
231
|
+
});
|
|
232
|
+
return results;
|
|
233
|
+
}
|
|
234
|
+
const files = await readMigrationFiles(input.migrationsDir);
|
|
235
|
+
if (files.length === 0)
|
|
236
|
+
return results;
|
|
237
|
+
if (!input.opts.dryRun) {
|
|
238
|
+
const ok = await ensureTracker(input.client);
|
|
239
|
+
if (!ok) {
|
|
240
|
+
results.push({
|
|
241
|
+
kind: "migrations",
|
|
242
|
+
label: `migrations/${TRACKER_TABLE}`,
|
|
243
|
+
action: "failed",
|
|
244
|
+
reason: "could not create tracker table",
|
|
245
|
+
});
|
|
246
|
+
return results;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
const tracker = (await fetchTracker(input.client)) ?? new Map();
|
|
250
|
+
for (const file of files) {
|
|
251
|
+
const label = `migrations/${file.filename}`;
|
|
252
|
+
const recordedHash = tracker.get(file.filename);
|
|
253
|
+
if (recordedHash === file.hash) {
|
|
254
|
+
results.push({ kind: "migrations", label, action: "unchanged" });
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
257
|
+
if (recordedHash !== undefined) {
|
|
258
|
+
results.push({
|
|
259
|
+
kind: "migrations",
|
|
260
|
+
label,
|
|
261
|
+
action: "failed",
|
|
262
|
+
reason: `already adopted with sha256 ${recordedHash.slice(0, 12)}…, refusing to overwrite with ${file.hash.slice(0, 12)}…`,
|
|
263
|
+
});
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
if (input.opts.dryRun) {
|
|
267
|
+
results.push({
|
|
268
|
+
kind: "migrations",
|
|
269
|
+
label,
|
|
270
|
+
action: "created",
|
|
271
|
+
reason: `would adopt (sha256 ${file.hash.slice(0, 12)}…)`,
|
|
272
|
+
});
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
275
|
+
const rec = await insertTrackerRow(input.client, file.filename, file.hash);
|
|
276
|
+
if (!rec.ok) {
|
|
277
|
+
results.push({
|
|
278
|
+
kind: "migrations",
|
|
279
|
+
label,
|
|
280
|
+
action: "failed",
|
|
281
|
+
reason: rec.reason,
|
|
282
|
+
});
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
results.push({
|
|
286
|
+
kind: "migrations",
|
|
287
|
+
label,
|
|
288
|
+
action: "created",
|
|
289
|
+
reason: `adopted (sha256 ${file.hash.slice(0, 12)}…)`,
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
return results;
|
|
293
|
+
}
|
|
108
294
|
//# sourceMappingURL=migrations.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"migrations.js","sourceRoot":"","sources":["../../src/reconcilers/migrations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"migrations.js","sourceRoot":"","sources":["../../src/reconcilers/migrations.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "directus-deploy-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Per-entity, non-atomic Directus deployment tool. Reconciles collections/fields/relations/roles/policies/permissions/flows/operations/migrations/seeds from git to any environment.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|