diff --git a/CLAUDE.md b/CLAUDE.md index f804b7e..7a82965 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -25,7 +25,7 @@ src/ │ │ ├── deployment.ts # Main class (configure, deploy, waitUntilReady, teardown) │ │ ├── types.ts # DeploymentOptions, DeploymentConfig │ │ ├── constants.ts # Config paths, auth providers, chart URLs -│ │ └── config/ # YAML templates (common/, auth/, helm/, operator/) +│ │ └── config/ # YAML templates (common/, auth/, new-frontend-system/, helm/, operator/) │ ├── keycloak/ # KeycloakHelper — Keycloak Helm deployment + OIDC setup │ └── orchestrator/ # Workflow orchestrator installer ├── playwright/ @@ -81,18 +81,22 @@ yarn check # typecheck + lint + prettier ## Key Architectural Concepts -### Configuration Merging (3-level cascade) +### Configuration Merging (layered cascade) ``` Package defaults (config/common/) ↓ deep merge Auth-specific (config/auth/{keycloak|guest|github}/) + ↓ deep merge (when useNewFrontendSystem) +New frontend system defaults (config/new-frontend-system/) ↓ deep merge User config (workspace's tests/config/*.yaml) ↓ = Final merged config ``` +`useNewFrontendSystem` is true when set explicitly, when the namespace ends with `-app-next`, or when `USE_NEW_FRONTEND_SYSTEM=true`. Secrets use the same layer order, then a single `envsubst` pass on the merged result. + Array merge uses "replace" strategy by default. Plugin arrays use `byKey: "package"` with normalized keys (strips trailing `-dynamic`). ### Plugin Metadata Resolution diff --git a/docs/CLAUDE.md b/docs/CLAUDE.md index 0882ece..d1401f7 100644 --- a/docs/CLAUDE.md +++ b/docs/CLAUDE.md @@ -200,7 +200,7 @@ When documenting, reference these source files: | YAML Merging | `src/utils/merge-yamls.ts` | | Bash ($) | `src/utils/bash.ts` | | envsubst | `src/utils/common.ts` | -| Config Templates | `src/deployment/rhdh/config/{common,auth,helm,operator}/` | +| Config Templates | `src/deployment/rhdh/config/{common,auth,new-frontend-system,helm,operator}/` | ## Common Tasks diff --git a/docs/api/deployment/deployment-types.md b/docs/api/deployment/deployment-types.md index 68fccb1..f7709d3 100644 --- a/docs/api/deployment/deployment-types.md +++ b/docs/api/deployment/deployment-types.md @@ -42,6 +42,8 @@ type DeploymentOptions = { method?: DeploymentMethod; valueFile?: string; subscription?: string; + disableWrappers?: string[]; + useNewFrontendSystem?: boolean; }; ``` @@ -56,6 +58,8 @@ type DeploymentOptions = { | `method` | `DeploymentMethod` | Installation method | | `valueFile` | `string` | Helm values file (Helm only) | | `subscription` | `string` | Backstage CR file (Operator only) | +| `disableWrappers` | `string[]` | Wrapper plugins to disable (PR builds) | +| `useNewFrontendSystem` | `boolean` | New frontend system (app-next / NFS). Omit to auto-detect from namespace suffix `-app-next` or `USE_NEW_FRONTEND_SYSTEM=true`; set `false` to disable. See [RHDH deployment](/guide/deployment/rhdh-deployment#new-frontend-system-usenewfrontendsystem) | ## DeploymentConfigBase @@ -67,6 +71,8 @@ type DeploymentConfigBase = { appConfig: string; secrets: string; dynamicPlugins: string; + disableWrappers: string[]; + useNewFrontendSystem: boolean; }; ``` diff --git a/docs/changelog.md b/docs/changelog.md index 8f60725..b194df9 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -2,6 +2,12 @@ All notable changes to this project will be documented in this file. +## [1.1.41] - Current + +### Added + +- **`useNewFrontendSystem`** — Backstage **app-next** / new frontend system: merges NFS layers from `config/new-frontend-system/` (secrets, default **app-auth** and **app-integrations** plugins, Helm `value_file.yaml`) into the same merge pipelines as common/auth/user. Secrets are merged with other layers **before** a single `envsubst` pass. NFS dynamic plugins act as **defaults** (workspace `tests/config/dynamic-plugins.yaml` overrides). **Auto-detection:** enabled when the namespace ends with `-app-next` or `USE_NEW_FRONTEND_SYSTEM=true`, unless `useNewFrontendSystem: false` is passed. Optional workspace `tests/config/value_file-app-next.yaml` is still merged last for Helm. + ## [1.1.40] - Current ### Changed diff --git a/docs/guide/configuration/config-files.md b/docs/guide/configuration/config-files.md index 4d65d99..d183527 100644 --- a/docs/guide/configuration/config-files.md +++ b/docs/guide/configuration/config-files.md @@ -46,6 +46,10 @@ catalog: Configure dynamic plugins: +::: tip `useNewFrontendSystem` +If you run against the **app-next** shell, enable the new frontend system (pass `useNewFrontendSystem: true`, use a project/namespace suffix **`-app-next`**, or set **`USE_NEW_FRONTEND_SYSTEM=true`** — see [RHDH deployment](/guide/deployment/rhdh-deployment#new-frontend-system-usenewfrontendsystem)). The package merges default **app-auth** and **app-integrations** OCI plugins as **defaults**; override versions in this file when they must differ. +::: + ```yaml includes: - dynamic-plugins.default.yaml diff --git a/docs/guide/configuration/environment-variables.md b/docs/guide/configuration/environment-variables.md index d49026c..f4d9d44 100644 --- a/docs/guide/configuration/environment-variables.md +++ b/docs/guide/configuration/environment-variables.md @@ -35,6 +35,7 @@ These are set automatically during deployment: | `CHART_URL` | Custom Helm chart URL | `oci://quay.io/rhdh/chart` | | `SKIP_KEYCLOAK_DEPLOYMENT` | Skip Keycloak auto-deploy | `false` | | `RHDH_SKIP_PLUGIN_METADATA_INJECTION` | Disable plugin metadata injection (local only, ignored in CI) | - | +| `USE_NEW_FRONTEND_SYSTEM` | When `"true"`, enables new-frontend-system (app-next) merges when `useNewFrontendSystem` is not set in `configure()` options | - | ## Plugin Metadata Variables @@ -53,6 +54,21 @@ These control automatic plugin configuration injection from metadata files. | `JOB_NAME` | CI job name (set by OpenShift CI/Prow) | If contains `periodic-`, nightly mode is activated | | `JOB_MODE` | CI-only: `nightly` or `pr-check` (set by step registry) | Informational | +## New frontend system (app-next) + +NFS merge layers ship under `config/new-frontend-system/` in the package (secrets, dynamic plugins, Helm values), same layering idea as `auth/`. + +**Enabling app-next behavior** + +| Mechanism | Effect | +|-----------|--------| +| `useNewFrontendSystem: true` in [`configure()`](/guide/deployment/rhdh-deployment#new-frontend-system-usenewfrontendsystem) | Explicit enable | +| `useNewFrontendSystem: false` | Explicit disable (overrides auto-detection) | +| Playwright project / namespace ends with `-app-next` | Auto-enabled when `useNewFrontendSystem` is omitted | +| `USE_NEW_FRONTEND_SYSTEM=true` | Auto-enabled for all namespaces when `useNewFrontendSystem` is omitted | + +**Overriding default OCI refs** for **app-auth** and **app-integrations** uses the same pattern as other plugins: add or adjust entries in your workspace `tests/config/dynamic-plugins.yaml` (merged after package NFS defaults, so your versions win). + ### OCI URL Generation When `GIT_PR_NUMBER` is set, the package replaces local plugin paths with OCI URLs: diff --git a/docs/guide/configuration/index.md b/docs/guide/configuration/index.md index a95c389..08311f1 100644 --- a/docs/guide/configuration/index.md +++ b/docs/guide/configuration/index.md @@ -9,7 +9,7 @@ The package provides configuration tools for ESLint, TypeScript, and RHDH deploy | [Configuration Files](/guide/configuration/config-files) | YAML configuration structure | | [ESLint Configuration](/guide/configuration/eslint-config) | Pre-configured ESLint rules | | [TypeScript Configuration](/guide/configuration/typescript-config) | Base TypeScript settings | -| [Environment Variables](/guide/configuration/environment-variables) | All environment variables | +| [Environment Variables](/guide/configuration/environment-variables) | All environment variables (including NFS / app-next, e.g. `USE_NEW_FRONTEND_SYSTEM`) | | [Disabling Conflicting Wrappers](/guide/configuration/disable-wrappers) | Disabling pre-enabled wrappers that may cause configuration conflicts | ## Project Configuration @@ -69,6 +69,8 @@ RHDH configurations are merged in layers: This allows you to override only what you need while using sensible defaults. +For tests targeting the **new frontend system** (app-next), see [RHDH deployment — New frontend system](/guide/deployment/rhdh-deployment#new-frontend-system-usenewfrontendsystem) and [NFS-related options](/guide/configuration/environment-variables#new-frontend-system-app-next). + ## Plugin Metadata Injection For PR builds, the package can automatically inject plugin configurations from metadata files. See [Plugin Metadata Injection](/guide/configuration/config-files#plugin-metadata-injection) for details. diff --git a/docs/guide/deployment/rhdh-deployment.md b/docs/guide/deployment/rhdh-deployment.md index 985152e..4afa2b8 100644 --- a/docs/guide/deployment/rhdh-deployment.md +++ b/docs/guide/deployment/rhdh-deployment.md @@ -57,6 +57,43 @@ test("example", async ({ rhdh }) => { | `dynamicPlugins` | `string` | Path to dynamic-plugins YAML | | `valueFile` | `string` | Helm values file (Helm only) | | `subscription` | `string` | Backstage CR file (Operator only) | +| `disableWrappers` | `string[]` | Wrapper plugin package names to disable (`GIT_PR_NUMBER` flows) | +| `useNewFrontendSystem` | `boolean` | Enables the Backstage **new frontend system** shell (app-next / NFS): merges app-next secrets, default OCI **app-auth** and **app-integrations** plugins (as defaults — override in `tests/config/dynamic-plugins.yaml`), and extra Helm values from `config/new-frontend-system/value_file.yaml` plus optional `tests/config/value_file-app-next.yaml`. Omit to **auto-detect**: on when the namespace ends with `-app-next` or `USE_NEW_FRONTEND_SYSTEM=true`. Pass `false` to force off. | + +### New frontend system (`useNewFrontendSystem`) + +Use the **app-next** frontend when any of these apply: + +- You pass `useNewFrontendSystem: true` in **`configure()`** (explicit), or +- The Playwright project name (which becomes the Kubernetes namespace) ends with **`-app-next`**, or +- You set environment variable **`USE_NEW_FRONTEND_SYSTEM=true`** + +Pass **`useNewFrontendSystem: false`** to run in a `-app-next` namespace without NFS layers. + +Typical explicit flow: + +```typescript +await rhdh.configure({ + auth: "keycloak", + useNewFrontendSystem: true, +}); +await rhdh.deploy(); +``` + +With a project named e.g. `my-plugin-app-next`, you can omit the flag and still get NFS merges: + +```typescript +await rhdh.configure({ auth: "keycloak" }); +await rhdh.deploy(); +``` + +What gets merged (same order as other config: package defaults → auth → NFS defaults → your workspace files; later wins; secrets are merged then **envsubst** runs once on the result): + +1. **Secrets** — `APP_CONFIG_app_packageName: app-next` and `ENABLE_STANDARD_MODULE_FEDERATION: "true"` (your `rhdh-secrets.yaml` still wins on conflicts and can use `$VAR` substitution). +2. **Dynamic plugins** — Default OCI refs for `red-hat-developer-hub-backstage-plugin-app-auth` and `...-app-integrations` from package YAML; override pins in **`tests/config/dynamic-plugins.yaml`** (same as other plugins). +3. **Helm** — Package `config/new-frontend-system/value_file.yaml`, then your `value_file.yaml`, then optional `tests/config/value_file-app-next.yaml` when that file exists. + +Workspace-specific **app-config** (titles, plugin routes, etc.) remains your responsibility. ### Example: Full Configuration @@ -113,13 +150,14 @@ await rhdh.deploy({ timeout: null }); `deploy()` automatically skips if the deployment already succeeded in the current test run (e.g., after a worker restart due to test failure). This prevents expensive re-deployments. This method: -1. Merges configuration files (common → auth → project) -2. [Injects plugin metadata](/guide/configuration/config-files#plugin-metadata-injection) into dynamic plugins config -3. Applies ConfigMaps (app-config, dynamic-plugins) -4. Applies Secrets (with environment variable substitution) -5. Installs RHDH via Helm or Operator -6. Waits for the deployment to be ready -7. Sets `RHDH_BASE_URL` environment variable +1. Merges configuration files (common → auth → optional NFS defaults → project overrides) for app-config, secrets, and dynamic plugins +2. Substitutes environment variables in the merged secrets (`envsubst`) +3. [Injects plugin metadata](/guide/configuration/config-files#plugin-metadata-injection) into dynamic plugins config +4. Applies ConfigMaps (app-config, dynamic-plugins) +5. Applies Secrets +6. Installs RHDH via Helm or Operator +7. Waits for the deployment to be ready +8. Sets `RHDH_BASE_URL` environment variable #### Base URL format diff --git a/docs/overlay/reference/environment-variables.md b/docs/overlay/reference/environment-variables.md index 9e8ba13..0a252c1 100644 --- a/docs/overlay/reference/environment-variables.md +++ b/docs/overlay/reference/environment-variables.md @@ -42,6 +42,14 @@ See [Running Locally - Secrets from Vault](/overlay/tutorials/running-locally#se | `INSTALLATION_METHOD` | Deployment method: `helm` or `operator` | `helm` | No | | `CHART_URL` | Custom Helm chart URL | `oci://quay.io/rhdh/chart` | No | +### New frontend system (app-next / NFS) + +When the new frontend system is active (see [`useNewFrontendSystem`](/guide/deployment/rhdh-deployment#new-frontend-system-usenewfrontendsystem) and [environment variables](/guide/configuration/environment-variables#new-frontend-system-app-next)), the package merges NFS defaults then your workspace files. Pin **app-auth** / **app-integrations** OCI refs in `tests/config/dynamic-plugins.yaml` like any other plugin (your file wins over package defaults). + +| Variable | Description | +|----------|-------------| +| `USE_NEW_FRONTEND_SYSTEM` | When `"true"`, enables NFS merges if `useNewFrontendSystem` is not set in `configure()` options | + ### Cluster Configuration | Variable | Description | Default | Required | diff --git a/docs/overlay/test-structure/configuration-files.md b/docs/overlay/test-structure/configuration-files.md index 0282212..fc33d1f 100644 --- a/docs/overlay/test-structure/configuration-files.md +++ b/docs/overlay/test-structure/configuration-files.md @@ -27,11 +27,23 @@ tests/config/ ├── rhdh-secrets.yaml # Kubernetes secrets (optional) ├── dynamic-plugins.yaml # Dynamic plugins (optional - usually not needed) ├── value_file.yaml # Helm values override (optional, Helm only) +├── value_file-app-next.yaml # Extra Helm values when new frontend system is active (optional) └── subscription.yaml # Operator subscription (optional, Operator only) ``` **All of these files are optional.** Only create them when you need to override or extend defaults. +## `useNewFrontendSystem` (app-next / NFS) + +When the new frontend system is enabled (see [`configure()`](/guide/deployment/rhdh-deployment#configureoptions) and [New frontend system](/guide/deployment/rhdh-deployment#new-frontend-system-usenewfrontendsystem)), `@red-hat-developer-hub/e2e-test-utils` merges: + +- **Secrets** — `APP_CONFIG_app_packageName=app-next` and `ENABLE_STANDARD_MODULE_FEDERATION=true` into the `rhdh-secrets` Secret (merged with common/auth/workspace layers before `envsubst`; you no longer need duplicate keys in a separate `rhdh-secrets-next.yaml` for that). +- **Dynamic plugins** — Default OCI entries for **app-auth** and **app-integrations** as package defaults; override versions in `tests/config/dynamic-plugins.yaml` ([guide](/guide/configuration/config-files#dynamic-pluginsyaml)). + +You can **remove** hand-maintained `app-auth` / `app-integrations` lines from `dynamic-plugins.yaml` when the framework defaults match your train. + +Optional **`value_file-app-next.yaml`** is merged last when the new frontend system is active and the file exists — use for chart tweaks specific to app-next runs. + ## app-config-rhdh.yaml (Optional) The main RHDH configuration file. This file is merged with default configurations from `@red-hat-developer-hub/e2e-test-utils`. diff --git a/package.json b/package.json index d692723..90ebb4e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@red-hat-developer-hub/e2e-test-utils", - "version": "1.1.40", + "version": "1.1.41", "description": "Test utilities for RHDH E2E tests", "license": "Apache-2.0", "repository": { diff --git a/src/deployment/rhdh/config/new-frontend-system/dynamic-plugins.yaml b/src/deployment/rhdh/config/new-frontend-system/dynamic-plugins.yaml new file mode 100644 index 0000000..8f8957b --- /dev/null +++ b/src/deployment/rhdh/config/new-frontend-system/dynamic-plugins.yaml @@ -0,0 +1,5 @@ +plugins: + - 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 + disabled: false + - 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 + disabled: false diff --git a/src/deployment/rhdh/config/new-frontend-system/secrets.yaml b/src/deployment/rhdh/config/new-frontend-system/secrets.yaml new file mode 100644 index 0000000..b8ba0f6 --- /dev/null +++ b/src/deployment/rhdh/config/new-frontend-system/secrets.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: Secret +metadata: + name: rhdh-secrets +type: Opaque +stringData: + APP_CONFIG_app_packageName: app-next + ENABLE_STANDARD_MODULE_FEDERATION: "true" diff --git a/src/deployment/rhdh/config/new-frontend-system/value_file.yaml b/src/deployment/rhdh/config/new-frontend-system/value_file.yaml new file mode 100644 index 0000000..20addaf --- /dev/null +++ b/src/deployment/rhdh/config/new-frontend-system/value_file.yaml @@ -0,0 +1,2 @@ +# Helm values merge layer for the new frontend system (app-next); merged when NFS layers are active (additive; extend as needed). +{} diff --git a/src/deployment/rhdh/constants.ts b/src/deployment/rhdh/constants.ts index 9d70ac4..8d1f316 100644 --- a/src/deployment/rhdh/constants.ts +++ b/src/deployment/rhdh/constants.ts @@ -18,6 +18,21 @@ export const DEFAULT_CONFIG_PATHS = { PACKAGE_ROOT, "dist/deployment/rhdh/config/common/dynamic-plugins.yaml", ), + /** New frontend system (app-next): paths merged when the deployment uses NFS layers (explicit flag, `-app-next` namespace, or `USE_NEW_FRONTEND_SYSTEM`). */ + newFrontendSystem: { + secrets: path.join( + PACKAGE_ROOT, + "dist/deployment/rhdh/config/new-frontend-system/secrets.yaml", + ), + dynamicPlugins: path.join( + PACKAGE_ROOT, + "dist/deployment/rhdh/config/new-frontend-system/dynamic-plugins.yaml", + ), + valueFile: path.join( + PACKAGE_ROOT, + "dist/deployment/rhdh/config/new-frontend-system/value_file.yaml", + ), + }, helm: { valueFile: path.join( PACKAGE_ROOT, diff --git a/src/deployment/rhdh/deployment.test.ts b/src/deployment/rhdh/deployment.test.ts index 19b1521..3bd83c8 100644 --- a/src/deployment/rhdh/deployment.test.ts +++ b/src/deployment/rhdh/deployment.test.ts @@ -49,4 +49,64 @@ describe("dynamic-plugins merge (no user config path)", () => { "metadata (OCI) must win over auth local path", ); }); + + it("keeps user app-auth OCI ref over NFS defaults for same logical plugin", () => { + const nfsDefaults: Record = { + plugins: [ + { + 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", + disabled: false, + }, + ], + }; + const userPlugins: Record = { + plugins: [ + { + package: + "oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/red-hat-developer-hub-backstage-plugin-app-auth:older__0.0.1", + disabled: false, + }, + ], + }; + const merged = deepMerge(nfsDefaults, userPlugins, { + arrayMergeStrategy: { + byKey: "package", + normalizeKey: (item) => + getNormalizedPluginMergeKey(item as Record), + }, + }); + const plugins = merged.plugins as Array<{ package?: string }>; + assert.strictEqual(plugins.length, 1); + assert.ok( + plugins[0].package?.includes("older__0.0.1"), + "user layer must win over NFS defaults for the same logical plugin", + ); + }); + + it("does not duplicate includes when NFS layer omits includes", () => { + const common: Record = { + includes: ["dynamic-plugins.default.yaml"], + plugins: [], + }; + const nfsLayer: Record = { + plugins: [ + { + 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", + disabled: false, + }, + ], + }; + const merged = deepMerge(common, nfsLayer, { + arrayMergeStrategy: { + byKey: "package", + normalizeKey: (item) => + getNormalizedPluginMergeKey(item as Record), + }, + }); + const includes = merged.includes as unknown[]; + assert.strictEqual(includes?.length, 1); + assert.strictEqual(includes[0], "dynamic-plugins.default.yaml"); + }); }); diff --git a/src/deployment/rhdh/deployment.ts b/src/deployment/rhdh/deployment.ts index 9f8093c..0d22c75 100644 --- a/src/deployment/rhdh/deployment.ts +++ b/src/deployment/rhdh/deployment.ts @@ -102,11 +102,15 @@ export class RHDHDeployment { private async _applySecrets(): Promise { const authConfig = AUTH_CONFIG_PATHS[this.deploymentConfig.auth]; - const secretsYaml = await mergeYamlFilesIfExists([ + const secretsPaths = [ DEFAULT_CONFIG_PATHS.secrets, authConfig.secrets, + ...(this.deploymentConfig.useNewFrontendSystem + ? [DEFAULT_CONFIG_PATHS.newFrontendSystem.secrets] + : []), this.deploymentConfig.secrets, - ]); + ]; + const secretsYaml = await mergeYamlFilesIfExists(secretsPaths); // Use cloneDeepWith to substitute env vars in-place, avoiding JSON.parse issues // with control characters in secrets (e.g., private keys with newlines) @@ -114,9 +118,11 @@ export class RHDHDeployment { if (typeof value === "string") return envsubst(value); }); + const secretPayload = substituted as Record; + await this.k8sClient.applySecretFromObject( "rhdh-secrets", - substituted as { stringData?: Record }, + secretPayload as { stringData?: Record }, this.deploymentConfig.namespace, ); } @@ -127,8 +133,8 @@ export class RHDHDeployment { } as const; /** - * Merges package defaults + auth config (+ optional user config) into a - * single dynamic plugins configuration. + * Merges package defaults + auth + optional new-frontend-system defaults + + * optional user config into a single dynamic plugins configuration. */ private async _mergeBaseConfigs( userConfigPath?: string, @@ -137,6 +143,9 @@ export class RHDHDeployment { const paths = [ DEFAULT_CONFIG_PATHS.dynamicPlugins, authConfig.dynamicPlugins, + ...(this.deploymentConfig.useNewFrontendSystem + ? [DEFAULT_CONFIG_PATHS.newFrontendSystem.dynamicPlugins] + : []), ...(userConfigPath ? [userConfigPath] : []), ]; return await mergeYamlFilesIfExists(paths, RHDHDeployment.pluginMergeOpts); @@ -224,10 +233,20 @@ export class RHDHDeployment { this.deploymentConfig.version, ); this._log(`Helm chart version resolved to: ${chartVersion}`); - const valueFileObject = (await mergeYamlFilesIfExists([ + const helmValuePaths = [ DEFAULT_CONFIG_PATHS.helm.valueFile, + ...(this.deploymentConfig.useNewFrontendSystem + ? [DEFAULT_CONFIG_PATHS.newFrontendSystem.valueFile] + : []), valueFile, - ])) as Record>; + ...(this.deploymentConfig.useNewFrontendSystem && + fs.existsSync(WorkspacePaths.valueFileAppNext) + ? [WorkspacePaths.valueFileAppNext] + : []), + ]; + const valueFileObject = (await mergeYamlFilesIfExists( + helmValuePaths, + )) as Record>; this._logBoxen("Value File", valueFileObject); @@ -505,14 +524,21 @@ export class RHDHDeployment { (process.env.INSTALLATION_METHOD as DeploymentMethod) ?? "helm"; + const namespace = input.namespace ?? this.deploymentConfig.namespace; + const useNewFrontendSystem = + input.useNewFrontendSystem ?? + (namespace.endsWith("-app-next") || + process.env.USE_NEW_FRONTEND_SYSTEM === "true"); + const base: DeploymentConfigBase = { version, - namespace: input.namespace ?? this.deploymentConfig.namespace, + namespace, auth: input.auth ?? "keycloak", appConfig: input.appConfig ?? WorkspacePaths.appConfig, secrets: input.secrets ?? WorkspacePaths.secrets, dynamicPlugins: input.dynamicPlugins ?? WorkspacePaths.dynamicPlugins, disableWrappers: input.disableWrappers ?? [], + useNewFrontendSystem, }; if (method === "helm") { diff --git a/src/deployment/rhdh/index.ts b/src/deployment/rhdh/index.ts index 8e83699..7996b0f 100644 --- a/src/deployment/rhdh/index.ts +++ b/src/deployment/rhdh/index.ts @@ -1 +1,2 @@ export { RHDHDeployment } from "./deployment.js"; +export * from "./types.js"; diff --git a/src/deployment/rhdh/types.ts b/src/deployment/rhdh/types.ts index 7e42b79..f2ec117 100644 --- a/src/deployment/rhdh/types.ts +++ b/src/deployment/rhdh/types.ts @@ -12,6 +12,8 @@ export type DeploymentOptions = { valueFile?: string; subscription?: string; disableWrappers?: string[]; + /** 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. */ + useNewFrontendSystem?: boolean; }; export type HelmDeploymentConfig = { @@ -32,6 +34,8 @@ export type DeploymentConfigBase = { secrets: string; dynamicPlugins: string; disableWrappers: string[]; + /** New frontend system (Backstage app-next / NFS shell). */ + useNewFrontendSystem: boolean; }; export type DeploymentConfig = DeploymentConfigBase & diff --git a/src/utils/workspace-paths.ts b/src/utils/workspace-paths.ts index 286ae67..522048e 100644 --- a/src/utils/workspace-paths.ts +++ b/src/utils/workspace-paths.ts @@ -70,6 +70,11 @@ export class WorkspacePaths { return path.resolve(this.e2eRoot, "tests/config/value_file.yaml"); } + /** 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. */ + static get valueFileAppNext(): string { + return path.resolve(this.e2eRoot, "tests/config/value_file-app-next.yaml"); + } + /** Default operator subscription path: `tests/config/subscription.yaml` */ static get subscription(): string { return path.resolve(this.e2eRoot, "tests/config/subscription.yaml");