Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/api/deployment/deployment-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ type DeploymentOptions = {
method?: DeploymentMethod;
valueFile?: string;
subscription?: string;
disableWrappers?: string[];
useNewFrontendSystem?: boolean;
};
```

Expand All @@ -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 shell); see [RHDH deployment](/guide/deployment/rhdh-deployment#new-frontend-system-usenewfrontendsystem) |

## DeploymentConfigBase

Expand All @@ -67,6 +71,8 @@ type DeploymentConfigBase = {
appConfig: string;
secrets: string;
dynamicPlugins: string;
disableWrappers: string[];
useNewFrontendSystem: boolean;
};
```

Expand Down
8 changes: 7 additions & 1 deletion docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@

All notable changes to this project will be documented in this file.

## [1.1.37] - Current
## [1.1.38] - Current

### Added

- **`useNewFrontendSystem`** — Optional flag on `rhdh.configure()` for Backstage **app-next** / new frontend system tests: merges `APP_CONFIG_app_packageName` and `ENABLE_STANDARD_MODULE_FEDERATION` into `rhdh-secrets`, adds default OCI dynamic plugins for **app-auth** and **app-integrations**, optional Helm merge layers (`value_file.new-frontend.yaml`, workspace `tests/config/value_file-app-next.yaml`). Env overrides: `RHDH_E2E_NFS_APP_AUTH_PACKAGE`, `RHDH_E2E_NFS_APP_INTEGRATIONS_PACKAGE` (full `oci://` refs). Exported constants `RHDH_E2E_NFS_APP_AUTH_PACKAGE_ENV` and `RHDH_E2E_NFS_APP_INTEGRATIONS_PACKAGE_ENV`. Types re-exported from `@red-hat-developer-hub/e2e-test-utils/rhdh`.

## [1.1.37]

### Added

Expand Down
4 changes: 4 additions & 0 deletions docs/guide/configuration/config-files.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ catalog:

Configure dynamic plugins:

::: tip `useNewFrontendSystem`
If you run against the **app-next** shell, set `useNewFrontendSystem: true` on [`configure()`](/guide/deployment/rhdh-deployment#new-frontend-system-usenewfrontendsystem) so the package merges default **app-auth** and **app-integrations** OCI plugins (and optional [env overrides](/guide/configuration/environment-variables#new-frontend-system-app-next-shell-plugins)). You can then omit those entries from this file when the defaults match your train.
:::

```yaml
includes:
- dynamic-plugins.default.yaml
Expand Down
13 changes: 13 additions & 0 deletions docs/guide/configuration/environment-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,19 @@ These control automatic plugin configuration injection from metadata files:
| `JOB_NAME` | CI job name (set by OpenShift CI/Prow) | If contains `periodic-`, injection is disabled |
| `JOB_MODE` | CI-only: `nightly` or `pr-check` (set by step registry) | Informational |

## New frontend system (app-next shell plugins)

When [`useNewFrontendSystem`](/guide/deployment/rhdh-deployment#new-frontend-system-usenewfrontendsystem) is `true`, the package adds default OCI packages for **app-auth** and **app-integrations**. You can override each with a **full** `oci://` reference (optional):

| Variable | Description | Default |
|----------|-------------|---------|
| `RHDH_E2E_NFS_APP_AUTH_PACKAGE` | Full `oci://` package ref for `red-hat-developer-hub-backstage-plugin-app-auth` | Baked default in package YAML |
| `RHDH_E2E_NFS_APP_INTEGRATIONS_PACKAGE` | Full `oci://` package ref for `red-hat-developer-hub-backstage-plugin-app-integrations` | Baked default in package YAML |

If an env var is **unset**, the default ref from the package is used. If set, it **replaces** that plugin entry (useful in CI to pin versions without publishing a new `@red-hat-developer-hub/e2e-test-utils` release).

Constants matching these names are exported as `RHDH_E2E_NFS_APP_AUTH_PACKAGE_ENV` and `RHDH_E2E_NFS_APP_INTEGRATIONS_PACKAGE_ENV` from `@red-hat-developer-hub/e2e-test-utils/rhdh`.

### OCI URL Generation

When `GIT_PR_NUMBER` is set, the package replaces local plugin paths with OCI URLs:
Expand Down
4 changes: 3 additions & 1 deletion docs/guide/configuration/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 shell plugin overrides) |
| [Disabling Conflicting Wrappers](/guide/configuration/disable-wrappers) | Disabling pre-enabled wrappers that may cause configuration conflicts |

