@intentius/sql-yodeler 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.
Files changed (308) hide show
  1. package/README.md +3 -3
  2. package/dist/apply-steps/index.d.ts +65 -0
  3. package/dist/apply-steps/index.js +106 -0
  4. package/dist/apply-steps/index.js.map +1 -0
  5. package/dist/approval-mode/index.d.ts +78 -0
  6. package/dist/approval-mode/index.js +105 -0
  7. package/dist/approval-mode/index.js.map +1 -0
  8. package/dist/chant/access.d.ts +87 -0
  9. package/dist/chant/access.js +169 -0
  10. package/dist/chant/access.js.map +1 -0
  11. package/dist/chant/build.js +7 -0
  12. package/dist/chant/build.js.map +1 -1
  13. package/dist/chant/drift.d.ts +17 -1
  14. package/dist/chant/drift.js +55 -2
  15. package/dist/chant/drift.js.map +1 -1
  16. package/dist/chant/plan.d.ts +18 -2
  17. package/dist/chant/plan.js +21 -3
  18. package/dist/chant/plan.js.map +1 -1
  19. package/dist/ci/render.d.ts +333 -0
  20. package/dist/ci/render.js +885 -0
  21. package/dist/ci/render.js.map +1 -0
  22. package/dist/ci/replay.d.ts +17 -0
  23. package/dist/ci/replay.js +69 -0
  24. package/dist/ci/replay.js.map +1 -0
  25. package/dist/cleanup/index.d.ts +86 -0
  26. package/dist/cleanup/index.js +207 -0
  27. package/dist/cleanup/index.js.map +1 -0
  28. package/dist/commands/apply.d.ts +113 -0
  29. package/dist/commands/apply.js +370 -30
  30. package/dist/commands/apply.js.map +1 -1
  31. package/dist/commands/approve.d.ts +13 -0
  32. package/dist/commands/approve.js +239 -13
  33. package/dist/commands/approve.js.map +1 -1
  34. package/dist/commands/checkpoint.d.ts +3 -0
  35. package/dist/commands/checkpoint.js +78 -0
  36. package/dist/commands/checkpoint.js.map +1 -0
  37. package/dist/commands/ci.d.ts +3 -0
  38. package/dist/commands/ci.js +130 -0
  39. package/dist/commands/ci.js.map +1 -0
  40. package/dist/commands/cleanup.d.ts +13 -0
  41. package/dist/commands/cleanup.js +138 -0
  42. package/dist/commands/cleanup.js.map +1 -0
  43. package/dist/commands/config.d.ts +3 -0
  44. package/dist/commands/config.js +136 -0
  45. package/dist/commands/config.js.map +1 -0
  46. package/dist/commands/docs.d.ts +11 -0
  47. package/dist/commands/docs.js +108 -0
  48. package/dist/commands/docs.js.map +1 -0
  49. package/dist/commands/drift.d.ts +13 -1
  50. package/dist/commands/drift.js +52 -5
  51. package/dist/commands/drift.js.map +1 -1
  52. package/dist/commands/index.js +16 -0
  53. package/dist/commands/index.js.map +1 -1
  54. package/dist/commands/init.js +1 -1
  55. package/dist/commands/init.js.map +1 -1
  56. package/dist/commands/lint.js +39 -7
  57. package/dist/commands/lint.js.map +1 -1
  58. package/dist/commands/new.js +133 -34
  59. package/dist/commands/new.js.map +1 -1
  60. package/dist/commands/override.js +48 -16
  61. package/dist/commands/override.js.map +1 -1
  62. package/dist/commands/plan.js +47 -6
  63. package/dist/commands/plan.js.map +1 -1
  64. package/dist/commands/report.d.ts +13 -0
  65. package/dist/commands/report.js +121 -0
  66. package/dist/commands/report.js.map +1 -0
  67. package/dist/commands/revert.d.ts +20 -0
  68. package/dist/commands/revert.js +246 -0
  69. package/dist/commands/revert.js.map +1 -0
  70. package/dist/commands/status.js +32 -5
  71. package/dist/commands/status.js.map +1 -1
  72. package/dist/commands/test.d.ts +3 -0
  73. package/dist/commands/test.js +164 -0
  74. package/dist/commands/test.js.map +1 -0
  75. package/dist/config/base.d.ts +69 -0
  76. package/dist/config/base.js +121 -0
  77. package/dist/config/base.js.map +1 -0
  78. package/dist/config/define.d.ts +240 -3
  79. package/dist/config/define.js +4 -0
  80. package/dist/config/define.js.map +1 -1
  81. package/dist/config/index.d.ts +2 -0
  82. package/dist/config/index.js +2 -0
  83. package/dist/config/index.js.map +1 -1
  84. package/dist/config/load.d.ts +1 -1
  85. package/dist/config/load.js +156 -7
  86. package/dist/config/load.js.map +1 -1
  87. package/dist/config/settings.d.ts +22 -1
  88. package/dist/config/settings.js +34 -2
  89. package/dist/config/settings.js.map +1 -1
  90. package/dist/credentials.d.ts +119 -0
  91. package/dist/credentials.js +119 -0
  92. package/dist/credentials.js.map +1 -0
  93. package/dist/exit.js +1 -1
  94. package/dist/exit.js.map +1 -1
  95. package/dist/history/postgres/ddl.d.ts +18 -0
  96. package/dist/history/postgres/ddl.js +27 -2
  97. package/dist/history/postgres/ddl.js.map +1 -1
  98. package/dist/history/postgres/store.d.ts +2 -0
  99. package/dist/history/postgres/store.js +7 -1
  100. package/dist/history/postgres/store.js.map +1 -1
  101. package/dist/history/rows.d.ts +16 -3
  102. package/dist/history/rows.js +30 -1
  103. package/dist/history/rows.js.map +1 -1
  104. package/dist/history/store.d.ts +2 -0
  105. package/dist/history/store.js +2 -2
  106. package/dist/history/store.js.map +1 -1
  107. package/dist/index.d.ts +8 -1
  108. package/dist/index.js +3 -0
  109. package/dist/index.js.map +1 -1
  110. package/dist/init/adopt.js +1 -1
  111. package/dist/init/adopt.js.map +1 -1
  112. package/dist/init/clickhouse-access.d.ts +64 -0
  113. package/dist/init/clickhouse-access.js +211 -0
  114. package/dist/init/clickhouse-access.js.map +1 -0
  115. package/dist/init/live.d.ts +4 -0
  116. package/dist/init/live.js +16 -0
  117. package/dist/init/live.js.map +1 -1
  118. package/dist/lint/access.d.ts +18 -0
  119. package/dist/lint/access.js +34 -0
  120. package/dist/lint/access.js.map +1 -0
  121. package/dist/lint/check.js +38 -6
  122. package/dist/lint/check.js.map +1 -1
  123. package/dist/lint/config.d.ts +7 -1
  124. package/dist/lint/config.js +11 -5
  125. package/dist/lint/config.js.map +1 -1
  126. package/dist/lint/index.d.ts +2 -0
  127. package/dist/lint/index.js +2 -0
  128. package/dist/lint/index.js.map +1 -1
  129. package/dist/lint/naming.d.ts +62 -0
  130. package/dist/lint/naming.js +138 -0
  131. package/dist/lint/naming.js.map +1 -0
  132. package/dist/lint/report.js +1 -1
  133. package/dist/lint/report.js.map +1 -1
  134. package/dist/lint/routines.d.ts +26 -0
  135. package/dist/lint/routines.js +65 -0
  136. package/dist/lint/routines.js.map +1 -0
  137. package/dist/lint/rules.d.ts +51 -6
  138. package/dist/lint/rules.js +23 -6
  139. package/dist/lint/rules.js.map +1 -1
  140. package/dist/lint/schema-checks.d.ts +63 -0
  141. package/dist/lint/schema-checks.js +128 -0
  142. package/dist/lint/schema-checks.js.map +1 -0
  143. package/dist/lint/statements.d.ts +22 -1
  144. package/dist/lint/statements.js +40 -1
  145. package/dist/lint/statements.js.map +1 -1
  146. package/dist/mcp/tools.d.ts +1 -1
  147. package/dist/mcp/tools.js +1 -1
  148. package/dist/mcp/tools.js.map +1 -1
  149. package/dist/migrations/checkpoint.d.ts +45 -0
  150. package/dist/migrations/checkpoint.js +108 -0
  151. package/dist/migrations/checkpoint.js.map +1 -0
  152. package/dist/migrations/checks.d.ts +19 -1
  153. package/dist/migrations/checks.js +15 -0
  154. package/dist/migrations/checks.js.map +1 -1
  155. package/dist/migrations/create.d.ts +13 -4
  156. package/dist/migrations/create.js +24 -7
  157. package/dist/migrations/create.js.map +1 -1
  158. package/dist/migrations/document.d.ts +10 -0
  159. package/dist/migrations/document.js +1 -0
  160. package/dist/migrations/document.js.map +1 -1
  161. package/dist/migrations/index.d.ts +2 -0
  162. package/dist/migrations/index.js +2 -0
  163. package/dist/migrations/index.js.map +1 -1
  164. package/dist/migrations/routines.d.ts +21 -0
  165. package/dist/migrations/routines.js +30 -0
  166. package/dist/migrations/routines.js.map +1 -0
  167. package/dist/notify/index.d.ts +124 -0
  168. package/dist/notify/index.js +210 -0
  169. package/dist/notify/index.js.map +1 -0
  170. package/dist/notify/verify.d.ts +53 -0
  171. package/dist/notify/verify.js +71 -0
  172. package/dist/notify/verify.js.map +1 -0
  173. package/dist/pr/model.d.ts +7 -1
  174. package/dist/pr/model.js +29 -7
  175. package/dist/pr/model.js.map +1 -1
  176. package/dist/pr/render.d.ts +4 -1
  177. package/dist/pr/render.js +49 -9
  178. package/dist/pr/render.js.map +1 -1
  179. package/dist/pr/tenants.d.ts +37 -0
  180. package/dist/pr/tenants.js +138 -0
  181. package/dist/pr/tenants.js.map +1 -0
  182. package/dist/probe.d.ts +27 -0
  183. package/dist/probe.js +106 -0
  184. package/dist/probe.js.map +1 -0
  185. package/dist/project.d.ts +35 -2
  186. package/dist/project.js +62 -2
  187. package/dist/project.js.map +1 -1
  188. package/dist/replay/clickhouse.d.ts +31 -0
  189. package/dist/replay/clickhouse.js +103 -6
  190. package/dist/replay/clickhouse.js.map +1 -1
  191. package/dist/replay/replay.d.ts +14 -3
  192. package/dist/replay/replay.js +62 -31
  193. package/dist/replay/replay.js.map +1 -1
  194. package/dist/replay/report.js +1 -1
  195. package/dist/replay/report.js.map +1 -1
  196. package/dist/report/audit.d.ts +138 -0
  197. package/dist/report/audit.js +219 -0
  198. package/dist/report/audit.js.map +1 -0
  199. package/dist/report/jsonl.d.ts +21 -0
  200. package/dist/report/jsonl.js +52 -0
  201. package/dist/report/jsonl.js.map +1 -0
  202. package/dist/report/model.d.ts +68 -0
  203. package/dist/report/model.js +127 -0
  204. package/dist/report/model.js.map +1 -0
  205. package/dist/report/render.d.ts +18 -0
  206. package/dist/report/render.js +127 -0
  207. package/dist/report/render.js.map +1 -0
  208. package/dist/schema-docs/render.d.ts +49 -0
  209. package/dist/schema-docs/render.js +359 -0
  210. package/dist/schema-docs/render.js.map +1 -0
  211. package/dist/schemas.d.ts +7 -2
  212. package/dist/schemas.js +7 -2
  213. package/dist/schemas.js.map +1 -1
  214. package/dist/sources/ddl.d.ts +48 -0
  215. package/dist/sources/ddl.js +53 -0
  216. package/dist/sources/ddl.js.map +1 -0
  217. package/dist/sources/index.d.ts +69 -0
  218. package/dist/sources/index.js +170 -0
  219. package/dist/sources/index.js.map +1 -0
  220. package/dist/steps/backfill.d.ts +40 -5
  221. package/dist/steps/backfill.js +128 -8
  222. package/dist/steps/backfill.js.map +1 -1
  223. package/dist/steps/index.d.ts +19 -1
  224. package/dist/steps/index.js +34 -7
  225. package/dist/steps/index.js.map +1 -1
  226. package/dist/steps/kinds.d.ts +42 -4
  227. package/dist/steps/kinds.js +88 -14
  228. package/dist/steps/kinds.js.map +1 -1
  229. package/dist/steps/postgres-migration.d.ts +38 -25
  230. package/dist/steps/postgres-migration.js +49 -32
  231. package/dist/steps/postgres-migration.js.map +1 -1
  232. package/dist/steps/rebuild.d.ts +15 -6
  233. package/dist/steps/rebuild.js +12 -9
  234. package/dist/steps/rebuild.js.map +1 -1
  235. package/dist/tenants/index.d.ts +41 -0
  236. package/dist/tenants/index.js +121 -0
  237. package/dist/tenants/index.js.map +1 -0
  238. package/dist/tenants/target.d.ts +23 -0
  239. package/dist/tenants/target.js +29 -0
  240. package/dist/tenants/target.js.map +1 -0
  241. package/dist/tenants/wave.d.ts +128 -0
  242. package/dist/tenants/wave.js +254 -0
  243. package/dist/tenants/wave.js.map +1 -0
  244. package/dist/testing/define.d.ts +62 -0
  245. package/dist/testing/define.js +32 -0
  246. package/dist/testing/define.js.map +1 -0
  247. package/dist/testing/files.d.ts +5 -0
  248. package/dist/testing/files.js +18 -0
  249. package/dist/testing/files.js.map +1 -0
  250. package/dist/testing/report.d.ts +14 -0
  251. package/dist/testing/report.js +83 -0
  252. package/dist/testing/report.js.map +1 -0
  253. package/dist/testing/run.d.ts +104 -0
  254. package/dist/testing/run.js +328 -0
  255. package/dist/testing/run.js.map +1 -0
  256. package/dist/versioned/approval.d.ts +6 -0
  257. package/dist/versioned/approval.js +11 -5
  258. package/dist/versioned/approval.js.map +1 -1
  259. package/dist/versioned/checks.d.ts +8 -2
  260. package/dist/versioned/checks.js +34 -13
  261. package/dist/versioned/checks.js.map +1 -1
  262. package/dist/versioned/driver.d.ts +2 -2
  263. package/dist/versioned/engine.d.ts +16 -0
  264. package/dist/versioned/engine.js +20 -6
  265. package/dist/versioned/engine.js.map +1 -1
  266. package/dist/versioned/explain.d.ts +2 -0
  267. package/dist/versioned/explain.js +3 -1
  268. package/dist/versioned/explain.js.map +1 -1
  269. package/dist/versioned/index.d.ts +1 -0
  270. package/dist/versioned/index.js +1 -0
  271. package/dist/versioned/index.js.map +1 -1
  272. package/dist/versioned/op.d.ts +6 -1
  273. package/dist/versioned/op.js +7 -2
  274. package/dist/versioned/op.js.map +1 -1
  275. package/dist/versioned/policy.d.ts +33 -2
  276. package/dist/versioned/policy.js +59 -8
  277. package/dist/versioned/policy.js.map +1 -1
  278. package/dist/versioned/report.js +9 -0
  279. package/dist/versioned/report.js.map +1 -1
  280. package/dist/versioned/revert.d.ts +128 -0
  281. package/dist/versioned/revert.js +251 -0
  282. package/dist/versioned/revert.js.map +1 -0
  283. package/dist/versioned/state.d.ts +25 -0
  284. package/dist/versioned/state.js +37 -4
  285. package/dist/versioned/state.js.map +1 -1
  286. package/dist/waves/index.d.ts +224 -0
  287. package/dist/waves/index.js +353 -0
  288. package/dist/waves/index.js.map +1 -0
  289. package/dist/waves/promotion.d.ts +56 -0
  290. package/dist/waves/promotion.js +108 -0
  291. package/dist/waves/promotion.js.map +1 -0
  292. package/dist/waves/record.d.ts +34 -0
  293. package/dist/waves/record.js +20 -0
  294. package/dist/waves/record.js.map +1 -0
  295. package/package.json +11 -7
  296. package/schemas/apply.schema.json +162 -3
  297. package/schemas/checkpoint.schema.json +19 -0
  298. package/schemas/cleanup.schema.json +40 -0
  299. package/schemas/drift.schema.json +26 -1
  300. package/schemas/event.schema.json +36 -0
  301. package/schemas/lint-rules.schema.json +4 -0
  302. package/schemas/lint.schema.json +4 -0
  303. package/schemas/new.schema.json +41 -3
  304. package/schemas/plan.schema.json +157 -0
  305. package/schemas/report.schema.json +114 -0
  306. package/schemas/revert.schema.json +69 -0
  307. package/schemas/status.schema.json +64 -3
  308. package/schemas/test.schema.json +41 -0
