@ankhorage/infra 4.0.0 → 4.1.1
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/CHANGELOG.md +12 -0
- package/README.md +6 -1
- package/dist/adapters/minikube/base/index.d.ts +1 -0
- package/dist/adapters/minikube/base/index.d.ts.map +1 -1
- package/dist/adapters/minikube/base/index.js +176 -78
- package/dist/adapters/minikube/base/index.js.map +1 -1
- package/dist/adapters/minikube/index.d.ts.map +1 -1
- package/dist/adapters/minikube/index.js +3 -0
- package/dist/adapters/minikube/index.js.map +1 -1
- package/dist/project/index.d.ts +1 -1
- package/dist/project/index.d.ts.map +1 -1
- package/dist/project/index.js +1 -1
- package/dist/project/index.js.map +1 -1
- package/dist/readme-usage.js +5 -0
- package/dist/readme-usage.js.map +1 -1
- package/dist/runtime.d.ts +6 -0
- package/dist/runtime.d.ts.map +1 -1
- package/dist/runtime.js +24 -0
- package/dist/runtime.js.map +1 -1
- package/package.json +1 -1
- package/src/adapters/minikube/README.md +20 -2
- package/src/adapters/minikube/base/index.test.ts +165 -1
- package/src/adapters/minikube/base/index.ts +186 -74
- package/src/adapters/minikube/base/portForwardRuntime.test.ts +624 -0
- package/src/adapters/minikube/base/twoAppIsolation.integration.test.ts +272 -9
- package/src/adapters/minikube/base/upgradeReconciliation.test.ts +135 -0
- package/src/adapters/minikube/index.ts +4 -0
- package/src/project/index.test.ts +46 -0
- package/src/project/index.ts +1 -0
- package/src/readme-usage.ts +5 -0
- package/src/runtime.ts +31 -0
|
@@ -60,6 +60,7 @@ const PORT_REFERENCE_SLUG = 'my-app';
|
|
|
60
60
|
export function generateMinikubeBaseArtifacts(args: {
|
|
61
61
|
manifest: InfraManifestInput;
|
|
62
62
|
appSlug: string;
|
|
63
|
+
appRuntimeEnabled: boolean;
|
|
63
64
|
extraResources: string[];
|
|
64
65
|
providerNamespaces: string[];
|
|
65
66
|
providerLifecycle: MinikubeProviderLifecycle[];
|
|
@@ -68,6 +69,7 @@ export function generateMinikubeBaseArtifacts(args: {
|
|
|
68
69
|
const {
|
|
69
70
|
manifest,
|
|
70
71
|
appSlug,
|
|
72
|
+
appRuntimeEnabled,
|
|
71
73
|
extraResources,
|
|
72
74
|
providerNamespaces,
|
|
73
75
|
providerLifecycle,
|
|
@@ -109,6 +111,7 @@ export function generateMinikubeBaseArtifacts(args: {
|
|
|
109
111
|
path: `${root}/README.md`,
|
|
110
112
|
content: getReadmeMarkdown({
|
|
111
113
|
appSlug,
|
|
114
|
+
appRuntimeEnabled,
|
|
112
115
|
defaultAppImage,
|
|
113
116
|
monitoringEnabled,
|
|
114
117
|
authProvider,
|
|
@@ -150,32 +153,37 @@ export function generateMinikubeBaseArtifacts(args: {
|
|
|
150
153
|
path: `${k8sRoot}/namespaces/${namespace}.yaml`,
|
|
151
154
|
content: getNamespaceManifest(namespace),
|
|
152
155
|
})),
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
156
|
+
...(appRuntimeEnabled
|
|
157
|
+
? [
|
|
158
|
+
{
|
|
159
|
+
path: `${k8sRoot}/app.configmap.yaml`,
|
|
160
|
+
content: getAppConfigMap({
|
|
161
|
+
appSlug,
|
|
162
|
+
authScope,
|
|
163
|
+
authProvider,
|
|
164
|
+
databaseProvider,
|
|
165
|
+
secretStoreProvider,
|
|
166
|
+
storageMetadata,
|
|
167
|
+
monitoringEnabled,
|
|
168
|
+
domain,
|
|
169
|
+
}),
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
path: `${k8sRoot}/app/deployment.yaml`,
|
|
173
|
+
content: getAppDeploymentManifest(defaultAppImage),
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
path: `${k8sRoot}/app/service.yaml`,
|
|
177
|
+
content: getAppServiceManifest(),
|
|
178
|
+
},
|
|
179
|
+
]
|
|
180
|
+
: []),
|
|
174
181
|
...supabaseResources,
|
|
175
182
|
{
|
|
176
183
|
path: `${k8sRoot}/kustomization.yaml`,
|
|
177
184
|
content: getKustomizationManifest({
|
|
178
185
|
namespaceResources,
|
|
186
|
+
appRuntimeEnabled,
|
|
179
187
|
supabaseEnabled: supabaseKubernetesEnabled,
|
|
180
188
|
extraResources,
|
|
181
189
|
}),
|
|
@@ -184,6 +192,7 @@ export function generateMinikubeBaseArtifacts(args: {
|
|
|
184
192
|
path: `${scriptsRoot}/up.sh`,
|
|
185
193
|
content: getUpScript({
|
|
186
194
|
appSlug,
|
|
195
|
+
appRuntimeEnabled,
|
|
187
196
|
defaultAppImage,
|
|
188
197
|
supabaseKubernetesEnabled,
|
|
189
198
|
profileModel,
|
|
@@ -203,6 +212,7 @@ export function generateMinikubeBaseArtifacts(args: {
|
|
|
203
212
|
path: `${scriptsRoot}/port-forward.sh`,
|
|
204
213
|
content: getPortForwardScript({
|
|
205
214
|
appSlug,
|
|
215
|
+
appRuntimeEnabled,
|
|
206
216
|
supabaseKubernetesEnabled,
|
|
207
217
|
supabaseHostPorts,
|
|
208
218
|
}),
|
|
@@ -231,6 +241,7 @@ export function generateMinikubeBaseArtifacts(args: {
|
|
|
231
241
|
path: `${scriptsRoot}/status.sh`,
|
|
232
242
|
content: getStatusScript({
|
|
233
243
|
appSlug,
|
|
244
|
+
appRuntimeEnabled,
|
|
234
245
|
supabaseKubernetesEnabled,
|
|
235
246
|
profileModel,
|
|
236
247
|
supabaseHostPorts,
|
|
@@ -248,6 +259,7 @@ export function generateMinikubeBaseArtifacts(args: {
|
|
|
248
259
|
|
|
249
260
|
function getReadmeMarkdown(args: {
|
|
250
261
|
appSlug: string;
|
|
262
|
+
appRuntimeEnabled: boolean;
|
|
251
263
|
defaultAppImage: string;
|
|
252
264
|
monitoringEnabled: boolean;
|
|
253
265
|
authProvider: string;
|
|
@@ -262,6 +274,7 @@ function getReadmeMarkdown(args: {
|
|
|
262
274
|
}): string {
|
|
263
275
|
const {
|
|
264
276
|
appSlug,
|
|
277
|
+
appRuntimeEnabled,
|
|
265
278
|
defaultAppImage,
|
|
266
279
|
monitoringEnabled,
|
|
267
280
|
authProvider,
|
|
@@ -278,9 +291,7 @@ function getReadmeMarkdown(args: {
|
|
|
278
291
|
'namespaces/app.yaml',
|
|
279
292
|
...(supabaseKubernetesEnabled ? ['namespaces/supabase.yaml'] : []),
|
|
280
293
|
...providerNamespaces.map((namespace) => `namespaces/${namespace}.yaml`),
|
|
281
|
-
'app.configmap.yaml',
|
|
282
|
-
'app/deployment.yaml',
|
|
283
|
-
'app/service.yaml',
|
|
294
|
+
...(appRuntimeEnabled ? ['app.configmap.yaml', 'app/deployment.yaml', 'app/service.yaml'] : []),
|
|
284
295
|
...(supabaseKubernetesEnabled
|
|
285
296
|
? [
|
|
286
297
|
'supabase/bootstrap.sql',
|
|
@@ -343,6 +354,14 @@ function getReadmeMarkdown(args: {
|
|
|
343
354
|
? `\nConfigured OAuth providers are wired into GoTrue through generated \`GOTRUE_EXTERNAL_*\` runtime keys. The keys are named in \`.env.example\`; values must come from trusted secret resolution for the configured \`credentialsRef\` entries.\n`
|
|
344
355
|
: '';
|
|
345
356
|
|
|
357
|
+
const runtimeForwardDescription = appRuntimeEnabled
|
|
358
|
+
? supabaseKubernetesEnabled
|
|
359
|
+
? '`app` and `supabase-gateway`'
|
|
360
|
+
: '`app`'
|
|
361
|
+
: supabaseKubernetesEnabled
|
|
362
|
+
? '`supabase-gateway`'
|
|
363
|
+
: 'no host endpoints';
|
|
364
|
+
|
|
346
365
|
return `# Minikube Infra
|
|
347
366
|
|
|
348
367
|
This directory is generated from \`ankh.config.json\` (infra manifest).
|
|
@@ -350,7 +369,7 @@ This directory is generated from \`ankh.config.json\` (infra manifest).
|
|
|
350
369
|
## Ownership Model
|
|
351
370
|
|
|
352
371
|
- App slug / Minikube profile: \`${appSlug}\`
|
|
353
|
-
- App runtime
|
|
372
|
+
- App runtime: \`${appRuntimeEnabled ? `deployment/app-runtime in namespace ${APP_NAMESPACE}` : 'disabled (no enabled Web deploy target)'}\`
|
|
354
373
|
- Supabase namespace: \`${supabaseKubernetesEnabled ? SUPABASE_NAMESPACE : 'unused'}\`
|
|
355
374
|
${providerNamespaceLine}- Default app image: \`${defaultAppImage}\`
|
|
356
375
|
|
|
@@ -380,11 +399,18 @@ host-level Supabase Compose runtime.
|
|
|
380
399
|
|
|
381
400
|
## Lifecycle Semantics
|
|
382
401
|
|
|
383
|
-
- \`up.sh\`: starts \`minikube -p ${appSlug}\`, deploys provider namespaces, runs migrations with CLI telemetry disabled for that command, starts slug-owned port-forwards, and deploys the app runtime.
|
|
402
|
+
- \`up.sh\`: starts \`minikube -p ${appSlug}\`, deploys provider namespaces, runs migrations with CLI telemetry disabled for that command, starts slug-owned port-forwards${appRuntimeEnabled ? ', and deploys the Web app runtime' : ''}.
|
|
384
403
|
- \`down.sh\`: stops slug-owned port-forwards, then stops \`minikube -p ${appSlug}\`. Persistent data remains in the profile.
|
|
385
404
|
- \`reset.sh\`: requires \`ANKH_RESET_CONFIRM=${appSlug}\`; ${resetDescription}. It does not delete the Minikube profile.
|
|
386
405
|
- \`destroy.sh\`: deletes only \`minikube -p ${appSlug}\`.
|
|
387
406
|
|
|
407
|
+
### Port-forward groups
|
|
408
|
+
|
|
409
|
+
- \`./scripts/port-forward.sh start runtime\` idempotently ensures ${runtimeForwardDescription}, the generated host endpoints required by the running application. The same group supports \`stop\` and \`status\`.
|
|
410
|
+
- \`runtime\` excludes \`studio\` and \`db-migration\`, which are operational/bootstrap endpoints.
|
|
411
|
+
- \`all\` retains every generated forward, including operational/bootstrap endpoints.
|
|
412
|
+
- Concrete targets remain available for individual lifecycle control.
|
|
413
|
+
|
|
388
414
|
## Generated Resources
|
|
389
415
|
|
|
390
416
|
${resourceLines}
|
|
@@ -419,8 +445,7 @@ Pinned images:
|
|
|
419
445
|
|
|
420
446
|
## Host URLs
|
|
421
447
|
|
|
422
|
-
|
|
423
|
-
- Supabase gateway: \`http://127.0.0.1:${supabaseHostPorts.gateway}\`
|
|
448
|
+
${appRuntimeEnabled ? `- App: \`http://127.0.0.1:${supabaseHostPorts.app}\`\n` : ''}- Supabase gateway: \`http://127.0.0.1:${supabaseHostPorts.gateway}\`
|
|
424
449
|
- Studio: \`http://127.0.0.1:${supabaseHostPorts.studio}\`
|
|
425
450
|
- DB migration endpoint: \`127.0.0.1:${supabaseHostPorts.db}\`
|
|
426
451
|
|
|
@@ -956,6 +981,7 @@ function normalizeBuckets(rawBuckets: readonly string[]): string[] {
|
|
|
956
981
|
|
|
957
982
|
function getKustomizationManifest(args: {
|
|
958
983
|
namespaceResources: string[];
|
|
984
|
+
appRuntimeEnabled: boolean;
|
|
959
985
|
supabaseEnabled: boolean;
|
|
960
986
|
extraResources: string[];
|
|
961
987
|
}): string {
|
|
@@ -976,9 +1002,9 @@ function getKustomizationManifest(args: {
|
|
|
976
1002
|
: [];
|
|
977
1003
|
const resources = [
|
|
978
1004
|
...args.namespaceResources,
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
1005
|
+
...(args.appRuntimeEnabled
|
|
1006
|
+
? ['app.configmap.yaml', 'app/deployment.yaml', 'app/service.yaml']
|
|
1007
|
+
: []),
|
|
982
1008
|
...supabaseResources,
|
|
983
1009
|
...args.extraResources,
|
|
984
1010
|
];
|
|
@@ -2252,6 +2278,7 @@ spec:
|
|
|
2252
2278
|
|
|
2253
2279
|
function getUpScript(args: {
|
|
2254
2280
|
appSlug: string;
|
|
2281
|
+
appRuntimeEnabled: boolean;
|
|
2255
2282
|
defaultAppImage: string;
|
|
2256
2283
|
supabaseKubernetesEnabled: boolean;
|
|
2257
2284
|
profileModel: ResolvedProfileModel;
|
|
@@ -2262,6 +2289,7 @@ function getUpScript(args: {
|
|
|
2262
2289
|
}): string {
|
|
2263
2290
|
const {
|
|
2264
2291
|
appSlug,
|
|
2292
|
+
appRuntimeEnabled,
|
|
2265
2293
|
defaultAppImage,
|
|
2266
2294
|
supabaseKubernetesEnabled,
|
|
2267
2295
|
profileModel,
|
|
@@ -2281,6 +2309,14 @@ function getUpScript(args: {
|
|
|
2281
2309
|
secretStoreProvider,
|
|
2282
2310
|
});
|
|
2283
2311
|
const supabaseMigrationCommand = getSupabaseMigrationCommandScript();
|
|
2312
|
+
const disabledAppRuntimeReconciliation = appRuntimeEnabled
|
|
2313
|
+
? ''
|
|
2314
|
+
: `reconcile_disabled_app_runtime() {
|
|
2315
|
+
kubectl --context "\${PROFILE}" -n "\${APP_NAMESPACE}" delete deployment/app-runtime service/app-runtime configmap/app-infra-config --ignore-not-found
|
|
2316
|
+
"\${PORT_FORWARD_SCRIPT}" stop obsolete
|
|
2317
|
+
}
|
|
2318
|
+
`;
|
|
2319
|
+
const reconcileDisabledAppRuntime = appRuntimeEnabled ? '' : 'reconcile_disabled_app_runtime';
|
|
2284
2320
|
|
|
2285
2321
|
return `#!/usr/bin/env bash
|
|
2286
2322
|
set -Eeuo pipefail
|
|
@@ -2296,6 +2332,7 @@ DRIVER="\${MINIKUBE_DRIVER:-}"
|
|
|
2296
2332
|
APP_NAMESPACE="${APP_NAMESPACE}"
|
|
2297
2333
|
SUPABASE_NAMESPACE="${SUPABASE_NAMESPACE}"
|
|
2298
2334
|
SUPABASE_RUNTIME_ENABLED="${supabaseKubernetesEnabled ? 'true' : 'false'}"
|
|
2335
|
+
APP_RUNTIME_ENABLED="${appRuntimeEnabled ? 'true' : 'false'}"
|
|
2299
2336
|
APP_BUILD_ENABLED="\${APP_BUILD_ENABLED:-}"
|
|
2300
2337
|
APP_SOURCE_DIR="\${APP_SOURCE_DIR:-}"
|
|
2301
2338
|
APP_WEB_EXPORT_DIR="\${APP_WEB_EXPORT_DIR:-}"
|
|
@@ -2726,6 +2763,7 @@ apply_namespace_manifests() {
|
|
|
2726
2763
|
done
|
|
2727
2764
|
}
|
|
2728
2765
|
|
|
2766
|
+
${disabledAppRuntimeReconciliation}
|
|
2729
2767
|
${providerLifecycleStageScripts}
|
|
2730
2768
|
|
|
2731
2769
|
load_env_file_preserving_process_env
|
|
@@ -2799,7 +2837,7 @@ else
|
|
|
2799
2837
|
kubectl --context "\${PROFILE}" apply -k "\${K8S_DIR}"
|
|
2800
2838
|
fi
|
|
2801
2839
|
|
|
2802
|
-
if [[ "\${APP_BUILD_ENABLED}" == "true" ]]; then
|
|
2840
|
+
if [[ "\${APP_RUNTIME_ENABLED}" == "true" && "\${APP_BUILD_ENABLED}" == "true" ]]; then
|
|
2803
2841
|
if [[ ! -x "\${BUILD_SCRIPT}" ]]; then
|
|
2804
2842
|
echo "Missing build helper script: \${BUILD_SCRIPT}"
|
|
2805
2843
|
exit 1
|
|
@@ -2814,6 +2852,7 @@ else
|
|
|
2814
2852
|
EXPORT_DIR="\${APP_SOURCE_DIR}/\${APP_WEB_EXPORT_DIR}"
|
|
2815
2853
|
fi
|
|
2816
2854
|
|
|
2855
|
+
if [[ "\${APP_RUNTIME_ENABLED}" == "true" ]]; then
|
|
2817
2856
|
case "\${APP_IMAGE_SYNC_STRATEGY}" in
|
|
2818
2857
|
minikube-build)
|
|
2819
2858
|
if [[ ! -f "\${EXPORT_DIR}/index.html" ]]; then
|
|
@@ -2835,15 +2874,18 @@ case "\${APP_IMAGE_SYNC_STRATEGY}" in
|
|
|
2835
2874
|
exit 1
|
|
2836
2875
|
;;
|
|
2837
2876
|
esac
|
|
2877
|
+
fi
|
|
2838
2878
|
|
|
2839
2879
|
if [[ "\${SUPABASE_RUNTIME_ENABLED}" == "true" ]]; then
|
|
2840
2880
|
kubectl --context "\${PROFILE}" apply -k "\${K8S_DIR}"
|
|
2841
2881
|
fi
|
|
2842
2882
|
|
|
2883
|
+
${reconcileDisabledAppRuntime}
|
|
2843
2884
|
wait_for_provider_readiness
|
|
2844
2885
|
run_provider_migrations
|
|
2845
2886
|
run_provider_reconciliation
|
|
2846
2887
|
|
|
2888
|
+
if [[ "\${APP_RUNTIME_ENABLED}" == "true" ]]; then
|
|
2847
2889
|
if [[ -n "\${APP_IMAGE_PULL_SECRET_NAME}" ]]; then
|
|
2848
2890
|
if [[ -z "\${APP_IMAGE_PULL_SECRET_USERNAME}" || -z "\${APP_IMAGE_PULL_SECRET_PASSWORD}" ]]; then
|
|
2849
2891
|
echo "APP_IMAGE_PULL_SECRET_NAME is set, but username/password are missing."
|
|
@@ -2875,6 +2917,7 @@ fi
|
|
|
2875
2917
|
|
|
2876
2918
|
kubectl --context "\${PROFILE}" -n "\${APP_NAMESPACE}" rollout status deployment/app-runtime --timeout=180s >/dev/null
|
|
2877
2919
|
"\${PORT_FORWARD_SCRIPT}" start app >/dev/null
|
|
2920
|
+
fi
|
|
2878
2921
|
|
|
2879
2922
|
trap - ERR
|
|
2880
2923
|
echo "Minikube infrastructure for '\${PROFILE}' is running."
|
|
@@ -2988,10 +3031,44 @@ CMD ["nginx", "-g", "daemon off;"]
|
|
|
2988
3031
|
|
|
2989
3032
|
function getPortForwardScript(args: {
|
|
2990
3033
|
appSlug: string;
|
|
3034
|
+
appRuntimeEnabled: boolean;
|
|
2991
3035
|
supabaseKubernetesEnabled: boolean;
|
|
2992
3036
|
supabaseHostPorts: SupabaseHostPorts;
|
|
2993
3037
|
}): string {
|
|
2994
|
-
const { appSlug, supabaseKubernetesEnabled, supabaseHostPorts } = args;
|
|
3038
|
+
const { appSlug, appRuntimeEnabled, supabaseKubernetesEnabled, supabaseHostPorts } = args;
|
|
3039
|
+
const runtimeForwardNames = [
|
|
3040
|
+
...(appRuntimeEnabled ? ['app'] : []),
|
|
3041
|
+
...(supabaseKubernetesEnabled ? ['supabase-gateway'] : []),
|
|
3042
|
+
];
|
|
3043
|
+
const allForwardNames = [
|
|
3044
|
+
...runtimeForwardNames,
|
|
3045
|
+
...(supabaseKubernetesEnabled ? ['studio', 'db-migration'] : []),
|
|
3046
|
+
];
|
|
3047
|
+
const managedForwardNames = ['app', 'supabase-gateway', 'studio', 'db-migration'];
|
|
3048
|
+
const obsoleteForwardNames = managedForwardNames.filter(
|
|
3049
|
+
(name) => !allForwardNames.includes(name),
|
|
3050
|
+
);
|
|
3051
|
+
const appTargetCase = ` app)
|
|
3052
|
+
echo "${APP_NAMESPACE} service/app-runtime \${APP_PORT_FORWARD_LOCAL_PORT} \${APP_PORT_FORWARD_REMOTE_PORT}"
|
|
3053
|
+
;;`;
|
|
3054
|
+
const supabaseTargetCases = ` supabase-gateway)
|
|
3055
|
+
echo "${SUPABASE_NAMESPACE} service/gateway \${SUPABASE_GATEWAY_FORWARD_LOCAL_PORT} \${SUPABASE_GATEWAY_FORWARD_REMOTE_PORT}"
|
|
3056
|
+
;;
|
|
3057
|
+
studio)
|
|
3058
|
+
echo "${SUPABASE_NAMESPACE} service/studio \${SUPABASE_STUDIO_FORWARD_LOCAL_PORT} \${SUPABASE_STUDIO_FORWARD_REMOTE_PORT}"
|
|
3059
|
+
;;
|
|
3060
|
+
db-migration)
|
|
3061
|
+
echo "${SUPABASE_NAMESPACE} service/postgres \${SUPABASE_DB_FORWARD_LOCAL_PORT} \${SUPABASE_DB_FORWARD_REMOTE_PORT}"
|
|
3062
|
+
;;`;
|
|
3063
|
+
const concreteForwardNames = [
|
|
3064
|
+
...(appRuntimeEnabled ? ['app'] : []),
|
|
3065
|
+
...(supabaseKubernetesEnabled ? ['supabase-gateway', 'studio', 'db-migration'] : []),
|
|
3066
|
+
];
|
|
3067
|
+
const forwardUsage = [...concreteForwardNames, 'runtime', 'all'].join('|');
|
|
3068
|
+
const forwardNamesDescription =
|
|
3069
|
+
concreteForwardNames.length > 0
|
|
3070
|
+
? `${concreteForwardNames.join(', ')}, runtime, or all`
|
|
3071
|
+
: 'runtime or all';
|
|
2995
3072
|
|
|
2996
3073
|
return `#!/usr/bin/env bash
|
|
2997
3074
|
set -euo pipefail
|
|
@@ -3002,6 +3079,7 @@ STATE_DIR="\${ROOT_DIR}/.state/forwards"
|
|
|
3002
3079
|
APP_SLUG="${appSlug}"
|
|
3003
3080
|
PROFILE="\${ANKH_APP_SLUG:-${appSlug}}"
|
|
3004
3081
|
SUPABASE_RUNTIME_ENABLED="${supabaseKubernetesEnabled ? 'true' : 'false'}"
|
|
3082
|
+
APP_RUNTIME_ENABLED="${appRuntimeEnabled ? 'true' : 'false'}"
|
|
3005
3083
|
APP_PORT_FORWARD_LOCAL_PORT="\${APP_PORT_FORWARD_LOCAL_PORT:-${supabaseHostPorts.app}}"
|
|
3006
3084
|
APP_PORT_FORWARD_REMOTE_PORT="\${APP_PORT_FORWARD_REMOTE_PORT:-80}"
|
|
3007
3085
|
SUPABASE_GATEWAY_FORWARD_LOCAL_PORT="\${SUPABASE_GATEWAY_FORWARD_LOCAL_PORT:-${supabaseHostPorts.gateway}}"
|
|
@@ -3010,6 +3088,10 @@ SUPABASE_STUDIO_FORWARD_LOCAL_PORT="\${SUPABASE_STUDIO_FORWARD_LOCAL_PORT:-${sup
|
|
|
3010
3088
|
SUPABASE_STUDIO_FORWARD_REMOTE_PORT="\${SUPABASE_STUDIO_FORWARD_REMOTE_PORT:-3000}"
|
|
3011
3089
|
SUPABASE_DB_FORWARD_LOCAL_PORT="\${SUPABASE_DB_FORWARD_LOCAL_PORT:-${supabaseHostPorts.db}}"
|
|
3012
3090
|
SUPABASE_DB_FORWARD_REMOTE_PORT="\${SUPABASE_DB_FORWARD_REMOTE_PORT:-5432}"
|
|
3091
|
+
RUNTIME_FORWARD_NAMES=(${runtimeForwardNames.join(' ')})
|
|
3092
|
+
ALL_FORWARD_NAMES=(${allForwardNames.join(' ')})
|
|
3093
|
+
MANAGED_FORWARD_NAMES=(${managedForwardNames.join(' ')})
|
|
3094
|
+
OBSOLETE_FORWARD_NAMES=(${obsoleteForwardNames.join(' ')})
|
|
3013
3095
|
|
|
3014
3096
|
if [[ -f "\${ROOT_DIR}/.env" ]]; then
|
|
3015
3097
|
set -a
|
|
@@ -3018,6 +3100,7 @@ if [[ -f "\${ROOT_DIR}/.env" ]]; then
|
|
|
3018
3100
|
set +a
|
|
3019
3101
|
fi
|
|
3020
3102
|
SUPABASE_RUNTIME_ENABLED="${supabaseKubernetesEnabled ? 'true' : 'false'}"
|
|
3103
|
+
APP_RUNTIME_ENABLED="${appRuntimeEnabled ? 'true' : 'false'}"
|
|
3021
3104
|
|
|
3022
3105
|
if [[ "\${PROFILE}" != "\${APP_SLUG}" ]]; then
|
|
3023
3106
|
echo "ANKH_APP_SLUG must remain the generated canonical slug '\${APP_SLUG}' for this infra directory."
|
|
@@ -3037,20 +3120,10 @@ pid_file_for() {
|
|
|
3037
3120
|
|
|
3038
3121
|
target_for() {
|
|
3039
3122
|
case "\${1}" in
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
;;
|
|
3043
|
-
supabase-gateway)
|
|
3044
|
-
echo "${SUPABASE_NAMESPACE} service/gateway \${SUPABASE_GATEWAY_FORWARD_LOCAL_PORT} \${SUPABASE_GATEWAY_FORWARD_REMOTE_PORT}"
|
|
3045
|
-
;;
|
|
3046
|
-
studio)
|
|
3047
|
-
echo "${SUPABASE_NAMESPACE} service/studio \${SUPABASE_STUDIO_FORWARD_LOCAL_PORT} \${SUPABASE_STUDIO_FORWARD_REMOTE_PORT}"
|
|
3048
|
-
;;
|
|
3049
|
-
db-migration)
|
|
3050
|
-
echo "${SUPABASE_NAMESPACE} service/postgres \${SUPABASE_DB_FORWARD_LOCAL_PORT} \${SUPABASE_DB_FORWARD_REMOTE_PORT}"
|
|
3051
|
-
;;
|
|
3123
|
+
${appTargetCase}
|
|
3124
|
+
${supabaseTargetCases}
|
|
3052
3125
|
*)
|
|
3053
|
-
echo "Unknown forward '\${1}'. Use
|
|
3126
|
+
echo "Unknown forward '\${1}'. Use ${forwardNamesDescription}." >&2
|
|
3054
3127
|
return 1
|
|
3055
3128
|
;;
|
|
3056
3129
|
esac
|
|
@@ -3186,6 +3259,11 @@ start_forward() {
|
|
|
3186
3259
|
pid_file="$(pid_file_for "\${name}")"
|
|
3187
3260
|
read -r namespace resource local_port remote_port <<<"$(target_for "\${name}")"
|
|
3188
3261
|
|
|
3262
|
+
if [[ "\${name}" == "app" && "\${APP_RUNTIME_ENABLED}" != "true" ]]; then
|
|
3263
|
+
echo "\${name}: skipped (Web app runtime disabled)"
|
|
3264
|
+
return 0
|
|
3265
|
+
fi
|
|
3266
|
+
|
|
3189
3267
|
if [[ -f "\${pid_file}" ]]; then
|
|
3190
3268
|
local existing_pid
|
|
3191
3269
|
existing_pid="$(cat "\${pid_file}")"
|
|
@@ -3215,28 +3293,52 @@ start_forward() {
|
|
|
3215
3293
|
return 1
|
|
3216
3294
|
fi
|
|
3217
3295
|
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3296
|
+
for start_attempt in {1..5}; do
|
|
3297
|
+
nohup kubectl --context "\${PROFILE}" -n "\${namespace}" port-forward "\${resource}" "\${local_port}:\${remote_port}" >"\${STATE_DIR}/\${PROFILE}-\${name}.log" 2>&1 &
|
|
3298
|
+
local pid="$!"
|
|
3299
|
+
echo "\${pid}" > "\${pid_file}"
|
|
3221
3300
|
|
|
3222
|
-
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3301
|
+
for readiness_attempt in {1..20}; do
|
|
3302
|
+
if ! is_pid_running "\${pid}"; then
|
|
3303
|
+
rm -f "\${pid_file}"
|
|
3304
|
+
if [[ "\${start_attempt}" -lt 5 ]]; then
|
|
3305
|
+
echo "\${name}: port-forward attempt \${start_attempt} exited before readiness; retrying"
|
|
3306
|
+
sleep 2
|
|
3307
|
+
break
|
|
3308
|
+
fi
|
|
3309
|
+
|
|
3310
|
+
echo "\${name}: failed to start local port \${local_port} for \${namespace}/\${resource}:\${remote_port} after \${start_attempt} attempts"
|
|
3311
|
+
print_forward_log_tail "\${name}"
|
|
3312
|
+
return 1
|
|
3313
|
+
fi
|
|
3314
|
+
if is_port_accepting "\${local_port}"; then
|
|
3315
|
+
sleep 1
|
|
3316
|
+
if is_pid_running "\${pid}" && is_port_accepting "\${local_port}"; then
|
|
3317
|
+
sleep 0.5
|
|
3318
|
+
if is_pid_running "\${pid}"; then
|
|
3319
|
+
echo "\${name}: started (pid \${pid}, local port \${local_port})"
|
|
3320
|
+
return 0
|
|
3321
|
+
fi
|
|
3322
|
+
fi
|
|
3323
|
+
fi
|
|
3324
|
+
sleep 0.5
|
|
3325
|
+
done
|
|
3326
|
+
|
|
3327
|
+
if [[ -f "\${pid_file}" ]]; then
|
|
3328
|
+
terminate_forward_process "\${name}" "\${pid}" "\${namespace}" "\${resource}" "\${local_port}" "\${remote_port}" || return 1
|
|
3226
3329
|
rm -f "\${pid_file}"
|
|
3227
|
-
|
|
3228
|
-
|
|
3229
|
-
|
|
3230
|
-
|
|
3231
|
-
|
|
3330
|
+
|
|
3331
|
+
if [[ "\${start_attempt}" -lt 5 ]]; then
|
|
3332
|
+
echo "\${name}: port-forward attempt \${start_attempt} did not become ready; retrying"
|
|
3333
|
+
sleep 2
|
|
3334
|
+
else
|
|
3335
|
+
echo "\${name}: did not become ready on local port \${local_port} for \${namespace}/\${resource}:\${remote_port} after \${start_attempt} attempts"
|
|
3336
|
+
print_forward_log_tail "\${name}"
|
|
3337
|
+
return 1
|
|
3338
|
+
fi
|
|
3232
3339
|
fi
|
|
3233
|
-
sleep 0.5
|
|
3234
3340
|
done
|
|
3235
3341
|
|
|
3236
|
-
echo "\${name}: did not become ready on local port \${local_port} for \${namespace}/\${resource}:\${remote_port}"
|
|
3237
|
-
print_forward_log_tail "\${name}"
|
|
3238
|
-
terminate_forward_process "\${name}" "\${pid}" "\${namespace}" "\${resource}" "\${local_port}" "\${remote_port}" || return 1
|
|
3239
|
-
rm -f "\${pid_file}"
|
|
3240
3342
|
return 1
|
|
3241
3343
|
}
|
|
3242
3344
|
|
|
@@ -3295,26 +3397,34 @@ status_forward() {
|
|
|
3295
3397
|
|
|
3296
3398
|
for_each_forward() {
|
|
3297
3399
|
local action="\${1}"
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
"\${
|
|
3302
|
-
|
|
3303
|
-
|
|
3400
|
+
shift
|
|
3401
|
+
local name
|
|
3402
|
+
while [[ "\${#}" -gt 0 ]]; do
|
|
3403
|
+
name="\${1}"
|
|
3404
|
+
shift
|
|
3405
|
+
"\${action}_forward" "\${name}"
|
|
3406
|
+
done
|
|
3304
3407
|
}
|
|
3305
3408
|
|
|
3306
3409
|
ACTION="\${1:-start}"
|
|
3307
3410
|
NAME="\${2:-all}"
|
|
3308
3411
|
|
|
3309
3412
|
case "\${ACTION}:\${NAME}" in
|
|
3310
|
-
start:
|
|
3311
|
-
stop:
|
|
3312
|
-
|
|
3413
|
+
start:runtime) for_each_forward start ${runtimeForwardNames.join(' ')} ;;
|
|
3414
|
+
stop:runtime)
|
|
3415
|
+
for_each_forward stop ${runtimeForwardNames.join(' ')}
|
|
3416
|
+
for_each_forward stop ${obsoleteForwardNames.join(' ')}
|
|
3417
|
+
;;
|
|
3418
|
+
status:runtime) for_each_forward status ${runtimeForwardNames.join(' ')} ;;
|
|
3419
|
+
start:all) for_each_forward start ${allForwardNames.join(' ')} ;;
|
|
3420
|
+
stop:all) for_each_forward stop ${managedForwardNames.join(' ')} ;;
|
|
3421
|
+
status:all) for_each_forward status ${allForwardNames.join(' ')} ;;
|
|
3422
|
+
stop:obsolete) for_each_forward stop ${obsoleteForwardNames.join(' ')} ;;
|
|
3313
3423
|
start:*) start_forward "\${NAME}" ;;
|
|
3314
3424
|
stop:*) stop_forward "\${NAME}" ;;
|
|
3315
3425
|
status:*) status_forward "\${NAME}" ;;
|
|
3316
3426
|
*)
|
|
3317
|
-
echo "Usage: ./scripts/port-forward.sh {start|stop|status} {
|
|
3427
|
+
echo "Usage: ./scripts/port-forward.sh {start|stop|status} {${forwardUsage}}"
|
|
3318
3428
|
exit 1
|
|
3319
3429
|
;;
|
|
3320
3430
|
esac
|
|
@@ -3448,6 +3558,7 @@ echo "Deleted Minikube profile '\${PROFILE}'."
|
|
|
3448
3558
|
|
|
3449
3559
|
function getStatusScript(args: {
|
|
3450
3560
|
appSlug: string;
|
|
3561
|
+
appRuntimeEnabled: boolean;
|
|
3451
3562
|
supabaseKubernetesEnabled: boolean;
|
|
3452
3563
|
profileModel: ResolvedProfileModel;
|
|
3453
3564
|
supabaseHostPorts: SupabaseHostPorts;
|
|
@@ -3456,6 +3567,7 @@ function getStatusScript(args: {
|
|
|
3456
3567
|
}): string {
|
|
3457
3568
|
const {
|
|
3458
3569
|
appSlug,
|
|
3570
|
+
appRuntimeEnabled,
|
|
3459
3571
|
supabaseKubernetesEnabled,
|
|
3460
3572
|
profileModel,
|
|
3461
3573
|
supabaseHostPorts,
|
|
@@ -3540,7 +3652,7 @@ for namespace in ${namespaces}; do
|
|
|
3540
3652
|
fi
|
|
3541
3653
|
done
|
|
3542
3654
|
|
|
3543
|
-
if kubectl --context "\${PROFILE}" -n ${APP_NAMESPACE} get deployment app-runtime >/dev/null 2>&1; then
|
|
3655
|
+
if [[ "${appRuntimeEnabled ? 'true' : 'false'}" == "true" ]] && kubectl --context "\${PROFILE}" -n ${APP_NAMESPACE} get deployment app-runtime >/dev/null 2>&1; then
|
|
3544
3656
|
kubectl --context "\${PROFILE}" -n ${APP_NAMESPACE} rollout status deployment/app-runtime --timeout=5s >/dev/null 2>&1 && echo "- app-runtime: ready" || echo "- app-runtime: not ready"
|
|
3545
3657
|
fi
|
|
3546
3658
|
|