## Project Configuration
Expand Down Expand Up @@ -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 [`useNewFrontendSystem`](/guide/deployment/rhdh-deployment#new-frontend-system-usenewfrontendsystem) on `configure()` and [NFS-related environment variables](/guide/configuration/environment-variables#new-frontend-system-app-next-shell-plugins).

## 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.
37 changes: 31 additions & 6 deletions docs/guide/deployment/rhdh-deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,30 @@ 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` | When `true`, enables the Backstage **new frontend system** shell (app-next): merges `APP_CONFIG_app_packageName` / `ENABLE_STANDARD_MODULE_FEDERATION` into `rhdh-secrets`, adds OCI **app-auth** and **app-integrations** dynamic plugins (with optional env overrides — see [Environment Variables](/guide/configuration/environment-variables#new-frontend-system-app-next-shell-plugins)), and merges extra Helm values (`value_file.new-frontend.yaml`, optional workspace `tests/config/value_file-app-next.yaml`). Defaults to `false`. |

### New frontend system (`useNewFrontendSystem`)

Set `useNewFrontendSystem: true` in **`configure()`** when tests must run against the **app-next** frontend (often called NFS in docs). Typical flow:

```typescript
await rhdh.configure({
auth: "keycloak",
useNewFrontendSystem: true,
});
await rhdh.deploy();
```

Do **not** rely on the worker fixture’s argument-free `configure()` call for this flag — pass it in `beforeAll` with the rest of your deployment options **before** `deploy()`, as you do for `auth` and custom config paths.

What gets merged:

1. **Secrets** — `APP_CONFIG_app_packageName: app-next` and `ENABLE_STANDARD_MODULE_FEDERATION: "true"` (workspace `rhdh-secrets.yaml` still supplies plugin-specific secrets).
2. **Dynamic plugins** — Default OCI refs for `red-hat-developer-hub-backstage-plugin-app-auth` and `...-app-integrations`, overridable via `RHDH_E2E_NFS_APP_AUTH_PACKAGE` and `RHDH_E2E_NFS_APP_INTEGRATIONS_PACKAGE` (full `oci://` URIs).
3. **Helm** — Package merge layer `config/helm/value_file.new-frontend.yaml` (shipped with the package), 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

Expand Down Expand Up @@ -114,12 +138,13 @@ await rhdh.deploy({ timeout: null });

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
2. Optionally applies **new frontend system** merges when [`useNewFrontendSystem`](#deploymentoptions) was set on `configure()` (secrets, optional OCI shell plugins, Helm layers)
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 (with environment variable substitution)
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

Expand Down
11 changes: 11 additions & 0 deletions docs/overlay/reference/environment-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,17 @@ 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 (optional OCI overrides)

Used when tests call `configure({ useNewFrontendSystem: true })`. Same semantics as the [guide environment reference](/guide/configuration/environment-variables#new-frontend-system-app-next-shell-plugins): full `oci://` refs; unset keeps package defaults.

| Variable | Description |
|----------|-------------|
| `RHDH_E2E_NFS_APP_AUTH_PACKAGE` | Override default OCI ref for app-auth |
| `RHDH_E2E_NFS_APP_INTEGRATIONS_PACKAGE` | Override default OCI ref for app-integrations |

Set these in Vault or CI job env when you need to pin shell plugin versions per pipeline.

### Cluster Configuration

| Variable | Description | Default | Required |
Expand Down
12 changes: 12 additions & 0 deletions docs/overlay/test-structure/configuration-files.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 useNewFrontendSystem is true (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 you pass `useNewFrontendSystem: true` to [`configure()`](/guide/deployment/rhdh-deployment#configureoptions), `@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 (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**, overridable via `RHDH_E2E_NFS_APP_AUTH_PACKAGE` / `RHDH_E2E_NFS_APP_INTEGRATIONS_PACKAGE` ([guide](/guide/configuration/environment-variables#new-frontend-system-app-next-shell-plugins)).

You can **remove** hand-maintained `app-auth` / `app-integrations` lines from `dynamic-plugins.yaml` when the framework supplies them. Keep workspace-only plugins and metadata-driven config as today.

Optional **`value_file-app-next.yaml`** is merged last when `useNewFrontendSystem` is true 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`.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@red-hat-developer-hub/e2e-test-utils",
"version": "1.1.37",
"version": "1.1.38",
"description": "Test utilities for RHDH E2E tests",
"license": "Apache-2.0",
"repository": {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
includes:
- dynamic-plugins.default.yaml
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
Original file line number Diff line number Diff line change
@@ -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"
2 changes: 2 additions & 0 deletions src/deployment/rhdh/config/helm/value_file.new-frontend.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Helm values merge layer when useNewFrontendSystem is true (additive; extend as needed).
{}
15 changes: 15 additions & 0 deletions src/deployment/rhdh/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,26 @@ export const DEFAULT_CONFIG_PATHS = {
PACKAGE_ROOT,
"dist/deployment/rhdh/config/common/dynamic-plugins.yaml",
),
/** New frontend system (app-next): merged when useNewFrontendSystem is true */
newFrontendSystem: {
secrets: path.join(
PACKAGE_ROOT,
"dist/deployment/rhdh/config/common/new-frontend-system-secrets.yaml",
),
dynamicPlugins: path.join(
PACKAGE_ROOT,
"dist/deployment/rhdh/config/common/new-frontend-system-dynamic-plugins.yaml",
),
},
helm: {
valueFile: path.join(
PACKAGE_ROOT,
"dist/deployment/rhdh/config/helm/value_file.yaml",
),
valueFileNewFrontend: path.join(
PACKAGE_ROOT,
"dist/deployment/rhdh/config/helm/value_file.new-frontend.yaml",
),
},
operator: {
subscription: path.join(
Expand Down
34 changes: 34 additions & 0 deletions src/deployment/rhdh/deployment.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,38 @@ describe("dynamic-plugins merge (no user config path)", () => {
"metadata (OCI) must win over auth local path",
);
});

it("dedupes NFS shell plugin against duplicate OCI ref for same logical plugin", () => {
const userPlugins: Record<string, unknown> = {
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 nfsMerge: Record<string, unknown> = {
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(userPlugins, nfsMerge, {
arrayMergeStrategy: {
byKey: "package",
normalizeKey: (item) =>
getNormalizedPluginMergeKey(item as Record<string, unknown>),
},
});
const plugins = merged.plugins as Array<{ package?: string }>;
assert.strictEqual(plugins.length, 1);
assert.ok(
plugins[0].package?.includes("bs_1.49.4__0.0.1"),
"NFS fragment should merge into same logical plugin entry",
);
});
});
40 changes: 37 additions & 3 deletions src/deployment/rhdh/deployment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
AUTH_CONFIG_PATHS,
CHART_URL,
} from "./constants.js";
import { loadNewFrontendShellPlugins } from "./new-frontend-system-plugins.js";
import type {
DeploymentOptions,
DeploymentConfig,
Expand Down Expand Up @@ -114,9 +115,17 @@ export class RHDHDeployment {
if (typeof value === "string") return envsubst(value);
});

let secretPayload = substituted as Record<string, unknown>;
if (this.deploymentConfig.useNewFrontendSystem) {
const nfsSecrets = await mergeYamlFilesIfExists([
DEFAULT_CONFIG_PATHS.newFrontendSystem.secrets,
]);
secretPayload = deepMerge(secretPayload, nfsSecrets);
}

await this.k8sClient.applySecretFromObject(
"rhdh-secrets",
substituted as { stringData?: Record<string, string> },
secretPayload as { stringData?: Record<string, string> },
this.deploymentConfig.namespace,
);
}
Expand Down Expand Up @@ -192,6 +201,20 @@ export class RHDHDeployment {
config = await this._mergeGeneratedWithBase(generated);
}

if (this.deploymentConfig.useNewFrontendSystem) {
const nfsPlugins = loadNewFrontendShellPlugins() as Record<
string,
unknown
>;
config = deepMerge(config, nfsPlugins, {
arrayMergeStrategy: {
byKey: "package",
normalizeKey: (item) =>
getNormalizedPluginMergeKey(item as Record<string, unknown>),
},
});
}

// Process for deployment: inject metadata (PR only) + resolve all packages to OCI
let result = await processPluginsForDeployment(
config as DynamicPluginsConfig,
Expand Down Expand Up @@ -224,10 +247,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.helm.valueFileNewFrontend]
: []),
valueFile,
])) as Record<string, Record<string, unknown>>;
...(this.deploymentConfig.useNewFrontendSystem &&
fs.existsSync(WorkspacePaths.valueFileAppNext)
? [WorkspacePaths.valueFileAppNext]
: []),
];
const valueFileObject = (await mergeYamlFilesIfExists(
helmValuePaths,
)) as Record<string, Record<string, unknown>>;

this._logBoxen("Value File", valueFileObject);

Expand Down Expand Up @@ -513,6 +546,7 @@ export class RHDHDeployment {
secrets: input.secrets ?? WorkspacePaths.secrets,
dynamicPlugins: input.dynamicPlugins ?? WorkspacePaths.dynamicPlugins,
disableWrappers: input.disableWrappers ?? [],
useNewFrontendSystem: input.useNewFrontendSystem ?? false,
};

if (method === "helm") {
Expand Down
5 changes: 5 additions & 0 deletions src/deployment/rhdh/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
export { RHDHDeployment } from "./deployment.js";
export {
RHDH_E2E_NFS_APP_AUTH_PACKAGE_ENV,
RHDH_E2E_NFS_APP_INTEGRATIONS_PACKAGE_ENV,
} from "./new-frontend-system-plugins.js";
export * from "./types.js";
Loading
Loading