@wtfalch/foundry 0.26.1 → 0.26.2

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.
@@ -135,7 +135,6 @@ export interface CoolifyPort {
135
135
  name: string;
136
136
  postgres_db: string;
137
137
  postgres_user: string;
138
- postgres_initdb_args?: string;
139
138
  }): Promise<{
140
139
  uuid: string;
141
140
  internal_db_url: string;
@@ -2220,6 +2219,14 @@ export declare class FoundryStepExecutor implements StepExecutor, StepDestroyer
2220
2219
  * `system:kind:key` slot of its own for the same reason.
2221
2220
  */
2222
2221
  private ensureCallsDatabase;
2222
+ /**
2223
+ * Sets `POSTGRES_INITDB_ARGS` on a Postgres database, once: the official
2224
+ * image's entrypoint passes it to `initdb`, which Coolify's own
2225
+ * `postgres_initdb_args` field never does ({@link CALLS_SYNAPSE_DB_INITDB_ARGS}).
2226
+ * `/databases/{uuid}/envs` is not a typed port method yet, so this goes
2227
+ * through `raw`. Nothing here is a secret.
2228
+ */
2229
+ private ensureDatabaseInitdbArgs;
2223
2230
  /**
2224
2231
  * Reads back {@link CALLS_SECRET_ENV_KEYS} from the MAS app's own envs
2225
2232
  * before minting fresh ones -- this stack's only memory across a re-run
@@ -567,21 +567,17 @@ const CALLS_MAS_DB_SCOPE_KEY = 'coolify_calls_mas_database';
567
567
  * Synapse refuses to start against a database whose `LC_COLLATE`/`LC_CTYPE`
568
568
  * is not `C` (https://element-hq.github.io/synapse/latest/postgres.html);
569
569
  * Coolify's official postgres image otherwise creates one with `en_US.utf8`.
570
- * `createPostgresDatabase` forwards this to Coolify's own
571
- * `postgres_initdb_args` field -- but Coolify stores that field and reads it
572
- * back unchanged without ever handing it to `initdb`: its Postgres start
573
- * action builds the container's env from `postgres_user`/`postgres_password`/
574
- * `postgres_db` and runtime envs only
575
- * (https://github.com/coollabsio/coolify/blob/main/app/Actions/Database/StartPostgresql.php).
576
- * A database created this way still comes up `en_US.utf8` and crash-loops
577
- * every Synapse app that reads it; live evidence and the real fix (not yet
578
- * chosen) are tracked in #494. This constant and the field it feeds stay in
579
- * place, inert, until that lands -- collation cannot be migrated onto an
580
- * existing database under any of the candidate fixes either. MAS has no
581
- * such requirement, so this is passed for the Synapse database only. Not
582
- * using Synapse's own `allow_unsafe_locale` escape hatch regardless of
583
- * which fix lands: that trades a loud startup refusal for silent index
584
- * corruption after a future glibc upgrade.
570
+ * Coolify's `postgres_initdb_args` field is stored and never handed to
571
+ * `initdb` (its Postgres start action builds the container's env from
572
+ * `postgres_user`/`postgres_password`/`postgres_db` and runtime envs only,
573
+ * https://github.com/coollabsio/coolify/blob/main/app/Actions/Database/StartPostgresql.php),
574
+ * so foundry no longer sends it (#494). The official `postgres` image's
575
+ * entrypoint does read the `POSTGRES_INITDB_ARGS` env: `ensureCallsDatabase`
576
+ * sets it on the Synapse database before that database first starts. It
577
+ * cannot change a database whose data directory `initdb` already made; MAS
578
+ * has no such requirement, so the env goes on the Synapse database only. Not
579
+ * using Synapse's own `allow_unsafe_locale` escape hatch: that trades a loud
580
+ * startup refusal for silent index corruption after a future glibc upgrade.
585
581
  */
586
582
  const CALLS_SYNAPSE_DB_INITDB_ARGS = '--locale=C --encoding=UTF8';
587
583
  /**
@@ -3298,13 +3294,23 @@ export class FoundryStepExecutor {
3298
3294
  * database, whose {@link CALLS_SERVICE_DB_SCOPE_KEY} has no
3299
3295
  * `system:kind:key` slot of its own for the same reason.
3300
3296
  */
3301
- async ensureCallsDatabase(org, context, projectUuid, environment, name, postgresDb, scopeKey, postgresInitdbArgs) {
3297
+ async ensureCallsDatabase(org, context, projectUuid, environment, name, postgresDb, scopeKey, initdbArgs) {
3298
+ // A database found by id or name may be one a failed run created and never
3299
+ // started (its env call threw), so the env is checked on every path. It
3300
+ // only takes effect before the first start; the callers start it later
3301
+ // (`getDatabaseStarted`).
3302
3302
  const existing = context.recordedIds()[scopeKey];
3303
- if (existing)
3303
+ if (existing) {
3304
+ if (initdbArgs)
3305
+ await this.ensureDatabaseInitdbArgs(existing, initdbArgs);
3304
3306
  return existing;
3307
+ }
3305
3308
  const found = (await this.ports.coolify.listDatabases()).find((d) => d.name === name && d.environment_id === environment.id);
3306
- if (found)
3309
+ if (found) {
3310
+ if (initdbArgs)
3311
+ await this.ensureDatabaseInitdbArgs(found.uuid, initdbArgs);
3307
3312
  return found.uuid;
3313
+ }
3308
3314
  const server = await this.resolveServer(org, context);
3309
3315
  const created = await this.ports.coolify.createPostgresDatabase({
3310
3316
  project_uuid: projectUuid,
@@ -3314,10 +3320,27 @@ export class FoundryStepExecutor {
3314
3320
  name,
3315
3321
  postgres_db: postgresDb,
3316
3322
  postgres_user: postgresDb,
3317
- ...(postgresInitdbArgs ? { postgres_initdb_args: postgresInitdbArgs } : {}),
3318
3323
  });
3324
+ if (initdbArgs)
3325
+ await this.ensureDatabaseInitdbArgs(created.uuid, initdbArgs);
3319
3326
  return created.uuid;
3320
3327
  }
3328
+ /**
3329
+ * Sets `POSTGRES_INITDB_ARGS` on a Postgres database, once: the official
3330
+ * image's entrypoint passes it to `initdb`, which Coolify's own
3331
+ * `postgres_initdb_args` field never does ({@link CALLS_SYNAPSE_DB_INITDB_ARGS}).
3332
+ * `/databases/{uuid}/envs` is not a typed port method yet, so this goes
3333
+ * through `raw`. Nothing here is a secret.
3334
+ */
3335
+ async ensureDatabaseInitdbArgs(dbId, args) {
3336
+ const envs = (await this.ports.coolify.raw('GET', `/databases/${dbId}/envs`));
3337
+ if (envs.some((e) => e.key === 'POSTGRES_INITDB_ARGS'))
3338
+ return;
3339
+ await this.ports.coolify.raw('POST', `/databases/${dbId}/envs`, {
3340
+ key: 'POSTGRES_INITDB_ARGS',
3341
+ value: args,
3342
+ });
3343
+ }
3321
3344
  /**
3322
3345
  * Reads back {@link CALLS_SECRET_ENV_KEYS} from the MAS app's own envs
3323
3346
  * before minting fresh ones -- this stack's only memory across a re-run
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wtfalch/foundry",
3
- "version": "0.26.1",
3
+ "version": "0.26.2",
4
4
  "description": "Foundry's SDK: the declared org's types, the plan and apply contracts, and the state store's interface.",
5
5
  "repository": {
6
6
  "type": "git",