@red-hat-developer-hub/e2e-test-utils 1.1.40 → 1.1.42
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/deployment/rhdh/config/new-frontend-system/dynamic-plugins.yaml +5 -0
- package/dist/deployment/rhdh/config/new-frontend-system/secrets.yaml +8 -0
- package/dist/deployment/rhdh/config/new-frontend-system/value_file.yaml +2 -0
- package/dist/deployment/rhdh/config/operator/subscription.yaml +1 -1
- package/dist/deployment/rhdh/constants.d.ts +6 -0
- package/dist/deployment/rhdh/constants.d.ts.map +1 -1
- package/dist/deployment/rhdh/constants.js +6 -0
- package/dist/deployment/rhdh/deployment.d.ts +3 -2
- package/dist/deployment/rhdh/deployment.d.ts.map +1 -1
- package/dist/deployment/rhdh/deployment.js +42 -45
- package/dist/deployment/rhdh/deployment.test.js +50 -0
- package/dist/deployment/rhdh/index.d.ts +1 -0
- package/dist/deployment/rhdh/index.d.ts.map +1 -1
- package/dist/deployment/rhdh/index.js +1 -0
- package/dist/deployment/rhdh/operator-setup.d.ts +2 -0
- package/dist/deployment/rhdh/operator-setup.d.ts.map +1 -0
- package/dist/deployment/rhdh/operator-setup.js +46 -0
- package/dist/deployment/rhdh/types.d.ts +4 -0
- package/dist/deployment/rhdh/types.d.ts.map +1 -1
- package/dist/playwright/global-setup.d.ts.map +1 -1
- package/dist/playwright/global-setup.js +2 -1
- package/dist/utils/workspace-paths.d.ts +2 -0
- package/dist/utils/workspace-paths.d.ts.map +1 -1
- package/dist/utils/workspace-paths.js +4 -0
- package/package.json +1 -1
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
plugins:
|
|
2
|
+
- package: oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/red-hat-developer-hub-backstage-plugin-app-auth:bs_1.49.4__0.0.1
|
|
3
|
+
disabled: false
|
|
4
|
+
- package: oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/red-hat-developer-hub-backstage-plugin-app-integrations:bs_1.49.4__0.0.1
|
|
5
|
+
disabled: false
|
|
@@ -4,6 +4,12 @@ export declare const DEFAULT_CONFIG_PATHS: {
|
|
|
4
4
|
appConfig: string;
|
|
5
5
|
secrets: string;
|
|
6
6
|
dynamicPlugins: string;
|
|
7
|
+
/** New frontend system (app-next): paths merged when the deployment uses NFS layers (explicit flag, `-app-next` namespace, or `USE_NEW_FRONTEND_SYSTEM`). */
|
|
8
|
+
newFrontendSystem: {
|
|
9
|
+
secrets: string;
|
|
10
|
+
dynamicPlugins: string;
|
|
11
|
+
valueFile: string;
|
|
12
|
+
};
|
|
7
13
|
helm: {
|
|
8
14
|
valueFile: string;
|
|
9
15
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/deployment/rhdh/constants.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAK1D,eAAO,MAAM,oBAAoB
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/deployment/rhdh/constants.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAK1D,eAAO,MAAM,oBAAoB;;;;IAa/B,6JAA6J;;;;;;;;;;;;CA2B9J,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,MAAM,CACpC,YAAY,EACZ;IACE,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,YAAY,CAAC;CAC9B,CAoCF,CAAC;AAEF,eAAO,MAAM,SAAS,6BAA6B,CAAC"}
|
|
@@ -5,6 +5,12 @@ export const DEFAULT_CONFIG_PATHS = {
|
|
|
5
5
|
appConfig: path.join(PACKAGE_ROOT, "dist/deployment/rhdh/config/common/app-config-rhdh.yaml"),
|
|
6
6
|
secrets: path.join(PACKAGE_ROOT, "dist/deployment/rhdh/config/common/rhdh-secrets.yaml"),
|
|
7
7
|
dynamicPlugins: path.join(PACKAGE_ROOT, "dist/deployment/rhdh/config/common/dynamic-plugins.yaml"),
|
|
8
|
+
/** New frontend system (app-next): paths merged when the deployment uses NFS layers (explicit flag, `-app-next` namespace, or `USE_NEW_FRONTEND_SYSTEM`). */
|
|
9
|
+
newFrontendSystem: {
|
|
10
|
+
secrets: path.join(PACKAGE_ROOT, "dist/deployment/rhdh/config/new-frontend-system/secrets.yaml"),
|
|
11
|
+
dynamicPlugins: path.join(PACKAGE_ROOT, "dist/deployment/rhdh/config/new-frontend-system/dynamic-plugins.yaml"),
|
|
12
|
+
valueFile: path.join(PACKAGE_ROOT, "dist/deployment/rhdh/config/new-frontend-system/value_file.yaml"),
|
|
13
|
+
},
|
|
8
14
|
helm: {
|
|
9
15
|
valueFile: path.join(PACKAGE_ROOT, "dist/deployment/rhdh/config/helm/value_file.yaml"),
|
|
10
16
|
},
|
|
@@ -13,8 +13,8 @@ export declare class RHDHDeployment {
|
|
|
13
13
|
/** Shared merge strategy for dynamic plugin arrays. */
|
|
14
14
|
private static readonly pluginMergeOpts;
|
|
15
15
|
/**
|
|
16
|
-
* Merges package defaults + auth
|
|
17
|
-
* single dynamic plugins configuration.
|
|
16
|
+
* Merges package defaults + auth + optional new-frontend-system defaults +
|
|
17
|
+
* optional user config into a single dynamic plugins configuration.
|
|
18
18
|
*/
|
|
19
19
|
private _mergeBaseConfigs;
|
|
20
20
|
/**
|
|
@@ -34,6 +34,7 @@ export declare class RHDHDeployment {
|
|
|
34
34
|
private _applyDynamicPlugins;
|
|
35
35
|
private _deployWithHelm;
|
|
36
36
|
private _deployWithOperator;
|
|
37
|
+
private get _labelSelector();
|
|
37
38
|
rolloutRestart(): Promise<void>;
|
|
38
39
|
/**
|
|
39
40
|
* Performs a clean restart by scaling down to 0 first, waiting for pods to terminate,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deployment.d.ts","sourceRoot":"","sources":["../../../src/deployment/rhdh/deployment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAwB1E,OAAO,KAAK,EACV,iBAAiB,EACjB,gBAAgB,EAGjB,MAAM,YAAY,CAAC;AAEpB,qBAAa,cAAc;IAClB,SAAS,yBAAgC;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,gBAAgB,CAAC;gBAE9B,SAAS,EAAE,MAAM;IAKvB,MAAM,CAAC,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;YA0CpD,eAAe;YAmBf,aAAa;
|
|
1
|
+
{"version":3,"file":"deployment.d.ts","sourceRoot":"","sources":["../../../src/deployment/rhdh/deployment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAwB1E,OAAO,KAAK,EACV,iBAAiB,EACjB,gBAAgB,EAGjB,MAAM,YAAY,CAAC;AAEpB,qBAAa,cAAc;IAClB,SAAS,yBAAgC;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,gBAAgB,EAAE,gBAAgB,CAAC;gBAE9B,SAAS,EAAE,MAAM;IAKvB,MAAM,CAAC,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;YA0CpD,eAAe;YAmBf,aAAa;IA2B3B,uDAAuD;IACvD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAE5B;IAEX;;;OAGG;YACW,iBAAiB;IAe/B;;OAEG;YACW,uBAAuB;IAgBrC;;;;;;;;OAQG;YACW,0BAA0B;YAsC1B,oBAAoB;YAWpB,eAAe;YAuEf,mBAAmB;IAmCjC,OAAO,KAAK,cAAc,GAIzB;IAEK,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAWrC;;;;OAIG;IACG,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;IAOpC,cAAc,CAAC,OAAO,GAAE,MAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IA6BpD,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;YAIjB,iBAAiB;YASjB,oBAAoB;IAsClC;;;OAGG;YACW,0BAA0B;IAwCxC,OAAO,CAAC,sBAAsB;IA2CxB,SAAS,CAAC,iBAAiB,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC;IAUrE,OAAO,CAAC,aAAa;IAUrB,OAAO,CAAC,IAAI;IAIZ,OAAO,CAAC,SAAS;CAMlB"}
|
|
@@ -62,32 +62,40 @@ export class RHDHDeployment {
|
|
|
62
62
|
}
|
|
63
63
|
async _applySecrets() {
|
|
64
64
|
const authConfig = AUTH_CONFIG_PATHS[this.deploymentConfig.auth];
|
|
65
|
-
const
|
|
65
|
+
const secretsPaths = [
|
|
66
66
|
DEFAULT_CONFIG_PATHS.secrets,
|
|
67
67
|
authConfig.secrets,
|
|
68
|
+
...(this.deploymentConfig.useNewFrontendSystem
|
|
69
|
+
? [DEFAULT_CONFIG_PATHS.newFrontendSystem.secrets]
|
|
70
|
+
: []),
|
|
68
71
|
this.deploymentConfig.secrets,
|
|
69
|
-
]
|
|
72
|
+
];
|
|
73
|
+
const secretsYaml = await mergeYamlFilesIfExists(secretsPaths);
|
|
70
74
|
// Use cloneDeepWith to substitute env vars in-place, avoiding JSON.parse issues
|
|
71
75
|
// with control characters in secrets (e.g., private keys with newlines)
|
|
72
76
|
const substituted = cloneDeepWith(secretsYaml, (value) => {
|
|
73
77
|
if (typeof value === "string")
|
|
74
78
|
return envsubst(value);
|
|
75
79
|
});
|
|
76
|
-
|
|
80
|
+
const secretPayload = substituted;
|
|
81
|
+
await this.k8sClient.applySecretFromObject("rhdh-secrets", secretPayload, this.deploymentConfig.namespace);
|
|
77
82
|
}
|
|
78
83
|
/** Shared merge strategy for dynamic plugin arrays. */
|
|
79
84
|
static pluginMergeOpts = {
|
|
80
85
|
arrayMergeStrategy: { byKey: "package" },
|
|
81
86
|
};
|
|
82
87
|
/**
|
|
83
|
-
* Merges package defaults + auth
|
|
84
|
-
* single dynamic plugins configuration.
|
|
88
|
+
* Merges package defaults + auth + optional new-frontend-system defaults +
|
|
89
|
+
* optional user config into a single dynamic plugins configuration.
|
|
85
90
|
*/
|
|
86
91
|
async _mergeBaseConfigs(userConfigPath) {
|
|
87
92
|
const authConfig = AUTH_CONFIG_PATHS[this.deploymentConfig.auth];
|
|
88
93
|
const paths = [
|
|
89
94
|
DEFAULT_CONFIG_PATHS.dynamicPlugins,
|
|
90
95
|
authConfig.dynamicPlugins,
|
|
96
|
+
...(this.deploymentConfig.useNewFrontendSystem
|
|
97
|
+
? [DEFAULT_CONFIG_PATHS.newFrontendSystem.dynamicPlugins]
|
|
98
|
+
: []),
|
|
91
99
|
...(userConfigPath ? [userConfigPath] : []),
|
|
92
100
|
];
|
|
93
101
|
return await mergeYamlFilesIfExists(paths, RHDHDeployment.pluginMergeOpts);
|
|
@@ -148,10 +156,18 @@ export class RHDHDeployment {
|
|
|
148
156
|
async _deployWithHelm(valueFile) {
|
|
149
157
|
const chartVersion = await this._resolveChartVersion(this.deploymentConfig.version);
|
|
150
158
|
this._log(`Helm chart version resolved to: ${chartVersion}`);
|
|
151
|
-
const
|
|
159
|
+
const helmValuePaths = [
|
|
152
160
|
DEFAULT_CONFIG_PATHS.helm.valueFile,
|
|
161
|
+
...(this.deploymentConfig.useNewFrontendSystem
|
|
162
|
+
? [DEFAULT_CONFIG_PATHS.newFrontendSystem.valueFile]
|
|
163
|
+
: []),
|
|
153
164
|
valueFile,
|
|
154
|
-
|
|
165
|
+
...(this.deploymentConfig.useNewFrontendSystem &&
|
|
166
|
+
fs.existsSync(WorkspacePaths.valueFileAppNext)
|
|
167
|
+
? [WorkspacePaths.valueFileAppNext]
|
|
168
|
+
: []),
|
|
169
|
+
];
|
|
170
|
+
const valueFileObject = (await mergeYamlFilesIfExists(helmValuePaths));
|
|
155
171
|
this._logBoxen("Value File", valueFileObject);
|
|
156
172
|
// Merge dynamic plugins into the values file (including auth-specific plugins)
|
|
157
173
|
if (!valueFileObject.global) {
|
|
@@ -213,44 +229,20 @@ export class RHDHDeployment {
|
|
|
213
229
|
});
|
|
214
230
|
this._log(`Catalog index image: ${catalogIndexImage}`);
|
|
215
231
|
}
|
|
216
|
-
this._logBoxen("
|
|
232
|
+
this._logBoxen("Backstage CR", subscriptionObject);
|
|
217
233
|
const subscriptionFilePath = path.join(os.tmpdir(), `${this.deploymentConfig.namespace}-subscription.yaml`);
|
|
218
234
|
fs.writeFileSync(subscriptionFilePath, yaml.dump(subscriptionObject));
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
versionArg = `-v ${version}`;
|
|
227
|
-
}
|
|
228
|
-
else if (version === "next") {
|
|
229
|
-
versionArg = "--next";
|
|
230
|
-
}
|
|
231
|
-
else {
|
|
232
|
-
throw new Error(`Invalid RHDH version "${version}". Use semantic version (e.g., "1.5") or "next".`);
|
|
233
|
-
}
|
|
234
|
-
this._log(`Using operator branch: ${branch}, version arg: ${versionArg}`);
|
|
235
|
-
await $ `
|
|
236
|
-
set -e;
|
|
237
|
-
curl -sf https://raw.githubusercontent.com/redhat-developer/rhdh-operator/refs/heads/${branch}/.rhdh/scripts/install-rhdh-catalog-source.sh | bash -s -- ${versionArg} --install-operator rhdh
|
|
238
|
-
|
|
239
|
-
timeout 300 bash -c '
|
|
240
|
-
while ! oc get crd/backstages.rhdh.redhat.com -n "${this.deploymentConfig.namespace}" >/dev/null 2>&1; do
|
|
241
|
-
echo "Waiting for Backstage CRD to be created..."
|
|
242
|
-
sleep 20
|
|
243
|
-
done
|
|
244
|
-
echo "Backstage CRD is created."
|
|
245
|
-
' || echo "Error: Timed out waiting for Backstage CRD creation."
|
|
246
|
-
|
|
247
|
-
oc apply -f "${subscriptionFilePath}" -n "${this.deploymentConfig.namespace}"
|
|
248
|
-
`;
|
|
249
|
-
this._log("Operator deployment executed successfully.");
|
|
235
|
+
await $ `oc apply -f "${subscriptionFilePath}" -n "${this.deploymentConfig.namespace}"`;
|
|
236
|
+
this._log("Backstage CR applied successfully.");
|
|
237
|
+
}
|
|
238
|
+
get _labelSelector() {
|
|
239
|
+
return this.deploymentConfig.method === "operator"
|
|
240
|
+
? "rhdh.redhat.com/app=backstage-developer-hub"
|
|
241
|
+
: "app.kubernetes.io/instance in (redhat-developer-hub,developer-hub)";
|
|
250
242
|
}
|
|
251
243
|
async rolloutRestart() {
|
|
252
244
|
this._log(`Restarting RHDH deployment in namespace ${this.deploymentConfig.namespace}...`);
|
|
253
|
-
await $ `oc rollout restart deployment -l '
|
|
245
|
+
await $ `oc rollout restart deployment -l '${this._labelSelector}' -n ${this.deploymentConfig.namespace}`;
|
|
254
246
|
this._log(`RHDH deployment restarted successfully in namespace ${this.deploymentConfig.namespace}`);
|
|
255
247
|
await this.waitUntilReady();
|
|
256
248
|
}
|
|
@@ -261,13 +253,13 @@ export class RHDHDeployment {
|
|
|
261
253
|
*/
|
|
262
254
|
async scaleDownAndRestart() {
|
|
263
255
|
const namespace = this.deploymentConfig.namespace;
|
|
264
|
-
await $ `oc scale deployment -l '
|
|
265
|
-
await $ `oc wait --for=delete pod -l '
|
|
266
|
-
await $ `oc scale deployment -l '
|
|
256
|
+
await $ `oc scale deployment -l '${this._labelSelector}' --replicas=0 -n ${namespace}`;
|
|
257
|
+
await $ `oc wait --for=delete pod -l '${this._labelSelector}' -n ${namespace} --timeout=120s || true`;
|
|
258
|
+
await $ `oc scale deployment -l '${this._labelSelector}' --replicas=1 -n ${namespace}`;
|
|
267
259
|
}
|
|
268
260
|
async waitUntilReady(timeout = 500) {
|
|
269
261
|
const namespace = this.deploymentConfig.namespace;
|
|
270
|
-
const labelSelector =
|
|
262
|
+
const labelSelector = this._labelSelector;
|
|
271
263
|
const startTime = Date.now();
|
|
272
264
|
try {
|
|
273
265
|
await this.k8sClient.waitForPodsWithFailureDetection(namespace, labelSelector, timeout);
|
|
@@ -358,14 +350,19 @@ export class RHDHDeployment {
|
|
|
358
350
|
const method = input.method ??
|
|
359
351
|
process.env.INSTALLATION_METHOD ??
|
|
360
352
|
"helm";
|
|
353
|
+
const namespace = input.namespace ?? this.deploymentConfig.namespace;
|
|
354
|
+
const useNewFrontendSystem = input.useNewFrontendSystem ??
|
|
355
|
+
(namespace.endsWith("-app-next") ||
|
|
356
|
+
process.env.USE_NEW_FRONTEND_SYSTEM === "true");
|
|
361
357
|
const base = {
|
|
362
358
|
version,
|
|
363
|
-
namespace
|
|
359
|
+
namespace,
|
|
364
360
|
auth: input.auth ?? "keycloak",
|
|
365
361
|
appConfig: input.appConfig ?? WorkspacePaths.appConfig,
|
|
366
362
|
secrets: input.secrets ?? WorkspacePaths.secrets,
|
|
367
363
|
dynamicPlugins: input.dynamicPlugins ?? WorkspacePaths.dynamicPlugins,
|
|
368
364
|
disableWrappers: input.disableWrappers ?? [],
|
|
365
|
+
useNewFrontendSystem,
|
|
369
366
|
};
|
|
370
367
|
if (method === "helm") {
|
|
371
368
|
return {
|
|
@@ -38,4 +38,54 @@ describe("dynamic-plugins merge (no user config path)", () => {
|
|
|
38
38
|
assert.strictEqual(plugins.length, 1, "merged config must have exactly one keycloak plugin");
|
|
39
39
|
assert.ok(plugins[0].package?.startsWith("oci://"), "metadata (OCI) must win over auth local path");
|
|
40
40
|
});
|
|
41
|
+
it("keeps user app-auth OCI ref over NFS defaults for same logical plugin", () => {
|
|
42
|
+
const nfsDefaults = {
|
|
43
|
+
plugins: [
|
|
44
|
+
{
|
|
45
|
+
package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/red-hat-developer-hub-backstage-plugin-app-auth:bs_1.49.4__0.0.1",
|
|
46
|
+
disabled: false,
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
};
|
|
50
|
+
const userPlugins = {
|
|
51
|
+
plugins: [
|
|
52
|
+
{
|
|
53
|
+
package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/red-hat-developer-hub-backstage-plugin-app-auth:older__0.0.1",
|
|
54
|
+
disabled: false,
|
|
55
|
+
},
|
|
56
|
+
],
|
|
57
|
+
};
|
|
58
|
+
const merged = deepMerge(nfsDefaults, userPlugins, {
|
|
59
|
+
arrayMergeStrategy: {
|
|
60
|
+
byKey: "package",
|
|
61
|
+
normalizeKey: (item) => getNormalizedPluginMergeKey(item),
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
const plugins = merged.plugins;
|
|
65
|
+
assert.strictEqual(plugins.length, 1);
|
|
66
|
+
assert.ok(plugins[0].package?.includes("older__0.0.1"), "user layer must win over NFS defaults for the same logical plugin");
|
|
67
|
+
});
|
|
68
|
+
it("does not duplicate includes when NFS layer omits includes", () => {
|
|
69
|
+
const common = {
|
|
70
|
+
includes: ["dynamic-plugins.default.yaml"],
|
|
71
|
+
plugins: [],
|
|
72
|
+
};
|
|
73
|
+
const nfsLayer = {
|
|
74
|
+
plugins: [
|
|
75
|
+
{
|
|
76
|
+
package: "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/red-hat-developer-hub-backstage-plugin-app-auth:bs_1.49.4__0.0.1",
|
|
77
|
+
disabled: false,
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
};
|
|
81
|
+
const merged = deepMerge(common, nfsLayer, {
|
|
82
|
+
arrayMergeStrategy: {
|
|
83
|
+
byKey: "package",
|
|
84
|
+
normalizeKey: (item) => getNormalizedPluginMergeKey(item),
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
const includes = merged.includes;
|
|
88
|
+
assert.strictEqual(includes?.length, 1);
|
|
89
|
+
assert.strictEqual(includes[0], "dynamic-plugins.default.yaml");
|
|
90
|
+
});
|
|
41
91
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/deployment/rhdh/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/deployment/rhdh/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,cAAc,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"operator-setup.d.ts","sourceRoot":"","sources":["../../../src/deployment/rhdh/operator-setup.ts"],"names":[],"mappings":"AAEA,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CA0DzD"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { $ } from "../../utils/bash.js";
|
|
2
|
+
export async function installRHDHOperator() {
|
|
3
|
+
if (process.env.INSTALLATION_METHOD !== "operator") {
|
|
4
|
+
return;
|
|
5
|
+
}
|
|
6
|
+
if (process.env.SKIP_OPERATOR_INSTALLATION === "true") {
|
|
7
|
+
console.log("Skipping RHDH operator installation");
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
const version = process.env.RHDH_VERSION ?? "next";
|
|
11
|
+
const isSemanticVersion = /^\d+(\.\d+)?$/.test(version);
|
|
12
|
+
const branch = isSemanticVersion ? `release-${version}` : "main";
|
|
13
|
+
let versionArgs;
|
|
14
|
+
if (isSemanticVersion) {
|
|
15
|
+
versionArgs = ["-v", version];
|
|
16
|
+
}
|
|
17
|
+
else if (version === "next") {
|
|
18
|
+
versionArgs = ["--next"];
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
throw new Error(`Invalid RHDH version "${version}". Use semantic version (e.g., "1.5") or "next".`);
|
|
22
|
+
}
|
|
23
|
+
console.log(`Installing RHDH operator (branch: ${branch}, version: ${versionArgs.join(" ")})...`);
|
|
24
|
+
const scriptUrl = `https://raw.githubusercontent.com/redhat-developer/rhdh-operator/refs/heads/${branch}/.rhdh/scripts/install-rhdh-catalog-source.sh`;
|
|
25
|
+
try {
|
|
26
|
+
await $ `curl -sf ${scriptUrl} | bash -s -- ${versionArgs} --install-operator rhdh`;
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
throw new Error(`install-rhdh-catalog-source.sh failed (branch: ${branch}, args: ${versionArgs.join(" ")} --install-operator rhdh).\nScript URL: ${scriptUrl}\n${error instanceof Error ? error.message : error}`, { cause: error });
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
await $ `
|
|
33
|
+
timeout 300 bash -c '
|
|
34
|
+
while ! oc get crd backstages.rhdh.redhat.com >/dev/null 2>&1; do
|
|
35
|
+
echo "Waiting for Backstage CRD to be created..."
|
|
36
|
+
sleep 10
|
|
37
|
+
done
|
|
38
|
+
echo "Backstage CRD is created."
|
|
39
|
+
'
|
|
40
|
+
`;
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
throw new Error("Timed out waiting for Backstage CRD (backstages.rhdh.redhat.com) after 300s. The operator may not have installed correctly.", { cause: error });
|
|
44
|
+
}
|
|
45
|
+
console.log("RHDH operator installation completed");
|
|
46
|
+
}
|
|
@@ -11,6 +11,8 @@ export type DeploymentOptions = {
|
|
|
11
11
|
valueFile?: string;
|
|
12
12
|
subscription?: string;
|
|
13
13
|
disableWrappers?: string[];
|
|
14
|
+
/** When true, merge new-frontend-system (app-next) layers. When omitted, auto-detect: namespace ends with `-app-next` or `USE_NEW_FRONTEND_SYSTEM=true`. Pass false to disable. */
|
|
15
|
+
useNewFrontendSystem?: boolean;
|
|
14
16
|
};
|
|
15
17
|
export type HelmDeploymentConfig = {
|
|
16
18
|
method: "helm";
|
|
@@ -28,6 +30,8 @@ export type DeploymentConfigBase = {
|
|
|
28
30
|
secrets: string;
|
|
29
31
|
dynamicPlugins: string;
|
|
30
32
|
disableWrappers: string[];
|
|
33
|
+
/** New frontend system (Backstage app-next / NFS shell). */
|
|
34
|
+
useNewFrontendSystem: boolean;
|
|
31
35
|
};
|
|
32
36
|
export type DeploymentConfig = DeploymentConfigBase & (HelmDeploymentConfig | OperatorDeploymentConfig);
|
|
33
37
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/deployment/rhdh/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,UAAU,CAAC;AACnD,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,CAAC;AAE3D,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/deployment/rhdh/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,UAAU,CAAC;AACnD,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,CAAC;AAE3D,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,mLAAmL;IACnL,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG;IACrC,MAAM,EAAE,UAAU,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,YAAY,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,4DAA4D;IAC5D,oBAAoB,EAAE,OAAO,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG,oBAAoB,GACjD,CAAC,oBAAoB,GAAG,wBAAwB,CAAC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"global-setup.d.ts","sourceRoot":"","sources":["../../src/playwright/global-setup.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"global-setup.d.ts","sourceRoot":"","sources":["../../src/playwright/global-setup.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AA8EnD,wBAA8B,WAAW,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAQ3E"}
|
|
@@ -7,6 +7,7 @@ import { resolve } from "path";
|
|
|
7
7
|
import { KubernetesClientHelper } from "../utils/kubernetes-client.js";
|
|
8
8
|
import { $ } from "../utils/bash.js";
|
|
9
9
|
import { KeycloakHelper } from "../deployment/keycloak/index.js";
|
|
10
|
+
import { installRHDHOperator } from "../deployment/rhdh/operator-setup.js";
|
|
10
11
|
import { DEFAULT_KEYCLOAK_CONFIG, DEFAULT_RHDH_CLIENT, DEFAULT_USERS, } from "../deployment/keycloak/constants.js";
|
|
11
12
|
import { loadLocalVaultSecrets } from "../utils/vault.js";
|
|
12
13
|
const REQUIRED_BINARIES = ["oc", "kubectl", "helm"];
|
|
@@ -67,7 +68,7 @@ export default async function globalSetup(config) {
|
|
|
67
68
|
await loadLocalVaultSecrets();
|
|
68
69
|
loadDotenvFromProjects(config);
|
|
69
70
|
await setClusterRouterBaseEnv();
|
|
70
|
-
await deployKeycloak();
|
|
71
|
+
await Promise.all([installRHDHOperator(), deployKeycloak()]);
|
|
71
72
|
console.log("Global setup completed successfully");
|
|
72
73
|
}
|
|
73
74
|
/**
|
|
@@ -37,6 +37,8 @@ export declare class WorkspacePaths {
|
|
|
37
37
|
static get dynamicPlugins(): string;
|
|
38
38
|
/** Default Helm value file path: `tests/config/value_file.yaml` */
|
|
39
39
|
static get valueFile(): string;
|
|
40
|
+
/** Optional Helm values merged after `value_file.yaml` when the new frontend system is active (explicit option, namespace suffix `-app-next`, or `USE_NEW_FRONTEND_SYSTEM=true`) and this file exists. */
|
|
41
|
+
static get valueFileAppNext(): string;
|
|
40
42
|
/** Default operator subscription path: `tests/config/subscription.yaml` */
|
|
41
43
|
static get subscription(): string;
|
|
42
44
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workspace-paths.d.ts","sourceRoot":"","sources":["../../src/utils/workspace-paths.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,cAAc;IACzB,OAAO;IAEP,4FAA4F;IAC5F,MAAM,KAAK,OAAO,IAAI,MAAM,CAE3B;IAED,4DAA4D;IAC5D,MAAM,CAAC,OAAO,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IAI5C,0DAA0D;IAC1D,MAAM,KAAK,aAAa,IAAI,MAAM,CAEjC;IAED,8DAA8D;IAC9D,MAAM,KAAK,WAAW,IAAI,MAAM,CAE/B;IAED,gFAAgF;IAChF,MAAM,KAAK,SAAS,IAAI,MAAM,CAE7B;IAID,mEAAmE;IACnE,MAAM,KAAK,SAAS,IAAI,MAAM,CAE7B;IAED,6DAA6D;IAC7D,MAAM,KAAK,OAAO,IAAI,MAAM,CAE3B;IAED,wEAAwE;IACxE,MAAM,KAAK,cAAc,IAAI,MAAM,CAElC;IAED,mEAAmE;IACnE,MAAM,KAAK,SAAS,IAAI,MAAM,CAE7B;IAED,2EAA2E;IAC3E,MAAM,KAAK,YAAY,IAAI,MAAM,CAEhC;CACF"}
|
|
1
|
+
{"version":3,"file":"workspace-paths.d.ts","sourceRoot":"","sources":["../../src/utils/workspace-paths.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,cAAc;IACzB,OAAO;IAEP,4FAA4F;IAC5F,MAAM,KAAK,OAAO,IAAI,MAAM,CAE3B;IAED,4DAA4D;IAC5D,MAAM,CAAC,OAAO,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM;IAI5C,0DAA0D;IAC1D,MAAM,KAAK,aAAa,IAAI,MAAM,CAEjC;IAED,8DAA8D;IAC9D,MAAM,KAAK,WAAW,IAAI,MAAM,CAE/B;IAED,gFAAgF;IAChF,MAAM,KAAK,SAAS,IAAI,MAAM,CAE7B;IAID,mEAAmE;IACnE,MAAM,KAAK,SAAS,IAAI,MAAM,CAE7B;IAED,6DAA6D;IAC7D,MAAM,KAAK,OAAO,IAAI,MAAM,CAE3B;IAED,wEAAwE;IACxE,MAAM,KAAK,cAAc,IAAI,MAAM,CAElC;IAED,mEAAmE;IACnE,MAAM,KAAK,SAAS,IAAI,MAAM,CAE7B;IAED,0MAA0M;IAC1M,MAAM,KAAK,gBAAgB,IAAI,MAAM,CAEpC;IAED,2EAA2E;IAC3E,MAAM,KAAK,YAAY,IAAI,MAAM,CAEhC;CACF"}
|
|
@@ -58,6 +58,10 @@ export class WorkspacePaths {
|
|
|
58
58
|
static get valueFile() {
|
|
59
59
|
return path.resolve(this.e2eRoot, "tests/config/value_file.yaml");
|
|
60
60
|
}
|
|
61
|
+
/** Optional Helm values merged after `value_file.yaml` when the new frontend system is active (explicit option, namespace suffix `-app-next`, or `USE_NEW_FRONTEND_SYSTEM=true`) and this file exists. */
|
|
62
|
+
static get valueFileAppNext() {
|
|
63
|
+
return path.resolve(this.e2eRoot, "tests/config/value_file-app-next.yaml");
|
|
64
|
+
}
|
|
61
65
|
/** Default operator subscription path: `tests/config/subscription.yaml` */
|
|
62
66
|
static get subscription() {
|
|
63
67
|
return path.resolve(this.e2eRoot, "tests/config/subscription.yaml");
|