@wtfalch/foundry 0.16.3 → 0.16.4
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
|
@@ -237,6 +237,8 @@ export interface CoolifyPort {
|
|
|
237
237
|
name?: string;
|
|
238
238
|
description?: string;
|
|
239
239
|
instant_deploy?: boolean;
|
|
240
|
+
/** Extra `docker run` options (`--entrypoint "..."` becomes the compose entrypoint). */
|
|
241
|
+
custom_docker_run_options?: string;
|
|
240
242
|
/**
|
|
241
243
|
* `host:container`, comma separated -- publishes host ports directly
|
|
242
244
|
* (`@wtfalch/providers`' `CoolifyClient.createDockerImageApplication`
|
|
@@ -46,6 +46,15 @@ export declare const PLATFORM_AUTH_KEY = "platform:auth";
|
|
|
46
46
|
* that was never actually applied.
|
|
47
47
|
*/
|
|
48
48
|
export declare const PLATFORM_AUTH_ZITADEL_APPLIED_IMAGE_TAG_SCOPE_KEY = "auth_zitadel_applied_image_tag";
|
|
49
|
+
/**
|
|
50
|
+
* The image has `Entrypoint /app/zitadel` and no `Cmd`, so without this it
|
|
51
|
+
* runs zitadel with no subcommand, exits, and restarts forever. Coolify turns
|
|
52
|
+
* `--entrypoint` in `custom_docker_run_options` into the compose `entrypoint`
|
|
53
|
+
* (its PATCH takes this field; it refuses `dockerfile`).
|
|
54
|
+
*/
|
|
55
|
+
export declare const AUTH_ZITADEL_RUN_OPTIONS = "--entrypoint \"/app/zitadel start-from-init --masterkeyFromEnv --tlsMode external\"";
|
|
56
|
+
/** The run options last applied to the ZITADEL app (value: the options string), so a changed value forces one redeploy. */
|
|
57
|
+
export declare const PLATFORM_AUTH_ZITADEL_RUN_OPTIONS_SCOPE_KEY = "zitadel_platform_auth_run_options_applied";
|
|
49
58
|
/**
|
|
50
59
|
* #251: the Synapse/MAS image tags an org's calls Matrix stack last
|
|
51
60
|
* successful apply actually set live. `coolifyCalls` (`executor.ts`)
|
|
@@ -41,6 +41,15 @@ export const PLATFORM_AUTH_KEY = 'platform:auth';
|
|
|
41
41
|
* that was never actually applied.
|
|
42
42
|
*/
|
|
43
43
|
export const PLATFORM_AUTH_ZITADEL_APPLIED_IMAGE_TAG_SCOPE_KEY = 'auth_zitadel_applied_image_tag';
|
|
44
|
+
/**
|
|
45
|
+
* The image has `Entrypoint /app/zitadel` and no `Cmd`, so without this it
|
|
46
|
+
* runs zitadel with no subcommand, exits, and restarts forever. Coolify turns
|
|
47
|
+
* `--entrypoint` in `custom_docker_run_options` into the compose `entrypoint`
|
|
48
|
+
* (its PATCH takes this field; it refuses `dockerfile`).
|
|
49
|
+
*/
|
|
50
|
+
export const AUTH_ZITADEL_RUN_OPTIONS = '--entrypoint "/app/zitadel start-from-init --masterkeyFromEnv --tlsMode external"';
|
|
51
|
+
/** The run options last applied to the ZITADEL app (value: the options string), so a changed value forces one redeploy. */
|
|
52
|
+
export const PLATFORM_AUTH_ZITADEL_RUN_OPTIONS_SCOPE_KEY = 'zitadel_platform_auth_run_options_applied';
|
|
44
53
|
/**
|
|
45
54
|
* #251: the Synapse/MAS image tags an org's calls Matrix stack last
|
|
46
55
|
* successful apply actually set live. `coolifyCalls` (`executor.ts`)
|
|
@@ -753,8 +762,15 @@ function planJobs(platform, byKey, claimed, observable) {
|
|
|
753
762
|
claimed.add(key);
|
|
754
763
|
if (!platform.jobs.enabled)
|
|
755
764
|
return { step: null, blocked: null };
|
|
756
|
-
if (live)
|
|
757
|
-
|
|
765
|
+
if (live) {
|
|
766
|
+
// The step also starts the scheduler's database (0.16.3), so a live app
|
|
767
|
+
// whose database the reader saw stopped plans it again. A status the
|
|
768
|
+
// reader could not read is absent, and plans nothing.
|
|
769
|
+
const databaseStatus = live.config.databaseStatus;
|
|
770
|
+
if (typeof databaseStatus !== 'string' || databaseStatus.startsWith('running')) {
|
|
771
|
+
return { step: null, blocked: null };
|
|
772
|
+
}
|
|
773
|
+
}
|
|
758
774
|
// No Coolify reader means the host wired no Coolify at all for the
|
|
759
775
|
// platform: the step's executor would throw every apply, and the scheduler
|
|
760
776
|
// could never be seen live, so it would re-plan forever. A fixed text: it
|
|
@@ -1103,7 +1119,10 @@ function planAuth(platform, recordedIds, executorBlocked, executorMissing, authD
|
|
|
1103
1119
|
connectorApplied &&
|
|
1104
1120
|
brokerApplied &&
|
|
1105
1121
|
brokerDeployed &&
|
|
1106
|
-
loginClientApplied
|
|
1122
|
+
loginClientApplied &&
|
|
1123
|
+
// The ZITADEL run options reach the container only through the auth
|
|
1124
|
+
// step's redeploy, so a platform recorded before them still plans it.
|
|
1125
|
+
recordedIds[PLATFORM_AUTH_ZITADEL_RUN_OPTIONS_SCOPE_KEY] === AUTH_ZITADEL_RUN_OPTIONS) {
|
|
1107
1126
|
return { step: null, blocked: null };
|
|
1108
1127
|
}
|
|
1109
1128
|
// The admin key was minted but never reached the host. ZITADEL shows a
|
|
@@ -770,7 +770,7 @@ export declare class ProvidersPlatformCloudflareReader implements PlatformCloudf
|
|
|
770
770
|
export declare class ProvidersPlatformCoolifyReader implements PlatformCoolifyReader {
|
|
771
771
|
private readonly client;
|
|
772
772
|
private readonly platformStore;
|
|
773
|
-
constructor(client: Pick<CoolifyPort, 'getApplication' | 'listDatabaseBackups'>, platformStore: Pick<PlatformStore, 'getServiceIds'>);
|
|
773
|
+
constructor(client: Pick<CoolifyPort, 'getApplication' | 'getDatabase' | 'listDatabaseBackups'>, platformStore: Pick<PlatformStore, 'getServiceIds'>);
|
|
774
774
|
listResources(): Promise<LiveResource[]>;
|
|
775
775
|
}
|
|
776
776
|
export {};
|
|
@@ -6,7 +6,7 @@ import { redactSecrets } from '../calls-sfu-deploy-support.js';
|
|
|
6
6
|
import { ensureCloudflaredConnector } from './cloudflared-connector.js';
|
|
7
7
|
import { ACCESS_POLICY_NAME, getDatabaseStarted, isNotFoundError, isRunningOrStarting, } from './executor.js';
|
|
8
8
|
import { coolifyDomains } from './hostnames.js';
|
|
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';
|
|
9
|
+
import { AUTH_ZITADEL_RUN_OPTIONS, 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_AUTH_ZITADEL_RUN_OPTIONS_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';
|
|
11
11
|
import { CreateInstanceError, createZitadelInstance, generateSystemApiKeypair, instanceWithoutBearerMessage, systemApiUsersEnv, } from './zitadel-system-api.js';
|
|
12
12
|
/** The key `runPlatformSteps` records the apex zone's id under (`system:kind:key`). */
|
|
@@ -871,6 +871,7 @@ async function provisionPlatformAuth(context, deps) {
|
|
|
871
871
|
docker_registry_image_name: AUTH_ZITADEL_IMAGE,
|
|
872
872
|
docker_registry_image_tag: AUTH_ZITADEL_IMAGE_TAG,
|
|
873
873
|
ports_exposes: AUTH_ZITADEL_PORT,
|
|
874
|
+
custom_docker_run_options: AUTH_ZITADEL_RUN_OPTIONS,
|
|
874
875
|
name: PLATFORM_AUTH_ZITADEL_APP_NAME,
|
|
875
876
|
description: `ZITADEL for the platform's own sign-in (#168, ${AUTH_ZITADEL_IMAGE}:${AUTH_ZITADEL_IMAGE_TAG})`,
|
|
876
877
|
instant_deploy: false,
|
|
@@ -882,9 +883,14 @@ async function provisionPlatformAuth(context, deps) {
|
|
|
882
883
|
// create must not leave the app unnamed for good, and the tunnel addresses
|
|
883
884
|
// the app by this name. (The port cannot read the current name back, and
|
|
884
885
|
// setting the same value again is harmless.)
|
|
886
|
+
// The run options go in the same patch, so an app made before they existed
|
|
887
|
+
// gets them too.
|
|
885
888
|
await deps.coolify.updateApplication(zitadelAppId, {
|
|
886
889
|
custom_internal_name: PLATFORM_AUTH_ZITADEL_INTERNAL_NAME,
|
|
890
|
+
custom_docker_run_options: AUTH_ZITADEL_RUN_OPTIONS,
|
|
887
891
|
});
|
|
892
|
+
// The container only takes new run options at its next deploy.
|
|
893
|
+
const zitadelRunOptionsNew = recorded[PLATFORM_AUTH_ZITADEL_RUN_OPTIONS_SCOPE_KEY] !== AUTH_ZITADEL_RUN_OPTIONS;
|
|
888
894
|
// #251: only on create, never unconditionally -- nothing here patches
|
|
889
895
|
// `docker_registry_image_tag` on an app `findOrCreatePlatformApp` found
|
|
890
896
|
// already running, so that is the only moment this tag is actually live.
|
|
@@ -1012,9 +1018,12 @@ async function provisionPlatformAuth(context, deps) {
|
|
|
1012
1018
|
await deps.coolify.bulkUpsertEnvs(brokerAppId, brokerEnvs);
|
|
1013
1019
|
// Deploy an app that was just created, is not running (a throw after the
|
|
1014
1020
|
// create left it never deployed, or it stopped), or whose envs changed.
|
|
1015
|
-
if (zitadelApp.justCreated || !zitadelApp.running || zitadelEnvsChanged) {
|
|
1021
|
+
if (zitadelApp.justCreated || !zitadelApp.running || zitadelEnvsChanged || zitadelRunOptionsNew) {
|
|
1016
1022
|
await deps.coolify.deploy(zitadelAppId);
|
|
1017
1023
|
await record(PLATFORM_AUTH_ZITADEL_DEPLOYED_SCOPE_KEY, zitadelAppId);
|
|
1024
|
+
// Only now: the options are live once the deploy went out. A throw between
|
|
1025
|
+
// the PATCH and here leaves the marker unset, so the next run deploys.
|
|
1026
|
+
await record(PLATFORM_AUTH_ZITADEL_RUN_OPTIONS_SCOPE_KEY, AUTH_ZITADEL_RUN_OPTIONS);
|
|
1018
1027
|
}
|
|
1019
1028
|
if (loginApp.justCreated || !loginApp.running || loginEnvsChanged) {
|
|
1020
1029
|
await deps.coolify.deploy(loginAppId);
|
|
@@ -5029,11 +5038,27 @@ export class ProvidersPlatformCoolifyReader {
|
|
|
5029
5038
|
if (recordedAppId) {
|
|
5030
5039
|
try {
|
|
5031
5040
|
const app = await this.client.getApplication(recordedAppId);
|
|
5041
|
+
// The scheduler's database status, so `planJobs` can see a stopped
|
|
5042
|
+
// one. Left out when it cannot be read: unknown is not "stopped".
|
|
5043
|
+
let databaseStatus;
|
|
5044
|
+
const databaseId = recorded[JOBS_DATABASE_SCOPE_KEY];
|
|
5045
|
+
if (databaseId) {
|
|
5046
|
+
try {
|
|
5047
|
+
databaseStatus = (await this.client.getDatabase(databaseId)).status;
|
|
5048
|
+
}
|
|
5049
|
+
catch {
|
|
5050
|
+
databaseStatus = undefined;
|
|
5051
|
+
}
|
|
5052
|
+
}
|
|
5032
5053
|
resources.push({
|
|
5033
5054
|
system: 'coolify',
|
|
5034
5055
|
kind: 'jobs',
|
|
5035
5056
|
key: JOBS_SCHEDULER_KEY,
|
|
5036
|
-
config: {
|
|
5057
|
+
config: {
|
|
5058
|
+
uuid: app.uuid,
|
|
5059
|
+
status: app.status,
|
|
5060
|
+
...(databaseStatus !== undefined && { databaseStatus }),
|
|
5061
|
+
},
|
|
5037
5062
|
});
|
|
5038
5063
|
}
|
|
5039
5064
|
catch {
|