@ankhorage/infra 4.1.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 +6 -0
- 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 +160 -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/package.json +1 -1
- package/src/adapters/minikube/README.md +18 -8
- package/src/adapters/minikube/base/index.test.ts +137 -6
- package/src/adapters/minikube/base/index.ts +170 -76
- package/src/adapters/minikube/base/portForwardRuntime.test.ts +355 -19
- package/src/adapters/minikube/base/upgradeReconciliation.test.ts +135 -0
- package/src/adapters/minikube/index.ts +4 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @ankhorage/infra
|
|
2
2
|
|
|
3
|
+
## 4.1.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 591cecb: Derive Minikube app runtime resources and canonical forward groups from enabled app deployment targets, reconcile obsolete Web runtime resources and owned forwards during native-only upgrades, and retry transient post-restart forwarding failures so native apps can recover provider endpoints without a nonexistent app Service.
|
|
8
|
+
|
|
3
9
|
## 4.1.0
|
|
4
10
|
|
|
5
11
|
### Minor Changes
|
|
@@ -5,6 +5,7 @@ export declare const APP_NAMESPACE = "app";
|
|
|
5
5
|
export declare function generateMinikubeBaseArtifacts(args: {
|
|
6
6
|
manifest: InfraManifestInput;
|
|
7
7
|
appSlug: string;
|
|
8
|
+
appRuntimeEnabled: boolean;
|
|
8
9
|
extraResources: string[];
|
|
9
10
|
providerNamespaces: string[];
|
|
10
11
|
providerLifecycle: MinikubeProviderLifecycle[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/adapters/minikube/base/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAGzD,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AAG9D,eAAO,MAAM,aAAa,QAAQ,CAAC;AAoDnC,wBAAgB,6BAA6B,CAAC,IAAI,EAAE;IAClD,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,iBAAiB,EAAE,yBAAyB,EAAE,CAAC;IAC/C,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B,GAAG,2BAA2B,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/adapters/minikube/base/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,gBAAgB,CAAC;AAClE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAGzD,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,cAAc,CAAC;AAG9D,eAAO,MAAM,aAAa,QAAQ,CAAC;AAoDnC,wBAAgB,6BAA6B,CAAC,IAAI,EAAE;IAClD,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,iBAAiB,EAAE,yBAAyB,EAAE,CAAC;IAC/C,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B,GAAG,2BAA2B,EAAE,CA8LhC"}
|
|
@@ -18,7 +18,7 @@ const PORT_BUCKET_SIZE = 20;
|
|
|
18
18
|
const PORT_BUCKET_COUNT = 1000;
|
|
19
19
|
const PORT_REFERENCE_SLUG = 'my-app';
|
|
20
20
|
export function generateMinikubeBaseArtifacts(args) {
|
|
21
|
-
const { manifest, appSlug, extraResources, providerNamespaces, providerLifecycle, extraEnvEntries, } = args;
|
|
21
|
+
const { manifest, appSlug, appRuntimeEnabled, extraResources, providerNamespaces, providerLifecycle, extraEnvEntries, } = args;
|
|
22
22
|
const root = 'infra/minikube';
|
|
23
23
|
const k8sRoot = `${root}/k8s`;
|
|
24
24
|
const scriptsRoot = `${root}/scripts`;
|
|
@@ -50,6 +50,7 @@ export function generateMinikubeBaseArtifacts(args) {
|
|
|
50
50
|
path: `${root}/README.md`,
|
|
51
51
|
content: getReadmeMarkdown({
|
|
52
52
|
appSlug,
|
|
53
|
+
appRuntimeEnabled,
|
|
53
54
|
defaultAppImage,
|
|
54
55
|
monitoringEnabled,
|
|
55
56
|
authProvider,
|
|
@@ -91,32 +92,37 @@ export function generateMinikubeBaseArtifacts(args) {
|
|
|
91
92
|
path: `${k8sRoot}/namespaces/${namespace}.yaml`,
|
|
92
93
|
content: getNamespaceManifest(namespace),
|
|
93
94
|
})),
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
95
|
+
...(appRuntimeEnabled
|
|
96
|
+
? [
|
|
97
|
+
{
|
|
98
|
+
path: `${k8sRoot}/app.configmap.yaml`,
|
|
99
|
+
content: getAppConfigMap({
|
|
100
|
+
appSlug,
|
|
101
|
+
authScope,
|
|
102
|
+
authProvider,
|
|
103
|
+
databaseProvider,
|
|
104
|
+
secretStoreProvider,
|
|
105
|
+
storageMetadata,
|
|
106
|
+
monitoringEnabled,
|
|
107
|
+
domain,
|
|
108
|
+
}),
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
path: `${k8sRoot}/app/deployment.yaml`,
|
|
112
|
+
content: getAppDeploymentManifest(defaultAppImage),
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
path: `${k8sRoot}/app/service.yaml`,
|
|
116
|
+
content: getAppServiceManifest(),
|
|
117
|
+
},
|
|
118
|
+
]
|
|
119
|
+
: []),
|
|
115
120
|
...supabaseResources,
|
|
116
121
|
{
|
|
117
122
|
path: `${k8sRoot}/kustomization.yaml`,
|
|
118
123
|
content: getKustomizationManifest({
|
|
119
124
|
namespaceResources,
|
|
125
|
+
appRuntimeEnabled,
|
|
120
126
|
supabaseEnabled: supabaseKubernetesEnabled,
|
|
121
127
|
extraResources,
|
|
122
128
|
}),
|
|
@@ -125,6 +131,7 @@ export function generateMinikubeBaseArtifacts(args) {
|
|
|
125
131
|
path: `${scriptsRoot}/up.sh`,
|
|
126
132
|
content: getUpScript({
|
|
127
133
|
appSlug,
|
|
134
|
+
appRuntimeEnabled,
|
|
128
135
|
defaultAppImage,
|
|
129
136
|
supabaseKubernetesEnabled,
|
|
130
137
|
profileModel,
|
|
@@ -144,6 +151,7 @@ export function generateMinikubeBaseArtifacts(args) {
|
|
|
144
151
|
path: `${scriptsRoot}/port-forward.sh`,
|
|
145
152
|
content: getPortForwardScript({
|
|
146
153
|
appSlug,
|
|
154
|
+
appRuntimeEnabled,
|
|
147
155
|
supabaseKubernetesEnabled,
|
|
148
156
|
supabaseHostPorts,
|
|
149
157
|
}),
|
|
@@ -172,6 +180,7 @@ export function generateMinikubeBaseArtifacts(args) {
|
|
|
172
180
|
path: `${scriptsRoot}/status.sh`,
|
|
173
181
|
content: getStatusScript({
|
|
174
182
|
appSlug,
|
|
183
|
+
appRuntimeEnabled,
|
|
175
184
|
supabaseKubernetesEnabled,
|
|
176
185
|
profileModel,
|
|
177
186
|
supabaseHostPorts,
|
|
@@ -187,14 +196,12 @@ export function generateMinikubeBaseArtifacts(args) {
|
|
|
187
196
|
];
|
|
188
197
|
}
|
|
189
198
|
function getReadmeMarkdown(args) {
|
|
190
|
-
const { appSlug, defaultAppImage, monitoringEnabled, authProvider, authzEngine, extraResources, supabaseHostPorts, supabaseKubernetesEnabled, profileModel, oauthProviders, providerNamespaces, providerLifecycle, } = args;
|
|
199
|
+
const { appSlug, appRuntimeEnabled, defaultAppImage, monitoringEnabled, authProvider, authzEngine, extraResources, supabaseHostPorts, supabaseKubernetesEnabled, profileModel, oauthProviders, providerNamespaces, providerLifecycle, } = args;
|
|
191
200
|
const resourceLines = [
|
|
192
201
|
'namespaces/app.yaml',
|
|
193
202
|
...(supabaseKubernetesEnabled ? ['namespaces/supabase.yaml'] : []),
|
|
194
203
|
...providerNamespaces.map((namespace) => `namespaces/${namespace}.yaml`),
|
|
195
|
-
'app.configmap.yaml',
|
|
196
|
-
'app/deployment.yaml',
|
|
197
|
-
'app/service.yaml',
|
|
204
|
+
...(appRuntimeEnabled ? ['app.configmap.yaml', 'app/deployment.yaml', 'app/service.yaml'] : []),
|
|
198
205
|
...(supabaseKubernetesEnabled
|
|
199
206
|
? [
|
|
200
207
|
'supabase/bootstrap.sql',
|
|
@@ -248,6 +255,13 @@ function getReadmeMarkdown(args) {
|
|
|
248
255
|
const oauthDescription = oauthProviders.length > 0
|
|
249
256
|
? `\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`
|
|
250
257
|
: '';
|
|
258
|
+
const runtimeForwardDescription = appRuntimeEnabled
|
|
259
|
+
? supabaseKubernetesEnabled
|
|
260
|
+
? '`app` and `supabase-gateway`'
|
|
261
|
+
: '`app`'
|
|
262
|
+
: supabaseKubernetesEnabled
|
|
263
|
+
? '`supabase-gateway`'
|
|
264
|
+
: 'no host endpoints';
|
|
251
265
|
return `# Minikube Infra
|
|
252
266
|
|
|
253
267
|
This directory is generated from \`ankh.config.json\` (infra manifest).
|
|
@@ -255,7 +269,7 @@ This directory is generated from \`ankh.config.json\` (infra manifest).
|
|
|
255
269
|
## Ownership Model
|
|
256
270
|
|
|
257
271
|
- App slug / Minikube profile: \`${appSlug}\`
|
|
258
|
-
- App runtime
|
|
272
|
+
- App runtime: \`${appRuntimeEnabled ? `deployment/app-runtime in namespace ${APP_NAMESPACE}` : 'disabled (no enabled Web deploy target)'}\`
|
|
259
273
|
- Supabase namespace: \`${supabaseKubernetesEnabled ? SUPABASE_NAMESPACE : 'unused'}\`
|
|
260
274
|
${providerNamespaceLine}- Default app image: \`${defaultAppImage}\`
|
|
261
275
|
|
|
@@ -285,14 +299,14 @@ host-level Supabase Compose runtime.
|
|
|
285
299
|
|
|
286
300
|
## Lifecycle Semantics
|
|
287
301
|
|
|
288
|
-
- \`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.
|
|
302
|
+
- \`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' : ''}.
|
|
289
303
|
- \`down.sh\`: stops slug-owned port-forwards, then stops \`minikube -p ${appSlug}\`. Persistent data remains in the profile.
|
|
290
304
|
- \`reset.sh\`: requires \`ANKH_RESET_CONFIRM=${appSlug}\`; ${resetDescription}. It does not delete the Minikube profile.
|
|
291
305
|
- \`destroy.sh\`: deletes only \`minikube -p ${appSlug}\`.
|
|
292
306
|
|
|
293
307
|
### Port-forward groups
|
|
294
308
|
|
|
295
|
-
- \`./scripts/port-forward.sh start runtime\` idempotently ensures ${
|
|
309
|
+
- \`./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\`.
|
|
296
310
|
- \`runtime\` excludes \`studio\` and \`db-migration\`, which are operational/bootstrap endpoints.
|
|
297
311
|
- \`all\` retains every generated forward, including operational/bootstrap endpoints.
|
|
298
312
|
- Concrete targets remain available for individual lifecycle control.
|
|
@@ -331,8 +345,7 @@ Pinned images:
|
|
|
331
345
|
|
|
332
346
|
## Host URLs
|
|
333
347
|
|
|
334
|
-
|
|
335
|
-
- Supabase gateway: \`http://127.0.0.1:${supabaseHostPorts.gateway}\`
|
|
348
|
+
${appRuntimeEnabled ? `- App: \`http://127.0.0.1:${supabaseHostPorts.app}\`\n` : ''}- Supabase gateway: \`http://127.0.0.1:${supabaseHostPorts.gateway}\`
|
|
336
349
|
- Studio: \`http://127.0.0.1:${supabaseHostPorts.studio}\`
|
|
337
350
|
- DB migration endpoint: \`127.0.0.1:${supabaseHostPorts.db}\`
|
|
338
351
|
|
|
@@ -748,9 +761,9 @@ function getKustomizationManifest(args) {
|
|
|
748
761
|
: [];
|
|
749
762
|
const resources = [
|
|
750
763
|
...args.namespaceResources,
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
764
|
+
...(args.appRuntimeEnabled
|
|
765
|
+
? ['app.configmap.yaml', 'app/deployment.yaml', 'app/service.yaml']
|
|
766
|
+
: []),
|
|
754
767
|
...supabaseResources,
|
|
755
768
|
...args.extraResources,
|
|
756
769
|
];
|
|
@@ -2004,7 +2017,7 @@ spec:
|
|
|
2004
2017
|
`;
|
|
2005
2018
|
}
|
|
2006
2019
|
function getUpScript(args) {
|
|
2007
|
-
const { appSlug, defaultAppImage, supabaseKubernetesEnabled, profileModel, secretStoreProvider, supabaseHostPorts, oauthProviders, providerLifecycle, } = args;
|
|
2020
|
+
const { appSlug, appRuntimeEnabled, defaultAppImage, supabaseKubernetesEnabled, profileModel, secretStoreProvider, supabaseHostPorts, oauthProviders, providerLifecycle, } = args;
|
|
2008
2021
|
const oauthEnvDefaults = getOAuthScriptEnvDefaults(oauthProviders);
|
|
2009
2022
|
const oauthRuntimeSecretLines = getOAuthRuntimeSecretLines(oauthProviders);
|
|
2010
2023
|
const oauthValidation = getOAuthRuntimeValidationScript(oauthProviders);
|
|
@@ -2016,6 +2029,14 @@ function getUpScript(args) {
|
|
|
2016
2029
|
secretStoreProvider,
|
|
2017
2030
|
});
|
|
2018
2031
|
const supabaseMigrationCommand = getSupabaseMigrationCommandScript();
|
|
2032
|
+
const disabledAppRuntimeReconciliation = appRuntimeEnabled
|
|
2033
|
+
? ''
|
|
2034
|
+
: `reconcile_disabled_app_runtime() {
|
|
2035
|
+
kubectl --context "\${PROFILE}" -n "\${APP_NAMESPACE}" delete deployment/app-runtime service/app-runtime configmap/app-infra-config --ignore-not-found
|
|
2036
|
+
"\${PORT_FORWARD_SCRIPT}" stop obsolete
|
|
2037
|
+
}
|
|
2038
|
+
`;
|
|
2039
|
+
const reconcileDisabledAppRuntime = appRuntimeEnabled ? '' : 'reconcile_disabled_app_runtime';
|
|
2019
2040
|
return `#!/usr/bin/env bash
|
|
2020
2041
|
set -Eeuo pipefail
|
|
2021
2042
|
|
|
@@ -2030,6 +2051,7 @@ DRIVER="\${MINIKUBE_DRIVER:-}"
|
|
|
2030
2051
|
APP_NAMESPACE="${APP_NAMESPACE}"
|
|
2031
2052
|
SUPABASE_NAMESPACE="${SUPABASE_NAMESPACE}"
|
|
2032
2053
|
SUPABASE_RUNTIME_ENABLED="${supabaseKubernetesEnabled ? 'true' : 'false'}"
|
|
2054
|
+
APP_RUNTIME_ENABLED="${appRuntimeEnabled ? 'true' : 'false'}"
|
|
2033
2055
|
APP_BUILD_ENABLED="\${APP_BUILD_ENABLED:-}"
|
|
2034
2056
|
APP_SOURCE_DIR="\${APP_SOURCE_DIR:-}"
|
|
2035
2057
|
APP_WEB_EXPORT_DIR="\${APP_WEB_EXPORT_DIR:-}"
|
|
@@ -2460,6 +2482,7 @@ apply_namespace_manifests() {
|
|
|
2460
2482
|
done
|
|
2461
2483
|
}
|
|
2462
2484
|
|
|
2485
|
+
${disabledAppRuntimeReconciliation}
|
|
2463
2486
|
${providerLifecycleStageScripts}
|
|
2464
2487
|
|
|
2465
2488
|
load_env_file_preserving_process_env
|
|
@@ -2533,7 +2556,7 @@ else
|
|
|
2533
2556
|
kubectl --context "\${PROFILE}" apply -k "\${K8S_DIR}"
|
|
2534
2557
|
fi
|
|
2535
2558
|
|
|
2536
|
-
if [[ "\${APP_BUILD_ENABLED}" == "true" ]]; then
|
|
2559
|
+
if [[ "\${APP_RUNTIME_ENABLED}" == "true" && "\${APP_BUILD_ENABLED}" == "true" ]]; then
|
|
2537
2560
|
if [[ ! -x "\${BUILD_SCRIPT}" ]]; then
|
|
2538
2561
|
echo "Missing build helper script: \${BUILD_SCRIPT}"
|
|
2539
2562
|
exit 1
|
|
@@ -2548,6 +2571,7 @@ else
|
|
|
2548
2571
|
EXPORT_DIR="\${APP_SOURCE_DIR}/\${APP_WEB_EXPORT_DIR}"
|
|
2549
2572
|
fi
|
|
2550
2573
|
|
|
2574
|
+
if [[ "\${APP_RUNTIME_ENABLED}" == "true" ]]; then
|
|
2551
2575
|
case "\${APP_IMAGE_SYNC_STRATEGY}" in
|
|
2552
2576
|
minikube-build)
|
|
2553
2577
|
if [[ ! -f "\${EXPORT_DIR}/index.html" ]]; then
|
|
@@ -2569,15 +2593,18 @@ case "\${APP_IMAGE_SYNC_STRATEGY}" in
|
|
|
2569
2593
|
exit 1
|
|
2570
2594
|
;;
|
|
2571
2595
|
esac
|
|
2596
|
+
fi
|
|
2572
2597
|
|
|
2573
2598
|
if [[ "\${SUPABASE_RUNTIME_ENABLED}" == "true" ]]; then
|
|
2574
2599
|
kubectl --context "\${PROFILE}" apply -k "\${K8S_DIR}"
|
|
2575
2600
|
fi
|
|
2576
2601
|
|
|
2602
|
+
${reconcileDisabledAppRuntime}
|
|
2577
2603
|
wait_for_provider_readiness
|
|
2578
2604
|
run_provider_migrations
|
|
2579
2605
|
run_provider_reconciliation
|
|
2580
2606
|
|
|
2607
|
+
if [[ "\${APP_RUNTIME_ENABLED}" == "true" ]]; then
|
|
2581
2608
|
if [[ -n "\${APP_IMAGE_PULL_SECRET_NAME}" ]]; then
|
|
2582
2609
|
if [[ -z "\${APP_IMAGE_PULL_SECRET_USERNAME}" || -z "\${APP_IMAGE_PULL_SECRET_PASSWORD}" ]]; then
|
|
2583
2610
|
echo "APP_IMAGE_PULL_SECRET_NAME is set, but username/password are missing."
|
|
@@ -2609,6 +2636,7 @@ fi
|
|
|
2609
2636
|
|
|
2610
2637
|
kubectl --context "\${PROFILE}" -n "\${APP_NAMESPACE}" rollout status deployment/app-runtime --timeout=180s >/dev/null
|
|
2611
2638
|
"\${PORT_FORWARD_SCRIPT}" start app >/dev/null
|
|
2639
|
+
fi
|
|
2612
2640
|
|
|
2613
2641
|
trap - ERR
|
|
2614
2642
|
echo "Minikube infrastructure for '\${PROFILE}' is running."
|
|
@@ -2717,12 +2745,37 @@ CMD ["nginx", "-g", "daemon off;"]
|
|
|
2717
2745
|
`;
|
|
2718
2746
|
}
|
|
2719
2747
|
function getPortForwardScript(args) {
|
|
2720
|
-
const { appSlug, supabaseKubernetesEnabled, supabaseHostPorts } = args;
|
|
2721
|
-
const runtimeForwardNames = [
|
|
2748
|
+
const { appSlug, appRuntimeEnabled, supabaseKubernetesEnabled, supabaseHostPorts } = args;
|
|
2749
|
+
const runtimeForwardNames = [
|
|
2750
|
+
...(appRuntimeEnabled ? ['app'] : []),
|
|
2751
|
+
...(supabaseKubernetesEnabled ? ['supabase-gateway'] : []),
|
|
2752
|
+
];
|
|
2722
2753
|
const allForwardNames = [
|
|
2723
2754
|
...runtimeForwardNames,
|
|
2724
2755
|
...(supabaseKubernetesEnabled ? ['studio', 'db-migration'] : []),
|
|
2725
2756
|
];
|
|
2757
|
+
const managedForwardNames = ['app', 'supabase-gateway', 'studio', 'db-migration'];
|
|
2758
|
+
const obsoleteForwardNames = managedForwardNames.filter((name) => !allForwardNames.includes(name));
|
|
2759
|
+
const appTargetCase = ` app)
|
|
2760
|
+
echo "${APP_NAMESPACE} service/app-runtime \${APP_PORT_FORWARD_LOCAL_PORT} \${APP_PORT_FORWARD_REMOTE_PORT}"
|
|
2761
|
+
;;`;
|
|
2762
|
+
const supabaseTargetCases = ` supabase-gateway)
|
|
2763
|
+
echo "${SUPABASE_NAMESPACE} service/gateway \${SUPABASE_GATEWAY_FORWARD_LOCAL_PORT} \${SUPABASE_GATEWAY_FORWARD_REMOTE_PORT}"
|
|
2764
|
+
;;
|
|
2765
|
+
studio)
|
|
2766
|
+
echo "${SUPABASE_NAMESPACE} service/studio \${SUPABASE_STUDIO_FORWARD_LOCAL_PORT} \${SUPABASE_STUDIO_FORWARD_REMOTE_PORT}"
|
|
2767
|
+
;;
|
|
2768
|
+
db-migration)
|
|
2769
|
+
echo "${SUPABASE_NAMESPACE} service/postgres \${SUPABASE_DB_FORWARD_LOCAL_PORT} \${SUPABASE_DB_FORWARD_REMOTE_PORT}"
|
|
2770
|
+
;;`;
|
|
2771
|
+
const concreteForwardNames = [
|
|
2772
|
+
...(appRuntimeEnabled ? ['app'] : []),
|
|
2773
|
+
...(supabaseKubernetesEnabled ? ['supabase-gateway', 'studio', 'db-migration'] : []),
|
|
2774
|
+
];
|
|
2775
|
+
const forwardUsage = [...concreteForwardNames, 'runtime', 'all'].join('|');
|
|
2776
|
+
const forwardNamesDescription = concreteForwardNames.length > 0
|
|
2777
|
+
? `${concreteForwardNames.join(', ')}, runtime, or all`
|
|
2778
|
+
: 'runtime or all';
|
|
2726
2779
|
return `#!/usr/bin/env bash
|
|
2727
2780
|
set -euo pipefail
|
|
2728
2781
|
|
|
@@ -2732,6 +2785,7 @@ STATE_DIR="\${ROOT_DIR}/.state/forwards"
|
|
|
2732
2785
|
APP_SLUG="${appSlug}"
|
|
2733
2786
|
PROFILE="\${ANKH_APP_SLUG:-${appSlug}}"
|
|
2734
2787
|
SUPABASE_RUNTIME_ENABLED="${supabaseKubernetesEnabled ? 'true' : 'false'}"
|
|
2788
|
+
APP_RUNTIME_ENABLED="${appRuntimeEnabled ? 'true' : 'false'}"
|
|
2735
2789
|
APP_PORT_FORWARD_LOCAL_PORT="\${APP_PORT_FORWARD_LOCAL_PORT:-${supabaseHostPorts.app}}"
|
|
2736
2790
|
APP_PORT_FORWARD_REMOTE_PORT="\${APP_PORT_FORWARD_REMOTE_PORT:-80}"
|
|
2737
2791
|
SUPABASE_GATEWAY_FORWARD_LOCAL_PORT="\${SUPABASE_GATEWAY_FORWARD_LOCAL_PORT:-${supabaseHostPorts.gateway}}"
|
|
@@ -2742,6 +2796,8 @@ SUPABASE_DB_FORWARD_LOCAL_PORT="\${SUPABASE_DB_FORWARD_LOCAL_PORT:-${supabaseHos
|
|
|
2742
2796
|
SUPABASE_DB_FORWARD_REMOTE_PORT="\${SUPABASE_DB_FORWARD_REMOTE_PORT:-5432}"
|
|
2743
2797
|
RUNTIME_FORWARD_NAMES=(${runtimeForwardNames.join(' ')})
|
|
2744
2798
|
ALL_FORWARD_NAMES=(${allForwardNames.join(' ')})
|
|
2799
|
+
MANAGED_FORWARD_NAMES=(${managedForwardNames.join(' ')})
|
|
2800
|
+
OBSOLETE_FORWARD_NAMES=(${obsoleteForwardNames.join(' ')})
|
|
2745
2801
|
|
|
2746
2802
|
if [[ -f "\${ROOT_DIR}/.env" ]]; then
|
|
2747
2803
|
set -a
|
|
@@ -2750,6 +2806,7 @@ if [[ -f "\${ROOT_DIR}/.env" ]]; then
|
|
|
2750
2806
|
set +a
|
|
2751
2807
|
fi
|
|
2752
2808
|
SUPABASE_RUNTIME_ENABLED="${supabaseKubernetesEnabled ? 'true' : 'false'}"
|
|
2809
|
+
APP_RUNTIME_ENABLED="${appRuntimeEnabled ? 'true' : 'false'}"
|
|
2753
2810
|
|
|
2754
2811
|
if [[ "\${PROFILE}" != "\${APP_SLUG}" ]]; then
|
|
2755
2812
|
echo "ANKH_APP_SLUG must remain the generated canonical slug '\${APP_SLUG}' for this infra directory."
|
|
@@ -2769,20 +2826,10 @@ pid_file_for() {
|
|
|
2769
2826
|
|
|
2770
2827
|
target_for() {
|
|
2771
2828
|
case "\${1}" in
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
;;
|
|
2775
|
-
supabase-gateway)
|
|
2776
|
-
echo "${SUPABASE_NAMESPACE} service/gateway \${SUPABASE_GATEWAY_FORWARD_LOCAL_PORT} \${SUPABASE_GATEWAY_FORWARD_REMOTE_PORT}"
|
|
2777
|
-
;;
|
|
2778
|
-
studio)
|
|
2779
|
-
echo "${SUPABASE_NAMESPACE} service/studio \${SUPABASE_STUDIO_FORWARD_LOCAL_PORT} \${SUPABASE_STUDIO_FORWARD_REMOTE_PORT}"
|
|
2780
|
-
;;
|
|
2781
|
-
db-migration)
|
|
2782
|
-
echo "${SUPABASE_NAMESPACE} service/postgres \${SUPABASE_DB_FORWARD_LOCAL_PORT} \${SUPABASE_DB_FORWARD_REMOTE_PORT}"
|
|
2783
|
-
;;
|
|
2829
|
+
${appTargetCase}
|
|
2830
|
+
${supabaseTargetCases}
|
|
2784
2831
|
*)
|
|
2785
|
-
echo "Unknown forward '\${1}'. Use
|
|
2832
|
+
echo "Unknown forward '\${1}'. Use ${forwardNamesDescription}." >&2
|
|
2786
2833
|
return 1
|
|
2787
2834
|
;;
|
|
2788
2835
|
esac
|
|
@@ -2918,6 +2965,11 @@ start_forward() {
|
|
|
2918
2965
|
pid_file="$(pid_file_for "\${name}")"
|
|
2919
2966
|
read -r namespace resource local_port remote_port <<<"$(target_for "\${name}")"
|
|
2920
2967
|
|
|
2968
|
+
if [[ "\${name}" == "app" && "\${APP_RUNTIME_ENABLED}" != "true" ]]; then
|
|
2969
|
+
echo "\${name}: skipped (Web app runtime disabled)"
|
|
2970
|
+
return 0
|
|
2971
|
+
fi
|
|
2972
|
+
|
|
2921
2973
|
if [[ -f "\${pid_file}" ]]; then
|
|
2922
2974
|
local existing_pid
|
|
2923
2975
|
existing_pid="$(cat "\${pid_file}")"
|
|
@@ -2947,28 +2999,52 @@ start_forward() {
|
|
|
2947
2999
|
return 1
|
|
2948
3000
|
fi
|
|
2949
3001
|
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
3002
|
+
for start_attempt in {1..5}; do
|
|
3003
|
+
nohup kubectl --context "\${PROFILE}" -n "\${namespace}" port-forward "\${resource}" "\${local_port}:\${remote_port}" >"\${STATE_DIR}/\${PROFILE}-\${name}.log" 2>&1 &
|
|
3004
|
+
local pid="$!"
|
|
3005
|
+
echo "\${pid}" > "\${pid_file}"
|
|
2953
3006
|
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
3007
|
+
for readiness_attempt in {1..20}; do
|
|
3008
|
+
if ! is_pid_running "\${pid}"; then
|
|
3009
|
+
rm -f "\${pid_file}"
|
|
3010
|
+
if [[ "\${start_attempt}" -lt 5 ]]; then
|
|
3011
|
+
echo "\${name}: port-forward attempt \${start_attempt} exited before readiness; retrying"
|
|
3012
|
+
sleep 2
|
|
3013
|
+
break
|
|
3014
|
+
fi
|
|
3015
|
+
|
|
3016
|
+
echo "\${name}: failed to start local port \${local_port} for \${namespace}/\${resource}:\${remote_port} after \${start_attempt} attempts"
|
|
3017
|
+
print_forward_log_tail "\${name}"
|
|
3018
|
+
return 1
|
|
3019
|
+
fi
|
|
3020
|
+
if is_port_accepting "\${local_port}"; then
|
|
3021
|
+
sleep 1
|
|
3022
|
+
if is_pid_running "\${pid}" && is_port_accepting "\${local_port}"; then
|
|
3023
|
+
sleep 0.5
|
|
3024
|
+
if is_pid_running "\${pid}"; then
|
|
3025
|
+
echo "\${name}: started (pid \${pid}, local port \${local_port})"
|
|
3026
|
+
return 0
|
|
3027
|
+
fi
|
|
3028
|
+
fi
|
|
3029
|
+
fi
|
|
3030
|
+
sleep 0.5
|
|
3031
|
+
done
|
|
3032
|
+
|
|
3033
|
+
if [[ -f "\${pid_file}" ]]; then
|
|
3034
|
+
terminate_forward_process "\${name}" "\${pid}" "\${namespace}" "\${resource}" "\${local_port}" "\${remote_port}" || return 1
|
|
2958
3035
|
rm -f "\${pid_file}"
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
3036
|
+
|
|
3037
|
+
if [[ "\${start_attempt}" -lt 5 ]]; then
|
|
3038
|
+
echo "\${name}: port-forward attempt \${start_attempt} did not become ready; retrying"
|
|
3039
|
+
sleep 2
|
|
3040
|
+
else
|
|
3041
|
+
echo "\${name}: did not become ready on local port \${local_port} for \${namespace}/\${resource}:\${remote_port} after \${start_attempt} attempts"
|
|
3042
|
+
print_forward_log_tail "\${name}"
|
|
3043
|
+
return 1
|
|
3044
|
+
fi
|
|
2964
3045
|
fi
|
|
2965
|
-
sleep 0.5
|
|
2966
3046
|
done
|
|
2967
3047
|
|
|
2968
|
-
echo "\${name}: did not become ready on local port \${local_port} for \${namespace}/\${resource}:\${remote_port}"
|
|
2969
|
-
print_forward_log_tail "\${name}"
|
|
2970
|
-
terminate_forward_process "\${name}" "\${pid}" "\${namespace}" "\${resource}" "\${local_port}" "\${remote_port}" || return 1
|
|
2971
|
-
rm -f "\${pid_file}"
|
|
2972
3048
|
return 1
|
|
2973
3049
|
}
|
|
2974
3050
|
|
|
@@ -3029,7 +3105,9 @@ for_each_forward() {
|
|
|
3029
3105
|
local action="\${1}"
|
|
3030
3106
|
shift
|
|
3031
3107
|
local name
|
|
3032
|
-
|
|
3108
|
+
while [[ "\${#}" -gt 0 ]]; do
|
|
3109
|
+
name="\${1}"
|
|
3110
|
+
shift
|
|
3033
3111
|
"\${action}_forward" "\${name}"
|
|
3034
3112
|
done
|
|
3035
3113
|
}
|
|
@@ -3038,17 +3116,21 @@ ACTION="\${1:-start}"
|
|
|
3038
3116
|
NAME="\${2:-all}"
|
|
3039
3117
|
|
|
3040
3118
|
case "\${ACTION}:\${NAME}" in
|
|
3041
|
-
start:runtime) for_each_forward start
|
|
3042
|
-
stop:runtime)
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
status:
|
|
3119
|
+
start:runtime) for_each_forward start ${runtimeForwardNames.join(' ')} ;;
|
|
3120
|
+
stop:runtime)
|
|
3121
|
+
for_each_forward stop ${runtimeForwardNames.join(' ')}
|
|
3122
|
+
for_each_forward stop ${obsoleteForwardNames.join(' ')}
|
|
3123
|
+
;;
|
|
3124
|
+
status:runtime) for_each_forward status ${runtimeForwardNames.join(' ')} ;;
|
|
3125
|
+
start:all) for_each_forward start ${allForwardNames.join(' ')} ;;
|
|
3126
|
+
stop:all) for_each_forward stop ${managedForwardNames.join(' ')} ;;
|
|
3127
|
+
status:all) for_each_forward status ${allForwardNames.join(' ')} ;;
|
|
3128
|
+
stop:obsolete) for_each_forward stop ${obsoleteForwardNames.join(' ')} ;;
|
|
3047
3129
|
start:*) start_forward "\${NAME}" ;;
|
|
3048
3130
|
stop:*) stop_forward "\${NAME}" ;;
|
|
3049
3131
|
status:*) status_forward "\${NAME}" ;;
|
|
3050
3132
|
*)
|
|
3051
|
-
echo "Usage: ./scripts/port-forward.sh {start|stop|status} {
|
|
3133
|
+
echo "Usage: ./scripts/port-forward.sh {start|stop|status} {${forwardUsage}}"
|
|
3052
3134
|
exit 1
|
|
3053
3135
|
;;
|
|
3054
3136
|
esac
|
|
@@ -3166,7 +3248,7 @@ echo "Deleted Minikube profile '\${PROFILE}'."
|
|
|
3166
3248
|
`;
|
|
3167
3249
|
}
|
|
3168
3250
|
function getStatusScript(args) {
|
|
3169
|
-
const { appSlug, supabaseKubernetesEnabled, profileModel, supabaseHostPorts, providerNamespaces, providerLifecycle, } = args;
|
|
3251
|
+
const { appSlug, appRuntimeEnabled, supabaseKubernetesEnabled, profileModel, supabaseHostPorts, providerNamespaces, providerLifecycle, } = args;
|
|
3170
3252
|
const namespaces = [
|
|
3171
3253
|
APP_NAMESPACE,
|
|
3172
3254
|
...(supabaseKubernetesEnabled ? [SUPABASE_NAMESPACE] : []),
|
|
@@ -3244,7 +3326,7 @@ for namespace in ${namespaces}; do
|
|
|
3244
3326
|
fi
|
|
3245
3327
|
done
|
|
3246
3328
|
|
|
3247
|
-
if kubectl --context "\${PROFILE}" -n ${APP_NAMESPACE} get deployment app-runtime >/dev/null 2>&1; then
|
|
3329
|
+
if [[ "${appRuntimeEnabled ? 'true' : 'false'}" == "true" ]] && kubectl --context "\${PROFILE}" -n ${APP_NAMESPACE} get deployment app-runtime >/dev/null 2>&1; then
|
|
3248
3330
|
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"
|
|
3249
3331
|
fi
|
|
3250
3332
|
|