Skip to content

Commit ee7d9d5

Browse files
feat(plugin-metadata): add OCI image URL generation for PR builds (#23)
When GIT_PR_NUMBER environment variable is set, local plugin paths are replaced with OCI URLs pointing to the plugin export overlays registry (ghcr.io/redhat-developer/rhdh-plugin-export-overlays). Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1 parent b9b8631 commit ee7d9d5

15 files changed

Lines changed: 505 additions & 214 deletions

docs/api/utils/plugin-metadata.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,13 +178,29 @@ async function generateDynamicPluginsConfigFromMetadata(
178178
- Throws error if no valid metadata files found
179179
- All generated plugins have `disabled: false`
180180

181+
**PR Build Behavior (when `GIT_PR_NUMBER` is set):**
182+
- Replaces local plugin paths with OCI URLs
183+
- Fetches plugin versions from source repo's `package.json`
184+
- Throws error if `source.json` or `plugins-list.yaml` not found
185+
- Throws error if version fetching fails
186+
181187
**Example:**
182188

183189
```typescript
184190
const config = await generateDynamicPluginsConfigFromMetadata();
185191
console.log(`Generated config with ${config.plugins?.length} plugins`);
186192
```
187193

194+
**Example Output (PR Build):**
195+
196+
```yaml
197+
plugins:
198+
- package: oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/my-plugin:pr_1234__1.0.0
199+
disabled: false
200+
pluginConfig:
201+
# ... from metadata
202+
```
203+
188204
---
189205

190206
### loadAndInjectPluginMetadata()

docs/changelog.md

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,38 +2,81 @@
22

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

5-
## [1.1.2] - Current
5+
## [1.1.5] - Current
66

77
### Added
8-
- Keycloak integration with modular auth configuration
8+
- **Plugin metadata auto-generation**: When `dynamic-plugins.yaml` doesn't exist, configuration is automatically generated from `metadata/*.yaml` files
9+
- **OCI URL generation for PR builds**: When `GIT_PR_NUMBER` is set, local plugin paths are replaced with OCI URLs (e.g., `oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/my-plugin:pr_1234__1.0.0`)
10+
- Plugin metadata injection into existing `dynamic-plugins.yaml` configurations
11+
- New utilities: `shouldInjectPluginMetadata()`, `generateDynamicPluginsConfigFromMetadata()`, `loadAndInjectPluginMetadata()`, `extractPluginName()`
12+
- **Early pod failure detection**: `waitForPodsWithFailureDetection()` in KubernetesClientHelper detects CrashLoopBackOff, ImagePullBackOff, init container failures, etc. within seconds instead of waiting for full timeout
13+
14+
### Changed
15+
- Plugin versions for OCI URLs are fetched from source repo's `package.json` using `source.json` commit ref
16+
- Metadata handling disabled for periodic builds (when `JOB_NAME` contains `periodic-`)
17+
- Strict error handling for PR builds (fails if source files missing or fetch fails)
18+
- Improved boxen formatting for YAML output
19+
- RHDH and Keycloak deployments now use early failure detection for faster error reporting
20+
21+
### Environment Variables
22+
- `GIT_PR_NUMBER`: Enables OCI URL generation for PR builds
23+
- `RHDH_SKIP_PLUGIN_METADATA_INJECTION`: Disables all metadata handling
24+
25+
## [1.1.4]
26+
27+
### Fixed
28+
- Keycloak: Use plain HTTP route to avoid certificate issues (#19)
29+
30+
### Security
31+
- Bump `lodash` from 4.17.21 to 4.17.23
32+
- Bump `tar` from 7.5.2 to 7.5.6
33+
34+
## [1.1.3]
35+
36+
### Added
37+
- Comprehensive VitePress documentation site (#14)
38+
39+
### Fixed
40+
- Corepack setup for Yarn 3 in CI workflow (#16)
41+
42+
## [1.1.2]
43+
44+
### Added
45+
- Keycloak integration with modular auth configuration (#8)
946
- KeycloakHelper class for Keycloak deployment and management
1047
- Support for guest and Keycloak authentication providers
1148
- Automatic Keycloak deployment in global setup
1249
- Default realm, client, groups, and users configuration
50+
- Keycloak integration documentation (#9)
1351

1452
### Changed
1553
- Improved RHDHDeployment class with `configure()` method
1654
- Enhanced configuration merging for auth-specific configs
1755
- Better environment variable handling
1856

57+
## [1.1.1]
58+
59+
### Added
60+
- Playwright helpers: UIHelper, LoginHelper, APIHelper (#7)
61+
- Page objects: CatalogPage, HomePage, CatalogImportPage, ExtensionsPage, NotificationPage
62+
1963
## [1.1.0]
2064

2165
### Added
2266
- Initial release of `rhdh-e2e-test-utils`
2367
- RHDHDeployment class for RHDH deployment
2468
- Playwright test fixtures (rhdh, uiHelper, loginHelper, baseURL)
2569
- Base Playwright configuration with `defineConfig`
26-
- UIhelper class for Material-UI interactions
27-
- LoginHelper class for authentication
28-
- APIHelper class for GitHub and Backstage APIs
29-
- Page objects (CatalogPage, HomePage, CatalogImportPage, ExtensionsPage, NotificationPage)
3070
- KubernetesClientHelper for Kubernetes operations
3171
- YAML merging utilities
3272
- Environment variable substitution
3373
- ESLint configuration factory
3474
- TypeScript base configuration
3575
- Support for Helm and Operator deployment methods
3676

77+
### Fixed
78+
- Config file resolution for published package (#6)
79+
3780
## [1.0.0]
3881

3982
### Added

docs/guide/configuration/config-files.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,26 @@ When injection is enabled, deployment will fail if:
205205
- No valid metadata files are found in the directory
206206
:::
207207
208+
### OCI URL Replacement for PR Builds
209+
210+
When `GIT_PR_NUMBER` is set (by OpenShift CI), local plugin paths are automatically replaced with OCI URLs pointing to the PR's built artifacts:
211+
212+
```yaml
213+
# Local development
214+
- package: ./dynamic-plugins/dist/backstage-community-plugin-tech-radar
215+
216+
# PR build (GIT_PR_NUMBER=1845)
217+
- package: oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-tech-radar:pr_1845__1.13.0
218+
```
219+
220+
This allows E2E tests to run against the actual OCI images built for the PR.
221+
222+
::: warning
223+
For PR builds, OCI URL generation is required. Deployment will fail if `source.json` or `plugins-list.yaml` doesn't exist, or if version fetching fails.
224+
:::
225+
226+
See [Plugin Metadata - OCI URL Generation](/guide/utilities/plugin-metadata#oci-url-generation-for-pr-builds) for complete details.
227+
208228
### Package Reference Matching
209229

210230
The package automatically matches plugins across different reference formats:

docs/guide/configuration/environment-variables.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,23 @@ These control automatic plugin configuration injection from metadata files:
3333

3434
| Variable | Description | Effect |
3535
|----------|-------------|--------|
36+
| `GIT_PR_NUMBER` | PR number (set by OpenShift CI) | Enables OCI URL generation for PR builds |
3637
| `RHDH_SKIP_PLUGIN_METADATA_INJECTION` | When set (any value), disables metadata injection | Opt-out |
3738
| `JOB_NAME` | CI job name (set by OpenShift CI/Prow) | If contains `periodic-`, injection is disabled |
3839

39-
See [Plugin Metadata Injection](/guide/configuration/config-files#plugin-metadata-injection) for details.
40+
### OCI URL Generation
41+
42+
When `GIT_PR_NUMBER` is set, the package replaces local plugin paths with OCI URLs:
43+
44+
```yaml
45+
# Before
46+
- package: ./dynamic-plugins/dist/my-plugin
47+
48+
# After (with GIT_PR_NUMBER=1234)
49+
- package: oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/my-plugin:pr_1234__1.0.0
50+
```
51+
52+
See [Plugin Metadata](/guide/utilities/plugin-metadata#oci-url-generation-for-pr-builds) for complete details.
4053
4154
## Keycloak Variables
4255

docs/guide/quick-start.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,11 @@ stringData:
7676
```
7777

7878
::: tip Skip dynamic-plugins.yaml
79-
If your workspace has a `metadata/` directory with Package CRD files, you can skip creating `dynamic-plugins.yaml`. The package will automatically generate configuration from metadata files. See [Plugin Metadata Injection](/guide/configuration/config-files#plugin-metadata-injection).
79+
If your workspace has a `metadata/` directory with Package CRD files, you can skip creating `dynamic-plugins.yaml`. The package will automatically generate configuration from metadata files.
80+
81+
For PR builds in CI (when `GIT_PR_NUMBER` is set), the package also automatically replaces local plugin paths with OCI URLs pointing to the PR's built artifacts.
82+
83+
See [Plugin Metadata Injection](/guide/configuration/config-files#plugin-metadata-injection) for details.
8084
:::
8185

8286
## Step 4: Create Environment File

docs/guide/utilities/kubernetes-client.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,32 @@ const domain = await k8sClient.getClusterIngressDomain();
9595
// Returns: "apps.cluster.example.com"
9696
```
9797

98+
## Pod Operations
99+
100+
### `waitForPodsWithFailureDetection(namespace, labelSelector, timeout?, pollInterval?)`
101+
102+
Wait for pods to be ready with early failure detection. Unlike `oc rollout status`, this method detects unrecoverable failure states (CrashLoopBackOff, ImagePullBackOff, etc.) within seconds and fails fast with container logs:
103+
104+
```typescript
105+
await k8sClient.waitForPodsWithFailureDetection(
106+
"my-namespace",
107+
"app.kubernetes.io/instance=my-app",
108+
300, // timeout in seconds (default: 300)
109+
5000 // poll interval in ms (default: 5000)
110+
);
111+
```
112+
113+
**Detected failure states:**
114+
- `CrashLoopBackOff` - container keeps crashing
115+
- `ImagePullBackOff` / `ErrImagePull` - can't pull image
116+
- `CreateContainerConfigError` - config issues (missing secrets, etc.)
117+
- `Init:*` variants - init container failures
118+
119+
When a failure is detected, the method:
120+
1. Logs the failure reason
121+
2. Fetches container logs via `oc logs`
122+
3. Throws an error with the failure details
123+
98124
## Deployment Operations
99125

100126
### `scaleDeployment(namespace, name, replicas)`

docs/guide/utilities/plugin-metadata.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,10 +127,49 @@ The `RHDHDeployment` class automatically uses these utilities during `deploy()`:
127127

128128
See [Configuration Files](/guide/configuration/config-files#plugin-metadata-injection) for detailed behavior.
129129

130+
## OCI URL Generation for PR Builds
131+
132+
When `GIT_PR_NUMBER` is set (by OpenShift CI), local plugin paths are automatically replaced with OCI URLs pointing to the PR's built artifacts.
133+
134+
### How It Works
135+
136+
1. Reads `source.json` from the workspace directory to get the source repo and commit ref
137+
2. Reads `plugins-list.yaml` to get the list of plugin paths
138+
3. Fetches each plugin's `package.json` from the source repo to get the current version
139+
4. Generates OCI URLs in the format:
140+
141+
```
142+
oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/{plugin-name}:pr_{PR_NUMBER}__{version}
143+
```
144+
145+
### Example
146+
147+
```yaml
148+
# Local development
149+
- package: ./dynamic-plugins/dist/backstage-community-plugin-tech-radar
150+
151+
# PR build (GIT_PR_NUMBER=1845)
152+
- package: oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-community-plugin-tech-radar:pr_1845__1.13.0
153+
```
154+
155+
### Required Files
156+
157+
For OCI URL generation, your workspace must have these files (generated by CI):
158+
159+
| File | Purpose |
160+
|------|---------|
161+
| `source.json` | Contains `repo` (GitHub URL) and `repo-ref` (commit SHA) |
162+
| `plugins-list.yaml` | Lists plugin paths (e.g., `plugins/tech-radar:`) |
163+
164+
::: warning
165+
For PR builds, OCI URL generation is strict - deployment will fail if required files are missing or version fetching fails. This ensures PR builds don't silently fall back to local paths.
166+
:::
167+
130168
## Environment Variables
131169

132170
| Variable | Effect |
133171
|----------|--------|
172+
| `GIT_PR_NUMBER` | Enables OCI URL generation for PR builds |
134173
| `RHDH_SKIP_PLUGIN_METADATA_INJECTION` | Disables all metadata handling |
135174
| `JOB_NAME` | If contains `periodic-`, disables metadata handling |
136175

docs/tutorials/ci-cd-integration.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,35 @@ on:
170170
- cron: "0 6 * * *" # Daily at 6 AM
171171
```
172172

173+
## OpenShift CI / Prow Integration
174+
175+
For OpenShift CI (Prow), the package supports automatic OCI URL generation for PR builds.
176+
177+
### Environment Variables
178+
179+
| Variable | Description | Set By |
180+
|----------|-------------|--------|
181+
| `GIT_PR_NUMBER` | PR number - enables OCI URL generation | OpenShift CI |
182+
| `JOB_NAME` | Job name (e.g., `pull-ci-...` or `periodic-...`) | OpenShift CI |
183+
184+
### OCI URL Generation
185+
186+
When `GIT_PR_NUMBER` is set, plugin paths are automatically replaced with OCI URLs:
187+
188+
```yaml
189+
# Before
190+
- package: ./dynamic-plugins/dist/my-plugin
191+
192+
# After (GIT_PR_NUMBER=1234)
193+
- package: oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/my-plugin:pr_1234__1.0.0
194+
```
195+
196+
### Periodic/Nightly Builds
197+
198+
For periodic builds (when `JOB_NAME` contains `periodic-`), metadata injection is disabled automatically. Tests use default RHDH configuration.
199+
200+
See [Plugin Metadata](/guide/utilities/plugin-metadata#oci-url-generation-for-pr-builds) for complete details.
201+
173202
## Best Practices
174203

175204
1. **Use fail-fast: false** - Run all projects even if one fails

docs/tutorials/plugin-testing.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,14 @@ myPlugin:
8484
```
8585
8686
::: tip Automatic Plugin Configuration
87-
If your workspace has a `metadata/` directory with Package CRD files, you can skip creating `dynamic-plugins.yaml`. The package will automatically generate configuration from metadata files during PR builds. See [Plugin Metadata Injection](/guide/configuration/config-files#plugin-metadata-injection) for details.
87+
If your workspace has a `metadata/` directory with Package CRD files, you can skip creating `dynamic-plugins.yaml`. The package will automatically:
88+
89+
1. **Generate configuration** from all metadata files (all plugins enabled)
90+
2. **Replace paths with OCI URLs** for PR builds (when `GIT_PR_NUMBER` is set)
91+
92+
Example OCI URL: `oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/my-plugin:pr_1234__1.0.0`
93+
94+
See [Plugin Metadata Injection](/guide/configuration/config-files#plugin-metadata-injection) for details.
8895
:::
8996

9097
## Step 4: Write Tests

package.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "rhdh-e2e-test-utils",
3-
"version": "1.1.4",
3+
"version": "1.1.5",
44
"description": "Test utilities for RHDH E2E tests",
55
"license": "Apache-2.0",
66
"type": "module",
@@ -82,7 +82,6 @@
8282
"@eslint/js": "^9.39.1",
8383
"@keycloak/keycloak-admin-client": "^26.0.0",
8484
"@kubernetes/client-node": "^1.4.0",
85-
"boxen": "^8.0.1",
8685
"eslint": "^9.39.1",
8786
"eslint-plugin-check-file": "^3.3.1",
8887
"eslint-plugin-playwright": "^2.4.0",

0 commit comments

Comments
 (0)