Skip to content

Commit 1b813ba

Browse files
fix: normalize -dynamic suffix in extractPluginName for PR OCI resolution (#89)
Plugins with local-path dynamicArtifact (ending in -dynamic) were not resolved to PR OCI images because the metadata map key included the -dynamic suffix while OCI URL lookups did not. extractPluginName now strips the suffix so both paths produce the same key. RHDHBUGS-2987
1 parent 922463d commit 1b813ba

5 files changed

Lines changed: 92 additions & 7 deletions

File tree

docs/changelog.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,13 @@
22

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

5-
## [1.1.31] - Current
5+
## [1.1.32] - Current
6+
7+
### Fixed
8+
9+
- **Normalize `-dynamic` suffix in `extractPluginName`**: Plugins whose metadata `dynamicArtifact` is a local path (ending in `-dynamic`) were not matched during PR OCI resolution or config injection, because the metadata map key included the `-dynamic` suffix while OCI URL lookups did not. `extractPluginName` now strips the `-dynamic` suffix so local paths and OCI refs for the same logical plugin produce the same key. ([RHDHBUGS-2987](https://issues.redhat.com/browse/RHDHBUGS-2987))
10+
11+
## [1.1.31]
612

713
### Fixed
814

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@red-hat-developer-hub/e2e-test-utils",
3-
"version": "1.1.31",
3+
"version": "1.1.32",
44
"description": "Test utilities for RHDH E2E tests",
55
"license": "Apache-2.0",
66
"repository": {

src/utils/plugin-metadata.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,16 +79,18 @@ export function isNightlyJob(): boolean {
7979

8080
/**
8181
* Extracts the plugin name from a package path or OCI reference.
82+
* Strips the `-dynamic` suffix so local paths and OCI refs for the same
83+
* logical plugin produce the same key.
8284
*
8385
* Handles various formats:
84-
* - Local path: ./dynamic-plugins/dist/backstage-community-plugin-tech-radar
86+
* - Local path: ./dynamic-plugins/dist/backstage-community-plugin-tech-radar-dynamic
8587
* - OCI with alias: oci://quay.io/rhdh/plugin@sha256:...!backstage-community-plugin-tech-radar
8688
* - OCI without alias: oci://quay.io/rhdh/backstage-community-plugin-tech-radar:tag
8789
*/
8890
export function extractPluginName(packageRef: string): string {
8991
const ref = packageRef.includes("!") ? packageRef.split("!")[0] : packageRef;
9092
const match = ref.match(/\/([^/:@]+)(?:[:@].*)?$/);
91-
return match?.[1] || packageRef;
93+
return (match?.[1] || packageRef).replace(/-dynamic$/, "");
9294
}
9395

9496
/**
@@ -346,7 +348,7 @@ export function getNormalizedPluginMergeKey(entry: {
346348
if (pkg === undefined || pkg === "") {
347349
return "";
348350
}
349-
return extractPluginName(pkg).replace(/-dynamic$/, "");
351+
return extractPluginName(pkg);
350352
}
351353

352354
async function resolvePluginPackages(

src/utils/tests/plugin-metadata.pr.test.ts

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,83 @@ describe("processPluginsForDeployment — PR mode", () => {
362362
}
363363
});
364364

365+
// ── -dynamic suffix normalization ────────────────────────────────────────
366+
367+
describe("-dynamic suffix normalization", () => {
368+
it("resolves OCI plugin to metadata when dynamicArtifact has -dynamic suffix", async () => {
369+
const metadataDir = await createMetadataFixture([
370+
{
371+
name: "backstage-plugin-catalog-backend-module-github",
372+
packageName: "@backstage/plugin-catalog-backend-module-github",
373+
dynamicArtifact:
374+
"./dynamic-plugins/dist/backstage-plugin-catalog-backend-module-github-dynamic",
375+
appConfigExamples: {
376+
catalog: { providers: { github: { org: "test" } } },
377+
},
378+
},
379+
]);
380+
381+
try {
382+
const config: DynamicPluginsConfig = {
383+
plugins: [
384+
{
385+
package:
386+
"oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-plugin-catalog-backend-module-github:bs_1.45.3__0.11.2",
387+
disabled: false,
388+
},
389+
],
390+
};
391+
392+
const result = await processPluginsForDeployment(config, metadataDir);
393+
394+
assert.ok(
395+
result.plugins![0].pluginConfig,
396+
"metadata config must be injected even when dynamicArtifact has -dynamic suffix but OCI URL does not",
397+
);
398+
assert.deepStrictEqual(
399+
result.plugins![0].pluginConfig,
400+
{ catalog: { providers: { github: { org: "test" } } } },
401+
"injected config must match metadata appConfigExamples",
402+
);
403+
} finally {
404+
await fs.remove(metadataDir);
405+
}
406+
});
407+
408+
it("keeps local -dynamic path unchanged when metadata also has -dynamic", async () => {
409+
const metadataDir = await createMetadataFixture([
410+
{
411+
name: "backstage-plugin-catalog-backend-module-github",
412+
packageName: "@backstage/plugin-catalog-backend-module-github",
413+
dynamicArtifact:
414+
"./dynamic-plugins/dist/backstage-plugin-catalog-backend-module-github-dynamic",
415+
},
416+
]);
417+
418+
try {
419+
const config: DynamicPluginsConfig = {
420+
plugins: [
421+
{
422+
package:
423+
"./dynamic-plugins/dist/backstage-plugin-catalog-backend-module-github-dynamic",
424+
disabled: false,
425+
},
426+
],
427+
};
428+
429+
const result = await processPluginsForDeployment(config, metadataDir);
430+
431+
assert.strictEqual(
432+
result.plugins![0].package,
433+
"./dynamic-plugins/dist/backstage-plugin-catalog-backend-module-github-dynamic",
434+
"local path with -dynamic must stay unchanged",
435+
);
436+
} finally {
437+
await fs.remove(metadataDir);
438+
}
439+
});
440+
});
441+
365442
// ── PR vs nightly precedence ────────────────────────────────────────────
366443

367444
describe("PR vs nightly precedence", () => {

src/utils/tests/plugin-metadata.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,12 @@ describe("extractPluginName", () => {
4343
);
4444
});
4545

46-
it("extracts name from local path", () => {
46+
it("extracts name from local path and strips -dynamic suffix", () => {
4747
assert.strictEqual(
4848
extractPluginName(
4949
"./dynamic-plugins/dist/backstage-community-plugin-keycloak-dynamic",
5050
),
51-
"backstage-community-plugin-keycloak-dynamic",
51+
"backstage-community-plugin-keycloak",
5252
);
5353
});
5454

0 commit comments

Comments
 (0)