@geekmidas/cli 10.0.0-alpha.82 → 10.0.0-alpha.84
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/{EndpointGenerator-DtnIGafh.mjs → EndpointGenerator-CVc6Oi1Y.mjs} +185 -82
- package/dist/EndpointGenerator-CVc6Oi1Y.mjs.map +1 -0
- package/dist/{EndpointGenerator-cKlnllIu.cjs → EndpointGenerator-CwLjBCFE.cjs} +203 -82
- package/dist/EndpointGenerator-CwLjBCFE.cjs.map +1 -0
- package/dist/{LegacyStateStore-Ceq7A_75.mjs → LegacyStateStore-CTsUFLNQ.mjs} +2 -2
- package/dist/{LegacyStateStore-Ceq7A_75.mjs.map → LegacyStateStore-CTsUFLNQ.mjs.map} +1 -1
- package/dist/{LegacyStateStore-Z-EKUGSX.cjs → LegacyStateStore-EDT2TUSe.cjs} +2 -2
- package/dist/{LegacyStateStore-Z-EKUGSX.cjs.map → LegacyStateStore-EDT2TUSe.cjs.map} +1 -1
- package/dist/{LocalStateStore-Bocb8dmZ.cjs → LocalStateStore-CdpzTvPn.cjs} +2 -2
- package/dist/{LocalStateStore-Bocb8dmZ.cjs.map → LocalStateStore-CdpzTvPn.cjs.map} +1 -1
- package/dist/{LocalStateStore-C72bwpG2.mjs → LocalStateStore-D1VfxRuK.mjs} +2 -2
- package/dist/{LocalStateStore-C72bwpG2.mjs.map → LocalStateStore-D1VfxRuK.mjs.map} +1 -1
- package/dist/{OpenApiTsGenerator-CdUM6Hvv.cjs → OpenApiTsGenerator-B--HV-sW.cjs} +2 -2
- package/dist/{OpenApiTsGenerator-CdUM6Hvv.cjs.map → OpenApiTsGenerator-B--HV-sW.cjs.map} +1 -1
- package/dist/{OpenApiTsGenerator-ByRPMbBN.mjs → OpenApiTsGenerator-CkvsPdgg.mjs} +2 -2
- package/dist/{OpenApiTsGenerator-ByRPMbBN.mjs.map → OpenApiTsGenerator-CkvsPdgg.mjs.map} +1 -1
- package/dist/{S3StateStore-35YfcdL_.cjs → S3StateStore-BPM74zwv.cjs} +2 -2
- package/dist/{S3StateStore-35YfcdL_.cjs.map → S3StateStore-BPM74zwv.cjs.map} +1 -1
- package/dist/{S3StateStore-C9upSW5o.mjs → S3StateStore-DVZ1YuGJ.mjs} +2 -2
- package/dist/{S3StateStore-C9upSW5o.mjs.map → S3StateStore-DVZ1YuGJ.mjs.map} +1 -1
- package/dist/{SSMStateStore-dOmFO6g1.mjs → SSMStateStore-DLvnGyyl.mjs} +2 -2
- package/dist/{SSMStateStore-dOmFO6g1.mjs.map → SSMStateStore-DLvnGyyl.mjs.map} +1 -1
- package/dist/{SSMStateStore-W-Ps22AQ.cjs → SSMStateStore-qerm5c36.cjs} +2 -2
- package/dist/{SSMStateStore-W-Ps22AQ.cjs.map → SSMStateStore-qerm5c36.cjs.map} +1 -1
- package/dist/{SubscriberGenerator-DQZeGkDW.mjs → SubscriberGenerator-BPqQf8fB.mjs} +2 -2
- package/dist/{SubscriberGenerator-DQZeGkDW.mjs.map → SubscriberGenerator-BPqQf8fB.mjs.map} +1 -1
- package/dist/{SubscriberGenerator-CYriX5BV.cjs → SubscriberGenerator-BVn7cQ-2.cjs} +2 -2
- package/dist/{SubscriberGenerator-CYriX5BV.cjs.map → SubscriberGenerator-BVn7cQ-2.cjs.map} +1 -1
- package/dist/{add-1T3y6E4M.cjs → add-BQ8v1ZII.cjs} +3 -3
- package/dist/{add-1T3y6E4M.cjs.map → add-BQ8v1ZII.cjs.map} +1 -1
- package/dist/{add-DnYHJOap.mjs → add-DbnzC7Kl.mjs} +3 -3
- package/dist/{add-DnYHJOap.mjs.map → add-DbnzC7Kl.mjs.map} +1 -1
- package/dist/{bundler-DlKdxCGh.mjs → bundler-D4030Afw.mjs} +5 -5
- package/dist/{bundler-DlKdxCGh.mjs.map → bundler-D4030Afw.mjs.map} +1 -1
- package/dist/{bundler-YNvLdvlh.cjs → bundler-DjrRffko.cjs} +5 -5
- package/dist/{bundler-YNvLdvlh.cjs.map → bundler-DjrRffko.cjs.map} +1 -1
- package/dist/{cli-CWee1-wU.cjs → cli-D8YQAYUX.cjs} +3 -3
- package/dist/{cli-CWee1-wU.cjs.map → cli-D8YQAYUX.cjs.map} +1 -1
- package/dist/{cli-qMszGvDu.mjs → cli-DwTa9d_8.mjs} +3 -3
- package/dist/{cli-qMszGvDu.mjs.map → cli-DwTa9d_8.mjs.map} +1 -1
- package/dist/{compose-D4sD4Lgr.mjs → compose-C5wz8mf9.mjs} +64 -24
- package/dist/compose-C5wz8mf9.mjs.map +1 -0
- package/dist/{compose-qnDyPJNp.cjs → compose-DqWh1TaO.cjs} +64 -24
- package/dist/compose-DqWh1TaO.cjs.map +1 -0
- package/dist/{config-Mr4rcXFC.d.cts → config-BzIfP8a-.d.cts} +16 -3
- package/dist/config-BzIfP8a-.d.cts.map +1 -0
- package/dist/{config-L_6NivCp.d.mts → config-DhdzmndX.d.mts} +16 -3
- package/dist/config-DhdzmndX.d.mts.map +1 -0
- package/dist/config.cjs +1 -1
- package/dist/config.d.cts +3 -3
- package/dist/config.d.mts +3 -3
- package/dist/config.mjs +1 -1
- package/dist/deploy/public.cjs +6 -6
- package/dist/deploy/public.d.cts +3 -3
- package/dist/deploy/public.d.cts.map +1 -1
- package/dist/deploy/public.d.mts +3 -3
- package/dist/deploy/public.d.mts.map +1 -1
- package/dist/deploy/public.mjs +6 -6
- package/dist/{deploy-C00DAKOt.mjs → deploy-BwIKGxWH.mjs} +14 -5
- package/dist/deploy-BwIKGxWH.mjs.map +1 -0
- package/dist/{deploy-CXP2fXvK.cjs → deploy-C8sWg81_.cjs} +14 -5
- package/dist/deploy-C8sWg81_.cjs.map +1 -0
- package/dist/{dokploy-BHcSmghb.cjs → dokploy-BkRxJbfi.cjs} +2 -2
- package/dist/{dokploy-BHcSmghb.cjs.map → dokploy-BkRxJbfi.cjs.map} +1 -1
- package/dist/{dokploy-B3zoCmJb.mjs → dokploy-ijjms1-h.mjs} +2 -2
- package/dist/{dokploy-B3zoCmJb.mjs.map → dokploy-ijjms1-h.mjs.map} +1 -1
- package/dist/{drivers-B4RP2B2O.mjs → drivers-DTZzxeIl.mjs} +2 -2
- package/dist/{drivers-B4RP2B2O.mjs.map → drivers-DTZzxeIl.mjs.map} +1 -1
- package/dist/{drivers-CJx76mcb.cjs → drivers-LYSdQDmd.cjs} +2 -2
- package/dist/{drivers-CJx76mcb.cjs.map → drivers-LYSdQDmd.cjs.map} +1 -1
- package/dist/{encryption-DPFljXtM.mjs → encryption-BRcBAmjL.mjs} +3 -3
- package/dist/{encryption-DPFljXtM.mjs.map → encryption-BRcBAmjL.mjs.map} +1 -1
- package/dist/{encryption-DLin89I_.cjs → encryption-g6PzwwfL.cjs} +3 -3
- package/dist/{encryption-DLin89I_.cjs.map → encryption-g6PzwwfL.cjs.map} +1 -1
- package/dist/{engine-CgzgIg-_.mjs → engine-BP0CZ5fh.mjs} +33 -13
- package/dist/engine-BP0CZ5fh.mjs.map +1 -0
- package/dist/{engine-BS3iX9Mu.cjs → engine-DLEJsZ3i.cjs} +33 -13
- package/dist/engine-DLEJsZ3i.cjs.map +1 -0
- package/dist/{github-D8KVmNRg.cjs → github-B8YjwdLK.cjs} +3 -3
- package/dist/{github-D8KVmNRg.cjs.map → github-B8YjwdLK.cjs.map} +1 -1
- package/dist/{github-DL4zwJsR.mjs → github-Zs-dVJbR.mjs} +3 -3
- package/dist/{github-DL4zwJsR.mjs.map → github-Zs-dVJbR.mjs.map} +1 -1
- package/dist/{index-C0UmP_lg.d.mts → index-D1ODeM9s.d.cts} +7 -3
- package/dist/index-D1ODeM9s.d.cts.map +1 -0
- package/dist/{index-DTEPwLml.d.cts → index-f77HdqN5.d.mts} +7 -3
- package/dist/index-f77HdqN5.d.mts.map +1 -0
- package/dist/index.cjs +553 -134
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +553 -134
- package/dist/index.mjs.map +1 -1
- package/dist/{migrate-DIjG8-QR.cjs → migrate-BfZN1S32.cjs} +3 -3
- package/dist/{migrate-DIjG8-QR.cjs.map → migrate-BfZN1S32.cjs.map} +1 -1
- package/dist/{migrate-CCejlgU0.mjs → migrate-CdXcX0XR.mjs} +3 -3
- package/dist/{migrate-CCejlgU0.mjs.map → migrate-CdXcX0XR.mjs.map} +1 -1
- package/dist/{migrate-Cd3kcI7o.mjs → migrate-DOMU4uKe.mjs} +3 -3
- package/dist/{migrate-Cd3kcI7o.mjs.map → migrate-DOMU4uKe.mjs.map} +1 -1
- package/dist/{migrate-BdKhIJgT.cjs → migrate-FoL_mZIz.cjs} +3 -3
- package/dist/{migrate-BdKhIJgT.cjs.map → migrate-FoL_mZIz.cjs.map} +1 -1
- package/dist/openapi.cjs +3 -3
- package/dist/openapi.d.cts +1 -1
- package/dist/openapi.d.mts +1 -1
- package/dist/openapi.mjs +3 -3
- package/dist/{ready-4kx2pAhm.cjs → ready-BpNbORRB.cjs} +5 -5
- package/dist/{ready-4kx2pAhm.cjs.map → ready-BpNbORRB.cjs.map} +1 -1
- package/dist/{ready-DhZbZtFw.mjs → ready-b6vm0-W-.mjs} +5 -5
- package/dist/{ready-DhZbZtFw.mjs.map → ready-b6vm0-W-.mjs.map} +1 -1
- package/dist/reconcile/public.d.cts +1 -1
- package/dist/reconcile/public.d.mts +1 -1
- package/dist/{resolve-ApSUK_HB.cjs → resolve-T2I-5FcT.cjs} +3 -3
- package/dist/{resolve-ApSUK_HB.cjs.map → resolve-T2I-5FcT.cjs.map} +1 -1
- package/dist/{resolve-DY9TaVeV.mjs → resolve-r7PAs6ng.mjs} +3 -3
- package/dist/{resolve-DY9TaVeV.mjs.map → resolve-r7PAs6ng.mjs.map} +1 -1
- package/dist/{rollback-DXU6cr7q.mjs → rollback-BSdxnW3X.mjs} +5 -5
- package/dist/{rollback-DXU6cr7q.mjs.map → rollback-BSdxnW3X.mjs.map} +1 -1
- package/dist/{rollback-CdGhCk1d.cjs → rollback-CPSDjGse.cjs} +5 -5
- package/dist/{rollback-CdGhCk1d.cjs.map → rollback-CPSDjGse.cjs.map} +1 -1
- package/dist/{runtime-ekxfPNM-.d.mts → runtime-CNu2C2hB.d.mts} +2 -2
- package/dist/{runtime-D6A-C6zh.d.cts.map → runtime-CNu2C2hB.d.mts.map} +1 -1
- package/dist/{runtime-D6A-C6zh.d.cts → runtime-DMLgL26v.d.cts} +2 -2
- package/dist/{runtime-ekxfPNM-.d.mts.map → runtime-DMLgL26v.d.cts.map} +1 -1
- package/dist/{seeds-DbyqaXW4.mjs → seeds-BK8caVMm.mjs} +1707 -1612
- package/dist/seeds-BK8caVMm.mjs.map +1 -0
- package/dist/{seeds-BLzrSwEr.cjs → seeds-DQ0FG57Z.cjs} +2558 -2421
- package/dist/seeds-DQ0FG57Z.cjs.map +1 -0
- package/dist/{sniffer-ByWtH28i.mjs → sniffer-CqE_KTTp.mjs} +6 -6
- package/dist/{sniffer-ByWtH28i.mjs.map → sniffer-CqE_KTTp.mjs.map} +1 -1
- package/dist/{sniffer-BjG-1mlD.cjs → sniffer-hSf5mRgV.cjs} +6 -6
- package/dist/{sniffer-BjG-1mlD.cjs.map → sniffer-hSf5mRgV.cjs.map} +1 -1
- package/dist/stages-CS1sjcRb.cjs +174 -0
- package/dist/stages-CS1sjcRb.cjs.map +1 -0
- package/dist/stages-CSXt7N2b.mjs +174 -0
- package/dist/stages-CSXt7N2b.mjs.map +1 -0
- package/dist/target/public.cjs +1 -1
- package/dist/target/public.d.cts +2 -2
- package/dist/target/public.d.mts +2 -2
- package/dist/target/public.mjs +1 -1
- package/dist/{types-DZtj9jeI.d.cts → types-BZn-8ssD.d.mts} +75 -22
- package/dist/types-BZn-8ssD.d.mts.map +1 -0
- package/dist/{types-BzCavjGt.d.mts → types-DiZj6hqp.d.cts} +76 -21
- package/dist/types-DiZj6hqp.d.cts.map +1 -0
- package/dist/vitest.cjs +1 -1
- package/dist/vitest.mjs +1 -1
- package/dist/workspace/index.cjs +2 -1
- package/dist/workspace/index.d.cts +3 -3
- package/dist/workspace/index.d.mts +3 -3
- package/dist/workspace/index.mjs +2 -2
- package/dist/{workspace-Bp8FEkF-.cjs → workspace-Bic_R3tz.cjs} +345 -99
- package/dist/workspace-Bic_R3tz.cjs.map +1 -0
- package/dist/{workspace-BBdqmkch.mjs → workspace-Drz4jsvy.mjs} +314 -98
- package/dist/workspace-Drz4jsvy.mjs.map +1 -0
- package/package.json +15 -15
- package/dist/EndpointGenerator-DtnIGafh.mjs.map +0 -1
- package/dist/EndpointGenerator-cKlnllIu.cjs.map +0 -1
- package/dist/compose-D4sD4Lgr.mjs.map +0 -1
- package/dist/compose-qnDyPJNp.cjs.map +0 -1
- package/dist/config-L_6NivCp.d.mts.map +0 -1
- package/dist/config-Mr4rcXFC.d.cts.map +0 -1
- package/dist/deploy-C00DAKOt.mjs.map +0 -1
- package/dist/deploy-CXP2fXvK.cjs.map +0 -1
- package/dist/engine-BS3iX9Mu.cjs.map +0 -1
- package/dist/engine-CgzgIg-_.mjs.map +0 -1
- package/dist/index-C0UmP_lg.d.mts.map +0 -1
- package/dist/index-DTEPwLml.d.cts.map +0 -1
- package/dist/seeds-BLzrSwEr.cjs.map +0 -1
- package/dist/seeds-DbyqaXW4.mjs.map +0 -1
- package/dist/types-BzCavjGt.d.mts.map +0 -1
- package/dist/types-DZtj9jeI.d.cts.map +0 -1
- package/dist/workspace-BBdqmkch.mjs.map +0 -1
- package/dist/workspace-Bp8FEkF-.cjs.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -4,22 +4,22 @@ import { r as DEFAULT_TIMEOUT_MS, t as CommandFailed } from "./run-BJLIerMM.mjs"
|
|
|
4
4
|
import { c as getDokployCredentials, f as removeDokployCredentials, i as LocalSandbox, l as getDokployRegistryId, m as storeHostingerToken, p as storeDokployCredentials, s as getCredentialsPath, u as getDokployToken } from "./credentials-pAtB70k3.mjs";
|
|
5
5
|
import { l as withOwningTsconfigJsx, r as discover, u as ConstructGenerator } from "./discover-BPelzeGW.mjs";
|
|
6
6
|
import { t as appKey } from "./derive-B4vDpzgP.mjs";
|
|
7
|
-
import {
|
|
7
|
+
import { I as stageSampleRate, M as deployedProblems, N as stageProblems, O as InvalidStages, c as getAppBuildOrder, k as TEST_STAGE, l as getAppGkmConfig, r as allConstructGlobs } from "./workspace-Drz4jsvy.mjs";
|
|
8
8
|
import { ConfigNotFound, NotABackendApp, NotInAnApp, loadAppConfig, loadConfig, loadWorkspaceConfig, loadWorkspaceSettings, parseModuleConfig } from "./config.mjs";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
9
|
+
import { $t as describeServices, An as maskPassword, B as WorkerGenerator, F as parseDevServices, Ft as cacheBackendFor, G as FAKE_ENV, H as workerEntryDir, Ht as TELEMETRY_CONTAINER, It as eventsBackendFor, J as derivedContainers, Jt as scopeTelemetryEnv, K as backendsOf$1, Kt as appTelemetry, Lt as providerOf, Mn as toEmbeddableSecrets, Nn as withCustomSecret, Nt as imageBuildCredentials, Pn as LOCAL_LOGS_EMAIL, Pt as isImageBuild, Sn as deployIdentity, U as QueueGenerator, V as workerBundleName, W as CronGenerator, Xt as telemetryOf, Y as reconcileWorkspace, Yt as surfaceClientTraced, _n as getKeyPath, an as createEntryWrapper, bt as pgClient, cn as loadEnvFiles, ct as LOCAL_CA_PATH, dn as prepareEntryCredentials, en as fakeKey, et as readLocalCredentials, gn as FileSecretsStore, gt as quoteIdentifier, in as createCredentialsPreload, ln as loadPortState, lt as forgetState, mt as postgresDatabaseNames, nn as portsOf, on as findAvailablePort, pn as secretsStoreFor, q as constructGlobs, rn as primaryPortKey, sn as isPortAvailable, un as loadSecretsForApp, x as dockerCommand, yn as projectKey, z as workerUnits, zt as CLUSTER_DATABASE } from "./seeds-BK8caVMm.mjs";
|
|
10
|
+
import { c as startTelemetryCode, l as telemetryFor, n as runtimeFor, o as mountRequestSpansCode, r as parseTelemetryFlag, s as routeTelemetry, t as EndpointGenerator, u as writeTelemetryModule } from "./EndpointGenerator-CVc6Oi1Y.mjs";
|
|
11
11
|
import { generateOpenApi, openapiCommand, resolveOpenApiConfig } from "./openapi.mjs";
|
|
12
|
-
import { s as isCacheBackend, t as SubscriberGenerator } from "./SubscriberGenerator-
|
|
12
|
+
import { s as isCacheBackend, t as SubscriberGenerator } from "./SubscriberGenerator-BPqQf8fB.mjs";
|
|
13
13
|
import { a as describeHolder, i as assignAppPorts, o as holderOf, r as appTag, s as withAppPorts, t as APP_TAG_ENV } from "./appPorts-C9z9Pzn9.mjs";
|
|
14
|
-
import { n as driversFor, r as eventsBackendsIn, t as cacheBackendsIn } from "./drivers-
|
|
14
|
+
import { n as driversFor, r as eventsBackendsIn, t as cacheBackendsIn } from "./drivers-DTZzxeIl.mjs";
|
|
15
15
|
import { n as withCompute, r as withRoutes, t as manifestModule } from "./emit-C1e8qD08.mjs";
|
|
16
|
-
import { g as createStateStore, n as sniffAppEnvironment, o as DokployApi, x as keyFingerprint } from "./sniffer-
|
|
17
|
-
import { t as deploy$1 } from "./deploy-
|
|
18
|
-
import { a as stackOverrideFile, c as parseDigests, d as removeEdgeRoutes, f as EDGE_PROJECT, i as ComposePushNeedsBuild, l as pinnedRef, o as composeProject, p as dockerCompose, r as ComposePinNeedsPull, s as stackDir, t as composeTarget, u as edgeDir } from "./compose-
|
|
16
|
+
import { g as createStateStore, n as sniffAppEnvironment, o as DokployApi, x as keyFingerprint } from "./sniffer-CqE_KTTp.mjs";
|
|
17
|
+
import { t as deploy$1 } from "./deploy-BwIKGxWH.mjs";
|
|
18
|
+
import { a as stackOverrideFile, c as parseDigests, d as removeEdgeRoutes, f as EDGE_PROJECT, i as ComposePushNeedsBuild, l as pinnedRef, o as composeProject, p as dockerCompose, r as ComposePinNeedsPull, s as stackDir, t as composeTarget, u as edgeDir } from "./compose-C5wz8mf9.mjs";
|
|
19
19
|
import { o as loadCredentialSchemas, t as CredentialsInvalid } from "./credentialSchemas-BJqRJNK4.mjs";
|
|
20
|
-
import { t as LocalStateStore } from "./LocalStateStore-
|
|
20
|
+
import { t as LocalStateStore } from "./LocalStateStore-D1VfxRuK.mjs";
|
|
21
21
|
import { a as getExecCommand, c as validateProjectName, i as findWorkspaceRoot, n as detectPackageManager$1, o as getInstallCommand, r as findWorkspacePackages, s as getRunCommand, t as checkDirectoryExists } from "./utils-D_fxUqvU.mjs";
|
|
22
|
-
import { a as writeTestHarness, i as TEST_MANIFEST_ENV, n as TEST_READY_FILE, t as TEST_READY_ENV } from "./ready-
|
|
22
|
+
import { a as writeTestHarness, i as TEST_MANIFEST_ENV, n as TEST_READY_FILE, t as TEST_READY_ENV } from "./ready-b6vm0-W-.mjs";
|
|
23
23
|
import { createRequire } from "node:module";
|
|
24
24
|
import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
25
25
|
import { Command, Option } from "commander";
|
|
@@ -47,7 +47,7 @@ import crypto from "crypto";
|
|
|
47
47
|
import { Function } from "@geekmidas/constructs/functions";
|
|
48
48
|
import { Topic } from "@geekmidas/constructs/topic";
|
|
49
49
|
//#region package.json
|
|
50
|
-
var version = "10.0.0-alpha.
|
|
50
|
+
var version = "10.0.0-alpha.84";
|
|
51
51
|
//#endregion
|
|
52
52
|
//#region src/prompt.ts
|
|
53
53
|
/**
|
|
@@ -130,7 +130,7 @@ const logger$8 = console;
|
|
|
130
130
|
* Validate Dokploy token by making a test API call
|
|
131
131
|
*/
|
|
132
132
|
async function validateDokployToken(endpoint, token) {
|
|
133
|
-
const { DokployApi } = await import("./sniffer-
|
|
133
|
+
const { DokployApi } = await import("./sniffer-CqE_KTTp.mjs").then((n) => n.c);
|
|
134
134
|
return new DokployApi({
|
|
135
135
|
baseUrl: endpoint,
|
|
136
136
|
token
|
|
@@ -530,10 +530,9 @@ var NoLocalCredentials = class extends Error {
|
|
|
530
530
|
/** The logins of every service the workspace last published. */
|
|
531
531
|
function devCredentials(workspace, credentials, ports) {
|
|
532
532
|
const containers = SIGNED_IN.filter((container) => portsOf(container).some((port) => ports[port.key] !== void 0));
|
|
533
|
-
const
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
via: `gkm compose --stage ${workspace.stages.local}`
|
|
533
|
+
const local = ports.openobserve !== void 0 ? {
|
|
534
|
+
url: `http://localhost:${ports.openobserve}`,
|
|
535
|
+
via: "gkm dev"
|
|
537
536
|
} : void 0;
|
|
538
537
|
return {
|
|
539
538
|
workspace: workspace.name,
|
|
@@ -753,6 +752,7 @@ async function collect(records) {
|
|
|
753
752
|
root,
|
|
754
753
|
stage: lead.workspace.stage,
|
|
755
754
|
manifest: group.find((r) => r.manifest)?.manifest ?? null,
|
|
755
|
+
telemetry: group.find((r) => r.telemetry)?.telemetry ?? null,
|
|
756
756
|
apps: discovered,
|
|
757
757
|
allowedOrigins: [...new Set(group.flatMap((r) => r.allowedOrigins))]
|
|
758
758
|
});
|
|
@@ -1097,6 +1097,7 @@ var DiscoverySession = class DiscoverySession {
|
|
|
1097
1097
|
workspace: options.workspace,
|
|
1098
1098
|
allowedOrigins: [...options.allowedOrigins ?? []],
|
|
1099
1099
|
...options.manifest ? { manifest: options.manifest } : {},
|
|
1100
|
+
...options.telemetry ? { telemetry: options.telemetry } : {},
|
|
1100
1101
|
apps: options.apps
|
|
1101
1102
|
};
|
|
1102
1103
|
writeRecord(registry, record);
|
|
@@ -1850,7 +1851,8 @@ async function devCommand(options) {
|
|
|
1850
1851
|
hooks,
|
|
1851
1852
|
skipBundle: true,
|
|
1852
1853
|
bustCache,
|
|
1853
|
-
serveEmpty: true
|
|
1854
|
+
serveEmpty: true,
|
|
1855
|
+
workspaceName: workspace.name
|
|
1854
1856
|
}));
|
|
1855
1857
|
logger$5.log(`🔨 Building ${workspaceAppName ?? "the app"}`);
|
|
1856
1858
|
const initial = await build();
|
|
@@ -1858,6 +1860,7 @@ async function devCommand(options) {
|
|
|
1858
1860
|
let secretsJsonPath;
|
|
1859
1861
|
let publicUrl;
|
|
1860
1862
|
let manifest;
|
|
1863
|
+
let telemetryUi;
|
|
1861
1864
|
const appSecrets = await loadSecretsForApp(workspace ? await secretsStoreFor(workspace, config.stages.local) : new FileSecretsStore(secretsRoot), config.stages.local);
|
|
1862
1865
|
if (workspace) {
|
|
1863
1866
|
const reconciled = await reconcileWorkspace(workspace, {
|
|
@@ -1869,10 +1872,25 @@ async function devCommand(options) {
|
|
|
1869
1872
|
logger$5.log("🐳 Services");
|
|
1870
1873
|
for (const line of describeServices(reconciled.services)) logger$5.log(line);
|
|
1871
1874
|
}
|
|
1875
|
+
if (!process.env["GKM_DISCOVERY_QUIET"] && reconciled.credentials && reconciled.ports) {
|
|
1876
|
+
const { services: logins } = devCredentials(workspace, reconciled.credentials, reconciled.ports);
|
|
1877
|
+
if (logins.length > 0) {
|
|
1878
|
+
logger$5.log("🔑 Logins (again any time: gkm dev:credentials)");
|
|
1879
|
+
for (const line of describeLogins(logins)) logger$5.log(line);
|
|
1880
|
+
}
|
|
1881
|
+
}
|
|
1872
1882
|
Object.assign(appSecrets, reconciled.env);
|
|
1883
|
+
const scoped = scopeTelemetryEnv(appSecrets, {
|
|
1884
|
+
uses: reconciled.manifest !== void 0 && appTelemetry(reconciled.manifest, workspaceAppName) !== void 0,
|
|
1885
|
+
serviceName: workspaceAppName,
|
|
1886
|
+
telemetry: reconciled.env
|
|
1887
|
+
});
|
|
1888
|
+
for (const key of Object.keys(appSecrets)) if (!(key in scoped)) delete appSecrets[key];
|
|
1889
|
+
Object.assign(appSecrets, scoped);
|
|
1873
1890
|
const own = reconciled.plan.resources.find((r) => (r.kind === "rest-api" || r.kind === "site") && appKey(r.id) === workspaceAppName);
|
|
1874
1891
|
publicUrl = own ? reconciled.env[own.envKey] : void 0;
|
|
1875
1892
|
manifest = reconciled.manifest;
|
|
1893
|
+
telemetryUi = telemetryUiOf(reconciled.services);
|
|
1876
1894
|
}
|
|
1877
1895
|
if (Object.keys(appSecrets).length > 0) {
|
|
1878
1896
|
const secretsDir = join(secretsRoot, ".gkm");
|
|
@@ -1895,6 +1913,7 @@ async function devCommand(options) {
|
|
|
1895
1913
|
},
|
|
1896
1914
|
allowedOrigins: workspace.dev?.allowedOrigins ?? [],
|
|
1897
1915
|
...manifest ? { manifest } : {},
|
|
1916
|
+
...telemetryUi ? { telemetry: telemetryUi } : {},
|
|
1898
1917
|
apps: [{
|
|
1899
1918
|
name: workspaceAppName,
|
|
1900
1919
|
type: "backend",
|
|
@@ -2203,17 +2222,20 @@ async function workspaceDevCommand(configured, options) {
|
|
|
2203
2222
|
logger$5.log("🔑 Logins (again any time: gkm dev:credentials)");
|
|
2204
2223
|
for (const line of describeLogins(logins)) logger$5.log(line);
|
|
2205
2224
|
}
|
|
2206
|
-
const secretsEnv = {
|
|
2225
|
+
const secretsEnv = scopeTelemetryEnv({
|
|
2207
2226
|
...rawSecrets,
|
|
2208
2227
|
...reconciled.env
|
|
2209
|
-
}
|
|
2228
|
+
}, {
|
|
2229
|
+
uses: false,
|
|
2230
|
+
serviceName: workspace.name
|
|
2231
|
+
});
|
|
2210
2232
|
const fakes = options.fake ? await serveFakes(reconciled.fakes, reconciled.ports) : [];
|
|
2211
2233
|
for (const { id, port } of fakes) logger$5.log(`🎭 ${id} fake: http://localhost:${port}`);
|
|
2212
2234
|
logger$5.log(options.migrate || options.seed ? "🗄️ Migrating the databases" : "🗄️ Checking for pending migrations");
|
|
2213
2235
|
if (options.migrate || options.seed) {
|
|
2214
|
-
const { prepareDevDatabases } = await import("./migrate-
|
|
2236
|
+
const { prepareDevDatabases } = await import("./migrate-CdXcX0XR.mjs");
|
|
2215
2237
|
await prepareDevDatabases(workspace, reconciled.env, { seed: !!options.seed });
|
|
2216
|
-
} else await import("./migrate-
|
|
2238
|
+
} else await import("./migrate-CdXcX0XR.mjs").then(({ reportPendingMigrations }) => reportPendingMigrations(workspace, reconciled.env)).catch((error) => {
|
|
2217
2239
|
logger$5.log(`⚠️ Could not check for pending migrations: ${error instanceof Error ? error.message : String(error)}`);
|
|
2218
2240
|
});
|
|
2219
2241
|
const appUrls = {};
|
|
@@ -2268,6 +2290,7 @@ async function workspaceDevCommand(configured, options) {
|
|
|
2268
2290
|
break;
|
|
2269
2291
|
}
|
|
2270
2292
|
}
|
|
2293
|
+
const workspaceTelemetry = telemetryUiOf(reconciled.services);
|
|
2271
2294
|
const discovery = await joinDiscovery({
|
|
2272
2295
|
role: "workspace",
|
|
2273
2296
|
port: discoveryPort(workspace.dev),
|
|
@@ -2278,6 +2301,7 @@ async function workspaceDevCommand(configured, options) {
|
|
|
2278
2301
|
},
|
|
2279
2302
|
allowedOrigins: workspace.dev?.allowedOrigins ?? [],
|
|
2280
2303
|
...reconciled.manifest ? { manifest: reconciled.manifest } : {},
|
|
2304
|
+
...workspaceTelemetry ? { telemetry: workspaceTelemetry } : {},
|
|
2281
2305
|
apps: buildOrder.flatMap((name) => {
|
|
2282
2306
|
const app = workspace.apps[name];
|
|
2283
2307
|
if (!app) return [];
|
|
@@ -2475,6 +2499,18 @@ var EntryRunner = class {
|
|
|
2475
2499
|
}
|
|
2476
2500
|
};
|
|
2477
2501
|
/**
|
|
2502
|
+
* Where the local OpenObserve is, and who signs in to it, when reconcile runs
|
|
2503
|
+
* one — for the discovery endpoint, which is told no password.
|
|
2504
|
+
*/
|
|
2505
|
+
function telemetryUiOf(services) {
|
|
2506
|
+
const ui = services.find((s) => s.container === TELEMETRY_CONTAINER);
|
|
2507
|
+
if (!ui) return void 0;
|
|
2508
|
+
return {
|
|
2509
|
+
url: ui.address,
|
|
2510
|
+
email: LOCAL_LOGS_EMAIL
|
|
2511
|
+
};
|
|
2512
|
+
}
|
|
2513
|
+
/**
|
|
2478
2514
|
* Generate the content of the dev server entry file (server.ts).
|
|
2479
2515
|
* Uses dynamic import for createApp so Credentials are populated
|
|
2480
2516
|
* before any app modules evaluate.
|
|
@@ -2520,6 +2556,7 @@ if (existsSync(secretsPath)) {
|
|
|
2520
2556
|
injectWs(server);
|
|
2521
2557
|
console.log('🔌 Telescope real-time updates enabled');
|
|
2522
2558
|
}`;
|
|
2559
|
+
const telemetry = startTelemetryCode(["/health", "/ready"]);
|
|
2523
2560
|
if (selfServing) return `#!/usr/bin/env node
|
|
2524
2561
|
/**
|
|
2525
2562
|
* Development server entry point for a surface that serves itself
|
|
@@ -2529,8 +2566,17 @@ ${credentialsInjection}${parentWatch}const port = process.argv.includes('--port'
|
|
|
2529
2566
|
? Number.parseInt(process.argv[process.argv.indexOf('--port') + 1])
|
|
2530
2567
|
: 3000;
|
|
2531
2568
|
|
|
2569
|
+
${telemetry}
|
|
2532
2570
|
// Dynamic import so Credentials are populated before the surface evaluates
|
|
2533
|
-
const { app } = await import('${appImportPath}');
|
|
2571
|
+
const { app: surface } = await import('${appImportPath}');
|
|
2572
|
+
|
|
2573
|
+
// Behind the request spans when there are any, as the production server is.
|
|
2574
|
+
const { Hono } = await import('hono');
|
|
2575
|
+
const app = requestSpans ? new Hono() : surface;
|
|
2576
|
+
if (requestSpans) {
|
|
2577
|
+
${mountRequestSpansCode("app").trim().replace(/\n/g, "\n ")}
|
|
2578
|
+
app.route('/', surface);
|
|
2579
|
+
}
|
|
2534
2580
|
|
|
2535
2581
|
${serveCode.replace(/^ {4}/gm, "")}
|
|
2536
2582
|
`;
|
|
@@ -2543,11 +2589,16 @@ ${credentialsInjection}${parentWatch}const port = process.argv.includes('--port'
|
|
|
2543
2589
|
? Number.parseInt(process.argv[process.argv.indexOf('--port') + 1])
|
|
2544
2590
|
: 3000;
|
|
2545
2591
|
|
|
2592
|
+
${telemetry}
|
|
2546
2593
|
// Dynamic import so Credentials are populated before env.ts evaluates
|
|
2547
2594
|
const { createApp } = await import('${appImportPath}');
|
|
2548
2595
|
|
|
2596
|
+
// The span middleware first, as the production server mounts it.
|
|
2597
|
+
const { Hono } = await import('hono');
|
|
2598
|
+
const root = new Hono();
|
|
2599
|
+
${mountRequestSpansCode("root")}
|
|
2549
2600
|
// createApp is async to support optional WebSocket setup
|
|
2550
|
-
const { app, start } = await createApp(
|
|
2601
|
+
const { app, start } = await createApp(root, ${enableOpenApi});
|
|
2551
2602
|
|
|
2552
2603
|
// Start the server
|
|
2553
2604
|
start({
|
|
@@ -2989,6 +3040,7 @@ export default app;
|
|
|
2989
3040
|
*/
|
|
2990
3041
|
async function writeSurfaceServer(outputDir, options) {
|
|
2991
3042
|
await mkdir(outputDir, { recursive: true });
|
|
3043
|
+
await writeTelemetryModule(outputDir, options.telemetry);
|
|
2992
3044
|
const shutdown = options.gracefulShutdown ? `
|
|
2993
3045
|
// Stop taking requests, let in-flight ones finish, then close what the
|
|
2994
3046
|
// construct opened — bounded by GKM_SHUTDOWN_TIMEOUT_MS, under Docker's 10s
|
|
@@ -3015,12 +3067,14 @@ process.on('SIGINT', shutdown);
|
|
|
3015
3067
|
*/
|
|
3016
3068
|
import { serve } from '@hono/node-server';
|
|
3017
3069
|
import { Hono } from 'hono';
|
|
3018
|
-
${options.gracefulShutdown ? "import { runShutdownHooks } from '@geekmidas/constructs';\n" : ""}
|
|
3070
|
+
${options.gracefulShutdown ? "import { runShutdownHooks } from '@geekmidas/constructs';\n" : ""}
|
|
3071
|
+
${startTelemetryCode([options.healthCheck])}
|
|
3072
|
+
const { app: surface } = await import('./app.js');
|
|
3019
3073
|
|
|
3020
3074
|
const port = Number(process.env.PORT) || 3000;
|
|
3021
3075
|
|
|
3022
3076
|
const app = new Hono();
|
|
3023
|
-
// First, so a probe is answered without reaching the surface's own routes.
|
|
3077
|
+
${mountRequestSpansCode("app")}// First, so a probe is answered without reaching the surface's own routes.
|
|
3024
3078
|
app.get(${JSON.stringify(options.healthCheck)}, (c) =>
|
|
3025
3079
|
c.json({ status: 'ok', timestamp: Date.now() }),
|
|
3026
3080
|
);
|
|
@@ -3217,11 +3271,23 @@ async function buildApp(input) {
|
|
|
3217
3271
|
});
|
|
3218
3272
|
if (selfServing) {
|
|
3219
3273
|
await writeSurfaceEntry(join(appRoot, ".gkm", "server"), selfServing.source);
|
|
3274
|
+
const telemetry = telemetryFor({
|
|
3275
|
+
node: telemetryOf(declared, selfServing.id),
|
|
3276
|
+
appRoot,
|
|
3277
|
+
app: appNameOf(input),
|
|
3278
|
+
cwd: workspaceRoot,
|
|
3279
|
+
serviceName: selfServing.id,
|
|
3280
|
+
...input.workspaceName && { workspaceName: input.workspaceName }
|
|
3281
|
+
});
|
|
3282
|
+
await writeTelemetryModule(join(appRoot, ".gkm", "server"), telemetry);
|
|
3220
3283
|
logger$4.log(`Generated a server for ${selfServing.id} from its own declaration`);
|
|
3221
3284
|
if (production?.bundle && !input.skipBundle) {
|
|
3222
3285
|
const outputDir = join(appRoot, ".gkm", "server");
|
|
3223
|
-
const entryPoint = await writeSurfaceServer(outputDir,
|
|
3224
|
-
|
|
3286
|
+
const entryPoint = await writeSurfaceServer(outputDir, {
|
|
3287
|
+
...production,
|
|
3288
|
+
...telemetry ? { telemetry } : {}
|
|
3289
|
+
});
|
|
3290
|
+
const { bundleServer } = await import("./bundler-D4030Afw.mjs");
|
|
3225
3291
|
await bundleServer({
|
|
3226
3292
|
entryPoint,
|
|
3227
3293
|
outputDir: join(outputDir, "dist"),
|
|
@@ -3256,12 +3322,7 @@ async function buildApp(input) {
|
|
|
3256
3322
|
events: eventsBackends
|
|
3257
3323
|
}),
|
|
3258
3324
|
eventsBackends,
|
|
3259
|
-
markOptional: input.markOptional ?? false
|
|
3260
|
-
...production && { telemetry: telemetryFor({
|
|
3261
|
-
appRoot,
|
|
3262
|
-
surfaceId: derived.surface?.id,
|
|
3263
|
-
workspaceName: input.workspaceName
|
|
3264
|
-
}) }
|
|
3325
|
+
markOptional: input.markOptional ?? false
|
|
3265
3326
|
};
|
|
3266
3327
|
const endpointGenerator = new EndpointGenerator();
|
|
3267
3328
|
const functionGenerator = new FunctionGenerator();
|
|
@@ -3279,6 +3340,15 @@ async function buildApp(input) {
|
|
|
3279
3340
|
topicGenerator.load(code, appRoot, bustCache)
|
|
3280
3341
|
]);
|
|
3281
3342
|
const allEndpoints = servedBy(loadedEndpoints, derived.surface);
|
|
3343
|
+
if (target === "server") buildContext.telemetry = telemetryFor({
|
|
3344
|
+
node: derived.surface ? telemetryOf(declared, derived.surface.id) : void 0,
|
|
3345
|
+
appRoot,
|
|
3346
|
+
app: appNameOf(input),
|
|
3347
|
+
cwd: workspaceRoot,
|
|
3348
|
+
serviceName: derived.surface?.id ?? basename(appRoot),
|
|
3349
|
+
...input.workspaceName && { workspaceName: input.workspaceName },
|
|
3350
|
+
routes: routeTelemetry(allEndpoints.map(({ construct }) => construct))
|
|
3351
|
+
});
|
|
3282
3352
|
logger$4.log(`Found ${allEndpoints.length} endpoints`);
|
|
3283
3353
|
logger$4.log(`Found ${allFunctions.length} functions`);
|
|
3284
3354
|
logger$4.log(`Found ${allCrons.length} crons`);
|
|
@@ -3306,6 +3376,14 @@ async function buildApp(input) {
|
|
|
3306
3376
|
const appName = Object.entries(input.workspace.apps).find(([, app]) => resolve(input.workspace.root, app.path) === resolve(appRoot))?.[0];
|
|
3307
3377
|
await buildWorkers({
|
|
3308
3378
|
context: buildContext,
|
|
3379
|
+
telemetry: (workerId) => telemetryFor({
|
|
3380
|
+
node: telemetryOf(declared, workerId),
|
|
3381
|
+
appRoot,
|
|
3382
|
+
app: appNameOf(input),
|
|
3383
|
+
cwd: workspaceRoot,
|
|
3384
|
+
serviceName: workerId,
|
|
3385
|
+
...input.workspaceName && { workspaceName: input.workspaceName }
|
|
3386
|
+
}),
|
|
3309
3387
|
workers: workerUnits(input.workspace, declared, background).filter((unit) => unit.app === appName),
|
|
3310
3388
|
serverDir: join(appRoot, ".gkm", "server"),
|
|
3311
3389
|
crons: allCrons,
|
|
@@ -3317,7 +3395,14 @@ async function buildApp(input) {
|
|
|
3317
3395
|
}
|
|
3318
3396
|
await generateOpenApi(allEndpoints.map(({ construct }) => construct), {
|
|
3319
3397
|
openapi: config.openapi,
|
|
3320
|
-
root: workspaceRoot
|
|
3398
|
+
root: workspaceRoot,
|
|
3399
|
+
...derived.surface ? clientTelemetry({
|
|
3400
|
+
manifest: declared,
|
|
3401
|
+
surfaceId: derived.surface.id,
|
|
3402
|
+
telemetry: input.workspace?.deploy?.telemetry,
|
|
3403
|
+
stage: input.stage,
|
|
3404
|
+
localStage: input.workspace?.stages.local ?? config.stages?.local
|
|
3405
|
+
}) : {}
|
|
3321
3406
|
});
|
|
3322
3407
|
return {
|
|
3323
3408
|
...result,
|
|
@@ -3335,9 +3420,11 @@ async function buildWorkers(input) {
|
|
|
3335
3420
|
const crons = owned(input.crons);
|
|
3336
3421
|
const queues = owned(input.queues);
|
|
3337
3422
|
const subscribers = owned(input.subscribers);
|
|
3423
|
+
const telemetry = input.telemetry(worker.id);
|
|
3338
3424
|
const entryPoint = await generator.build({
|
|
3339
3425
|
context: input.context,
|
|
3340
3426
|
workerId: worker.id,
|
|
3427
|
+
...telemetry ? { telemetry } : {},
|
|
3341
3428
|
outputDir: workerEntryDir(input.serverDir, worker.id),
|
|
3342
3429
|
crons,
|
|
3343
3430
|
queues,
|
|
@@ -3345,7 +3432,7 @@ async function buildWorkers(input) {
|
|
|
3345
3432
|
});
|
|
3346
3433
|
logger$4.log(`Generated worker ${worker.id}: ${crons.length} crons, ${queues.length} queues, ${subscribers.length} subscribers`);
|
|
3347
3434
|
if (!input.bundle) continue;
|
|
3348
|
-
const { bundleServer } = await import("./bundler-
|
|
3435
|
+
const { bundleServer } = await import("./bundler-D4030Afw.mjs");
|
|
3349
3436
|
const outfile = workerBundleName(worker.id);
|
|
3350
3437
|
await bundleServer({
|
|
3351
3438
|
entryPoint,
|
|
@@ -3364,6 +3451,22 @@ async function buildWorkers(input) {
|
|
|
3364
3451
|
logger$4.log(`✅ Bundle complete: .gkm/server/dist/${outfile}`);
|
|
3365
3452
|
}
|
|
3366
3453
|
}
|
|
3454
|
+
/**
|
|
3455
|
+
* Whether the surface's generated client propagates trace context, and at
|
|
3456
|
+
* what rate: on when a site that calls it has an edge to a `Telemetry`
|
|
3457
|
+
* construct, at the stage's sample rate — every trace locally, and on a build
|
|
3458
|
+
* for no stage. Off for a stage that sends no telemetry.
|
|
3459
|
+
*/
|
|
3460
|
+
function clientTelemetry(options) {
|
|
3461
|
+
if (!surfaceClientTraced(options.manifest, options.surfaceId)) return {};
|
|
3462
|
+
const local = !options.stage || options.stage === options.localStage;
|
|
3463
|
+
const sampleRate = stageSampleRate(options.telemetry, options.stage ?? "", local);
|
|
3464
|
+
return sampleRate === void 0 ? {} : { telemetry: { sampleRate } };
|
|
3465
|
+
}
|
|
3466
|
+
/** The app being built, by its workspace name or its directory's. */
|
|
3467
|
+
function appNameOf(input) {
|
|
3468
|
+
return (input.workspace ? Object.entries(input.workspace.apps).find(([, app]) => resolve(input.workspace.root, app.path) === resolve(input.appRoot))?.[0] : void 0) ?? basename(input.appRoot);
|
|
3469
|
+
}
|
|
3367
3470
|
async function buildForTarget(target, context, appRoot, workspaceRoot, endpointGenerator, functionGenerator, cronGenerator, subscriberGenerator, queueGenerator, topicGenerator, endpoints, functions, crons, subscribers, queues, topics, enableOpenApi, skipBundle, stage) {
|
|
3368
3471
|
const outputDir = join(appRoot, ".gkm", target);
|
|
3369
3472
|
await Promise.all([...SUPERSEDED_OUTPUT.map((dir) => join(appRoot, ".gkm", dir)), ...appRoot === workspaceRoot ? [] : [join(appRoot, ".gkm", "manifest")]].map((dir) => rm(dir, {
|
|
@@ -3415,7 +3518,7 @@ async function buildForTarget(target, context, appRoot, workspaceRoot, endpointG
|
|
|
3415
3518
|
let masterKey;
|
|
3416
3519
|
if (context.production?.bundle && !skipBundle) {
|
|
3417
3520
|
logger$4.log(`\n📦 Bundling production server...`);
|
|
3418
|
-
const { bundleServer } = await import("./bundler-
|
|
3521
|
+
const { bundleServer } = await import("./bundler-D4030Afw.mjs");
|
|
3419
3522
|
const allConstructs = [
|
|
3420
3523
|
...endpoints.map((e) => e.construct),
|
|
3421
3524
|
...functions.map((f) => f.construct),
|
|
@@ -5102,12 +5205,12 @@ const PNPM_VERSION = "pnpm@10.13.1";
|
|
|
5102
5205
|
const BIOME_SCHEMA = `https://biomejs.dev/schemas/${DEPENDENCY_VERSIONS["@biomejs/biome"].replace(/^[~^]/, "")}/schema.json`;
|
|
5103
5206
|
//#endregion
|
|
5104
5207
|
//#region src/init/versions.ts
|
|
5105
|
-
const require$
|
|
5208
|
+
const require$2 = createRequire(import.meta.url);
|
|
5106
5209
|
function loadPackageJson() {
|
|
5107
5210
|
try {
|
|
5108
|
-
return require$
|
|
5211
|
+
return require$2("../package.json");
|
|
5109
5212
|
} catch {
|
|
5110
|
-
return require$
|
|
5213
|
+
return require$2("../../package.json");
|
|
5111
5214
|
}
|
|
5112
5215
|
}
|
|
5113
5216
|
/**
|
|
@@ -5117,25 +5220,25 @@ function loadPackageJson() {
|
|
|
5117
5220
|
* Run: pnpm --filter @geekmidas/cli sync-versions
|
|
5118
5221
|
*/
|
|
5119
5222
|
const GEEKMIDAS_VERSIONS = {
|
|
5120
|
-
"@geekmidas/audit": "~10.0.0-alpha.
|
|
5121
|
-
"@geekmidas/auth": "~10.0.0-alpha.
|
|
5122
|
-
"@geekmidas/cache": "~10.0.0-alpha.
|
|
5123
|
-
"@geekmidas/client": "~10.0.0-alpha.
|
|
5124
|
-
"@geekmidas/cloud": "~10.0.0-alpha.
|
|
5125
|
-
"@geekmidas/constructs": "~10.0.0-alpha.
|
|
5126
|
-
"@geekmidas/db": "~10.0.0-alpha.
|
|
5127
|
-
"@geekmidas/emailkit": "~10.0.0-alpha.
|
|
5128
|
-
"@geekmidas/envkit": "~10.0.0-alpha.
|
|
5129
|
-
"@geekmidas/errors": "~10.0.0-alpha.
|
|
5130
|
-
"@geekmidas/events": "~10.0.0-alpha.
|
|
5131
|
-
"@geekmidas/logger": "~10.0.0-alpha.
|
|
5132
|
-
"@geekmidas/manifest": "~10.0.0-alpha.
|
|
5133
|
-
"@geekmidas/rate-limit": "~10.0.0-alpha.
|
|
5134
|
-
"@geekmidas/schema": "~10.0.0-alpha.
|
|
5135
|
-
"@geekmidas/services": "~10.0.0-alpha.
|
|
5136
|
-
"@geekmidas/storage": "~10.0.0-alpha.
|
|
5137
|
-
"@geekmidas/telescope": "~10.0.0-alpha.
|
|
5138
|
-
"@geekmidas/testkit": "~10.0.0-alpha.
|
|
5223
|
+
"@geekmidas/audit": "~10.0.0-alpha.84",
|
|
5224
|
+
"@geekmidas/auth": "~10.0.0-alpha.84",
|
|
5225
|
+
"@geekmidas/cache": "~10.0.0-alpha.84",
|
|
5226
|
+
"@geekmidas/client": "~10.0.0-alpha.84",
|
|
5227
|
+
"@geekmidas/cloud": "~10.0.0-alpha.84",
|
|
5228
|
+
"@geekmidas/constructs": "~10.0.0-alpha.84",
|
|
5229
|
+
"@geekmidas/db": "~10.0.0-alpha.84",
|
|
5230
|
+
"@geekmidas/emailkit": "~10.0.0-alpha.84",
|
|
5231
|
+
"@geekmidas/envkit": "~10.0.0-alpha.84",
|
|
5232
|
+
"@geekmidas/errors": "~10.0.0-alpha.84",
|
|
5233
|
+
"@geekmidas/events": "~10.0.0-alpha.84",
|
|
5234
|
+
"@geekmidas/logger": "~10.0.0-alpha.84",
|
|
5235
|
+
"@geekmidas/manifest": "~10.0.0-alpha.84",
|
|
5236
|
+
"@geekmidas/rate-limit": "~10.0.0-alpha.84",
|
|
5237
|
+
"@geekmidas/schema": "~10.0.0-alpha.84",
|
|
5238
|
+
"@geekmidas/services": "~10.0.0-alpha.84",
|
|
5239
|
+
"@geekmidas/storage": "~10.0.0-alpha.84",
|
|
5240
|
+
"@geekmidas/telescope": "~10.0.0-alpha.84",
|
|
5241
|
+
"@geekmidas/testkit": "~10.0.0-alpha.84",
|
|
5139
5242
|
"@geekmidas/cli": `~${loadPackageJson().version}`
|
|
5140
5243
|
};
|
|
5141
5244
|
//#endregion
|
|
@@ -5508,6 +5611,38 @@ coverage/
|
|
|
5508
5611
|
return files;
|
|
5509
5612
|
}
|
|
5510
5613
|
//#endregion
|
|
5614
|
+
//#region src/init/stagesAction.ts
|
|
5615
|
+
/**
|
|
5616
|
+
* How a scaffolded workflow names the `stages` action.
|
|
5617
|
+
*
|
|
5618
|
+
* A published CLI pins it to the commit it was released from: the release
|
|
5619
|
+
* build is given that commit as `GKM_RELEASE_COMMIT`, which the build writes
|
|
5620
|
+
* into the bundle (`define` in tsdown.config.ts). The action at that commit is
|
|
5621
|
+
* the one released beside this CLI, and a commit SHA cannot be moved under a
|
|
5622
|
+
* project the way a branch or a tag can.
|
|
5623
|
+
*
|
|
5624
|
+
* A CLI built anywhere else — a checkout, a local build — knows no released
|
|
5625
|
+
* commit, and names `main`.
|
|
5626
|
+
*/
|
|
5627
|
+
const require$1 = createRequire(import.meta.url);
|
|
5628
|
+
function cliVersion() {
|
|
5629
|
+
try {
|
|
5630
|
+
return require$1("../package.json").version;
|
|
5631
|
+
} catch {
|
|
5632
|
+
return require$1("../../package.json").version;
|
|
5633
|
+
}
|
|
5634
|
+
}
|
|
5635
|
+
/** The action, as a workflow's `uses:` names it before the `@`. */
|
|
5636
|
+
const STAGES_ACTION = "geekmidas/toolbox/actions/stages";
|
|
5637
|
+
const COMMIT = /^[0-9a-f]{40}$/;
|
|
5638
|
+
/**
|
|
5639
|
+
* The `uses:` value for the stages action, with a comment saying which CLI
|
|
5640
|
+
* release the pinned commit is.
|
|
5641
|
+
*/
|
|
5642
|
+
function stagesActionUses(commit = "1a6631b7e6dc71b7dd7b7afb8ca5b82225454826", version = cliVersion()) {
|
|
5643
|
+
return commit && COMMIT.test(commit) ? `${STAGES_ACTION}@${commit} # @geekmidas/cli ${version}` : `${STAGES_ACTION}@main # pin to a commit SHA: see the action's README`;
|
|
5644
|
+
}
|
|
5645
|
+
//#endregion
|
|
5511
5646
|
//#region src/init/generators/github.ts
|
|
5512
5647
|
/**
|
|
5513
5648
|
* The GitHub workflows a scaffold ships with.
|
|
@@ -5517,11 +5652,14 @@ coverage/
|
|
|
5517
5652
|
* release, labelled from their titles.
|
|
5518
5653
|
* - `deploy.yml` — when a deploy target was picked: a push to main deploys the
|
|
5519
5654
|
* stages that are not protected, publishing the drafted release deploys the
|
|
5520
|
-
* protected ones.
|
|
5655
|
+
* protected ones, and a manual run deploys the one stage it names.
|
|
5521
5656
|
*
|
|
5522
|
-
* The deploy workflow names no stage.
|
|
5523
|
-
*
|
|
5524
|
-
*
|
|
5657
|
+
* The deploy workflow names no stage. Its first job runs the
|
|
5658
|
+
* `geekmidas/toolbox/actions/stages` action, which asks the project's own
|
|
5659
|
+
* `gkm stages --github-output` which stages the run builds and deploys — so
|
|
5660
|
+
* the config stays the one place stages are declared, the rules for each event
|
|
5661
|
+
* are tested code in the CLI, and a workflow cannot fall out of step with
|
|
5662
|
+
* either.
|
|
5525
5663
|
*/
|
|
5526
5664
|
/** How each package manager is set up, installs, and runs a script. */
|
|
5527
5665
|
const TOOLING = {
|
|
@@ -5707,46 +5845,21 @@ template: |
|
|
|
5707
5845
|
**Full Changelog**: https://github.com/$OWNER/$REPOSITORY/compare/$PREVIOUS_TAG...v$RESOLVED_VERSION
|
|
5708
5846
|
`;
|
|
5709
5847
|
}
|
|
5710
|
-
|
|
5711
|
-
|
|
5712
|
-
|
|
5713
|
-
|
|
5714
|
-
|
|
5715
|
-
|
|
5716
|
-
- uses: aws-actions/configure-aws-credentials@v4
|
|
5717
|
-
with:
|
|
5718
|
-
role-to-assume: \${{ vars.AWS_ROLE_ARN }}
|
|
5719
|
-
aws-region: ${options.region}
|
|
5720
|
-
` : "";
|
|
5721
|
-
const keyDir = `~/.gkm/keys/${projectKey({ name: options.name })}`;
|
|
5722
|
-
const stageSecrets = sst ? credentials : `
|
|
5723
|
-
# The stage's secrets are kept in the encrypted .gkm/secrets/<stage>.json,
|
|
5724
|
-
# and each environment holds its key as GKM_SECRETS_KEY. .gkm/ is
|
|
5725
|
-
# gitignored, so a checkout has the key but not the file: set
|
|
5726
|
-
# secrets.store in gkm.config.ts to a store CI can reach before deploying
|
|
5727
|
-
# from here.
|
|
5728
|
-
# Owner-only, as the CLI writes its own keys. The stage reaches the shell
|
|
5729
|
-
# as a variable, never pasted into the script: on a manual run it is
|
|
5730
|
-
# whatever was typed.
|
|
5731
|
-
- name: Stage secrets key
|
|
5732
|
-
run: |
|
|
5733
|
-
mkdir -p -m 700 ${keyDir}
|
|
5734
|
-
(umask 077 && printf '%s' "$KEY" > ${keyDir}/"$STAGE".key)
|
|
5735
|
-
env:
|
|
5736
|
-
KEY: \${{ secrets.GKM_SECRETS_KEY }}
|
|
5737
|
-
STAGE: \${{ matrix.stage }}
|
|
5738
|
-
`;
|
|
5739
|
-
const deployEnv = sst ? "" : `
|
|
5740
|
-
DOKPLOY_API_TOKEN: \${{ secrets.DOKPLOY_API_TOKEN }}
|
|
5741
|
-
DOKPLOY_ENDPOINT: \${{ vars.DOKPLOY_ENDPOINT }}`;
|
|
5848
|
+
/**
|
|
5849
|
+
* What every deploy workflow starts with: its triggers, and the `stages` job,
|
|
5850
|
+
* which asks the project's own gkm (through the stages action) which stages
|
|
5851
|
+
* this run builds and deploys. Nothing in a workflow names a stage.
|
|
5852
|
+
*/
|
|
5853
|
+
function deployHeader(build) {
|
|
5742
5854
|
return `name: Deploy
|
|
5743
5855
|
|
|
5744
5856
|
# Which stages exist, and which are protected, is read from \`stages\` in
|
|
5745
|
-
# gkm.config.ts
|
|
5857
|
+
# gkm.config.ts by the project's own gkm, through the stages action — nothing
|
|
5858
|
+
# here names one:
|
|
5746
5859
|
#
|
|
5747
|
-
# push to main every deployed stage that is not protected
|
|
5860
|
+
# push to main ${build ? "builds every deployed stage, deploys those not protected" : "every deployed stage that is not protected"}
|
|
5748
5861
|
# release published the protected stages (publish the drafted release)
|
|
5749
|
-
# run workflow the one stage you name
|
|
5862
|
+
# run workflow the one stage you name, at the ref you name
|
|
5750
5863
|
on:
|
|
5751
5864
|
push:
|
|
5752
5865
|
branches: [main]
|
|
@@ -5757,17 +5870,27 @@ on:
|
|
|
5757
5870
|
stage:
|
|
5758
5871
|
description: A deployed stage from gkm.config.ts
|
|
5759
5872
|
required: true
|
|
5873
|
+
type: string
|
|
5874
|
+
ref:
|
|
5875
|
+
description: The commit, tag or branch to deploy (default the latest on main)
|
|
5876
|
+
required: false
|
|
5877
|
+
type: string
|
|
5760
5878
|
|
|
5761
5879
|
permissions:
|
|
5762
5880
|
contents: read
|
|
5763
|
-
|
|
5764
|
-
|
|
5765
|
-
|
|
5766
|
-
|
|
5881
|
+
`;
|
|
5882
|
+
}
|
|
5883
|
+
function stagesJob(options) {
|
|
5884
|
+
const pm = tooling(options);
|
|
5885
|
+
return ` stages:
|
|
5767
5886
|
name: Pick stages
|
|
5768
5887
|
runs-on: ubuntu-latest
|
|
5769
5888
|
outputs:
|
|
5770
|
-
|
|
5889
|
+
build: \${{ steps.stages.outputs.build }}
|
|
5890
|
+
deploy: \${{ steps.stages.outputs.deploy }}
|
|
5891
|
+
has-build: \${{ steps.stages.outputs.has-build }}
|
|
5892
|
+
has-deploy: \${{ steps.stages.outputs.has-deploy }}
|
|
5893
|
+
aws-region: \${{ steps.stages.outputs.aws-region }}
|
|
5771
5894
|
steps:
|
|
5772
5895
|
- uses: actions/checkout@v4
|
|
5773
5896
|
|
|
@@ -5775,44 +5898,286 @@ ${pm.setup}
|
|
|
5775
5898
|
- name: Install
|
|
5776
5899
|
run: ${pm.install}
|
|
5777
5900
|
|
|
5901
|
+
# Runs \`gkm stages --github-output\`: the rules for each event are the
|
|
5902
|
+
# installed CLI's, and a manual run naming a stage gkm.config.ts does not
|
|
5903
|
+
# deploy fails here.
|
|
5778
5904
|
- name: Read stages from gkm.config.ts
|
|
5779
|
-
id:
|
|
5905
|
+
id: stages
|
|
5906
|
+
uses: ${stagesActionUses()}
|
|
5907
|
+
with:
|
|
5908
|
+
stage: \${{ inputs.stage }}
|
|
5909
|
+
`;
|
|
5910
|
+
}
|
|
5911
|
+
/**
|
|
5912
|
+
* The registry login a compose build pushes with: GitHub's own token on
|
|
5913
|
+
* ghcr.io, otherwise a username variable and a password secret.
|
|
5914
|
+
*/
|
|
5915
|
+
function registryLogin(registry) {
|
|
5916
|
+
const host = registry.split("/")[0];
|
|
5917
|
+
const ghcr = host === "ghcr.io";
|
|
5918
|
+
return ` - uses: docker/login-action@v3
|
|
5919
|
+
with:
|
|
5920
|
+
registry: ${host}
|
|
5921
|
+
username: ${ghcr ? "${{ github.actor }}" : "${{ vars.REGISTRY_USERNAME }}"}
|
|
5922
|
+
password: ${ghcr ? "${{ secrets.GITHUB_TOKEN }}" : "${{ secrets.REGISTRY_PASSWORD }}"}
|
|
5923
|
+
`;
|
|
5924
|
+
}
|
|
5925
|
+
/**
|
|
5926
|
+
* The compose deploy: images are built and pushed by the runner, where the
|
|
5927
|
+
* code is, and pulled by the server, where the stage runs.
|
|
5928
|
+
*
|
|
5929
|
+
* - `build` (on a push): every deployed stage's images, tagged with the
|
|
5930
|
+
* commit, and their digests kept as the artifact `digests-<stage>`.
|
|
5931
|
+
* - `deploy`: the commit the event names — a release's tag, a manual run's
|
|
5932
|
+
* `ref` — then that commit's push build, whose digests pin each image. Over
|
|
5933
|
+
* SSH, with a pinned host key, the server checks the commit out and runs
|
|
5934
|
+
* `gkm compose` on exactly those images.
|
|
5935
|
+
*/
|
|
5936
|
+
function composeDeploy(options) {
|
|
5937
|
+
const pm = tooling(options);
|
|
5938
|
+
const registry = options.registry ?? "";
|
|
5939
|
+
return `${deployHeader(true)}
|
|
5940
|
+
jobs:
|
|
5941
|
+
${stagesJob(options)}
|
|
5942
|
+
build:
|
|
5943
|
+
name: Build \${{ matrix.stage }}
|
|
5944
|
+
needs: stages
|
|
5945
|
+
if: needs.stages.outputs.has-build == 'true'
|
|
5946
|
+
runs-on: ubuntu-latest
|
|
5947
|
+
strategy:
|
|
5948
|
+
fail-fast: false
|
|
5949
|
+
matrix:
|
|
5950
|
+
stage: \${{ fromJSON(needs.stages.outputs.build) }}
|
|
5951
|
+
# One GitHub environment per stage: its secrets, variables and approvals.
|
|
5952
|
+
environment: \${{ matrix.stage }}
|
|
5953
|
+
permissions:
|
|
5954
|
+
contents: read
|
|
5955
|
+
packages: write
|
|
5956
|
+
id-token: write
|
|
5957
|
+
steps:
|
|
5958
|
+
- uses: actions/checkout@v4
|
|
5959
|
+
|
|
5960
|
+
${pm.setup}
|
|
5961
|
+
- name: Install
|
|
5962
|
+
run: ${pm.install}
|
|
5963
|
+
|
|
5964
|
+
${registryLogin(registry)}
|
|
5965
|
+
# A site's public URLs are built into it, so the build reads the stage's
|
|
5966
|
+
# secrets store. With secrets.store on SSM or Secrets Manager the job
|
|
5967
|
+
# assumes the stage's role (AWS_ROLE_ARN, set by gkm deploy:github);
|
|
5968
|
+
# with the default 'file' store there is no role to assume.
|
|
5969
|
+
- name: Assume the stage's AWS role
|
|
5970
|
+
if: needs.stages.outputs.aws-region != ''
|
|
5971
|
+
uses: aws-actions/configure-aws-credentials@v4
|
|
5972
|
+
with:
|
|
5973
|
+
role-to-assume: \${{ vars.AWS_ROLE_ARN }}
|
|
5974
|
+
aws-region: \${{ needs.stages.outputs.aws-region }}
|
|
5975
|
+
|
|
5976
|
+
# Builds and pushes every image the stage runs, tagged with the commit,
|
|
5977
|
+
# and starts nothing.
|
|
5978
|
+
- name: Build and push
|
|
5979
|
+
run: ${pm.exec} gkm compose --stage "$STAGE" --build --push --tag "$SHA" --digests-file digests.json
|
|
5980
|
+
env:
|
|
5981
|
+
STAGE: \${{ matrix.stage }}
|
|
5982
|
+
SHA: \${{ github.sha }}
|
|
5983
|
+
|
|
5984
|
+
# What each tag pointed at when it was pushed. A deploy runs these
|
|
5985
|
+
# digests, so a tag moved since cannot change what is released.
|
|
5986
|
+
- uses: actions/upload-artifact@v4
|
|
5987
|
+
with:
|
|
5988
|
+
name: digests-\${{ matrix.stage }}
|
|
5989
|
+
path: digests.json
|
|
5990
|
+
retention-days: 90
|
|
5991
|
+
|
|
5992
|
+
deploy:
|
|
5993
|
+
name: Deploy \${{ matrix.stage }}
|
|
5994
|
+
needs: [stages, build]
|
|
5995
|
+
# The build is skipped on a release or a manual run: deploy then anyway,
|
|
5996
|
+
# but never after a failed build.
|
|
5997
|
+
if: \${{ !cancelled() && !failure() && needs.stages.outputs.has-deploy == 'true' }}
|
|
5998
|
+
runs-on: ubuntu-latest
|
|
5999
|
+
strategy:
|
|
6000
|
+
fail-fast: false
|
|
6001
|
+
matrix:
|
|
6002
|
+
stage: \${{ fromJSON(needs.stages.outputs.deploy) }}
|
|
6003
|
+
environment: \${{ matrix.stage }}
|
|
6004
|
+
concurrency:
|
|
6005
|
+
group: deploy-\${{ matrix.stage }}
|
|
6006
|
+
cancel-in-progress: false
|
|
6007
|
+
permissions:
|
|
6008
|
+
contents: read
|
|
6009
|
+
actions: read
|
|
6010
|
+
steps:
|
|
6011
|
+
# A release deploys its tag's commit, never its target_commitish — the
|
|
6012
|
+
# branch it was drafted against, which has moved on since.
|
|
6013
|
+
- name: Resolve the commit
|
|
6014
|
+
id: commit
|
|
6015
|
+
run: |
|
|
6016
|
+
case "$EVENT" in
|
|
6017
|
+
release) ref="tags/$TAG" ;;
|
|
6018
|
+
workflow_dispatch) ref="\${REF:-$SHA}" ;;
|
|
6019
|
+
*) ref="$SHA" ;;
|
|
6020
|
+
esac
|
|
6021
|
+
sha=$(gh api "repos/$REPO/commits/$ref" --jq .sha)
|
|
6022
|
+
echo "Deploying $sha"
|
|
6023
|
+
echo "sha=$sha" >> "$GITHUB_OUTPUT"
|
|
6024
|
+
env:
|
|
6025
|
+
GH_TOKEN: \${{ github.token }}
|
|
6026
|
+
REPO: \${{ github.repository }}
|
|
6027
|
+
EVENT: \${{ github.event_name }}
|
|
6028
|
+
TAG: \${{ github.event.release.tag_name }}
|
|
6029
|
+
REF: \${{ inputs.ref }}
|
|
6030
|
+
SHA: \${{ github.sha }}
|
|
6031
|
+
|
|
6032
|
+
# The push run of this workflow that built the commit for this stage:
|
|
6033
|
+
# this run on a push, the newest one with the stage's digests otherwise.
|
|
6034
|
+
- name: Find the commit's push build
|
|
6035
|
+
id: build
|
|
5780
6036
|
run: |
|
|
5781
|
-
$
|
|
5782
|
-
|
|
5783
|
-
|
|
5784
|
-
|
|
5785
|
-
|
|
5786
|
-
|
|
5787
|
-
|
|
5788
|
-
|
|
5789
|
-
|
|
5790
|
-
|
|
5791
|
-
|
|
5792
|
-
|
|
5793
|
-
|
|
5794
|
-
" >> "$GITHUB_OUTPUT"
|
|
6037
|
+
if [ "$EVENT" = push ]; then
|
|
6038
|
+
echo "run-id=$RUN_ID" >> "$GITHUB_OUTPUT"
|
|
6039
|
+
exit 0
|
|
6040
|
+
fi
|
|
6041
|
+
workflow=\${WORKFLOW_REF%%@*}
|
|
6042
|
+
workflow=\${workflow##*/}
|
|
6043
|
+
for id in $(gh run list --repo "$REPO" --workflow "$workflow" --event push --commit "$SHA" --limit 20 --json databaseId --jq '.[].databaseId'); do
|
|
6044
|
+
found=$(gh api "repos/$REPO/actions/runs/$id/artifacts?name=$ARTIFACT" --jq '[.artifacts[] | select(.expired | not)] | length')
|
|
6045
|
+
if [ "$found" -gt 0 ]; then
|
|
6046
|
+
echo "run-id=$id" >> "$GITHUB_OUTPUT"
|
|
6047
|
+
exit 0
|
|
6048
|
+
fi
|
|
6049
|
+
done
|
|
6050
|
+
echo "run-id=" >> "$GITHUB_OUTPUT"
|
|
5795
6051
|
env:
|
|
6052
|
+
GH_TOKEN: \${{ github.token }}
|
|
6053
|
+
REPO: \${{ github.repository }}
|
|
5796
6054
|
EVENT: \${{ github.event_name }}
|
|
5797
|
-
|
|
6055
|
+
RUN_ID: \${{ github.run_id }}
|
|
6056
|
+
WORKFLOW_REF: \${{ github.workflow_ref }}
|
|
6057
|
+
SHA: \${{ steps.commit.outputs.sha }}
|
|
6058
|
+
ARTIFACT: digests-\${{ matrix.stage }}
|
|
6059
|
+
|
|
6060
|
+
- name: Download digests-\${{ matrix.stage }}
|
|
6061
|
+
if: steps.build.outputs.run-id != ''
|
|
6062
|
+
uses: actions/download-artifact@v4
|
|
6063
|
+
with:
|
|
6064
|
+
name: digests-\${{ matrix.stage }}
|
|
6065
|
+
run-id: \${{ steps.build.outputs.run-id }}
|
|
6066
|
+
github-token: \${{ github.token }}
|
|
5798
6067
|
|
|
6068
|
+
- name: No digests — deploying by tag
|
|
6069
|
+
if: steps.build.outputs.run-id == ''
|
|
6070
|
+
run: |
|
|
6071
|
+
echo "::warning title=$STAGE deploys by tag, not digest::No push build of $SHA kept digests-$STAGE (never built, or older than 90 days). The server runs whatever the tag $SHA points at in the registry now, which anyone who can push there could have replaced."
|
|
6072
|
+
env:
|
|
6073
|
+
STAGE: \${{ matrix.stage }}
|
|
6074
|
+
SHA: \${{ steps.commit.outputs.sha }}
|
|
6075
|
+
|
|
6076
|
+
# Each environment holds DEPLOY_SSH_KEY (secret) and DEPLOY_KNOWN_HOSTS,
|
|
6077
|
+
# DEPLOY_HOST, DEPLOY_USER and DEPLOY_PATH (variables): the server's
|
|
6078
|
+
# host key is pinned, never accepted on first sight. DEPLOY_PATH is a
|
|
6079
|
+
# clone of this repository, with a docker login to ${registry.split("/")[0]}
|
|
6080
|
+
# and the stage's secrets.
|
|
6081
|
+
#
|
|
6082
|
+
# Every value reaches the server as an argument to a quoted heredoc —
|
|
6083
|
+
# nothing is pasted into the script.
|
|
6084
|
+
- name: Deploy on the server
|
|
6085
|
+
run: |
|
|
6086
|
+
mkdir -p ~/.ssh && chmod 700 ~/.ssh
|
|
6087
|
+
(umask 077 && printf '%s\\n' "$SSH_KEY" > ~/.ssh/deploy_key)
|
|
6088
|
+
printf '%s\\n' "$KNOWN_HOSTS" > ~/.ssh/known_hosts
|
|
6089
|
+
digests=""
|
|
6090
|
+
if [ -f digests.json ]; then digests=$(base64 -w0 < digests.json); fi
|
|
6091
|
+
ssh -i ~/.ssh/deploy_key -o IdentitiesOnly=yes -o StrictHostKeyChecking=yes \\
|
|
6092
|
+
"$DEPLOY_USER@$DEPLOY_HOST" \\
|
|
6093
|
+
"bash -s -- $(printf '%q ' "$STAGE" "$SHA" "$DEPLOY_PATH" "$digests")" <<'REMOTE'
|
|
6094
|
+
set -euo pipefail
|
|
6095
|
+
stage=$1 sha=$2 dir=$3 digests=$4
|
|
6096
|
+
cd "$dir"
|
|
6097
|
+
git fetch --quiet origin
|
|
6098
|
+
git checkout --quiet --detach "$sha"
|
|
6099
|
+
${pm.install}
|
|
6100
|
+
args=(--stage "$stage" --tag "$sha")
|
|
6101
|
+
if [ -n "$digests" ]; then
|
|
6102
|
+
mkdir -p .gkm
|
|
6103
|
+
printf '%s' "$digests" | base64 -d > ".gkm/digests-$stage.json"
|
|
6104
|
+
args+=(--digests-file ".gkm/digests-$stage.json")
|
|
6105
|
+
fi
|
|
6106
|
+
${pm.exec} gkm compose "\${args[@]}"
|
|
6107
|
+
REMOTE
|
|
6108
|
+
env:
|
|
6109
|
+
SSH_KEY: \${{ secrets.DEPLOY_SSH_KEY }}
|
|
6110
|
+
KNOWN_HOSTS: \${{ vars.DEPLOY_KNOWN_HOSTS }}
|
|
6111
|
+
DEPLOY_HOST: \${{ vars.DEPLOY_HOST }}
|
|
6112
|
+
DEPLOY_USER: \${{ vars.DEPLOY_USER }}
|
|
6113
|
+
DEPLOY_PATH: \${{ vars.DEPLOY_PATH }}
|
|
6114
|
+
STAGE: \${{ matrix.stage }}
|
|
6115
|
+
SHA: \${{ steps.commit.outputs.sha }}
|
|
6116
|
+
`;
|
|
6117
|
+
}
|
|
6118
|
+
/**
|
|
6119
|
+
* Dokploy and SST: `gkm deploy` builds, releases and health-checks a stage in
|
|
6120
|
+
* one step, from a checkout, so there is no separate build job — the stages
|
|
6121
|
+
* job's `deploy` list is the matrix, and `build` goes unused.
|
|
6122
|
+
*/
|
|
6123
|
+
function targetDeploy(options) {
|
|
6124
|
+
const pm = tooling(options);
|
|
6125
|
+
const sst = options.deployTarget === "sst";
|
|
6126
|
+
const credentials = sst ? `
|
|
6127
|
+
# An IAM role GitHub assumes through OIDC — no long-lived AWS keys. Set
|
|
6128
|
+
# AWS_ROLE_ARN as a variable on each environment.
|
|
6129
|
+
- uses: aws-actions/configure-aws-credentials@v4
|
|
6130
|
+
with:
|
|
6131
|
+
role-to-assume: \${{ vars.AWS_ROLE_ARN }}
|
|
6132
|
+
aws-region: ${options.region}
|
|
6133
|
+
` : "";
|
|
6134
|
+
const keyDir = `~/.gkm/keys/${projectKey({ name: options.name })}`;
|
|
6135
|
+
const stageSecrets = sst ? credentials : `
|
|
6136
|
+
# The stage's secrets are kept in the encrypted .gkm/secrets/<stage>.json,
|
|
6137
|
+
# and each environment holds its key as GKM_SECRETS_KEY. .gkm/ is
|
|
6138
|
+
# gitignored, so a checkout has the key but not the file: set
|
|
6139
|
+
# secrets.store in gkm.config.ts to a store CI can reach before deploying
|
|
6140
|
+
# from here.
|
|
6141
|
+
# Owner-only, as the CLI writes its own keys. The stage reaches the shell
|
|
6142
|
+
# as a variable, never pasted into the script: on a manual run it is
|
|
6143
|
+
# whatever was typed.
|
|
6144
|
+
- name: Stage secrets key
|
|
6145
|
+
run: |
|
|
6146
|
+
mkdir -p ${keyDir} && chmod 700 ${keyDir}
|
|
6147
|
+
(umask 077 && printf '%s' "$KEY" > ${keyDir}/"$STAGE".key)
|
|
6148
|
+
env:
|
|
6149
|
+
KEY: \${{ secrets.GKM_SECRETS_KEY }}
|
|
6150
|
+
STAGE: \${{ matrix.stage }}
|
|
6151
|
+
`;
|
|
6152
|
+
const deployEnv = sst ? "" : `
|
|
6153
|
+
DOKPLOY_API_TOKEN: \${{ secrets.DOKPLOY_API_TOKEN }}
|
|
6154
|
+
DOKPLOY_ENDPOINT: \${{ vars.DOKPLOY_ENDPOINT }}`;
|
|
6155
|
+
return `${deployHeader(false)}
|
|
6156
|
+
jobs:
|
|
6157
|
+
${stagesJob(options)}
|
|
5799
6158
|
deploy:
|
|
5800
6159
|
name: Deploy \${{ matrix.stage }}
|
|
5801
6160
|
needs: stages
|
|
5802
|
-
if: needs.stages.outputs.
|
|
6161
|
+
if: needs.stages.outputs.has-deploy == 'true'
|
|
5803
6162
|
runs-on: ubuntu-latest
|
|
5804
6163
|
strategy:
|
|
5805
6164
|
fail-fast: false
|
|
5806
6165
|
matrix:
|
|
5807
|
-
stage: \${{ fromJSON(needs.stages.outputs.
|
|
6166
|
+
stage: \${{ fromJSON(needs.stages.outputs.deploy) }}
|
|
5808
6167
|
# One GitHub environment per stage: its secrets and variables, and any
|
|
5809
6168
|
# approval rule you put on a protected one.
|
|
5810
6169
|
environment: \${{ matrix.stage }}
|
|
5811
6170
|
concurrency:
|
|
5812
6171
|
group: deploy-\${{ matrix.stage }}
|
|
5813
6172
|
cancel-in-progress: false
|
|
6173
|
+
permissions:
|
|
6174
|
+
contents: read${sst ? "\n id-token: write" : ""}
|
|
5814
6175
|
steps:
|
|
6176
|
+
# The event's own commit — a release's tag, the push — or the ref a
|
|
6177
|
+
# manual run names.
|
|
5815
6178
|
- uses: actions/checkout@v4
|
|
6179
|
+
with:
|
|
6180
|
+
ref: \${{ inputs.ref }}
|
|
5816
6181
|
|
|
5817
6182
|
${pm.setup}
|
|
5818
6183
|
- name: Install
|
|
@@ -5826,6 +6191,9 @@ ${stageSecrets}
|
|
|
5826
6191
|
STAGE: \${{ matrix.stage }}${deployEnv}
|
|
5827
6192
|
`;
|
|
5828
6193
|
}
|
|
6194
|
+
function deploy(options) {
|
|
6195
|
+
return options.deployTarget === "compose" ? composeDeploy(options) : targetDeploy(options);
|
|
6196
|
+
}
|
|
5829
6197
|
function generateGithubFiles(options) {
|
|
5830
6198
|
const files = [
|
|
5831
6199
|
{
|
|
@@ -6666,6 +7034,11 @@ export type ListUsersResponse = z.infer<typeof ListUsersResponseSchema>;
|
|
|
6666
7034
|
const perStage = (options, command) => Object.fromEntries(options.stages.deployed.map((stage) => [`deploy:${stage}`, command(stage)]));
|
|
6667
7035
|
function deployPackage(options) {
|
|
6668
7036
|
switch (options.deployTarget) {
|
|
7037
|
+
case "compose": return {
|
|
7038
|
+
scripts: perStage(options, (stage) => `gkm compose --stage ${stage}`),
|
|
7039
|
+
dependencies: {},
|
|
7040
|
+
devDependencies: {}
|
|
7041
|
+
};
|
|
6669
7042
|
case "dokploy": return {
|
|
6670
7043
|
scripts: perStage(options, (stage) => `gkm deploy --stage ${stage}`),
|
|
6671
7044
|
dependencies: {},
|
|
@@ -7175,6 +7548,13 @@ ${workspaceConstructsGlobs(options.routesStructure, dirname(options.apiPath)).ma
|
|
|
7175
7548
|
* `gkm build` builds for, and which backends a cache or a broker resolves to.
|
|
7176
7549
|
*/
|
|
7177
7550
|
function deployBlock(options) {
|
|
7551
|
+
if (options.deployTarget === "compose") return `
|
|
7552
|
+
// \`gkm compose --stage <stage>\` runs a stage as one Docker Compose stack on
|
|
7553
|
+
// the machine it runs on. CI builds every image and pushes it here; the
|
|
7554
|
+
// server pulls exactly those. On ghcr.io the owner is the repository's —
|
|
7555
|
+
// the user or organisation whose packages the workflow's token can write.
|
|
7556
|
+
deploy: { default: 'compose', registry: '${options.registry}' },
|
|
7557
|
+
`;
|
|
7178
7558
|
if (options.deployTarget !== "sst") return "";
|
|
7179
7559
|
return `
|
|
7180
7560
|
// \`gkm deploy\` runs \`sst deploy\` on the manifest \`gkm build\` writes to
|
|
@@ -9751,6 +10131,11 @@ const deployTargetChoices = [
|
|
|
9751
10131
|
value: "dokploy",
|
|
9752
10132
|
description: "Deploy to Dokploy (Docker-based hosting)"
|
|
9753
10133
|
},
|
|
10134
|
+
{
|
|
10135
|
+
title: "Server (Docker Compose)",
|
|
10136
|
+
value: "compose",
|
|
10137
|
+
description: "One Docker Compose stack per stage on your own server; CI builds the images"
|
|
10138
|
+
},
|
|
9754
10139
|
{
|
|
9755
10140
|
title: "AWS (SST)",
|
|
9756
10141
|
value: "sst",
|
|
@@ -9888,6 +10273,13 @@ async function initCommand(projectName, options = {}) {
|
|
|
9888
10273
|
message: "AWS region (e.g. eu-west-1):",
|
|
9889
10274
|
validate: (value) => AWS_REGION.test(value.trim()) || "An AWS region, like eu-west-1"
|
|
9890
10275
|
},
|
|
10276
|
+
{
|
|
10277
|
+
type: (_prev, values) => !options.yes && !options.registry && (options.deploy ?? values.deployTarget) === "compose" ? "text" : null,
|
|
10278
|
+
name: "registry",
|
|
10279
|
+
message: "Container registry CI pushes to (e.g. ghcr.io/<your GitHub owner>):",
|
|
10280
|
+
initial: (_prev, values) => defaultRegistry(projectName || options.name || values.name),
|
|
10281
|
+
validate: (value) => value.trim().length > 0 || "A registry, like ghcr.io/acme"
|
|
10282
|
+
},
|
|
9891
10283
|
{
|
|
9892
10284
|
type: options.yes || options.stages ? null : "text",
|
|
9893
10285
|
name: "deployedStages",
|
|
@@ -9989,6 +10381,7 @@ async function initCommand(projectName, options = {}) {
|
|
|
9989
10381
|
packageManager: pkgManager,
|
|
9990
10382
|
deployTarget,
|
|
9991
10383
|
stages: resolveStages(options, answers),
|
|
10384
|
+
...deployTarget === "compose" ? { registry: options.registry ?? answers.registry?.trim() ?? defaultRegistry(name) } : {},
|
|
9992
10385
|
...deployTarget === "sst" ? { region: options.region ?? (options.yes ? "eu-west-1" : answers.region?.trim()) } : {},
|
|
9993
10386
|
constructs,
|
|
9994
10387
|
frontendFramework
|
|
@@ -10160,6 +10553,13 @@ function printNextSteps(projectName, options, pkgManager) {
|
|
|
10160
10553
|
for (const stage of deployed) console.log(` ${getRunCommand(pkgManager, `deploy:${stage}`)}`);
|
|
10161
10554
|
console.log("");
|
|
10162
10555
|
}
|
|
10556
|
+
if (options.deployTarget === "compose") {
|
|
10557
|
+
console.log("🚀 Deployment (Docker Compose, on your server):");
|
|
10558
|
+
console.log(` Images are pushed to ${options.registry}; .github/workflows/deploy.yml builds them`);
|
|
10559
|
+
console.log(" and runs gkm compose on the server over SSH. See the comments in it for the");
|
|
10560
|
+
console.log(" environment variables and secrets each stage needs.");
|
|
10561
|
+
console.log("");
|
|
10562
|
+
}
|
|
10163
10563
|
if (options.deployTarget === "sst") {
|
|
10164
10564
|
console.log("🚀 Deployment (AWS, through SST):");
|
|
10165
10565
|
for (const stage of deployed) console.log(` ${getRunCommand(pkgManager, `deploy:${stage}`)} # gkm deploy: build, sst deploy, health checks`);
|
|
@@ -10199,6 +10599,14 @@ var UnknownDeployTarget = class extends Error {
|
|
|
10199
10599
|
this.name = "UnknownDeployTarget";
|
|
10200
10600
|
}
|
|
10201
10601
|
};
|
|
10602
|
+
/**
|
|
10603
|
+
* Where a compose deploy's images go when nobody said: GitHub's registry,
|
|
10604
|
+
* under an owner named after the project. The generated config says to change
|
|
10605
|
+
* it to the repository's owner, whose packages the workflow's token can write.
|
|
10606
|
+
*/
|
|
10607
|
+
function defaultRegistry(name) {
|
|
10608
|
+
return `ghcr.io/${(name ?? "my-org").toLowerCase()}`;
|
|
10609
|
+
}
|
|
10202
10610
|
/** `--region` that is not shaped like one, e.g. `europe` for `eu-west-1`. */
|
|
10203
10611
|
var NotAnAwsRegion = class extends Error {
|
|
10204
10612
|
region;
|
|
@@ -10903,7 +11311,7 @@ function testDatabases(reconciled) {
|
|
|
10903
11311
|
* starts without the reference data the app needs.
|
|
10904
11312
|
*/
|
|
10905
11313
|
async function migrateTestStage(workspace, env) {
|
|
10906
|
-
const { migrateAndSeed } = await import("./migrate-
|
|
11314
|
+
const { migrateAndSeed } = await import("./migrate-CdXcX0XR.mjs");
|
|
10907
11315
|
const { discover } = await import("./discover-BPelzeGW.mjs").then((n) => n.i);
|
|
10908
11316
|
const sources = {};
|
|
10909
11317
|
const manifest = await discover({
|
|
@@ -11239,7 +11647,7 @@ const program = new Command();
|
|
|
11239
11647
|
program.name("gkm").description("GeekMidas backend framework CLI").version(version).option("--cwd <path>", "Change working directory").option("--debug", "Enable debug mode (verbose errors with stack traces)").hook("preAction", () => {
|
|
11240
11648
|
if (program.opts().debug);
|
|
11241
11649
|
});
|
|
11242
|
-
program.command("init").description("Scaffold a new project").argument("[name]", "Project name").option("--template <template>", "Project template (minimal, api, serverless, worker)").option("--skip-install", "Skip dependency installation", false).option("-y, --yes", "Skip prompts, use defaults", false).option("--monorepo", "Setup as monorepo with packages/models", false).option("--api-path <path>", "API app path in monorepo (default: apps/api)").option("--pm <manager>", "Package manager (pnpm, npm, yarn, bun)").option("--deploy <target>", "Where it deploys (dokploy, sst, none)").option("--region <region>", "AWS region for an SST deploy (e.g. eu-west-1)").option("--stages <names>", "Deployed stages, comma-separated (e.g. staging,prod)").option("--protected-stage <name>", "Which deployed stage is production").option("--local-stage <name>", "What gkm dev runs as (e.g. dev)").action(async (name, options) => {
|
|
11650
|
+
program.command("init").description("Scaffold a new project").argument("[name]", "Project name").option("--template <template>", "Project template (minimal, api, serverless, worker)").option("--skip-install", "Skip dependency installation", false).option("-y, --yes", "Skip prompts, use defaults", false).option("--monorepo", "Setup as monorepo with packages/models", false).option("--api-path <path>", "API app path in monorepo (default: apps/api)").option("--pm <manager>", "Package manager (pnpm, npm, yarn, bun)").option("--deploy <target>", "Where it deploys (dokploy, compose, sst, none)").option("--region <region>", "AWS region for an SST deploy (e.g. eu-west-1)").option("--registry <registry>", "Container registry for a compose deploy (e.g. ghcr.io/acme)").option("--stages <names>", "Deployed stages, comma-separated (e.g. staging,prod)").option("--protected-stage <name>", "Which deployed stage is production").option("--local-stage <name>", "What gkm dev runs as (e.g. dev)").action(async (name, options) => {
|
|
11243
11651
|
try {
|
|
11244
11652
|
const globalOptions = program.opts();
|
|
11245
11653
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
@@ -11347,7 +11755,7 @@ program.command("migrate").description("Apply each database construct's migratio
|
|
|
11347
11755
|
try {
|
|
11348
11756
|
const globalOptions = program.opts();
|
|
11349
11757
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
11350
|
-
const { migrateCommand } = await import("./migrate-
|
|
11758
|
+
const { migrateCommand } = await import("./migrate-CdXcX0XR.mjs");
|
|
11351
11759
|
await migrateCommand({
|
|
11352
11760
|
...options,
|
|
11353
11761
|
...construct ? { construct } : {}
|
|
@@ -11361,7 +11769,7 @@ program.command("seed").description("Migrate, then run each database construct's
|
|
|
11361
11769
|
try {
|
|
11362
11770
|
const globalOptions = program.opts();
|
|
11363
11771
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
11364
|
-
const { seedCommand } = await import("./migrate-
|
|
11772
|
+
const { seedCommand } = await import("./migrate-CdXcX0XR.mjs");
|
|
11365
11773
|
await seedCommand({
|
|
11366
11774
|
...options,
|
|
11367
11775
|
...construct ? { construct } : {}
|
|
@@ -11375,7 +11783,7 @@ program.command("migration").description("Write a construct's next migration: an
|
|
|
11375
11783
|
try {
|
|
11376
11784
|
const globalOptions = program.opts();
|
|
11377
11785
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
11378
|
-
const { migrationCommand } = await import("./migrate-
|
|
11786
|
+
const { migrationCommand } = await import("./migrate-CdXcX0XR.mjs");
|
|
11379
11787
|
await migrationCommand({
|
|
11380
11788
|
construct,
|
|
11381
11789
|
...name ? { name } : {}
|
|
@@ -11483,7 +11891,7 @@ program.command("secrets:add").description("Build the keys a stage must be given
|
|
|
11483
11891
|
try {
|
|
11484
11892
|
const globalOptions = program.opts();
|
|
11485
11893
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
11486
|
-
const { secretsAddCommand } = await import("./add-
|
|
11894
|
+
const { secretsAddCommand } = await import("./add-DbnzC7Kl.mjs");
|
|
11487
11895
|
await secretsAddCommand(options);
|
|
11488
11896
|
} catch (error) {
|
|
11489
11897
|
console.error(formatError(error));
|
|
@@ -11494,7 +11902,7 @@ program.command("encryption:rotate").description("Add a new current key to an En
|
|
|
11494
11902
|
try {
|
|
11495
11903
|
const globalOptions = program.opts();
|
|
11496
11904
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
11497
|
-
const { encryptionRotateCommand } = await import("./encryption-
|
|
11905
|
+
const { encryptionRotateCommand } = await import("./encryption-BRcBAmjL.mjs");
|
|
11498
11906
|
await encryptionRotateCommand(construct, options);
|
|
11499
11907
|
} catch (error) {
|
|
11500
11908
|
console.error(formatError(error));
|
|
@@ -11505,7 +11913,7 @@ program.command("encryption:retire").description("Remove an old key from an Encr
|
|
|
11505
11913
|
try {
|
|
11506
11914
|
const globalOptions = program.opts();
|
|
11507
11915
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
11508
|
-
const { encryptionRetireCommand } = await import("./encryption-
|
|
11916
|
+
const { encryptionRetireCommand } = await import("./encryption-BRcBAmjL.mjs");
|
|
11509
11917
|
await encryptionRetireCommand(construct, key, options);
|
|
11510
11918
|
} catch (error) {
|
|
11511
11919
|
console.error(formatError(error));
|
|
@@ -11548,7 +11956,7 @@ program.command("secrets:reconcile").description("Backfill missing custom secret
|
|
|
11548
11956
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
11549
11957
|
const { loadWorkspaceConfig } = await import("./config.mjs");
|
|
11550
11958
|
const { reconcileMissingSecrets } = await import("./reconcile--I7V4Klj.mjs");
|
|
11551
|
-
const { secretsStoreFor } = await import("./seeds-
|
|
11959
|
+
const { secretsStoreFor } = await import("./seeds-BK8caVMm.mjs").then((n) => n.hn);
|
|
11552
11960
|
const { workspace } = await loadWorkspaceConfig();
|
|
11553
11961
|
const stage = options.stage ?? workspace.stages.local;
|
|
11554
11962
|
const store = await secretsStoreFor(workspace, stage);
|
|
@@ -11557,7 +11965,7 @@ program.command("secrets:reconcile").description("Backfill missing custom secret
|
|
|
11557
11965
|
console.error(`No secrets found for stage "${stage}". Run "gkm secrets:init --stage ${stage}" first.`);
|
|
11558
11966
|
process.exit(1);
|
|
11559
11967
|
}
|
|
11560
|
-
const { derivedContainers } = await import("./seeds-
|
|
11968
|
+
const { derivedContainers } = await import("./seeds-BK8caVMm.mjs").then((n) => n.X);
|
|
11561
11969
|
const result = reconcileMissingSecrets(secrets, workspace, await derivedContainers(workspace, stage));
|
|
11562
11970
|
if (!result) {
|
|
11563
11971
|
console.log(`\n✓ Secrets for stage "${stage}" are up-to-date`);
|
|
@@ -11575,7 +11983,7 @@ program.command("secrets:migrate").description("Copy a deployed stage's secrets
|
|
|
11575
11983
|
try {
|
|
11576
11984
|
const globalOptions = program.opts();
|
|
11577
11985
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
11578
|
-
const { secretsMigrateCommand } = await import("./migrate-
|
|
11986
|
+
const { secretsMigrateCommand } = await import("./migrate-DOMU4uKe.mjs");
|
|
11579
11987
|
await secretsMigrateCommand(options);
|
|
11580
11988
|
} catch (error) {
|
|
11581
11989
|
console.error(formatError(error));
|
|
@@ -11583,7 +11991,7 @@ program.command("secrets:migrate").description("Copy a deployed stage's secrets
|
|
|
11583
11991
|
}
|
|
11584
11992
|
});
|
|
11585
11993
|
program.command("deploy").description("Deploy a stage through its target").option("--target <name>", "Deploy target: dokploy, compose, sst, or one named in deploy.targets (default: deploy.default)").option("--provider <provider>", "[DEPRECATED] Use --target instead").requiredOption("--stage <stage>", "Deployment stage (e.g., production, staging)").option("--tag <tag>", "Image tag (default: stage-timestamp; compose: the commit). Compose pulls a given tag").option("--skip-push", "Skip pushing image to registry").option("--skip-build", "Skip build step (use existing build)").option("--json", "Write events as JSON lines instead of progress; never prompts").option("--dry-run", "Show what would be created or reused; change, build and push nothing").option("--atomic", "If the release fails, roll back every app it released, not only the failed ones").option("--allow-dev-services <list>", "Server targets: run MinIO and/or Mailpit (minio,mailpit) for mail and buckets the stage's secrets don't configure. Not production-grade").action(async (options) => {
|
|
11586
|
-
const { deployCli } = await import("./cli-
|
|
11994
|
+
const { deployCli } = await import("./cli-DwTa9d_8.mjs");
|
|
11587
11995
|
const globalOptions = program.opts();
|
|
11588
11996
|
const code = await deployCli({
|
|
11589
11997
|
cwd: resolve(globalOptions.cwd ?? process.cwd()),
|
|
@@ -11600,7 +12008,7 @@ program.command("deploy").description("Deploy a stage through its target").optio
|
|
|
11600
12008
|
});
|
|
11601
12009
|
program.command("deploy:rollback").description("Put a stage's app back on its previous release (Dokploy): one app with --app, every app with --atomic").requiredOption("--stage <stage>", "A deployed stage").option("--app <app>", "The app to roll back").option("--atomic", "Roll back every app that has an earlier release").action(async (options) => {
|
|
11602
12010
|
try {
|
|
11603
|
-
const { rollbackStage } = await import("./rollback-
|
|
12011
|
+
const { rollbackStage } = await import("./rollback-BSdxnW3X.mjs").then((n) => n.a);
|
|
11604
12012
|
const { terminalCredentials } = await import("./terminal-BdvrmkaC.mjs");
|
|
11605
12013
|
const globalOptions = program.opts();
|
|
11606
12014
|
await rollbackStage({
|
|
@@ -11636,13 +12044,24 @@ program.command("deploy:github").description("Let GitHub Actions deploy a stage:
|
|
|
11636
12044
|
try {
|
|
11637
12045
|
const globalOptions = program.opts();
|
|
11638
12046
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
11639
|
-
const { deployGithubCommand } = await import("./github-
|
|
12047
|
+
const { deployGithubCommand } = await import("./github-Zs-dVJbR.mjs");
|
|
11640
12048
|
await deployGithubCommand(options);
|
|
11641
12049
|
} catch (error) {
|
|
11642
12050
|
console.error(formatError(error));
|
|
11643
12051
|
process.exit(1);
|
|
11644
12052
|
}
|
|
11645
12053
|
});
|
|
12054
|
+
program.command("stages").description("The workspace's stages from gkm.config.ts: local, deployed and protected").option("--json", "Print them as JSON").option("--github-output", "Write the stages, and which this workflow run builds and deploys, to $GITHUB_OUTPUT").option("--event <name>", "The event to plan for (default: $GITHUB_EVENT_NAME)").option("--stage <stage>", "The stage a workflow_dispatch deploys").action(async (options) => {
|
|
12055
|
+
try {
|
|
12056
|
+
const globalOptions = program.opts();
|
|
12057
|
+
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
12058
|
+
const { stagesCommand } = await import("./stages-CSXt7N2b.mjs");
|
|
12059
|
+
await stagesCommand(options);
|
|
12060
|
+
} catch (error) {
|
|
12061
|
+
console.error(formatError(error));
|
|
12062
|
+
process.exit(1);
|
|
12063
|
+
}
|
|
12064
|
+
});
|
|
11646
12065
|
program.command("deploy:list").description("List Dokploy resources (projects, registries)").option("--endpoint <url>", "Dokploy server URL (uses stored credentials if logged in)").option("--projects", "List projects").option("--registries", "List registries").action(async (options) => {
|
|
11647
12066
|
try {
|
|
11648
12067
|
const globalOptions = program.opts();
|