Skip to content
Merged
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
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.31] - Current
## [1.1.32] - Current

### Fixed

- **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))

## [1.1.31]

### Fixed

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.31",
"version": "1.1.32",
"description": "Test utilities for RHDH E2E tests",
"license": "Apache-2.0",
"repository": {
Expand Down
8 changes: 5 additions & 3 deletions src/utils/plugin-metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,16 +79,18 @@ export function isNightlyJob(): boolean {

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

/**
Expand Down Expand Up @@ -346,7 +348,7 @@ export function getNormalizedPluginMergeKey(entry: {
if (pkg === undefined || pkg === "") {
return "";
}
return extractPluginName(pkg).replace(/-dynamic$/, "");
return extractPluginName(pkg);
}

async function resolvePluginPackages(
Expand Down
77 changes: 77 additions & 0 deletions src/utils/tests/plugin-metadata.pr.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

describe("processPluginsForDeployment — PR mode", () => {
const env = withCleanEnv();
beforeEach(() => {

Check warning on line 20 in src/utils/tests/plugin-metadata.pr.test.ts

View workflow job for this annotation

GitHub Actions / Build and Check

Expected blank line before this statement
env.save();
delete process.env.E2E_NIGHTLY_MODE;
delete process.env.JOB_NAME;
Expand Down Expand Up @@ -362,6 +362,83 @@
}
});

// ── -dynamic suffix normalization ────────────────────────────────────────

describe("-dynamic suffix normalization", () => {
it("resolves OCI plugin to metadata when dynamicArtifact has -dynamic suffix", async () => {
const metadataDir = await createMetadataFixture([
{
name: "backstage-plugin-catalog-backend-module-github",
packageName: "@backstage/plugin-catalog-backend-module-github",
dynamicArtifact:
"./dynamic-plugins/dist/backstage-plugin-catalog-backend-module-github-dynamic",
appConfigExamples: {
catalog: { providers: { github: { org: "test" } } },
},
},
]);

try {
const config: DynamicPluginsConfig = {
plugins: [
{
package:
"oci://ghcr.io/redhat-developer/rhdh-plugin-export-overlays/backstage-plugin-catalog-backend-module-github:bs_1.45.3__0.11.2",
disabled: false,
},
],
};

const result = await processPluginsForDeployment(config, metadataDir);

assert.ok(
result.plugins![0].pluginConfig,
"metadata config must be injected even when dynamicArtifact has -dynamic suffix but OCI URL does not",
);
assert.deepStrictEqual(
result.plugins![0].pluginConfig,
{ catalog: { providers: { github: { org: "test" } } } },
"injected config must match metadata appConfigExamples",
);
} finally {
await fs.remove(metadataDir);
}
});

it("keeps local -dynamic path unchanged when metadata also has -dynamic", async () => {
const metadataDir = await createMetadataFixture([
{
name: "backstage-plugin-catalog-backend-module-github",
packageName: "@backstage/plugin-catalog-backend-module-github",
dynamicArtifact:
"./dynamic-plugins/dist/backstage-plugin-catalog-backend-module-github-dynamic",
},
]);

try {
const config: DynamicPluginsConfig = {
plugins: [
{
package:
"./dynamic-plugins/dist/backstage-plugin-catalog-backend-module-github-dynamic",
disabled: false,
},
],
};

const result = await processPluginsForDeployment(config, metadataDir);

assert.strictEqual(
result.plugins![0].package,
"./dynamic-plugins/dist/backstage-plugin-catalog-backend-module-github-dynamic",
"local path with -dynamic must stay unchanged",
);
} finally {
await fs.remove(metadataDir);
}
});
});

// ── PR vs nightly precedence ────────────────────────────────────────────

describe("PR vs nightly precedence", () => {
Expand Down
4 changes: 2 additions & 2 deletions src/utils/tests/plugin-metadata.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ describe("extractPluginName", () => {
);
});

it("extracts name from local path", () => {
it("extracts name from local path and strips -dynamic suffix", () => {
assert.strictEqual(
extractPluginName(
"./dynamic-plugins/dist/backstage-community-plugin-keycloak-dynamic",
),
"backstage-community-plugin-keycloak-dynamic",
"backstage-community-plugin-keycloak",
);
});

Expand Down
Loading