@wtfalch/foundry 0.16.2 → 0.16.3
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/plan/executor.d.ts
CHANGED
|
@@ -142,6 +142,7 @@ export interface CoolifyPort {
|
|
|
142
142
|
getDatabase(uuid: string): Promise<{
|
|
143
143
|
uuid: string;
|
|
144
144
|
internal_db_url?: string;
|
|
145
|
+
status?: string;
|
|
145
146
|
}>;
|
|
146
147
|
/**
|
|
147
148
|
* Every database Coolify holds. `coolifyDatabase` finds its own by name and
|
|
@@ -1357,6 +1358,25 @@ export declare const ACCESS_POLICY_NAME = "foundry: allowed emails";
|
|
|
1357
1358
|
* uses for the org's own app.
|
|
1358
1359
|
*/
|
|
1359
1360
|
export declare function isRunningOrStarting(status: string | undefined): boolean;
|
|
1361
|
+
/**
|
|
1362
|
+
* Reads a Postgres database and starts it when Coolify reports it as not
|
|
1363
|
+
* running. `createPostgresDatabase` does not start what it creates (no
|
|
1364
|
+
* `instant_deploy`), and a database found by name or by recorded id may have
|
|
1365
|
+
* been left stopped, so every site that points an app at a database calls this
|
|
1366
|
+
* instead of `getDatabase`. Returns what `getDatabase` returned.
|
|
1367
|
+
*/
|
|
1368
|
+
export declare function getDatabaseStarted(coolify: {
|
|
1369
|
+
getDatabase(uuid: string): Promise<{
|
|
1370
|
+
uuid: string;
|
|
1371
|
+
internal_db_url?: string;
|
|
1372
|
+
status?: string;
|
|
1373
|
+
}>;
|
|
1374
|
+
raw(method: string, path: string, body?: unknown): Promise<unknown>;
|
|
1375
|
+
}, dbId: string): Promise<{
|
|
1376
|
+
uuid: string;
|
|
1377
|
+
internal_db_url?: string;
|
|
1378
|
+
status?: string;
|
|
1379
|
+
}>;
|
|
1360
1380
|
export declare class FoundryStepExecutor implements StepExecutor, StepDestroyer {
|
|
1361
1381
|
private readonly ports;
|
|
1362
1382
|
constructor(ports: FoundryStepExecutorPorts);
|
package/dist/plan/executor.js
CHANGED
|
@@ -551,6 +551,20 @@ export function isRunningOrStarting(status) {
|
|
|
551
551
|
return true;
|
|
552
552
|
return !status.startsWith('exited') && !status.startsWith('stopped');
|
|
553
553
|
}
|
|
554
|
+
/**
|
|
555
|
+
* Reads a Postgres database and starts it when Coolify reports it as not
|
|
556
|
+
* running. `createPostgresDatabase` does not start what it creates (no
|
|
557
|
+
* `instant_deploy`), and a database found by name or by recorded id may have
|
|
558
|
+
* been left stopped, so every site that points an app at a database calls this
|
|
559
|
+
* instead of `getDatabase`. Returns what `getDatabase` returned.
|
|
560
|
+
*/
|
|
561
|
+
export async function getDatabaseStarted(coolify, dbId) {
|
|
562
|
+
const db = await coolify.getDatabase(dbId);
|
|
563
|
+
if (db.status !== undefined && !db.status.startsWith('running')) {
|
|
564
|
+
await coolify.raw('POST', `/databases/${dbId}/start`);
|
|
565
|
+
}
|
|
566
|
+
return db;
|
|
567
|
+
}
|
|
554
568
|
// ---------------------------------------------------------------------------
|
|
555
569
|
// Executor
|
|
556
570
|
// ---------------------------------------------------------------------------
|
|
@@ -1442,7 +1456,7 @@ export class FoundryStepExecutor {
|
|
|
1442
1456
|
* never logged, never interpolated into a thrown error.
|
|
1443
1457
|
*/
|
|
1444
1458
|
async pushDatabaseUrl(appId, dbId, dbName) {
|
|
1445
|
-
const db = await this.ports.coolify
|
|
1459
|
+
const db = await getDatabaseStarted(this.ports.coolify, dbId);
|
|
1446
1460
|
// Nothing to push; `planApp` reports this as blocked from the live reader.
|
|
1447
1461
|
if (!db.internal_db_url)
|
|
1448
1462
|
return { pushed: false, changed: false };
|
|
@@ -2027,7 +2041,7 @@ export class FoundryStepExecutor {
|
|
|
2027
2041
|
// recorded, logged, or interpolated into a thrown error. Its own call,
|
|
2028
2042
|
// separate from the two app-env calls above, since it has nothing to
|
|
2029
2043
|
// push once `internal_db_url` is absent.
|
|
2030
|
-
const db = await this.ports.coolify
|
|
2044
|
+
const db = await getDatabaseStarted(this.ports.coolify, dbId);
|
|
2031
2045
|
if (db.internal_db_url) {
|
|
2032
2046
|
const dbEnvs = [
|
|
2033
2047
|
{ key: 'DATABASE_URL_OWNER', value: db.internal_db_url },
|
|
@@ -2224,8 +2238,8 @@ export class FoundryStepExecutor {
|
|
|
2224
2238
|
const masDbId = await this.ensureCallsDatabase(context, projectUuid, environment, names.masDb, 'mas', CALLS_MAS_DB_SCOPE_KEY);
|
|
2225
2239
|
context.recordScopeId(CALLS_MAS_DB_SCOPE_KEY, masDbId);
|
|
2226
2240
|
const [synapseDbRow, masDbRow] = await Promise.all([
|
|
2227
|
-
this.ports.coolify
|
|
2228
|
-
this.ports.coolify
|
|
2241
|
+
getDatabaseStarted(this.ports.coolify, synapseDbId),
|
|
2242
|
+
getDatabaseStarted(this.ports.coolify, masDbId),
|
|
2229
2243
|
]);
|
|
2230
2244
|
const synapseDb = synapseDbRow.internal_db_url
|
|
2231
2245
|
? parseCallsDbUrl(synapseDbRow.internal_db_url)
|
|
@@ -2517,9 +2531,9 @@ export class FoundryStepExecutor {
|
|
|
2517
2531
|
const serviceDbId = await this.ensureCallsDatabase(context, projectUuid, environment, names.serviceDb, 'chat', CHAT_SERVICE_DB_SCOPE_KEY);
|
|
2518
2532
|
context.recordScopeId(CHAT_SERVICE_DB_SCOPE_KEY, serviceDbId);
|
|
2519
2533
|
const [synapseDbRow, masDbRow, serviceDbRow] = await Promise.all([
|
|
2520
|
-
this.ports.coolify
|
|
2521
|
-
this.ports.coolify
|
|
2522
|
-
this.ports.coolify
|
|
2534
|
+
getDatabaseStarted(this.ports.coolify, synapseDbId),
|
|
2535
|
+
getDatabaseStarted(this.ports.coolify, masDbId),
|
|
2536
|
+
getDatabaseStarted(this.ports.coolify, serviceDbId),
|
|
2523
2537
|
]);
|
|
2524
2538
|
const synapseDb = synapseDbRow.internal_db_url
|
|
2525
2539
|
? parseCallsDbUrl(synapseDbRow.internal_db_url)
|
|
@@ -2692,7 +2706,7 @@ export class FoundryStepExecutor {
|
|
|
2692
2706
|
const dbName = `${name}-db`;
|
|
2693
2707
|
const dbId = await this.ensureCallsDatabase(context, projectUuid, environment, dbName, dbName.replace(/-/g, '_'), CALLS_SERVICE_DB_SCOPE_KEY);
|
|
2694
2708
|
context.recordScopeId(CALLS_SERVICE_DB_SCOPE_KEY, dbId);
|
|
2695
|
-
const db = await this.ports.coolify
|
|
2709
|
+
const db = await getDatabaseStarted(this.ports.coolify, dbId);
|
|
2696
2710
|
if (!db.internal_db_url) {
|
|
2697
2711
|
throw new Error(`coolify:calls-service for ${org.slug}: its database has no internal_db_url yet -- retry this apply once Coolify reports one`);
|
|
2698
2712
|
}
|
|
@@ -51,7 +51,7 @@ export declare const JOBS_ADMIN_TOKEN_REF = "jobs:scheduler:adminToken";
|
|
|
51
51
|
* org's own app, reused here for the platform's one scheduler instead of once
|
|
52
52
|
* per org.
|
|
53
53
|
*/
|
|
54
|
-
type JobsCoolifyPort = Pick<CoolifyPort, 'findProjectByName' | 'createProject' | 'findOrCreateEnvironment' | 'listServers' | 'requireGithubApp' | 'findApplicationByName' | 'createGithubAppApplication' | 'listDatabases' | 'createPostgresDatabase' | 'getDatabase' | 'bulkUpsertEnvs' | 'getApplication' | 'deploy'>;
|
|
54
|
+
type JobsCoolifyPort = Pick<CoolifyPort, 'findProjectByName' | 'createProject' | 'findOrCreateEnvironment' | 'listServers' | 'requireGithubApp' | 'findApplicationByName' | 'createGithubAppApplication' | 'listDatabases' | 'createPostgresDatabase' | 'getDatabase' | 'raw' | 'bulkUpsertEnvs' | 'getApplication' | 'deploy'>;
|
|
55
55
|
/**
|
|
56
56
|
* Options for {@link FoundryPlatformStepExecutor}'s constructor, replacing
|
|
57
57
|
* four positional arguments that shifted on every merge that added a
|
|
@@ -340,7 +340,7 @@ export interface PlatformMailRuntime {
|
|
|
340
340
|
* {@link PlatformStepExecutionContext}, bundled like {@link PlatformAuthDeps}.
|
|
341
341
|
*/
|
|
342
342
|
export interface PlatformArchonDeps {
|
|
343
|
-
coolify: Pick<CoolifyPort, 'findProjectByName' | 'createProject' | 'findOrCreateEnvironment' | 'listServers' | 'findApplicationByName' | 'getApplication' | 'requireGithubApp' | 'createGithubAppApplication' | 'createDockerfileApplication' | 'listDatabases' | 'createPostgresDatabase' | 'getDatabase' | 'bulkUpsertEnvs' | 'listEnvs' | 'updateApplication' | 'deploy'>;
|
|
343
|
+
coolify: Pick<CoolifyPort, 'findProjectByName' | 'createProject' | 'findOrCreateEnvironment' | 'listServers' | 'findApplicationByName' | 'getApplication' | 'requireGithubApp' | 'createGithubAppApplication' | 'createDockerfileApplication' | 'listDatabases' | 'createPostgresDatabase' | 'getDatabase' | 'raw' | 'bulkUpsertEnvs' | 'listEnvs' | 'updateApplication' | 'deploy'>;
|
|
344
344
|
cloudflare: Pick<CloudflarePort, 'findZoneByApex' | 'findTunnelByName' | 'createTunnel' | 'putTunnelConfig' | 'getTunnelToken' | 'findDnsRecord' | 'createDnsRecord' | 'updateDnsRecord' | 'listAccessApps' | 'createAccessApp' | 'listAccessPolicies' | 'createAccessPolicy' | 'deleteAccessApp'>;
|
|
345
345
|
/** Must target the platform's own ZITADEL instance, or `zitadelForInstance` must be set. */
|
|
346
346
|
zitadel: Pick<ZitadelPort, 'findOrCreateOrg' | 'findOrCreateProject' | 'createOidcApp' | 'listApps' | 'deleteApp'>;
|
|
@@ -4,7 +4,7 @@ import { applyObjects, openInstance, platformMailSettingsObjects } from '@wtfalc
|
|
|
4
4
|
import { VERSIONS, floatingTagBlocked } from '../bootstrap/versions.js';
|
|
5
5
|
import { redactSecrets } from '../calls-sfu-deploy-support.js';
|
|
6
6
|
import { ensureCloudflaredConnector } from './cloudflared-connector.js';
|
|
7
|
-
import { ACCESS_POLICY_NAME, isNotFoundError, isRunningOrStarting } from './executor.js';
|
|
7
|
+
import { ACCESS_POLICY_NAME, getDatabaseStarted, isNotFoundError, isRunningOrStarting, } from './executor.js';
|
|
8
8
|
import { coolifyDomains } from './hostnames.js';
|
|
9
9
|
import { JOBS_SCHEDULER_KEY, PLATFORM_AI_APPLIED_GITREF_SCOPE_KEY, PLATFORM_AI_APPLIED_HOSTNAME_SCOPE_KEY, PLATFORM_AI_DEPLOY_PENDING_SCOPE_KEY, PLATFORM_AI_INTERNAL_URL_SCOPE_KEY, PLATFORM_AI_KEY, PLATFORM_AI_MANAGEMENT_KEY_CONFLICT_SCOPE_KEY, PLATFORM_AI_MANAGEMENT_KEY_SCOPE_KEY, PLATFORM_AI_MANAGEMENT_KEY_UNDELIVERED_SCOPE_KEY, PLATFORM_AI_MIGRATE_BLOCKED_SCOPE_KEY, PLATFORM_AI_ORGANISATION_SCOPE_KEY, PLATFORM_AI_SIGNING_KEY_SET_SCOPE_KEY, PLATFORM_AI_SIGNING_KEY_UNDELIVERED_SCOPE_KEY, PLATFORM_ARCHON_APPLIED_BROKER_SCOPE_KEY, PLATFORM_ARCHON_APPLIED_GIT_REF_SCOPE_KEY, PLATFORM_ARCHON_APPLIED_HOSTNAME_SCOPE_KEY, PLATFORM_ARCHON_CONNECTOR_APP_SCOPE_KEY, PLATFORM_ARCHON_GATE_CLOSED_SCOPE_KEY, PLATFORM_ARCHON_KEY, PLATFORM_ARCHON_MASTER_CLOUDFLARE_TOKEN_REF, PLATFORM_ARCHON_MASTER_COOLIFY_TOKEN_REF, PLATFORM_ARCHON_MASTER_COOLIFY_URL_REF, PLATFORM_AUTH_ADMIN_UNDELIVERED_SCOPE_KEY, PLATFORM_AUTH_ADMIN_USER_SCOPE_KEY, PLATFORM_AUTH_BROKER_DEPLOYED_SCOPE_KEY, PLATFORM_AUTH_BROKER_SCOPE_KEY, PLATFORM_AUTH_CONNECTOR_APP_SCOPE_KEY, PLATFORM_AUTH_INSTANCE_SCOPE_KEY, PLATFORM_AUTH_INSTANCE_UNDELIVERED_SCOPE_KEY, PLATFORM_AUTH_KEY, PLATFORM_AUTH_LOGIN_CLIENT_UNDELIVERED_SCOPE_KEY, PLATFORM_AUTH_LOGIN_CLIENT_USER_SCOPE_KEY, PLATFORM_AUTH_ZITADEL_APPLIED_IMAGE_TAG_SCOPE_KEY, PLATFORM_BACKUP_DATABASE_SCOPE_KEYS, PLATFORM_BACKUP_SERVICE_KEYS, PLATFORM_FILES_APPLIED_GIT_REF_SCOPE_KEY, PLATFORM_FILES_APPLIED_HOSTNAME_SCOPE_KEY, PLATFORM_FILES_INTERNAL_URL_SCOPE_KEY, PLATFORM_FILES_INTROSPECTION_SCOPE_KEY, PLATFORM_FILES_INTROSPECTION_UNDELIVERED_SCOPE_KEY, PLATFORM_FILES_KEY, PLATFORM_FILES_MANAGEMENT_KEY_SCOPE_KEY, PLATFORM_FILES_MANAGEMENT_UNDELIVERED_SCOPE_KEY, PLATFORM_FILES_ZITADEL_PROJECT_SCOPE_KEY, PLATFORM_INTEGRATIONS_APPLIED_GITREF_SCOPE_KEY, PLATFORM_INTEGRATIONS_APPLIED_HOSTNAME_SCOPE_KEY, PLATFORM_INTEGRATIONS_KEY, PLATFORM_INTEGRATIONS_KEY_SET_SCOPE_KEY, PLATFORM_INTEGRATIONS_KEY_UNDELIVERED_SCOPE_KEY, PLATFORM_MAIL_ADMIN_KEY_SCOPE_KEY, PLATFORM_MAIL_ADMIN_UNDELIVERED_SCOPE_KEY, PLATFORM_MAIL_APPLIED_GIT_REF_SCOPE_KEY, PLATFORM_MAIL_APPLIED_HOSTNAME_SCOPE_KEY, PLATFORM_MAIL_CONNECTOR_APP_SCOPE_KEY, PLATFORM_MAIL_INTERNAL_URL_SCOPE_KEY, PLATFORM_MAIL_KEY, PLATFORM_MAIL_ZITADEL_PROJECT_SCOPE_KEY, parseBrokerDeployRecord, parseLoginClientRecord, platformMailMxHost, } from './platform-diff.js';
|
|
10
10
|
import { applyCallsSfuPlatformStep } from './platform-sfu.js';
|
|
@@ -429,7 +429,7 @@ export class FoundryPlatformStepExecutor {
|
|
|
429
429
|
});
|
|
430
430
|
appId = created.uuid;
|
|
431
431
|
}
|
|
432
|
-
const db = await coolify
|
|
432
|
+
const db = await getDatabaseStarted(coolify, dbId);
|
|
433
433
|
if (!db.internal_db_url) {
|
|
434
434
|
throw new Error(`platform step coolify:jobs: database ${dbId} has no internal_db_url yet; not deploying the scheduler without a database`);
|
|
435
435
|
}
|
|
@@ -852,7 +852,7 @@ async function provisionPlatformAuth(context, deps) {
|
|
|
852
852
|
dbId = created.uuid;
|
|
853
853
|
await record(PLATFORM_AUTH_DB_SCOPE_KEY, dbId);
|
|
854
854
|
}
|
|
855
|
-
const db = await deps.coolify
|
|
855
|
+
const db = await getDatabaseStarted(deps.coolify, dbId);
|
|
856
856
|
if (!db.internal_db_url) {
|
|
857
857
|
// Static config check before either app is touched (`diff.ts`'s
|
|
858
858
|
// `coolifyCalls` follows the same rule for its own databases): Coolify
|
|
@@ -2108,7 +2108,7 @@ async function provisionPlatformArchon(context, deps) {
|
|
|
2108
2108
|
}
|
|
2109
2109
|
await record(PLATFORM_ARCHON_DB_SCOPE_KEY, dbId);
|
|
2110
2110
|
}
|
|
2111
|
-
const db = await deps.coolify
|
|
2111
|
+
const db = await getDatabaseStarted(deps.coolify, dbId);
|
|
2112
2112
|
if (!db.internal_db_url) {
|
|
2113
2113
|
throw new Error('coolify:app for the platform (archon): the database has no internal_db_url yet -- retry this apply once Coolify reports one');
|
|
2114
2114
|
}
|
|
@@ -3264,7 +3264,7 @@ async function provisionPlatformAi(context, deps) {
|
|
|
3264
3264
|
}
|
|
3265
3265
|
await record(PLATFORM_AI_DB_SCOPE_KEY, dbId);
|
|
3266
3266
|
}
|
|
3267
|
-
const db = await coolify
|
|
3267
|
+
const db = await getDatabaseStarted(coolify, dbId);
|
|
3268
3268
|
if (!db.internal_db_url) {
|
|
3269
3269
|
throw new Error('coolify:app for the platform (ai): the database has no internal_db_url yet -- retry this apply once Coolify reports one');
|
|
3270
3270
|
}
|
|
@@ -3987,7 +3987,7 @@ async function provisionPlatformFiles(context, deps) {
|
|
|
3987
3987
|
}
|
|
3988
3988
|
await record(PLATFORM_FILES_DB_SCOPE_KEY, dbId);
|
|
3989
3989
|
}
|
|
3990
|
-
const db = await deps.coolify
|
|
3990
|
+
const db = await getDatabaseStarted(deps.coolify, dbId);
|
|
3991
3991
|
if (!db.internal_db_url) {
|
|
3992
3992
|
throw new Error('coolify:app for the platform (files): the database has no internal_db_url yet -- retry this apply once Coolify reports one');
|
|
3993
3993
|
}
|
|
@@ -4346,7 +4346,7 @@ async function provisionPlatformIntegrations(action, context, deps) {
|
|
|
4346
4346
|
}
|
|
4347
4347
|
await record(INTEGRATIONS_DATABASE_SCOPE_KEY, dbId);
|
|
4348
4348
|
}
|
|
4349
|
-
const db = await coolify
|
|
4349
|
+
const db = await getDatabaseStarted(coolify, dbId);
|
|
4350
4350
|
if (!db.internal_db_url) {
|
|
4351
4351
|
throw new Error(`platform:integrations: database ${dbId} has no internal_db_url yet; not deploying the integrations host without a database`);
|
|
4352
4352
|
}
|