@@ -0,0 +1,333 @@
1
+ /**
2
+ * `yodel ci` (#65): a project's CI for GitHub Actions, GitLab CI and Forgejo
3
+ * Actions, rendered by the installed package, so a fix to the pipelines
4
+ * reaches a project when it upgrades yodel and renders again. Until #65 the
5
+ * templates carried this as scripts/ci.ts.
6
+ *
7
+ * yodel ci write the files
8
+ * yodel ci --check exit 1 when a file differs from what this renders
9
+ * yodel ci --replay the lint job's replay check on this machine (./replay.ts)
10
+ *
11
+ * yodel.config.ts `ci` picks the forges (default all three) and names the
12
+ * module that declares the project's own jobs, which are merged after
13
+ * yodel's into the pull request pipeline and kept on every render
14
+ * ({@link ProjectJobs}).
15
+ *
16
+ * Environments are the keys of `sql.profiles` in chant.config.ts, in order,
17
+ * but `replay`, which is the lint job's throwaway server.
18
+ * Each one needs ops/migrate-<env>.op.ts and ops/watch-<env>.op.ts.
19
+ * The apply pipeline's waves are yodel.config.ts `waves`, in order; without
20
+ * it, one wave per environment in profile order, each with gate `always`.
21
+ *
22
+ * Three pipelines per forge, each declared with chant: yodel-pr with the
23
+ * github lexicon's Workflow, Job and Step (Forgejo renders the same
24
+ * declaration through the forgejo lexicon's dialect) and the gitlab
25
+ * lexicon's Workflow and Job; yodel-apply with chant's
26
+ * generateOpWavesPipeline, from the waves spec this writes
27
+ * (yodel-waves.json); the watch with generateOpsPipeline.
28
+ *
29
+ * - yodel-pr: on a pull (merge) request, `yodel ci --check` (these files are
30
+ * what yodel ci renders), `yodel lint`, and the replay check into a
31
+ * throwaway server the job starts (the `replay` profile), then for each
32
+ * environment `yodel plan <env> --comment`, which posts the pending
33
+ * migrations and the digest to approve. One job per environment, holding
34
+ * that environment's reader credentials and nothing else.
35
+ * - yodel-apply: on a push to main, one job per wave, each needing the one
36
+ * before, running `chant run wave`: it plans the environment (`yodel apply
37
+ * <env> --wave-plan`), reads the wave's gate policy from yodel-waves.json
38
+ * as the commit before the push has it, waits for an approval when that
39
+ * policy asks for one (exit 3, and the waves after it do not run), and
40
+ * applies (`yodel apply <env> --wave-apply`). The only jobs that hold a
41
+ * writer's credentials, one environment's each, with
42
+ * YODEL_CREDENTIALS=writer. Two merges in quick succession do not fail the
43
+ * second apply: it waits for the first's lock (YODEL_LOCK_WAIT), and an
44
+ * apply whose commit is no longer main's tip stands down
45
+ * (YODEL_STAND_DOWN), since the newer commit's waves apply the same
46
+ * environments.
47
+ * - watch-<env>: the environment's WatchOp on its own schedule, rendered by
48
+ * chant's generateOpsPipeline, with the reader's credentials. After the
49
+ * Op, `yodel drift <env> --issue` compares the server with the schema the
50
+ * newest applied migration records (so a migration waiting at its gate is
51
+ * not drift), keeps one tracking issue for the environment (opened on
52
+ * drift, updated while it changes, closed when it is gone), and fails the
53
+ * job on drift. The issue is written with the job's token on GitHub
54
+ * (issues: write) and Forgejo, and with GITLAB_TOKEN on GitLab.
55
+ *
56
+ * The scheduled watch never pushes. Its first phase (chant lifecycle
57
+ * snapshot) commits a snapshot to chant/lifecycle and tries to push it; the
58
+ * drift it reports comes from `chant lifecycle diff --live`, declared against
59
+ * live, which needs no snapshot on the remote. So the job sets a push URL
60
+ * that cannot be pushed to: the push fails, chant carries on, and the job
61
+ * works the same with a read-only token (GitHub `contents: read`, GitLab's
62
+ * CI_JOB_TOKEN) as with Forgejo's token, which can write. A push that could
63
+ * land would race the approvals people push to chant/lifecycle.
64
+ *
65
+ * Every job installs @intentius/sql-yodeler from npm with `npm ci`, which
66
+ * needs no token, in IMAGE. With yodel.config.ts `ci.image` (#66), the CI
67
+ * image ghcr.io/intentius/sql-yodeler pinned by its digest, every job runs
68
+ * in that image instead, which carries node, yodel, chant and the lexicons
69
+ * on PATH, and no job runs `npm ci` ({@link Toolchain}).
70
+ */
71
+ import { type ApprovalMode } from "../config/define.js";
72
+ import { type CloudToken, type Role } from "../credentials.js";
73
+ import type { Declarable } from "@intentius/chant/declarable";
74
+ export type Forge = "github" | "gitlab" | "forgejo";
75
+ export declare const FORGES: readonly Forge[];
76
+ export interface RenderedFile {
77
+ /** Relative to the project. */
78
+ path: string;
79
+ content: string;
80
+ }
81
+ /** The image every job runs in, where the forge runs jobs in a container. It needs git, so not -slim. */
82
+ export declare const IMAGE = "node:22-bookworm";
83
+ /** The CI image (#66): yodel, chant and the sql lexicon, published for each release. */
84
+ export declare const YODEL_IMAGE = "ghcr.io/intentius/sql-yodeler";
85
+ /**
86
+ * What the jobs run in. By default IMAGE, and each job installs the
87
+ * project's packages with `npm ci` and puts node_modules/.bin on PATH. With
88
+ * `ci.image` the yodel image (pinned by digest): its yodel, chant and tsx
89
+ * are on PATH, and a checkout resolves chant and the lexicons from the
90
+ * image's /node_modules, so nothing is installed.
91
+ */
92
+ export interface Toolchain {
93
+ image: string;
94
+ /** The yodel image: no `npm ci`, and every job in the container. */
95
+ yodelImage: boolean;
96
+ }
97
+ export declare const toolchainOf: (envs: Pick<Environments, "image">) => Toolchain;
98
+ export declare const MAIN = "main";
99
+ /** DEV for dev: the prefix of an environment's variables. */
100
+ export declare const prefixOf: (env: string) => string;
101
+ export type Dialect = "clickhouse" | "postgres";
102
+ /** The environments to render for: chant.config.ts's sql.dialect and its profiles, in order. */
103
+ export interface Environments {
104
+ dialect: Dialect;
105
+ names: readonly string[];
106
+ /** The forges to render for: yodel.config.ts `ci.forges`, default every one. */
107
+ forges?: readonly Forge[];
108
+ /** The project's own jobs (yodel.config.ts `ci.jobs`), merged after yodel's. */
109
+ jobs?: ProjectJobs;
110
+ /** yodel.config.ts `ci.image`: the yodel image every job runs in, by digest. */
111
+ image?: string;
112
+ /** yodel.config.ts `ci.resume`: the scheduled job that resumes a wave whose approval arrived. */
113
+ resume?: {
114
+ schedule: string;
115
+ };
116
+ /** The apply pipeline's waves, in order. */
117
+ waves: readonly Wave[];
118
+ /** chant.config.ts declares the `replay` profile, so the lint job runs the replay check. */
119
+ replay: boolean;
120
+ /** The project has tests/*.test.ts: with the replay profile, the lint job runs yodel test on its server too (#54). */
121
+ tests?: boolean;
122
+ /**
123
+ * The environments whose profile is made with credentials() (#50): the
124
+ * variables each role reads, and the cloud token source that mints its
125
+ * password, if any. An environment not here reads the default variables.
126
+ */
127
+ credentials?: Record<string, EnvCredentials>;
128
+ }
129
+ /** What a job holding one role of an environment needs: the variables it reads, and the cloud identity its token source mints from. */
130
+ export interface RoleNeeds {
131
+ variables: string[];
132
+ cloud?: CloudToken;
133
+ }
134
+ export type EnvCredentials = Record<Role, RoleNeeds>;
135
+ /** DEV_CLICKHOUSE for dev on ClickHouse: what an environment's variables start with. */
136
+ export declare const variablePrefix: (env: string, dialect: Dialect) => string;
137
+ /** The variables a job reading `env` holds: the URL and the reader (the variables credentials() names; none for a token-minted password). */
138
+ export declare const readerVariables: (env: string, dialect: Dialect, creds?: EnvCredentials) => string[];
139
+ /** The variables the apply job for `env` holds: the URL and the writer. */
140
+ export declare const writerVariables: (env: string, dialect: Dialect, creds?: EnvCredentials) => string[];
141
+ /** The GitLab ID token per cloud: its variable and its audience. */
142
+ export declare const ID_TOKENS: Record<CloudToken, {
143
+ variable: string;
144
+ aud: string;
145
+ }>;
146
+ /** The write probe a pull request job runs before its plan: it holds no writer for `envs`. */
147
+ export declare const writeProbe: (envs: readonly string[]) => string;
148
+ /**
149
+ * The approvals: `chant approve` records them on the chant/lifecycle branch,
150
+ * and approvers push it. A CI checkout fetches one ref, so fetch this one too.
151
+ * The remote-tracking ref is what chant's push lease reads.
152
+ */
153
+ export declare const FETCH_APPROVALS = "git fetch --no-tags origin '+refs/heads/chant/lifecycle:refs/remotes/origin/chant/lifecycle' && git branch -f chant/lifecycle origin/chant/lifecycle || echo 'no chant/lifecycle branch yet, so nothing is approved'";
154
+ /** The apply jobs' lock settings: wait for another apply's lock, and stand down for a newer commit on main. */
155
+ export declare const APPLY_LOCK: Record<string, string>;
156
+ /** The watch reads; it never pushes. See the comment at the top. */
157
+ export declare const NO_PUSH = "git remote set-url --push origin no-push://the-drift-watch-only-reads";
158
+ /** After the watch's `chant run`: drift against the history, the environment's tracking issue, and exit 2 on drift. */
159
+ export declare const watchDrift: (env: string) => string;
160
+ /**
161
+ * The replay check: `yodel lint --replay replay --reset` replays every
162
+ * migration, in order, into a fresh database on the `replay` profile's
163
+ * server and fails when one does not give the schema it recorded. That
164
+ * server is a throwaway container the lint job starts as a service, the
165
+ * image chant's emulator runs, which the job (in IMAGE, on every forge)
166
+ * reaches by the service's name; never a server whose data matters, since
167
+ * --reset drops what the history names there first.
168
+ */
169
+ export declare const REPLAY_PROFILE = "replay";
170
+ interface ReplayService {
171
+ /**
172
+ * The service's name, and its host where the job runs in a container.
173
+ * Prefixed, so it cannot meet another container's alias on a runner's
174
+ * shared network: a host that answers for two servers would split the replay.
175
+ */
176
+ name: string;
177
+ image: string;
178
+ port: number;
179
+ /** The service container's environment. */
180
+ env: Record<string, string>;
181
+ health: string;
182
+ /** The server's URL at `host`, on `port` (default: the service's own). */
183
+ url: (host: string, port?: number) => string;
184
+ /** What the lint job sets besides the URL: the throwaway server's credentials. */
185
+ jobEnv: Record<string, string>;
186
+ }
187
+ export declare const REPLAY_SERVICE: Record<Dialect, ReplayService>;
188
+ /** Waits up to 90 s for the replay server's port; a shell-free one-liner, so every forge runs it the same. */
189
+ export declare const waitFor: (host: string, port: number) => string;
190
+ export declare const LINT = "yodel lint";
191
+ export declare const REPLAY = "yodel lint --replay replay --reset";
192
+ /** yodel test (#54), after the replay check on the same throwaway server, its outcome as JUnit XML. */
193
+ export declare const TEST = "yodel test --env replay --reset --junit yodel-test.xml";
194
+ /** Fails a pull request whose pipelines differ from what yodel ci renders. */
195
+ export declare const CI_CHECK = "yodel ci --check";
196
+ /**
197
+ * Webhook events (yodel.config.ts `notify`): the variables the apply, plan
198
+ * and watch jobs pass from the forge's secrets. yodel sends nothing while
199
+ * they are unset (empty), so an unconfigured repository needs neither.
200
+ * GitLab jobs have the project's variables already.
201
+ */
202
+ export declare const WEBHOOK_VARIABLES: string[];
203
+ /** Where the plan and apply jobs write `yodel report`, kept as the job's artifact. */
204
+ export declare const REPORT_DIR = "yodel-report";
205
+ /**
206
+ * `yodel report <env>` as JSON and as the HTML run view, into REPORT_DIR.
207
+ * It runs whatever the job's outcome, and a gap it reports (exit 4) does not
208
+ * fail the job: the report is for reading. `yodel` is the project's, named
209
+ * by path, since GitLab's after_script does not keep before_script's PATH;
210
+ * in the yodel image, the image's, which is on PATH.
211
+ */
212
+ export declare const reportCommand: (env: string, tc?: Toolchain) => string;
213
+ /** The artifact a job keeps its report in. */
214
+ export declare const reportArtifact: (job: string) => string;
215
+ type Actions = "github" | "forgejo";
216
+ export declare function actionsReview(forge: Actions, envs_: Environments): RenderedFile;
217
+ export declare const GITLAB_WATCH_FILE = ".gitlab/yodel-watch.gitlab-ci.yml";
218
+ export declare const GITLAB_APPLY_FILE = ".gitlab/yodel-apply.gitlab-ci.yml";
219
+ export declare function gitlabPipeline(envs_: Environments): RenderedFile;
220
+ /** When a wave waits for an approval; yodel.config.ts `waves[].gate`. */
221
+ export type WaveGate = "always" | "on-destructive" | "never";
222
+ export interface Wave {
223
+ env: string;
224
+ gate: WaveGate;
225
+ /**
226
+ * The environment whose history must record a migration applied before
227
+ * this one applies it (yodel.config.ts `waves[].requires`, default the
228
+ * wave before): this wave's jobs, and its plan job, read it with its reader.
229
+ */
230
+ requires?: string;
231
+ /**
232
+ * A tenant set's wave (#56): a run per tenant, `<env>/<tenant>`, or per
233
+ * slot of a set read at run time, `<env>/@<i>of<n>`, in place of the
234
+ * environment's one, all behind the wave's one gate.
235
+ */
236
+ targets?: readonly string[];
237
+ /** Split the wave into a deciding job and this many share jobs (yodel.config.ts `waves[].shares`). */
238
+ shares?: number;
239
+ /** Which approvals of the wave's digest count (yodel.config.ts `waves[].approval`, #48); absent, `ledger`. */
240
+ approval?: ApprovalMode;
241
+ }
242
+ /** The waves spec: committed, and read by every wave job (its gate policy at the commit before the push). */
243
+ export declare const WAVES_SPEC = "yodel-waves.json";
244
+ export declare const APPLY_PIPELINE = "yodel-apply";
245
+ interface WavesSpec {
246
+ name: string;
247
+ op: string;
248
+ plan: string[];
249
+ apply: string[];
250
+ branches: string[];
251
+ waves: Array<{
252
+ name: string;
253
+ runs: Array<{
254
+ target: string;
255
+ op: string;
256
+ }>;
257
+ gate: WaveGate;
258
+ shares?: number;
259
+ approval?: ApprovalMode;
260
+ environment?: {
261
+ name: string;
262
+ };
263
+ variables?: Record<string, string>;
264
+ }>;
265
+ /** The scheduled resume job (yodel.config.ts `ci.resume`); only the pipelines are rendered from it, the spec file leaves it out. */
266
+ resume?: {
267
+ schedule: string;
268
+ };
269
+ }
270
+ /**
271
+ * The waves spec. What the file holds is the same for every forge; each
272
+ * forge's jobs get their own variables on top (`variables`).
273
+ */
274
+ export declare function wavesSpec(waves: readonly Wave[], variables?: (env: string) => Record<string, string>, resume?: {
275
+ schedule: string;
276
+ }): WavesSpec;
277
+ /** The waves spec file and the apply pipeline on each forge. */
278
+ export declare function applyPipelines(dir: string, envs: Environments): Promise<RenderedFile[]>;
279
+ /** yodel.config.ts `waves`, checked against the environments; one wave per environment, gate `always`, without it. */
280
+ export declare function readWaves(dir: string, envs: readonly string[]): Promise<Wave[]>;
281
+ /**
282
+ * Each wave of an environment with a tenant set (#56), with its runs: a
283
+ * run per tenant of a list or a file, or for a set given by a query,
284
+ * `shares` slots (one without) that read the tenants when the wave runs.
285
+ * The query is not run here, so the pipeline stays the same as tenants come
286
+ * and go; a list or a file is in the repository, and changing it is
287
+ * rendering again.
288
+ */
289
+ export declare function withTenants(dir: string, waves: readonly Wave[]): Promise<Wave[]>;
290
+ /**
291
+ * The watch's spec for one environment: the Op, and on GitHub and Forgejo the
292
+ * reader's secrets. A GitLab job already has the project's variables (a
293
+ * writer's only under its environment, which the watch does not declare), and
294
+ * `NAME: $NAME` there would refer to itself.
295
+ */
296
+ export declare function watchSpec(env: string, dialect: Dialect, forge: Forge, creds?: EnvCredentials): {
297
+ name: string;
298
+ variables?: Record<string, string>;
299
+ permissions?: Record<string, string>;
300
+ };
301
+ export declare function watchPipelines(dir: string, envs_: Environments): Promise<RenderedFile[]>;
302
+ /** The dialect and the environments chant.config.ts declares, in order. */
303
+ export declare function environments(dir: string): Promise<Environments>;
304
+ /** The roles of each environment whose profile is made with credentials(). */
305
+ export declare function credentialsIn(profiles: Record<string, unknown>, envs: readonly string[]): Record<string, EnvCredentials>;
306
+ /**
307
+ * The project's own jobs (#65): the module yodel.config.ts `ci.jobs` names,
308
+ * relative to the project, declaring jobs with chant's lexicons. `actions`
309
+ * (the github lexicon's Job) goes into yodel-pr on GitHub and Forgejo, after
310
+ * yodel's jobs; `gitlab` (the gitlab lexicon's Job) into .gitlab-ci.yml,
311
+ * after yodel's, its stages after `review`. They are declared here, not
312
+ * edited into the rendered files, so every `yodel ci` keeps them:
313
+ *
314
+ * ```ts
315
+ * // ci/jobs.ts
316
+ * import { Job, Step } from "@intentius/chant-lexicon-github";
317
+ * import { Job as GitLabJob, Image } from "@intentius/chant-lexicon-gitlab";
318
+ * export const actions = { test: new Job({ "runs-on": "ubuntu-latest", steps: [new Step({ uses: "actions/checkout@v7" }), new Step({ run: "npm test" })] }) };
319
+ * export const gitlab = { test: new GitLabJob({ stage: "test", image: new Image({ name: "node:22" }), script: ["npm test"] }) };
320
+ * ```
321
+ */
322
+ export interface ProjectJobs {
323
+ actions?: Record<string, Declarable>;
324
+ gitlab?: Record<string, Declarable>;
325
+ }
326
+ /** Loads the module `ci.jobs` names. */
327
+ export declare function loadProjectJobs(dir: string, file: string): Promise<ProjectJobs>;
328
+ /** The pipelines that need no Op discovery: pull requests, and GitLab's main file. */
329
+ export declare function review(envs: Environments): RenderedFile[];
330
+ /** The forge a rendered file is for; undefined for the waves spec, which every forge's apply reads. */
331
+ export declare function forgeOf(path: string): Forge | undefined;
332
+ export declare function render(dir: string): Promise<RenderedFile[]>;
333
+ export {};