You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat: configurable OCI registry for DPDY {{inherit}} refs in nightly mode (#104)
* feat: configurable OCI registry for DPDY {{inherit}} refs in nightly mode
Decouple the {{inherit}} tag registry from metadata's dynamicArtifact to
avoid registry mismatches (e.g. metadata switching from RHEC to ghcr.io
while DPDY stays on RHEC). The registry is now resolved via:
1. NIGHTLY_DPDY_OCI_REGISTRY_MAP (per-plugin JSON override)
2. NIGHTLY_DPDY_OCI_REGISTRY (blanket override)
3. Default: registry.access.redhat.com/rhdh
Also adds selective config injection in nightly: only non-DPDY OCI
plugins get appConfigExamples injected; DPDY plugins inherit config
from RHDH, and wrapper plugins get no injection.
Assisted-by: Claude Code
Co-Authored-By: Claude Code <noreply@anthropic.com>
* docs: clarify {{inherit}} resolves both OCI tag and config from DPDY
Rewrite confusing references across docs and source comments:
- {{inherit}} tells RHDH to resolve both the OCI tag (version) AND
default config from its built-in DPDY, not just one or the other
- Replace vague "DPDY OCI plugin" with explicit "plugins in
default.packages.yaml whose metadata spec.dynamicArtifact is OCI"
- Remove redundant tests covered by existing assertions
Assisted-by: Claude Code
Co-Authored-By: Claude Code <noreply@anthropic.com>
---------
Co-authored-by: Claude Code <noreply@anthropic.com>
@@ -47,7 +49,7 @@ const name = extractPluginName("oci://quay.io/rhdh/backstage-community-plugin-te
47
49
Returns a stable merge key for a plugin entry so that OCI and local path for the same logical plugin match when merging dynamic-plugins configs. Strips a trailing `-dynamic` suffix so that e.g. `backstage-community-plugin-catalog-backend-module-keycloak-dynamic` (local) and `backstage-community-plugin-catalog-backend-module-keycloak` (from OCI) map to the same key.
48
50
49
51
```typescript
50
-
function getNormalizedPluginMergeKey(entry: { package?: string }): string
52
+
function getNormalizedPluginMergeKey(entry: { package?:string }):string;
Determines whether the current execution is a nightly/periodic job. Controls whether metadata config injection is enabled and which OCI resolution strategy is used.
80
84
81
85
```typescript
82
-
function isNightlyJob(): boolean
86
+
function isNightlyJob():boolean;
83
87
```
84
88
85
89
**Returns:**`true` if running in nightly mode, `false` for PR/local mode.
86
90
87
91
**Priority order:**
92
+
88
93
1. If `GIT_PR_NUMBER` is set → returns `false` (PR mode takes precedence)
89
94
2. If `E2E_NIGHTLY_MODE` is `"true"` or `"1"` → returns `true`
90
95
3. If `JOB_NAME` contains `periodic-` → returns `true`
@@ -97,7 +102,7 @@ function isNightlyJob(): boolean
97
102
Gets the metadata directory path.
98
103
99
104
```typescript
100
-
function getMetadataDirectory(metadataPath?: string): string | null
105
+
function getMetadataDirectory(metadataPath?:string):string|null;
101
106
```
102
107
103
108
**Parameters:**
@@ -115,8 +120,8 @@ Parses all metadata files in a directory and builds a map of plugin name to conf
115
120
116
121
```typescript
117
122
asyncfunction parseAllMetadataFiles(
118
-
metadataDir: string
119
-
): Promise<Map<string, PluginMetadata>>
123
+
metadataDir:string,
124
+
):Promise<Map<string, PluginMetadata>>;
120
125
```
121
126
122
127
**Parameters:**
@@ -134,8 +139,8 @@ Auto-generates plugin entries from workspace metadata files when no user-provide
134
139
135
140
```typescript
136
141
asyncfunction generatePluginsFromMetadata(
137
-
metadataPath?: string
138
-
): Promise<DynamicPluginsConfig>
142
+
metadataPath?:string,
143
+
):Promise<DynamicPluginsConfig>;
139
144
```
140
145
141
146
**Parameters:**
@@ -154,22 +159,25 @@ Unified entry point for both PR and nightly plugin resolution flows. Called auto
154
159
```typescript
155
160
asyncfunction processPluginsForDeployment(
156
161
config:DynamicPluginsConfig,
157
-
metadataPath?: string
158
-
): Promise<DynamicPluginsConfig>
162
+
metadataPath?:string,
163
+
dpdyPackages?:Set<string>,
164
+
):Promise<DynamicPluginsConfig>;
159
165
```
160
166
161
167
**Parameters:**
162
168
| Parameter | Type | Default | Description |
163
169
|-----------|------|---------|-------------|
164
170
|`config`|[`DynamicPluginsConfig`](#dynamicpluginsconfig)| - | The plugins config to process |
165
171
|`metadataPath`|`string`|`"../metadata"`| Path to metadata directory |
172
+
|`dpdyPackages`|`Set<string>`| - | Pre-loaded DPDY package set (for testing; fetched automatically if omitted in nightly) |
166
173
167
174
**Returns:** Processed configuration with resolved OCI references.
168
175
169
176
**Behavior:**
177
+
170
178
-**PR mode** (`!isNightlyJob()`): Injects `appConfigExamples` from metadata as base config, then resolves packages to OCI URLs (PR-specific if `GIT_PR_NUMBER` set, metadata refs otherwise)
-**Nightly mode** (`isNightlyJob()`): Plugins in `default.packages.yaml` whose metadata `spec.dynamicArtifact` is an OCI ref use `{{inherit}}` with configurable registry (default `registry.access.redhat.com/rhdh`, overridable via `NIGHTLY_DPDY_OCI_REGISTRY` or `NIGHTLY_DPDY_OCI_REGISTRY_MAP`) — RHDH resolves both the OCI tag and default config from its built-in DPDY. Plugins NOT in `default.packages.yaml` with OCI metadata use full metadata refs with config injection.
180
+
- Respects `RHDH_SKIP_PLUGIN_METADATA_INJECTION` to skip config injection (local only, ignored in CI)
173
181
174
182
---
175
183
@@ -178,7 +186,7 @@ async function processPluginsForDeployment(
178
186
Creates a dynamic plugins config that disables wrapper plugins. Used during PR builds when wrapper plugins would conflict with PR-built OCI images.
179
187
180
188
```typescript
181
-
function disablePluginWrappers(plugins: string[]): DynamicPluginsConfig
189
+
function disablePluginWrappers(plugins:string[]):DynamicPluginsConfig;
Copy file name to clipboardExpand all lines: docs/changelog.md
+9-1Lines changed: 9 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,7 +2,15 @@
2
2
3
3
All notable changes to this project will be documented in this file.
4
4
5
-
## [1.1.39] - Current
5
+
## [1.1.40] - Current
6
+
7
+
### Changed
8
+
9
+
- **Nightly `{{inherit}}` resolution**: In nightly mode, plugins listed in [`default.packages.yaml`](https://github.com/redhat-developer/rhdh/blob/main/default.packages.yaml) whose metadata `spec.dynamicArtifact` is an OCI ref now resolve to `{{inherit}}` tags instead of pinned OCI refs. The `{{inherit}}` tag tells RHDH to resolve both the OCI tag (version) and default config from its built-in DPDY (`dynamic-plugins.default.yaml` in the catalog index image), so no config injection is needed from our side. This tests against the exact versions and configuration shipped in the RC. Plugins NOT in `default.packages.yaml` with OCI metadata continue using full metadata refs with config injection (they aren't in RHDH's built-in defaults). The DPDY list is fetched at runtime from the `rhdh` repo using `RELEASE_BRANCH_NAME` (required in CI, defaults to `main` locally). The `{{inherit}}` registry defaults to `registry.access.redhat.com/rhdh` and can be overridden with `NIGHTLY_DPDY_OCI_REGISTRY` (blanket) or `NIGHTLY_DPDY_OCI_REGISTRY_MAP` (per-plugin JSON: `{"registry": ["pkg1", "pkg2"]}`). This decouples the `{{inherit}}` registry from metadata's `spec.dynamicArtifact`, avoiding mismatches when metadata points to `ghcr.io` but the DPDY uses `registry.access.redhat.com`.
10
+
-**`RHDH_SKIP_PLUGIN_METADATA_INJECTION` is local-only**: This env var is now ignored in CI (`CI=true`). It was intended for local development opt-out only — in CI, metadata injection should always run to ensure consistent test behavior.
11
+
-**`RELEASE_BRANCH_NAME` required in CI for nightly**: When running nightly mode in CI, `RELEASE_BRANCH_NAME` must be set (exported by the OpenShift CI step registry). Locally it defaults to `main`.
Copy file name to clipboardExpand all lines: docs/guide/configuration/config-files.md
+23-14Lines changed: 23 additions & 14 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -212,18 +212,24 @@ Your `pluginConfig` in `dynamic-plugins.yaml` overrides values from metadata.
212
212
### When Injection is Enabled
213
213
214
214
Plugin metadata injection is **enabled by default** for:
215
+
215
216
- Local development
216
217
- PR builds in CI
217
218
218
-
Injection is **disabled** when:
219
-
-[`RHDH_SKIP_PLUGIN_METADATA_INJECTION`](/guide/configuration/environment-variables#plugin-metadata-variables) environment variable is set
220
-
-`JOB_NAME` contains `periodic-` (nightly/periodic CI builds)
219
+
Injection is **disabled locally** when:
220
+
221
+
-[`RHDH_SKIP_PLUGIN_METADATA_INJECTION`](/guide/configuration/environment-variables#plugin-metadata-variables) is set to `true` (ignored in CI)
222
+
223
+
In **nightly mode** (`E2E_NIGHTLY_MODE=true` or `JOB_NAME` contains `periodic-`):
224
+
225
+
- Only plugins NOT in `default.packages.yaml` with OCI metadata get injection; plugins in `default.packages.yaml` use `{{inherit}}` — RHDH resolves both the OCI tag and default config from its built-in DPDY
221
226
222
227
::: warning
223
228
When injection is enabled, deployment will fail if:
229
+
224
230
- The `metadata/` directory doesn't exist
225
231
- No valid metadata files are found in the directory
226
-
:::
232
+
:::
227
233
228
234
### OCI URL Replacement for PR Builds
229
235
@@ -244,6 +250,7 @@ This allows E2E tests to run against the actual OCI images built for the PR.
244
250
If you want to reproduce OCI URL replacement locally, create the required files at the workspace root:
0 commit comments