@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
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
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
|
+
|
|
9
|
+
## 4.1.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- 66ef9aa: Add a provider-aware runtime port-forward lifecycle and export `ensureProjectInfrastructureRuntime` from `@ankhorage/infra/project`.
|
|
14
|
+
|
|
3
15
|
## 4.0.0
|
|
4
16
|
|
|
5
17
|
### Major Changes
|
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
# INFRA
|
|
5
5
|
|
|
6
|
-
         
|
|
7
7
|
|
|
8
8
|
Executable infra provider and standalone CLI for Ankhorage project workflows.
|
|
9
9
|
|
|
@@ -37,6 +37,11 @@ omit it when cwd is already inside `apps/<project>`. Programmatic project
|
|
|
37
37
|
operations accept an explicit project path and do not require Studio or a
|
|
38
38
|
particular workspace layout.
|
|
39
39
|
|
|
40
|
+
Running applications can repair their provider-aware host endpoints through
|
|
41
|
+
`ensureProjectInfrastructureRuntime()` from `@ankhorage/infra/project`. This
|
|
42
|
+
operation only ensures the generated runtime port-forward group; it does not
|
|
43
|
+
deploy, bootstrap, or reconcile infrastructure.
|
|
44
|
+
|
|
40
45
|
Source: `src/readme-usage.ts`
|
|
41
46
|
|
|
42
47
|
```ts
|
|
@@ -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,11 +299,18 @@ 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
|
|
|
307
|
+
### Port-forward groups
|
|
308
|
+
|
|
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\`.
|
|
310
|
+
- \`runtime\` excludes \`studio\` and \`db-migration\`, which are operational/bootstrap endpoints.
|
|
311
|
+
- \`all\` retains every generated forward, including operational/bootstrap endpoints.
|
|
312
|
+
- Concrete targets remain available for individual lifecycle control.
|
|
313
|
+
|
|
293
314
|
## Generated Resources
|
|
294
315
|
|
|
295
316
|
${resourceLines}
|
|
@@ -324,8 +345,7 @@ Pinned images:
|
|
|
324
345
|
|
|
325
346
|
## Host URLs
|
|
326
347
|
|
|
327
|
-
|
|
328
|
-
- 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}\`
|
|
329
349
|
- Studio: \`http://127.0.0.1:${supabaseHostPorts.studio}\`
|
|
330
350
|
- DB migration endpoint: \`127.0.0.1:${supabaseHostPorts.db}\`
|
|
331
351
|
|
|
@@ -741,9 +761,9 @@ function getKustomizationManifest(args) {
|
|
|
741
761
|
: [];
|
|
742
762
|
const resources = [
|
|
743
763
|
...args.namespaceResources,
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
764
|
+
...(args.appRuntimeEnabled
|
|
765
|
+
? ['app.configmap.yaml', 'app/deployment.yaml', 'app/service.yaml']
|
|
766
|
+
: []),
|
|
747
767
|
...supabaseResources,
|
|
748
768
|
...args.extraResources,
|
|
749
769
|
];
|
|
@@ -1997,7 +2017,7 @@ spec:
|
|
|
1997
2017
|
`;
|
|
1998
2018
|
}
|
|
1999
2019
|
function getUpScript(args) {
|
|
2000
|
-
const { appSlug, defaultAppImage, supabaseKubernetesEnabled, profileModel, secretStoreProvider, supabaseHostPorts, oauthProviders, providerLifecycle, } = args;
|
|
2020
|
+
const { appSlug, appRuntimeEnabled, defaultAppImage, supabaseKubernetesEnabled, profileModel, secretStoreProvider, supabaseHostPorts, oauthProviders, providerLifecycle, } = args;
|
|
2001
2021
|
const oauthEnvDefaults = getOAuthScriptEnvDefaults(oauthProviders);
|
|
2002
2022
|
const oauthRuntimeSecretLines = getOAuthRuntimeSecretLines(oauthProviders);
|
|
2003
2023
|
const oauthValidation = getOAuthRuntimeValidationScript(oauthProviders);
|
|
@@ -2009,6 +2029,14 @@ function getUpScript(args) {
|
|
|
2009
2029
|
secretStoreProvider,
|
|
2010
2030
|
});
|
|
2011
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';
|
|
2012
2040
|
return `#!/usr/bin/env bash
|
|
2013
2041
|
set -Eeuo pipefail
|
|
2014
2042
|
|
|
@@ -2023,6 +2051,7 @@ DRIVER="\${MINIKUBE_DRIVER:-}"
|
|
|
2023
2051
|
APP_NAMESPACE="${APP_NAMESPACE}"
|
|
2024
2052
|
SUPABASE_NAMESPACE="${SUPABASE_NAMESPACE}"
|
|
2025
2053
|
SUPABASE_RUNTIME_ENABLED="${supabaseKubernetesEnabled ? 'true' : 'false'}"
|
|
2054
|
+
APP_RUNTIME_ENABLED="${appRuntimeEnabled ? 'true' : 'false'}"
|
|
2026
2055
|
APP_BUILD_ENABLED="\${APP_BUILD_ENABLED:-}"
|
|
2027
2056
|
APP_SOURCE_DIR="\${APP_SOURCE_DIR:-}"
|
|
2028
2057
|
APP_WEB_EXPORT_DIR="\${APP_WEB_EXPORT_DIR:-}"
|
|
@@ -2453,6 +2482,7 @@ apply_namespace_manifests() {
|
|
|
2453
2482
|
done
|
|
2454
2483
|
}
|
|
2455
2484
|
|
|
2485
|
+
${disabledAppRuntimeReconciliation}
|
|
2456
2486
|
${providerLifecycleStageScripts}
|
|
2457
2487
|
|
|
2458
2488
|
load_env_file_preserving_process_env
|
|
@@ -2526,7 +2556,7 @@ else
|
|
|
2526
2556
|
kubectl --context "\${PROFILE}" apply -k "\${K8S_DIR}"
|
|
2527
2557
|
fi
|
|
2528
2558
|
|
|
2529
|
-
if [[ "\${APP_BUILD_ENABLED}" == "true" ]]; then
|
|
2559
|
+
if [[ "\${APP_RUNTIME_ENABLED}" == "true" && "\${APP_BUILD_ENABLED}" == "true" ]]; then
|
|
2530
2560
|
if [[ ! -x "\${BUILD_SCRIPT}" ]]; then
|
|
2531
2561
|
echo "Missing build helper script: \${BUILD_SCRIPT}"
|
|
2532
2562
|
exit 1
|
|
@@ -2541,6 +2571,7 @@ else
|
|
|
2541
2571
|
EXPORT_DIR="\${APP_SOURCE_DIR}/\${APP_WEB_EXPORT_DIR}"
|
|
2542
2572
|
fi
|
|
2543
2573
|
|
|
2574
|
+
if [[ "\${APP_RUNTIME_ENABLED}" == "true" ]]; then
|
|
2544
2575
|
case "\${APP_IMAGE_SYNC_STRATEGY}" in
|
|
2545
2576
|
minikube-build)
|
|
2546
2577
|
if [[ ! -f "\${EXPORT_DIR}/index.html" ]]; then
|
|
@@ -2562,15 +2593,18 @@ case "\${APP_IMAGE_SYNC_STRATEGY}" in
|
|
|
2562
2593
|
exit 1
|
|
2563
2594
|
;;
|
|
2564
2595
|
esac
|
|
2596
|
+
fi
|
|
2565
2597
|
|
|
2566
2598
|
if [[ "\${SUPABASE_RUNTIME_ENABLED}" == "true" ]]; then
|
|
2567
2599
|
kubectl --context "\${PROFILE}" apply -k "\${K8S_DIR}"
|
|
2568
2600
|
fi
|
|
2569
2601
|
|
|
2602
|
+
${reconcileDisabledAppRuntime}
|
|
2570
2603
|
wait_for_provider_readiness
|
|
2571
2604
|
run_provider_migrations
|
|
2572
2605
|
run_provider_reconciliation
|
|
2573
2606
|
|
|
2607
|
+
if [[ "\${APP_RUNTIME_ENABLED}" == "true" ]]; then
|
|
2574
2608
|
if [[ -n "\${APP_IMAGE_PULL_SECRET_NAME}" ]]; then
|
|
2575
2609
|
if [[ -z "\${APP_IMAGE_PULL_SECRET_USERNAME}" || -z "\${APP_IMAGE_PULL_SECRET_PASSWORD}" ]]; then
|
|
2576
2610
|
echo "APP_IMAGE_PULL_SECRET_NAME is set, but username/password are missing."
|
|
@@ -2602,6 +2636,7 @@ fi
|
|
|
2602
2636
|
|
|
2603
2637
|
kubectl --context "\${PROFILE}" -n "\${APP_NAMESPACE}" rollout status deployment/app-runtime --timeout=180s >/dev/null
|
|
2604
2638
|
"\${PORT_FORWARD_SCRIPT}" start app >/dev/null
|
|
2639
|
+
fi
|
|
2605
2640
|
|
|
2606
2641
|
trap - ERR
|
|
2607
2642
|
echo "Minikube infrastructure for '\${PROFILE}' is running."
|
|
@@ -2710,7 +2745,37 @@ CMD ["nginx", "-g", "daemon off;"]
|
|
|
2710
2745
|
`;
|
|
2711
2746
|
}
|
|
2712
2747
|
function getPortForwardScript(args) {
|
|
2713
|
-
const { appSlug, supabaseKubernetesEnabled, supabaseHostPorts } = args;
|
|
2748
|
+
const { appSlug, appRuntimeEnabled, supabaseKubernetesEnabled, supabaseHostPorts } = args;
|
|
2749
|
+
const runtimeForwardNames = [
|
|
2750
|
+
...(appRuntimeEnabled ? ['app'] : []),
|
|
2751
|
+
...(supabaseKubernetesEnabled ? ['supabase-gateway'] : []),
|
|
2752
|
+
];
|
|
2753
|
+
const allForwardNames = [
|
|
2754
|
+
...runtimeForwardNames,
|
|
2755
|
+
...(supabaseKubernetesEnabled ? ['studio', 'db-migration'] : []),
|
|
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';
|
|
2714
2779
|
return `#!/usr/bin/env bash
|
|
2715
2780
|
set -euo pipefail
|
|
2716
2781
|
|
|
@@ -2720,6 +2785,7 @@ STATE_DIR="\${ROOT_DIR}/.state/forwards"
|
|
|
2720
2785
|
APP_SLUG="${appSlug}"
|
|
2721
2786
|
PROFILE="\${ANKH_APP_SLUG:-${appSlug}}"
|
|
2722
2787
|
SUPABASE_RUNTIME_ENABLED="${supabaseKubernetesEnabled ? 'true' : 'false'}"
|
|
2788
|
+
APP_RUNTIME_ENABLED="${appRuntimeEnabled ? 'true' : 'false'}"
|
|
2723
2789
|
APP_PORT_FORWARD_LOCAL_PORT="\${APP_PORT_FORWARD_LOCAL_PORT:-${supabaseHostPorts.app}}"
|
|
2724
2790
|
APP_PORT_FORWARD_REMOTE_PORT="\${APP_PORT_FORWARD_REMOTE_PORT:-80}"
|
|
2725
2791
|
SUPABASE_GATEWAY_FORWARD_LOCAL_PORT="\${SUPABASE_GATEWAY_FORWARD_LOCAL_PORT:-${supabaseHostPorts.gateway}}"
|
|
@@ -2728,6 +2794,10 @@ SUPABASE_STUDIO_FORWARD_LOCAL_PORT="\${SUPABASE_STUDIO_FORWARD_LOCAL_PORT:-${sup
|
|
|
2728
2794
|
SUPABASE_STUDIO_FORWARD_REMOTE_PORT="\${SUPABASE_STUDIO_FORWARD_REMOTE_PORT:-3000}"
|
|
2729
2795
|
SUPABASE_DB_FORWARD_LOCAL_PORT="\${SUPABASE_DB_FORWARD_LOCAL_PORT:-${supabaseHostPorts.db}}"
|
|
2730
2796
|
SUPABASE_DB_FORWARD_REMOTE_PORT="\${SUPABASE_DB_FORWARD_REMOTE_PORT:-5432}"
|
|
2797
|
+
RUNTIME_FORWARD_NAMES=(${runtimeForwardNames.join(' ')})
|
|
2798
|
+
ALL_FORWARD_NAMES=(${allForwardNames.join(' ')})
|
|
2799
|
+
MANAGED_FORWARD_NAMES=(${managedForwardNames.join(' ')})
|
|
2800
|
+
OBSOLETE_FORWARD_NAMES=(${obsoleteForwardNames.join(' ')})
|
|
2731
2801
|
|
|
2732
2802
|
if [[ -f "\${ROOT_DIR}/.env" ]]; then
|
|
2733
2803
|
set -a
|
|
@@ -2736,6 +2806,7 @@ if [[ -f "\${ROOT_DIR}/.env" ]]; then
|
|
|
2736
2806
|
set +a
|
|
2737
2807
|
fi
|
|
2738
2808
|
SUPABASE_RUNTIME_ENABLED="${supabaseKubernetesEnabled ? 'true' : 'false'}"
|
|
2809
|
+
APP_RUNTIME_ENABLED="${appRuntimeEnabled ? 'true' : 'false'}"
|
|
2739
2810
|
|
|
2740
2811
|
if [[ "\${PROFILE}" != "\${APP_SLUG}" ]]; then
|
|
2741
2812
|
echo "ANKH_APP_SLUG must remain the generated canonical slug '\${APP_SLUG}' for this infra directory."
|
|
@@ -2755,20 +2826,10 @@ pid_file_for() {
|
|
|
2755
2826
|
|
|
2756
2827
|
target_for() {
|
|
2757
2828
|
case "\${1}" in
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
;;
|
|
2761
|
-
supabase-gateway)
|
|
2762
|
-
echo "${SUPABASE_NAMESPACE} service/gateway \${SUPABASE_GATEWAY_FORWARD_LOCAL_PORT} \${SUPABASE_GATEWAY_FORWARD_REMOTE_PORT}"
|
|
2763
|
-
;;
|
|
2764
|
-
studio)
|
|
2765
|
-
echo "${SUPABASE_NAMESPACE} service/studio \${SUPABASE_STUDIO_FORWARD_LOCAL_PORT} \${SUPABASE_STUDIO_FORWARD_REMOTE_PORT}"
|
|
2766
|
-
;;
|
|
2767
|
-
db-migration)
|
|
2768
|
-
echo "${SUPABASE_NAMESPACE} service/postgres \${SUPABASE_DB_FORWARD_LOCAL_PORT} \${SUPABASE_DB_FORWARD_REMOTE_PORT}"
|
|
2769
|
-
;;
|
|
2829
|
+
${appTargetCase}
|
|
2830
|
+
${supabaseTargetCases}
|
|
2770
2831
|
*)
|
|
2771
|
-
echo "Unknown forward '\${1}'. Use
|
|
2832
|
+
echo "Unknown forward '\${1}'. Use ${forwardNamesDescription}." >&2
|
|
2772
2833
|
return 1
|
|
2773
2834
|
;;
|
|
2774
2835
|
esac
|
|
@@ -2904,6 +2965,11 @@ start_forward() {
|
|
|
2904
2965
|
pid_file="$(pid_file_for "\${name}")"
|
|
2905
2966
|
read -r namespace resource local_port remote_port <<<"$(target_for "\${name}")"
|
|
2906
2967
|
|
|
2968
|
+
if [[ "\${name}" == "app" && "\${APP_RUNTIME_ENABLED}" != "true" ]]; then
|
|
2969
|
+
echo "\${name}: skipped (Web app runtime disabled)"
|
|
2970
|
+
return 0
|
|
2971
|
+
fi
|
|
2972
|
+
|
|
2907
2973
|
if [[ -f "\${pid_file}" ]]; then
|
|
2908
2974
|
local existing_pid
|
|
2909
2975
|
existing_pid="$(cat "\${pid_file}")"
|
|
@@ -2933,28 +2999,52 @@ start_forward() {
|
|
|
2933
2999
|
return 1
|
|
2934
3000
|
fi
|
|
2935
3001
|
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
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}"
|
|
2939
3006
|
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
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
|
|
2944
3035
|
rm -f "\${pid_file}"
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
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
|
|
2950
3045
|
fi
|
|
2951
|
-
sleep 0.5
|
|
2952
3046
|
done
|
|
2953
3047
|
|
|
2954
|
-
echo "\${name}: did not become ready on local port \${local_port} for \${namespace}/\${resource}:\${remote_port}"
|
|
2955
|
-
print_forward_log_tail "\${name}"
|
|
2956
|
-
terminate_forward_process "\${name}" "\${pid}" "\${namespace}" "\${resource}" "\${local_port}" "\${remote_port}" || return 1
|
|
2957
|
-
rm -f "\${pid_file}"
|
|
2958
3048
|
return 1
|
|
2959
3049
|
}
|
|
2960
3050
|
|
|
@@ -3013,26 +3103,34 @@ status_forward() {
|
|
|
3013
3103
|
|
|
3014
3104
|
for_each_forward() {
|
|
3015
3105
|
local action="\${1}"
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
"\${
|
|
3020
|
-
|
|
3021
|
-
|
|
3106
|
+
shift
|
|
3107
|
+
local name
|
|
3108
|
+
while [[ "\${#}" -gt 0 ]]; do
|
|
3109
|
+
name="\${1}"
|
|
3110
|
+
shift
|
|
3111
|
+
"\${action}_forward" "\${name}"
|
|
3112
|
+
done
|
|
3022
3113
|
}
|
|
3023
3114
|
|
|
3024
3115
|
ACTION="\${1:-start}"
|
|
3025
3116
|
NAME="\${2:-all}"
|
|
3026
3117
|
|
|
3027
3118
|
case "\${ACTION}:\${NAME}" in
|
|
3028
|
-
start:
|
|
3029
|
-
stop:
|
|
3030
|
-
|
|
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(' ')} ;;
|
|
3031
3129
|
start:*) start_forward "\${NAME}" ;;
|
|
3032
3130
|
stop:*) stop_forward "\${NAME}" ;;
|
|
3033
3131
|
status:*) status_forward "\${NAME}" ;;
|
|
3034
3132
|
*)
|
|
3035
|
-
echo "Usage: ./scripts/port-forward.sh {start|stop|status} {
|
|
3133
|
+
echo "Usage: ./scripts/port-forward.sh {start|stop|status} {${forwardUsage}}"
|
|
3036
3134
|
exit 1
|
|
3037
3135
|
;;
|
|
3038
3136
|
esac
|
|
@@ -3150,7 +3248,7 @@ echo "Deleted Minikube profile '\${PROFILE}'."
|
|
|
3150
3248
|
`;
|
|
3151
3249
|
}
|
|
3152
3250
|
function getStatusScript(args) {
|
|
3153
|
-
const { appSlug, supabaseKubernetesEnabled, profileModel, supabaseHostPorts, providerNamespaces, providerLifecycle, } = args;
|
|
3251
|
+
const { appSlug, appRuntimeEnabled, supabaseKubernetesEnabled, profileModel, supabaseHostPorts, providerNamespaces, providerLifecycle, } = args;
|
|
3154
3252
|
const namespaces = [
|
|
3155
3253
|
APP_NAMESPACE,
|
|
3156
3254
|
...(supabaseKubernetesEnabled ? [SUPABASE_NAMESPACE] : []),
|
|
@@ -3228,7 +3326,7 @@ for namespace in ${namespaces}; do
|
|
|
3228
3326
|
fi
|
|
3229
3327
|
done
|
|
3230
3328
|
|
|
3231
|
-
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
|
|
3232
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"
|
|
3233
3331
|
fi
|
|
3234
3332
|
|