Configuration Files
Overlay Documentation
This page covers writing tests within rhdh-plugin-export-overlays. For using rhdh-e2e-test-utils in external projects, see the Guide.
This page explains the YAML configuration files used in overlay E2E tests.
If you're looking for the general file formats and examples, see Configuration Files (Guide). This page focuses on overlay-specific behavior such as metadata auto-generation and OCI URL replacement.
All Configuration Files Are Optional
Key Concept
All configuration files in tests/config/ are optional. The package provides sensible defaults. Only create a configuration file when you need to override or extend the defaults (i.e., when the default config does not already cover your use case).
If your plugin works with the package defaults and metadata-based configuration, you may not need any configuration files at all.
Configuration File Location
Configuration files are placed in tests/config/:
tests/config/
├── app-config-rhdh.yaml # RHDH application configuration (optional)
├── rhdh-secrets.yaml # Kubernetes secrets (optional)
├── dynamic-plugins.yaml # Dynamic plugins (optional - usually not needed)
├── value_file.yaml # Helm values override (optional, Helm only)
└── subscription.yaml # Operator subscription (optional, Operator only)2
3
4
5
6
All of these files are optional. Only create them when you need to override or extend defaults.
app-config-rhdh.yaml (Optional)
The main RHDH configuration file. This file is merged with default configurations from rhdh-e2e-test-utils.
Only create this file when you need to:
- Override a default value in the RHDH app config
- Add config keys that are not provided by the defaults
Purpose
- Set plugin-specific configuration values
- Configure backend settings
- Customize the RHDH instance title
- Allow external hosts for reading
Structure
# RHDH app config file
# This file merges with the default values from rhdh-e2e-test-utils
app:
title: RHDH <Plugin Name> Test Instance
backend:
reading:
allow:
- host: ${EXTERNAL_HOST}
# Plugin-specific configuration
<pluginName>:
setting1: value1
setting2: value22
3
4
5
6
7
8
9
10
11
12
13
14
15
Referencing Secrets
Use ${VAR_NAME} syntax to reference values from rhdh-secrets.yaml:
backend:
reading:
allow:
- host: ${TECH_RADAR_DATA_URL}
techRadar:
url: "http://${TECH_RADAR_DATA_URL}/tech-radar"2
3
4
5
6
These reference the Kubernetes Secret created by rhdh-secrets.yaml. The secret must define TECH_RADAR_DATA_URL for this to work.
Real Example: Tech Radar
# rhdh app config file
# this file is used to merge with the default values of the rhdh app config
app:
title: RHDH Tech Radar Test Instance
backend:
reading:
allow:
- host: ${TECH_RADAR_DATA_URL}
techRadar:
url: "http://${TECH_RADAR_DATA_URL}/tech-radar"2
3
4
5
6
7
8
9
10
11
rhdh-secrets.yaml (Optional)
A Kubernetes Secret manifest that bridges environment variables to the RHDH deployment.
Only create this file when you need to pass environment variables into RHDH configuration files.
Environment Variable Substitution
Important
Environment variable substitution is performed ONLY on rhdh-secrets.yaml.
When this file is processed, any $VAR_NAME references are replaced with actual values from the environment. Other config files (app-config-rhdh.yaml, dynamic-plugins.yaml) do not get direct substitution - they reference the secrets created by this file.
When Is This File Needed?
| Where you need the variable | rhdh-secrets.yaml required? |
|---|---|
Test code (*.spec.ts) | No - use process.env directly |
RHDH configs (app-config-rhdh.yaml, etc.) | Yes |
How It Works
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────────┐
│ Vault / .env │────▶│ rhdh-secrets.yaml│────▶│ app-config-rhdh.yaml│
│ MY_SECRET=value │ │ MY_SECRET: $VAR │ │ ${MY_SECRET} │
│ │ │ (substituted) │ │ (references secret) │
└─────────────────┘ └──────────────────┘ └─────────────────────┘2
3
4
5
- Environment variable exists (from Vault in CI, or
.envlocally) rhdh-secrets.yamlreferences it with$VAR_NAME- substituted with actual value- RHDH configs reference the secret with
${VAR_NAME}
Structure
apiVersion: v1
kind: Secret
metadata:
name: rhdh-secrets
type: Opaque
stringData:
# $VAR_NAME is replaced with the actual value from environment
TECH_RADAR_DATA_URL: $TECH_RADAR_DATA_URL
API_KEY: $VAULT_MY_API_KEY2
3
4
5
6
7
8
9
Real Example: Tech Radar
apiVersion: v1
kind: Secret
metadata:
name: rhdh-secrets
type: Opaque
stringData:
TECH_RADAR_DATA_URL: $TECH_RADAR_DATA_URL2
3
4
5
6
7
Then in app-config-rhdh.yaml, you can use ${TECH_RADAR_DATA_URL}:
techRadar:
url: "http://${TECH_RADAR_DATA_URL}/tech-radar"2
dynamic-plugins.yaml (Optional)
Configuration for dynamic plugins. This file is optional and in most cases should not be provided.
Best Practice
Do NOT create dynamic-plugins.yaml unless you have a specific reason. When the file doesn't exist, all plugins in the workspace are automatically enabled with their default configurations from metadata. Only create this file if you need to override specific plugin settings.
How Plugin Configuration is Generated
The package uses plugin metadata files (in metadata/*.yaml at the workspace level) to automatically configure plugins:
workspaces/<plugin-name>/
├── metadata/ # Plugin metadata (Package CRD format)
│ ├── plugin-frontend.yaml # Frontend plugin metadata
│ └── plugin-backend.yaml # Backend plugin metadata
├── e2e-tests/ # Your test project
│ └── tests/config/
│ └── dynamic-plugins.yaml # Optional - usually not needed
└── plugins/ # Plugin source code2
3
4
5
6
7
8
The metadata files contain spec.appConfigExamples with the plugin's default configuration. These are automatically read and used during deployment.
When File Doesn't Exist (Recommended)
When tests/config/dynamic-plugins.yaml is missing, the package auto-generates a complete configuration:
- Scans for plugin metadata in
../metadata/(relative to e2e-tests) - Reads each
*.yamlfile as Package CRD format - Extracts
spec.dynamicArtifactandspec.appConfigExamples[0].content - Generates plugin entries with:
package: The dynamicArtifact pathdisabled: false(enabled by default)pluginConfig: From appConfigExamples
- Merges with package defaults and auth config
Result: All plugins from metadata are enabled with their default configurations. This is the recommended approach for most plugins.
When File Exists
When tests/config/dynamic-plugins.yaml exists:
- Package defaults are loaded
- Auth-specific plugins (keycloak/guest) are merged
- Your custom config is merged on top (overrides earlier values)
- Plugin metadata is injected only for plugins listed in your file
Important: If you provide this file, you take control of which plugins are enabled. Plugins not listed in your file won't get metadata injected automatically.
When to Create This File
Only create this file when:
- You need to disable specific plugins
- You need to override default plugin settings from metadata
- The plugin has no metadata files
- You need different configuration than the metadata defaults
Structure (If Needed)
plugins:
- package: "@company/backstage-plugin-example"
disabled: false
pluginConfig:
example:
setting: customValue # Overrides metadata default2
3
4
5
6
See Also
For detailed information about plugin metadata handling, see the package documentation:
value_file.yaml (Optional, Helm Only)
Override Helm chart values for RHDH deployment.
Only create this file when you need to:
- Override default Helm values
- Configure cluster-specific settings
- Customize resource limits or replicas
Structure
# Override Helm values
upstream:
backstage:
resources:
limits:
memory: 4Gi2
3
4
5
6
This file is merged with the package's default Helm values.
subscription.yaml (Optional, Operator Only)
Override Operator subscription settings.
Only create this file when you need to:
- Use a specific operator channel
- Configure operator-specific settings
- Override default subscription configuration
Structure
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
name: rhdh
spec:
channel: fast2
3
4
5
6
This file is merged with the package's default subscription configuration.
Plugin Package References
When providing plugin packages (in dynamic-plugins.yaml if you create one), you can use either:
- Local paths:
./dynamic-plugins/dist/my-plugin - OCI references:
oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/my-plugin:1.0.0
Both formats work for local development.
PR Builds and OCI Images
When GIT_PR_NUMBER is set (either in CI or locally), the package automatically replaces plugin paths with OCI image references built from that PR.
How It Works
- The
/publishcommand (as a PR comment) triggers a workflow that builds OCI images from the PR - Images are pushed to
ghcr.io/redhat-developer/rhdh-plugin-export-overlays - When tests run with
GIT_PR_NUMBERset (CI or local), the package:- Reads
source.jsonandplugins-list.yaml - Fetches plugin versions from the source repo's
package.jsonfiles - Replaces plugin paths with OCI URLs pointing to the PR-built images
- Reads
OCI URL Format
oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/{plugin-name}:pr_{PR_NUMBER}__{version}Automatic Replacement
In CI (PR executions): The replacement happens automatically. It doesn't matter what format you use in your configuration - it will be replaced with the OCI reference for that PR's built images.
Locally with GIT_PR_NUMBER: If you set GIT_PR_NUMBER locally, it will fetch and use the published OCI images from that PR. This is useful for testing PR builds locally.
# Test locally using PR 1845's published OCI images
export GIT_PR_NUMBER=1845
yarn test2
3
For a full local workflow, see Local OCI Testing.
What You Don't Need to Do
The OCI URL replacement is automatic. You don't need to:
- Create or modify any configuration files for PR builds
- Specify OCI URLs manually
- Handle different configurations for local vs CI
The package handles this transparently based on the GIT_PR_NUMBER environment variable.
Required Files for OCI URL Generation
When GIT_PR_NUMBER is set, these files must exist in the workspace root:
| File | Purpose |
|---|---|
source.json | Contains repo (GitHub URL) and repo-ref (commit SHA) |
plugins-list.yaml | Lists plugin paths (e.g., plugins/tech-radar:) |
In CI, these are generated automatically. For local testing with GIT_PR_NUMBER, you may need to create them or copy them from a CI run.
Strict Validation
OCI URL generation is strict - deployment will fail if required files are missing or version fetching fails. This ensures builds don't silently fall back to local paths.
Configuration Merging
rhdh-e2e-test-utils merges your configuration with defaults in this order:
- Base defaults from
rhdh-e2e-test-utils/config/common/ - Auth-specific from
rhdh-e2e-test-utils/config/auth/{guest,keycloak}/ - Deployment method from
rhdh-e2e-test-utils/config/{helm,operator}/ - Your custom config from
tests/config/
Later files override earlier ones using deep merge.
Merge Strategies
Arrays use the "replace" strategy by default:
# Base config
backend:
reading:
allow:
- host: localhost
# Your config (replaces the array)
backend:
reading:
allow:
- host: ${EXTERNAL_HOST}
# Result
backend:
reading:
allow:
- host: ${EXTERNAL_HOST} # localhost is replaced2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Setting Environment Variables
Environment variables can be set in multiple ways:
1. In Test Code
Set variables in beforeAll:
test.beforeAll(async ({ rhdh }) => {
// Deploy external service first
await $`bash ${setupScript} ${project}`;
// Get the service URL and set as env var
process.env.TECH_RADAR_DATA_URL = await getServiceUrl();
// Now deploy RHDH (will use the env var)
await rhdh.deploy();
});2
3
4
5
6
7
8
9
10
2. In .env File
For local development:
# .env
TECH_RADAR_DATA_URL=my-service.example.com2
3. In Vault (CI)
Add secrets to the Vault with VAULT_ prefix. They are automatically exported during OpenShift CI execution:
VAULT_TECH_RADAR_DATA_URL: my-service.apps.cluster.example.comThen reference in your config:
techRadar:
url: "http://${VAULT_TECH_RADAR_DATA_URL}/tech-radar"2
Secret Naming
All secrets in Vault must start with VAULT_ prefix for automatic export.
Common Configuration Patterns
Allow External Hosts
backend:
reading:
allow:
- host: ${EXTERNAL_HOST}2
3
4
Set Plugin URL
<pluginName>:
url: "http://${SERVICE_URL}/<endpoint>"2
Custom App Title
app:
title: RHDH <Plugin> Test Instance2
Related Pages
- Directory Layout - Where config files go
- Spec Files - Using config in tests
- Environment Variables - All supported variables