@intentius/sql-yodeler 0.2.0 → 0.3.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/README.md +3 -3
- package/dist/chant/build.js +7 -0
- package/dist/chant/build.js.map +1 -1
- package/dist/ci/render.d.ts +289 -0
- package/dist/ci/render.js +688 -0
- package/dist/ci/render.js.map +1 -0
- package/dist/ci/replay.d.ts +17 -0
- package/dist/ci/replay.js +69 -0
- package/dist/ci/replay.js.map +1 -0
- package/dist/commands/apply.d.ts +113 -0
- package/dist/commands/apply.js +228 -21
- package/dist/commands/apply.js.map +1 -1
- package/dist/commands/approve.js +44 -0
- package/dist/commands/approve.js.map +1 -1
- package/dist/commands/checkpoint.d.ts +3 -0
- package/dist/commands/checkpoint.js +78 -0
- package/dist/commands/checkpoint.js.map +1 -0
- package/dist/commands/ci.d.ts +3 -0
- package/dist/commands/ci.js +118 -0
- package/dist/commands/ci.js.map +1 -0
- package/dist/commands/docs.d.ts +11 -0
- package/dist/commands/docs.js +108 -0
- package/dist/commands/docs.js.map +1 -0
- package/dist/commands/drift.d.ts +13 -1
- package/dist/commands/drift.js +18 -2
- package/dist/commands/drift.js.map +1 -1
- package/dist/commands/index.js +10 -0
- package/dist/commands/index.js.map +1 -1
- package/dist/commands/init.js +1 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/lint.js +11 -3
- package/dist/commands/lint.js.map +1 -1
- package/dist/commands/override.js +48 -16
- package/dist/commands/override.js.map +1 -1
- package/dist/commands/plan.js +5 -1
- package/dist/commands/plan.js.map +1 -1
- package/dist/commands/report.d.ts +13 -0
- package/dist/commands/report.js +121 -0
- package/dist/commands/report.js.map +1 -0
- package/dist/commands/revert.d.ts +20 -0
- package/dist/commands/revert.js +246 -0
- package/dist/commands/revert.js.map +1 -0
- package/dist/commands/status.js +32 -5
- package/dist/commands/status.js.map +1 -1
- package/dist/config/base.d.ts +69 -0
- package/dist/config/base.js +121 -0
- package/dist/config/base.js.map +1 -0
- package/dist/config/define.d.ts +123 -1
- package/dist/config/define.js +2 -0
- package/dist/config/define.js.map +1 -1
- package/dist/config/index.d.ts +2 -0
- package/dist/config/index.js +2 -0
- package/dist/config/index.js.map +1 -1
- package/dist/config/load.d.ts +1 -1
- package/dist/config/load.js +90 -5
- package/dist/config/load.js.map +1 -1
- package/dist/config/settings.d.ts +4 -1
- package/dist/config/settings.js +8 -2
- package/dist/config/settings.js.map +1 -1
- package/dist/exit.js +1 -1
- package/dist/exit.js.map +1 -1
- package/dist/history/postgres/ddl.d.ts +18 -0
- package/dist/history/postgres/ddl.js +27 -2
- package/dist/history/postgres/ddl.js.map +1 -1
- package/dist/history/postgres/store.d.ts +2 -0
- package/dist/history/postgres/store.js +7 -1
- package/dist/history/postgres/store.js.map +1 -1
- package/dist/history/rows.d.ts +16 -3
- package/dist/history/rows.js +30 -1
- package/dist/history/rows.js.map +1 -1
- package/dist/history/store.d.ts +2 -0
- package/dist/history/store.js +2 -2
- package/dist/history/store.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lint/check.js +17 -2
- package/dist/lint/check.js.map +1 -1
- package/dist/lint/report.js +1 -1
- package/dist/lint/report.js.map +1 -1
- package/dist/lint/routines.d.ts +26 -0
- package/dist/lint/routines.js +65 -0
- package/dist/lint/routines.js.map +1 -0
- package/dist/lint/rules.d.ts +16 -4
- package/dist/lint/rules.js +9 -4
- package/dist/lint/rules.js.map +1 -1
- package/dist/mcp/tools.d.ts +1 -1
- package/dist/mcp/tools.js +1 -1
- package/dist/mcp/tools.js.map +1 -1
- package/dist/migrations/checkpoint.d.ts +45 -0
- package/dist/migrations/checkpoint.js +110 -0
- package/dist/migrations/checkpoint.js.map +1 -0
- package/dist/migrations/create.js +2 -0
- package/dist/migrations/create.js.map +1 -1
- package/dist/migrations/document.d.ts +10 -0
- package/dist/migrations/document.js +1 -0
- package/dist/migrations/document.js.map +1 -1
- package/dist/migrations/index.d.ts +2 -0
- package/dist/migrations/index.js +2 -0
- package/dist/migrations/index.js.map +1 -1
- package/dist/migrations/routines.d.ts +31 -0
- package/dist/migrations/routines.js +55 -0
- package/dist/migrations/routines.js.map +1 -0
- package/dist/notify/index.d.ts +124 -0
- package/dist/notify/index.js +210 -0
- package/dist/notify/index.js.map +1 -0
- package/dist/notify/verify.d.ts +53 -0
- package/dist/notify/verify.js +71 -0
- package/dist/notify/verify.js.map +1 -0
- package/dist/pr/model.d.ts +3 -0
- package/dist/pr/model.js +16 -2
- package/dist/pr/model.js.map +1 -1
- package/dist/pr/render.js +27 -1
- package/dist/pr/render.js.map +1 -1
- package/dist/project.d.ts +19 -2
- package/dist/project.js +33 -1
- package/dist/project.js.map +1 -1
- package/dist/replay/replay.d.ts +9 -1
- package/dist/replay/replay.js +62 -31
- package/dist/replay/replay.js.map +1 -1
- package/dist/replay/report.js +1 -1
- package/dist/replay/report.js.map +1 -1
- package/dist/report/audit.d.ts +138 -0
- package/dist/report/audit.js +202 -0
- package/dist/report/audit.js.map +1 -0
- package/dist/report/jsonl.d.ts +21 -0
- package/dist/report/jsonl.js +52 -0
- package/dist/report/jsonl.js.map +1 -0
- package/dist/report/model.d.ts +68 -0
- package/dist/report/model.js +127 -0
- package/dist/report/model.js.map +1 -0
- package/dist/report/render.d.ts +18 -0
- package/dist/report/render.js +127 -0
- package/dist/report/render.js.map +1 -0
- package/dist/schema-docs/render.d.ts +49 -0
- package/dist/schema-docs/render.js +359 -0
- package/dist/schema-docs/render.js.map +1 -0
- package/dist/schemas.d.ts +5 -2
- package/dist/schemas.js +5 -2
- package/dist/schemas.js.map +1 -1
- package/dist/sources/ddl.d.ts +53 -0
- package/dist/sources/ddl.js +347 -0
- package/dist/sources/ddl.js.map +1 -0
- package/dist/sources/index.d.ts +69 -0
- package/dist/sources/index.js +170 -0
- package/dist/sources/index.js.map +1 -0
- package/dist/steps/postgres-migration.d.ts +35 -25
- package/dist/steps/postgres-migration.js +42 -29
- package/dist/steps/postgres-migration.js.map +1 -1
- package/dist/tenants/index.d.ts +40 -0
- package/dist/tenants/index.js +122 -0
- package/dist/tenants/index.js.map +1 -0
- package/dist/tenants/target.d.ts +23 -0
- package/dist/tenants/target.js +29 -0
- package/dist/tenants/target.js.map +1 -0
- package/dist/versioned/engine.d.ts +6 -0
- package/dist/versioned/engine.js +12 -2
- package/dist/versioned/engine.js.map +1 -1
- package/dist/versioned/index.d.ts +1 -0
- package/dist/versioned/index.js +1 -0
- package/dist/versioned/index.js.map +1 -1
- package/dist/versioned/op.d.ts +6 -1
- package/dist/versioned/op.js +7 -2
- package/dist/versioned/op.js.map +1 -1
- package/dist/versioned/policy.d.ts +33 -2
- package/dist/versioned/policy.js +59 -8
- package/dist/versioned/policy.js.map +1 -1
- package/dist/versioned/report.js +9 -0
- package/dist/versioned/report.js.map +1 -1
- package/dist/versioned/revert.d.ts +128 -0
- package/dist/versioned/revert.js +251 -0
- package/dist/versioned/revert.js.map +1 -0
- package/dist/versioned/state.d.ts +25 -0
- package/dist/versioned/state.js +36 -3
- package/dist/versioned/state.js.map +1 -1
- package/dist/waves/index.d.ts +179 -0
- package/dist/waves/index.js +268 -0
- package/dist/waves/index.js.map +1 -0
- package/dist/waves/promotion.d.ts +56 -0
- package/dist/waves/promotion.js +108 -0
- package/dist/waves/promotion.js.map +1 -0
- package/dist/waves/record.d.ts +24 -0
- package/dist/waves/record.js +20 -0
- package/dist/waves/record.js.map +1 -0
- package/package.json +11 -7
- package/schemas/apply.schema.json +162 -3
- package/schemas/checkpoint.schema.json +19 -0
- package/schemas/drift.schema.json +26 -1
- package/schemas/event.schema.json +36 -0
- package/schemas/lint.schema.json +4 -0
- package/schemas/plan.schema.json +118 -0
- package/schemas/report.schema.json +114 -0
- package/schemas/revert.schema.json +69 -0
- package/schemas/status.schema.json +64 -3
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** A wave's decision as the history records it (#87). Pure, for ../report/audit.ts. */
|
|
2
|
+
/** The pipeline's name, and the op chant records the wave gates under. */
|
|
3
|
+
export declare const WAVES_PIPELINE = "yodel-apply";
|
|
4
|
+
/**
|
|
5
|
+
* What a wave's apply records of chant's decision, in each migration's
|
|
6
|
+
* `started` history row (`note.wave`): the gate and the set digest it was
|
|
7
|
+
* let through on, so `yodel report` finds the approval on the wave's gate
|
|
8
|
+
* (`<op>-wave-<k>`) and not the migrations Op's, and knows a wave whose
|
|
9
|
+
* policy at the base needed none.
|
|
10
|
+
*/
|
|
11
|
+
export interface WaveRecord {
|
|
12
|
+
wave: number;
|
|
13
|
+
/** chant's op the wave gates are recorded under (the spec's name), and the wave's gate. */
|
|
14
|
+
op: string;
|
|
15
|
+
gate: string;
|
|
16
|
+
/** The wave's set digest. */
|
|
17
|
+
digest: string;
|
|
18
|
+
status: "approved" | "not-required";
|
|
19
|
+
/** For `not-required`: the policy and the commit it was read at. */
|
|
20
|
+
policy?: string;
|
|
21
|
+
base?: string;
|
|
22
|
+
}
|
|
23
|
+
/** Reads `note.wave` from a history row's note, or undefined. */
|
|
24
|
+
export declare function waveRecordOf(note: string): WaveRecord | undefined;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** A wave's decision as the history records it (#87). Pure, for ../report/audit.ts. */
|
|
2
|
+
/** The pipeline's name, and the op chant records the wave gates under. */
|
|
3
|
+
export const WAVES_PIPELINE = "yodel-apply";
|
|
4
|
+
/** Reads `note.wave` from a history row's note, or undefined. */
|
|
5
|
+
export function waveRecordOf(note) {
|
|
6
|
+
if (!note.startsWith("{"))
|
|
7
|
+
return undefined;
|
|
8
|
+
try {
|
|
9
|
+
const w = JSON.parse(note).wave;
|
|
10
|
+
if (!w || typeof w.gate !== "string" || typeof w.digest !== "string" || typeof w.op !== "string")
|
|
11
|
+
return undefined;
|
|
12
|
+
if (w.status !== "approved" && w.status !== "not-required")
|
|
13
|
+
return undefined;
|
|
14
|
+
return w;
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=record.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"record.js","sourceRoot":"","sources":["../../src/waves/record.ts"],"names":[],"mappings":"AAAA,uFAAuF;AAEvF,0EAA0E;AAC1E,MAAM,CAAC,MAAM,cAAc,GAAG,aAAa,CAAC;AAsB5C,iEAAiE;AACjE,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,SAAS,CAAC;IAC5C,IAAI,CAAC;QACH,MAAM,CAAC,GAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAoC,CAAC,IAAI,CAAC;QACpE,IAAI,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ;YAAE,OAAO,SAAS,CAAC;QACnH,IAAI,CAAC,CAAC,MAAM,KAAK,UAAU,IAAI,CAAC,CAAC,MAAM,KAAK,cAAc;YAAE,OAAO,SAAS,CAAC;QAC7E,OAAO,CAAe,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intentius/sql-yodeler",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Schema management and migrations for ClickHouse and Postgres, on chant's sql lexicon",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -12,6 +12,10 @@
|
|
|
12
12
|
".": {
|
|
13
13
|
"types": "./dist/index.d.ts",
|
|
14
14
|
"default": "./dist/index.js"
|
|
15
|
+
},
|
|
16
|
+
"./webhook": {
|
|
17
|
+
"types": "./dist/notify/verify.d.ts",
|
|
18
|
+
"default": "./dist/notify/verify.js"
|
|
15
19
|
}
|
|
16
20
|
},
|
|
17
21
|
"bin": {
|
|
@@ -41,16 +45,16 @@
|
|
|
41
45
|
"bench": "npm run build && tsx bench/run.ts"
|
|
42
46
|
},
|
|
43
47
|
"dependencies": {
|
|
44
|
-
"@intentius/chant": "^0.
|
|
45
|
-
"@intentius/chant-lexicon-
|
|
48
|
+
"@intentius/chant": "^0.117.0",
|
|
49
|
+
"@intentius/chant-lexicon-forgejo": "^0.117.0",
|
|
50
|
+
"@intentius/chant-lexicon-github": "^0.117.0",
|
|
51
|
+
"@intentius/chant-lexicon-gitlab": "^0.117.0",
|
|
52
|
+
"@intentius/chant-lexicon-sql": "^0.117.0",
|
|
46
53
|
"tsx": "^4.23.15"
|
|
47
54
|
},
|
|
48
55
|
"devDependencies": {
|
|
49
56
|
"@eslint/js": "^10.0.1",
|
|
50
|
-
"@intentius/chant-lexicon-docker": "^0.
|
|
51
|
-
"@intentius/chant-lexicon-forgejo": "^0.115.0",
|
|
52
|
-
"@intentius/chant-lexicon-github": "^0.115.0",
|
|
53
|
-
"@intentius/chant-lexicon-gitlab": "^0.115.0",
|
|
57
|
+
"@intentius/chant-lexicon-docker": "^0.117.0",
|
|
54
58
|
"@types/node": "^22.20.5",
|
|
55
59
|
"@types/pg": "^8.23.1",
|
|
56
60
|
"ajv": "^8.20.0",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://intentius.io/sql-yodeler/schemas/v1/apply.schema.json",
|
|
4
4
|
"title": "yodel apply <env> --json",
|
|
5
|
-
"description": "Version 1. On a project with migrations, the status (status.schema.json) with mode \"versioned\" and what apply did; with --execute (the migrations Op's Apply step), what the step applied; on a project without migrations, the declarative outcome with chant's plan. Within a version, fields are only added; a reader ignores fields it does not know.",
|
|
5
|
+
"description": "Version 1. On a project with migrations, the status (status.schema.json) with mode \"versioned\" and what apply did; with --execute (the migrations Op's Apply step) or --wave-apply (a wave job's apply), what the step applied; with --wave-plan, the wave plan it wrote; on a project without migrations, the declarative outcome with chant's plan. Within a version, fields are only added; a reader ignores fields it does not know.",
|
|
6
6
|
"oneOf": [
|
|
7
7
|
{
|
|
8
8
|
"$ref": "#/$defs/versioned"
|
|
@@ -10,6 +10,9 @@
|
|
|
10
10
|
{
|
|
11
11
|
"$ref": "#/$defs/execute"
|
|
12
12
|
},
|
|
13
|
+
{
|
|
14
|
+
"$ref": "#/$defs/wavePlan"
|
|
15
|
+
},
|
|
13
16
|
{
|
|
14
17
|
"$ref": "#/$defs/declarative"
|
|
15
18
|
}
|
|
@@ -35,6 +38,27 @@
|
|
|
35
38
|
},
|
|
36
39
|
"notice": {
|
|
37
40
|
"type": "string"
|
|
41
|
+
},
|
|
42
|
+
"waited": {
|
|
43
|
+
"description": "The run waited for another apply's lock (--lock-wait): for how long, who held it when the run first found it held, and where.",
|
|
44
|
+
"type": "object",
|
|
45
|
+
"additionalProperties": false,
|
|
46
|
+
"required": [
|
|
47
|
+
"ms",
|
|
48
|
+
"heldBy",
|
|
49
|
+
"where"
|
|
50
|
+
],
|
|
51
|
+
"properties": {
|
|
52
|
+
"ms": {
|
|
53
|
+
"type": "integer"
|
|
54
|
+
},
|
|
55
|
+
"heldBy": {
|
|
56
|
+
"type": "string"
|
|
57
|
+
},
|
|
58
|
+
"where": {
|
|
59
|
+
"type": "string"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
38
62
|
}
|
|
39
63
|
}
|
|
40
64
|
},
|
|
@@ -51,17 +75,22 @@
|
|
|
51
75
|
"const": "versioned"
|
|
52
76
|
},
|
|
53
77
|
"status": {
|
|
54
|
-
"description": "planned (--plan, something pending), unchanged, refused, denied (a policy rule denies the plan, with no override), gated (waiting at the Op's gate for a person's approval), failed, applied.",
|
|
78
|
+
"description": "planned (--plan, something pending), unchanged, refused, denied (a policy rule denies the plan, with no override), stood-down (--stand-down: a newer commit's apply applies this environment, so this one applied nothing), gated (waiting at the Op's gate for a person's approval), failed, applied.",
|
|
55
79
|
"enum": [
|
|
56
80
|
"planned",
|
|
57
81
|
"unchanged",
|
|
58
82
|
"refused",
|
|
59
83
|
"denied",
|
|
84
|
+
"stood-down",
|
|
60
85
|
"gated",
|
|
61
86
|
"failed",
|
|
62
87
|
"applied"
|
|
63
88
|
]
|
|
64
89
|
},
|
|
90
|
+
"stoodDown": {
|
|
91
|
+
"description": "stood-down: why, in one line.",
|
|
92
|
+
"type": "string"
|
|
93
|
+
},
|
|
65
94
|
"preChecks": {
|
|
66
95
|
"description": "The first pending migration's checks, when one failed before the gate.",
|
|
67
96
|
"type": "object",
|
|
@@ -173,7 +202,15 @@
|
|
|
173
202
|
"type": "string"
|
|
174
203
|
},
|
|
175
204
|
"status": {
|
|
176
|
-
"
|
|
205
|
+
"description": "applied, or stood-down (--stand-down: a newer commit came while the step waited for the lock, and it applied nothing).",
|
|
206
|
+
"enum": [
|
|
207
|
+
"applied",
|
|
208
|
+
"stood-down"
|
|
209
|
+
]
|
|
210
|
+
},
|
|
211
|
+
"stoodDown": {
|
|
212
|
+
"description": "stood-down: why, in one line.",
|
|
213
|
+
"type": "string"
|
|
177
214
|
},
|
|
178
215
|
"planDigest": {
|
|
179
216
|
"description": "The digest the gate approved.",
|
|
@@ -204,6 +241,10 @@
|
|
|
204
241
|
},
|
|
205
242
|
"lock": {
|
|
206
243
|
"$ref": "#/$defs/lock"
|
|
244
|
+
},
|
|
245
|
+
"wavePlanDigest": {
|
|
246
|
+
"description": "--wave-apply: the wave plan digest chant's wave decision named.",
|
|
247
|
+
"type": "string"
|
|
207
248
|
}
|
|
208
249
|
}
|
|
209
250
|
},
|
|
@@ -264,6 +305,124 @@
|
|
|
264
305
|
"$ref": "plan.schema.json#/$defs/declarative"
|
|
265
306
|
}
|
|
266
307
|
}
|
|
308
|
+
},
|
|
309
|
+
"wavePlan": {
|
|
310
|
+
"description": "--wave-plan: the plan file chant run wave reads, as written.",
|
|
311
|
+
"type": "object",
|
|
312
|
+
"additionalProperties": false,
|
|
313
|
+
"required": [
|
|
314
|
+
"planDigest",
|
|
315
|
+
"destructive",
|
|
316
|
+
"empty",
|
|
317
|
+
"environment",
|
|
318
|
+
"migrations",
|
|
319
|
+
"gate",
|
|
320
|
+
"base",
|
|
321
|
+
"pending",
|
|
322
|
+
"destructiveSteps",
|
|
323
|
+
"requires"
|
|
324
|
+
],
|
|
325
|
+
"properties": {
|
|
326
|
+
"planDigest": {
|
|
327
|
+
"description": "The wave plan digest: over the migrations' digest, the gate policy at the base commit and whether a pending step is destructive.",
|
|
328
|
+
"type": "string"
|
|
329
|
+
},
|
|
330
|
+
"destructive": {
|
|
331
|
+
"type": "boolean"
|
|
332
|
+
},
|
|
333
|
+
"empty": {
|
|
334
|
+
"description": "Nothing is pending.",
|
|
335
|
+
"type": "boolean"
|
|
336
|
+
},
|
|
337
|
+
"environment": {
|
|
338
|
+
"type": "string"
|
|
339
|
+
},
|
|
340
|
+
"migrations": {
|
|
341
|
+
"description": "The migrations' plan digest, as yodel apply --digest prints it.",
|
|
342
|
+
"type": "string"
|
|
343
|
+
},
|
|
344
|
+
"gate": {
|
|
345
|
+
"enum": [
|
|
346
|
+
"always",
|
|
347
|
+
"on-destructive",
|
|
348
|
+
"never"
|
|
349
|
+
]
|
|
350
|
+
},
|
|
351
|
+
"base": {
|
|
352
|
+
"description": "The base commit the gate was read at.",
|
|
353
|
+
"type": "string"
|
|
354
|
+
},
|
|
355
|
+
"pending": {
|
|
356
|
+
"$ref": "common.schema.json#/$defs/stringList"
|
|
357
|
+
},
|
|
358
|
+
"destructiveSteps": {
|
|
359
|
+
"type": "array",
|
|
360
|
+
"items": {
|
|
361
|
+
"$ref": "#/$defs/destructiveStep"
|
|
362
|
+
}
|
|
363
|
+
},
|
|
364
|
+
"requires": {
|
|
365
|
+
"description": "Each environment this one requires, and the pending migrations its history records applied; part of the plan digest.",
|
|
366
|
+
"type": "array",
|
|
367
|
+
"items": {
|
|
368
|
+
"type": "object",
|
|
369
|
+
"additionalProperties": false,
|
|
370
|
+
"required": [
|
|
371
|
+
"env",
|
|
372
|
+
"applied"
|
|
373
|
+
],
|
|
374
|
+
"properties": {
|
|
375
|
+
"env": {
|
|
376
|
+
"type": "string"
|
|
377
|
+
},
|
|
378
|
+
"applied": {
|
|
379
|
+
"type": "array",
|
|
380
|
+
"items": {
|
|
381
|
+
"type": "object",
|
|
382
|
+
"additionalProperties": false,
|
|
383
|
+
"required": [
|
|
384
|
+
"id",
|
|
385
|
+
"checksum"
|
|
386
|
+
],
|
|
387
|
+
"properties": {
|
|
388
|
+
"id": {
|
|
389
|
+
"type": "string"
|
|
390
|
+
},
|
|
391
|
+
"checksum": {
|
|
392
|
+
"type": "string"
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
},
|
|
402
|
+
"destructiveStep": {
|
|
403
|
+
"type": "object",
|
|
404
|
+
"additionalProperties": false,
|
|
405
|
+
"required": [
|
|
406
|
+
"migration",
|
|
407
|
+
"step",
|
|
408
|
+
"what",
|
|
409
|
+
"why"
|
|
410
|
+
],
|
|
411
|
+
"properties": {
|
|
412
|
+
"migration": {
|
|
413
|
+
"type": "string"
|
|
414
|
+
},
|
|
415
|
+
"step": {
|
|
416
|
+
"type": "integer"
|
|
417
|
+
},
|
|
418
|
+
"what": {
|
|
419
|
+
"type": "string"
|
|
420
|
+
},
|
|
421
|
+
"why": {
|
|
422
|
+
"description": "The lint rules that class it (destructive, pg-rewrite, pg-lock, ch-mutation, ch-rebuild), or op-step, manual-step.",
|
|
423
|
+
"type": "string"
|
|
424
|
+
}
|
|
425
|
+
}
|
|
267
426
|
}
|
|
268
427
|
}
|
|
269
428
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://intentius.io/sql-yodeler/schemas/v1/checkpoint.schema.json",
|
|
4
|
+
"title": "yodel checkpoint <name> --json",
|
|
5
|
+
"description": "Version 1. The checkpoint written: its id and directory, the migration whose recorded schema it creates (its parent), its checksum, how many statements it holds, and the SHA-256 of the recorded schema it was written from. Within a version, fields are only added; a reader ignores fields it does not know.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": ["written", "id", "path", "parent", "checksum", "dialect", "statements", "schema"],
|
|
9
|
+
"properties": {
|
|
10
|
+
"written": { "const": true },
|
|
11
|
+
"id": { "type": "string" },
|
|
12
|
+
"path": { "type": "string" },
|
|
13
|
+
"parent": { "type": "string" },
|
|
14
|
+
"checksum": { "type": "string" },
|
|
15
|
+
"dialect": { "$ref": "common.schema.json#/$defs/dialect" },
|
|
16
|
+
"statements": { "type": "integer", "minimum": 1 },
|
|
17
|
+
"schema": { "type": "string" }
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -31,6 +31,31 @@
|
|
|
31
31
|
"type": "object",
|
|
32
32
|
"additionalProperties": { "$ref": "common.schema.json#/$defs/stringList" }
|
|
33
33
|
},
|
|
34
|
-
"
|
|
34
|
+
"against": {
|
|
35
|
+
"description": "What the server was compared with: src, the project's declarations; or history, the schema the newest applied migration records (migration null when none is applied yet).",
|
|
36
|
+
"oneOf": [
|
|
37
|
+
{ "type": "object", "additionalProperties": false, "required": ["source"], "properties": { "source": { "const": "src" } } },
|
|
38
|
+
{
|
|
39
|
+
"type": "object",
|
|
40
|
+
"additionalProperties": false,
|
|
41
|
+
"required": ["source", "migration"],
|
|
42
|
+
"properties": { "source": { "const": "history" }, "migration": { "type": ["string", "null"] } }
|
|
43
|
+
}
|
|
44
|
+
]
|
|
45
|
+
},
|
|
46
|
+
"drifted": { "description": "A declared object changed or is gone: the command exits 2.", "type": "boolean" },
|
|
47
|
+
"fingerprint": { "description": "A hash of the environment and what drifted: the same for the same drift, run after run.", "type": "string" },
|
|
48
|
+
"issue": {
|
|
49
|
+
"description": "--issue: what yodel did with the environment's tracking issue, and the issue when there is one.",
|
|
50
|
+
"type": "object",
|
|
51
|
+
"additionalProperties": false,
|
|
52
|
+
"required": ["action"],
|
|
53
|
+
"properties": {
|
|
54
|
+
"action": { "enum": ["opened", "updated", "unchanged", "closed", "left", "none"] },
|
|
55
|
+
"number": { "type": "integer" },
|
|
56
|
+
"url": { "type": "string" }
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"issueError": { "description": "--issue: the tracking issue could not be written, and why.", "type": "string" }
|
|
35
60
|
}
|
|
36
61
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://intentius.io/sql-yodeler/schemas/v1/event.schema.json",
|
|
4
|
+
"title": "a yodel webhook event",
|
|
5
|
+
"description": "Version 1. The body yodel apply, yodel plan and yodel drift post to the webhook yodel.config.ts notify names, signed with HMAC-SHA256 over '<x-yodel-timestamp>.<body>' in the x-yodel-signature header. Within a version, fields are only added; a receiver ignores fields it does not know.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": ["version", "id", "event", "at", "environment", "command", "status", "summary", "migrations"],
|
|
9
|
+
"properties": {
|
|
10
|
+
"version": { "const": 1 },
|
|
11
|
+
"id": { "type": "string", "description": "Unique per event; also the x-yodel-delivery header." },
|
|
12
|
+
"event": { "enum": ["waiting", "refused", "failed", "drift"] },
|
|
13
|
+
"at": { "type": "string", "format": "date-time" },
|
|
14
|
+
"environment": { "type": "string" },
|
|
15
|
+
"command": { "enum": ["apply", "plan", "drift"] },
|
|
16
|
+
"status": { "type": "string", "description": "The command's own word for the outcome: gated, refused, denied, failed, incomplete, drifted." },
|
|
17
|
+
"summary": { "type": "string" },
|
|
18
|
+
"migrations": { "type": "array", "items": { "type": "string" }, "description": "The pending migrations, for apply and plan." },
|
|
19
|
+
"digest": { "type": "string", "description": "The plan digest the run computed." },
|
|
20
|
+
"approve": { "type": "string", "description": "On waiting: the command that approves the plan." },
|
|
21
|
+
"reason": { "type": "string" },
|
|
22
|
+
"drift": {
|
|
23
|
+
"type": "object",
|
|
24
|
+
"additionalProperties": false,
|
|
25
|
+
"required": ["changed", "missing"],
|
|
26
|
+
"properties": {
|
|
27
|
+
"changed": { "type": "array", "items": { "type": "string" } },
|
|
28
|
+
"missing": { "type": "array", "items": { "type": "string" } },
|
|
29
|
+
"fingerprint": { "type": "string", "description": "The same drift has the same fingerprint run after run, so a receiver can tell a repeat from new drift." }
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"runUrl": { "type": "string" },
|
|
33
|
+
"repository": { "type": "string" },
|
|
34
|
+
"commit": { "type": "string" }
|
|
35
|
+
}
|
|
36
|
+
}
|
package/schemas/lint.schema.json
CHANGED
package/schemas/plan.schema.json
CHANGED
|
@@ -341,6 +341,124 @@
|
|
|
341
341
|
"description": "The project declares no migrations Op for the environment: the first line of how to declare one.",
|
|
342
342
|
"type": "string"
|
|
343
343
|
},
|
|
344
|
+
"wave": {
|
|
345
|
+
"description": "The environment's wave of the apply pipeline, when yodel.config.ts declares waves and names it.",
|
|
346
|
+
"type": "object",
|
|
347
|
+
"additionalProperties": false,
|
|
348
|
+
"required": [
|
|
349
|
+
"wave",
|
|
350
|
+
"gate",
|
|
351
|
+
"base",
|
|
352
|
+
"baseSource",
|
|
353
|
+
"destructiveSteps",
|
|
354
|
+
"waits",
|
|
355
|
+
"planDigest",
|
|
356
|
+
"digest",
|
|
357
|
+
"approve",
|
|
358
|
+
"promotions",
|
|
359
|
+
"blocked"
|
|
360
|
+
],
|
|
361
|
+
"properties": {
|
|
362
|
+
"wave": {
|
|
363
|
+
"description": "1-based, in yodel.config.ts waves.",
|
|
364
|
+
"type": "integer",
|
|
365
|
+
"minimum": 1
|
|
366
|
+
},
|
|
367
|
+
"gate": {
|
|
368
|
+
"description": "The gate policy at the base commit.",
|
|
369
|
+
"enum": [
|
|
370
|
+
"always",
|
|
371
|
+
"on-destructive",
|
|
372
|
+
"never"
|
|
373
|
+
]
|
|
374
|
+
},
|
|
375
|
+
"base": {
|
|
376
|
+
"type": "string"
|
|
377
|
+
},
|
|
378
|
+
"baseSource": {
|
|
379
|
+
"type": "string"
|
|
380
|
+
},
|
|
381
|
+
"destructiveSteps": {
|
|
382
|
+
"type": "array",
|
|
383
|
+
"items": {
|
|
384
|
+
"$ref": "apply.schema.json#/$defs/destructiveStep"
|
|
385
|
+
}
|
|
386
|
+
},
|
|
387
|
+
"waits": {
|
|
388
|
+
"description": "Under that gate, the wave waits for an approval of this plan.",
|
|
389
|
+
"type": "boolean"
|
|
390
|
+
},
|
|
391
|
+
"planDigest": {
|
|
392
|
+
"description": "The wave plan digest.",
|
|
393
|
+
"type": "string"
|
|
394
|
+
},
|
|
395
|
+
"digest": {
|
|
396
|
+
"description": "The set digest the wave's gate binds.",
|
|
397
|
+
"type": "string"
|
|
398
|
+
},
|
|
399
|
+
"approve": {
|
|
400
|
+
"description": "The chant approve command for the wave, for a person to run.",
|
|
401
|
+
"type": "string"
|
|
402
|
+
},
|
|
403
|
+
"promotions": {
|
|
404
|
+
"description": "Each environment this one requires (waves[].requires) and what its history records of each pending migration.",
|
|
405
|
+
"type": "array",
|
|
406
|
+
"items": {
|
|
407
|
+
"type": "object",
|
|
408
|
+
"additionalProperties": false,
|
|
409
|
+
"required": [
|
|
410
|
+
"env",
|
|
411
|
+
"from",
|
|
412
|
+
"migrations"
|
|
413
|
+
],
|
|
414
|
+
"properties": {
|
|
415
|
+
"env": {
|
|
416
|
+
"type": "string"
|
|
417
|
+
},
|
|
418
|
+
"from": {
|
|
419
|
+
"description": "Where the requirement is declared: yodel.config.ts, at the base commit, or both.",
|
|
420
|
+
"type": "string"
|
|
421
|
+
},
|
|
422
|
+
"migrations": {
|
|
423
|
+
"type": "array",
|
|
424
|
+
"items": {
|
|
425
|
+
"type": "object",
|
|
426
|
+
"additionalProperties": false,
|
|
427
|
+
"required": [
|
|
428
|
+
"id",
|
|
429
|
+
"checksum",
|
|
430
|
+
"ran"
|
|
431
|
+
],
|
|
432
|
+
"properties": {
|
|
433
|
+
"id": {
|
|
434
|
+
"type": "string"
|
|
435
|
+
},
|
|
436
|
+
"checksum": {
|
|
437
|
+
"type": "string"
|
|
438
|
+
},
|
|
439
|
+
"ran": {
|
|
440
|
+
"enum": [
|
|
441
|
+
"applied",
|
|
442
|
+
"not applied",
|
|
443
|
+
"applied with another checksum"
|
|
444
|
+
]
|
|
445
|
+
},
|
|
446
|
+
"recorded": {
|
|
447
|
+
"description": "The checksum the required environment recorded, when it differs.",
|
|
448
|
+
"type": "string"
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
},
|
|
456
|
+
"blocked": {
|
|
457
|
+
"description": "A pending migration has not run where it must first: the wave refuses it until it has.",
|
|
458
|
+
"type": "boolean"
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
},
|
|
344
462
|
"sinceLast": {
|
|
345
463
|
"description": "The pull request comment this plan replaces showed another digest: what moved since.",
|
|
346
464
|
"type": "object",
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://intentius.io/sql-yodeler/schemas/v1/report.schema.json",
|
|
4
|
+
"title": "yodel report [<env>...] --json",
|
|
5
|
+
"description": "Version 1. Every environment's migrations side by side, the audit log derived from each environment's history table and chant's gate ledger, and the gaps those sources show. Within a version, fields are only added; a reader ignores fields it does not know.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"required": ["version", "generatedAt", "project", "dialect", "migrations", "environments", "audit", "gaps"],
|
|
9
|
+
"properties": {
|
|
10
|
+
"version": { "const": 1 },
|
|
11
|
+
"generatedAt": { "type": "string", "description": "When the report was read, ISO 8601 UTC." },
|
|
12
|
+
"project": { "type": "string", "description": "The project directory." },
|
|
13
|
+
"dialect": { "enum": ["clickhouse", "postgres"] },
|
|
14
|
+
"migrations": { "type": "array", "items": { "type": "string" }, "description": "The migrations in chain order, then any an environment applied that the directory no longer has." },
|
|
15
|
+
"environments": { "type": "array", "items": { "$ref": "#/$defs/environment" } },
|
|
16
|
+
"audit": { "type": "array", "items": { "$ref": "#/$defs/entry" }, "description": "Every environment's audit entries, oldest first." },
|
|
17
|
+
"gaps": { "type": "array", "items": { "$ref": "#/$defs/gap" } },
|
|
18
|
+
"auditFile": {
|
|
19
|
+
"type": "object",
|
|
20
|
+
"additionalProperties": false,
|
|
21
|
+
"required": ["path", "appended", "missing"],
|
|
22
|
+
"description": "With --audit: the file, how many entries were appended (0 with --check), and the entries of the file the sources no longer give.",
|
|
23
|
+
"properties": {
|
|
24
|
+
"path": { "type": "string" },
|
|
25
|
+
"appended": { "type": "integer", "minimum": 0 },
|
|
26
|
+
"missing": { "type": "array", "items": { "$ref": "#/$defs/entry" } }
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"$defs": {
|
|
31
|
+
"environment": {
|
|
32
|
+
"type": "object",
|
|
33
|
+
"additionalProperties": false,
|
|
34
|
+
"required": ["name", "notes", "migrations"],
|
|
35
|
+
"properties": {
|
|
36
|
+
"name": { "type": "string" },
|
|
37
|
+
"history": { "type": "string", "description": "<database>.history" },
|
|
38
|
+
"op": {
|
|
39
|
+
"type": "object",
|
|
40
|
+
"additionalProperties": false,
|
|
41
|
+
"required": ["name", "gate"],
|
|
42
|
+
"properties": { "name": { "type": "string" }, "gate": { "type": "string" } }
|
|
43
|
+
},
|
|
44
|
+
"error": { "type": "string", "description": "Why the environment could not be read." },
|
|
45
|
+
"notes": { "type": "array", "items": { "type": "string" } },
|
|
46
|
+
"migrations": { "type": "array", "items": { "$ref": "#/$defs/migration" } }
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"migration": {
|
|
50
|
+
"type": "object",
|
|
51
|
+
"additionalProperties": false,
|
|
52
|
+
"required": ["id", "state", "inDirectory"],
|
|
53
|
+
"properties": {
|
|
54
|
+
"id": { "type": "string" },
|
|
55
|
+
"state": { "enum": ["applied", "pending", "failed", "started", "reverted"] },
|
|
56
|
+
"inDirectory": { "type": "boolean" },
|
|
57
|
+
"at": { "type": "string" },
|
|
58
|
+
"by": { "type": "string" },
|
|
59
|
+
"digest": { "type": "string" },
|
|
60
|
+
"approvedBy": { "type": "string" },
|
|
61
|
+
"approvedAt": { "type": "string" }
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"entry": {
|
|
65
|
+
"type": "object",
|
|
66
|
+
"additionalProperties": false,
|
|
67
|
+
"required": ["id", "at", "environment", "kind", "source"],
|
|
68
|
+
"description": "One audit entry; audit.jsonl holds one per line.",
|
|
69
|
+
"properties": {
|
|
70
|
+
"id": { "type": "string", "description": "A hash of the entry and its source: the same sources give the same id." },
|
|
71
|
+
"at": { "type": "string" },
|
|
72
|
+
"environment": { "type": "string" },
|
|
73
|
+
"kind": { "enum": ["approval-requested", "approved", "override", "silenced", "applied", "refused", "failed", "repaired", "reverted"] },
|
|
74
|
+
"by": { "type": "string" },
|
|
75
|
+
"migration": { "type": "string" },
|
|
76
|
+
"digest": { "type": "string" },
|
|
77
|
+
"detail": { "type": "string" },
|
|
78
|
+
"wave": {
|
|
79
|
+
"type": "object",
|
|
80
|
+
"additionalProperties": false,
|
|
81
|
+
"required": ["gate", "digest", "status"],
|
|
82
|
+
"description": "On an applied entry a wave of the apply pipeline applied: the wave's gate, its set digest, and whether the wave was approved or its policy at the base needed no approval.",
|
|
83
|
+
"properties": { "gate": { "type": "string" }, "digest": { "type": "string" }, "status": { "enum": ["approved", "not-required"] } }
|
|
84
|
+
},
|
|
85
|
+
"source": {
|
|
86
|
+
"oneOf": [
|
|
87
|
+
{
|
|
88
|
+
"type": "object",
|
|
89
|
+
"additionalProperties": false,
|
|
90
|
+
"required": ["ledger", "op", "gate"],
|
|
91
|
+
"properties": { "ledger": { "type": "string" }, "op": { "type": "string" }, "gate": { "type": "string" } }
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"type": "object",
|
|
95
|
+
"additionalProperties": false,
|
|
96
|
+
"required": ["history", "seq", "run"],
|
|
97
|
+
"properties": { "history": { "type": "string" }, "seq": { "type": "integer", "minimum": 1 }, "run": { "type": "string" } }
|
|
98
|
+
}
|
|
99
|
+
]
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
"gap": {
|
|
104
|
+
"type": "object",
|
|
105
|
+
"additionalProperties": false,
|
|
106
|
+
"required": ["environment", "kind", "detail"],
|
|
107
|
+
"properties": {
|
|
108
|
+
"environment": { "type": "string" },
|
|
109
|
+
"kind": { "enum": ["history-row", "approval"] },
|
|
110
|
+
"detail": { "type": "string" }
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|