Skip to content

feat(extensions): add source metadata to entities#3944

Open
christoph-jerolimov wants to merge 12 commits into
redhat-developer:mainfrom
christoph-jerolimov:add-source-metadata
Open

feat(extensions): add source metadata to entities#3944
christoph-jerolimov wants to merge 12 commits into
redhat-developer:mainfrom
christoph-jerolimov:add-source-metadata

Conversation

@christoph-jerolimov

Copy link
Copy Markdown
Member

This is a copy of #3711 where GitHub didn't updated the PR and now didn't let me reopen it because I force pushed the last 4 commits into your @hopehadfield branch. Normally this works fine. So here is a follow-up. You're work lgtm, Hope. -- I changes some configurations and moved the plugins yamls so that they are picked up now in the included Backstage app by the catalog-extensions-module.

From the origin PR:

Hey, I just made a Pull Request!

Resolves RHIDP-13665 / Epic RHIDP-13606

Problem

When RHDH is configured with multiple catalog index images (CATALOG_INDEX_IMAGE + EXTRA_CATALOG_INDEX_IMAGES), the install-dynamic-plugins init container extracts entities from each image into separate directories. However, once BaseEntityProvider ingests them into the Backstage catalog, all source information is lost with the current implementation.

Solution

Add an extensions.backstage.io/catalog-source annotation that is automatically derived from the on-disk directory layout and set on every entity emitted by BaseEntityProvider.

The derivation logic:

  • Entities from extra/<name>/catalog-entities/… get catalog-source: "<name>" (matching the name from EXTRA_CATALOG_INDEX_IMAGES)
  • All other entities get catalog-source: "primary"

Changes

File Change
extensions-common/src/annotations.ts Add CATALOG_SOURCE to ExtensionsAnnotation enum
catalog-backend-module-extensions/src/providers/BaseEntityProvider.ts Add deriveCatalogSource() static method; update addProviderAnnotations() to set the annotation using the entity's file path
catalog-backend-module-extensions/src/providers/BaseEntityProvider.test.ts 12 new tests: source derivation (7) + annotation integration (5)
docs/catalog/plugins.md Document the new annotation
catalog-backend-module-extensions/README.md Document multi-source catalog layout and source derivation

How to test

Unit tests:

cd workspaces/extensions/plugins/catalog-backend-module-extensions
yarn backstage-cli package test --watchAll=false

Local dev (manual):

  1. Create a multi-source directory:
    test-extensions/
      catalog-entities/plugins/primary-plugin.yaml
      extra/community/catalog-entities/plugins/community-plugin.yaml
    
  2. Set extensions.directory in app-config.yaml to point at it
  3. Start the backend and inspect the relevant plugin entities

Design decisions

  • "primary" as default. Vendor-neutral. The UI/config layer can map it to a display label as desired.
  • Freeform string values. Not an enforced enum — operators choose source names via EXTRA_CATALOG_INDEX_IMAGES (community=quay.io/...).
  • Applies to all entity kinds. Implemented in BaseEntityProvider, so Plugins, Packages, and Collections all get the annotation.
  • No change to duplicate handling. Existing first-wins dedup policy is unchanged; source annotations don't affect it.

✔️ Checklist

  • A changeset describing the change and affected packages. (more info)
  • Added or Updated documentation
  • Tests for new functionality and regression tests for bug fixes
  • Screenshots attached (for UI changes)

hopehadfield and others added 11 commits July 23, 2026 10:32
Signed-off-by: Hope Hadfield <hhadfiel@redhat.com>
Signed-off-by: Hope Hadfield <hhadfiel@redhat.com>
Signed-off-by: Hope Hadfield <hhadfiel@redhat.com>
Signed-off-by: Hope Hadfield <hhadfiel@redhat.com>
Signed-off-by: Hope Hadfield <hhadfiel@redhat.com>
Signed-off-by: Hope Hadfield <hhadfiel@redhat.com>
…ing extensions

Signed-off-by: Christoph Jerolimov <jerolimov+git@redhat.com>
Signed-off-by: Christoph Jerolimov <jerolimov+git@redhat.com>
Signed-off-by: Christoph Jerolimov <jerolimov+git@redhat.com>
…w catalog-source annotation gots automatically added

Signed-off-by: Christoph Jerolimov <jerolimov+git@redhat.com>
…in playwright on that message

Signed-off-by: Christoph Jerolimov <jerolimov+git@redhat.com>
@rhdh-gh-app

rhdh-gh-app Bot commented Jul 23, 2026

Copy link
Copy Markdown

Important

This PR includes changes that affect public-facing API. Please ensure you are adding/updating documentation for new features or behavior.

Changed Packages

Package Name Package Path Changeset Bump Current Version
@red-hat-developer-hub/backstage-plugin-catalog-backend-module-extensions workspaces/extensions/plugins/catalog-backend-module-extensions minor v0.19.0
@red-hat-developer-hub/backstage-plugin-extensions-common workspaces/extensions/plugins/extensions-common minor v0.19.0

@rhdh-qodo-merge

Copy link
Copy Markdown

PR Summary by Qodo

Add derived catalog-source annotation to extension entities

✨ Enhancement 🧪 Tests 📝 Documentation ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Derive and apply extensions.backstage.io/catalog-source to all extension entities from file
 layout.
• Add unit coverage and docs for multi-source catalog indexing behavior.
• Update local/e2e config and examples to load via the catalog extensions module.
Diagram

graph TD
  A{{"install-dynamic-plugins"}} --> B[/"extensions/ (YAML)"/] --> C["BaseEntityProvider"] --> D["deriveCatalogSource"] --> E["catalog-source annotation"] --> F[("Backstage catalog")] --> G["Extensions UI"]

  subgraph Legend
    direction LR
    _ext{{"External"}} ~~~ _fs[/"Files"/] ~~~ _svc["Service/Module"] ~~~ _db[("Catalog store")]
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Encode source in provider name/locationKey only
  • ➕ No new annotation surface area
  • ➕ Source would be visible in catalog location metadata
  • ➖ Harder for UI/consumers to query reliably across providers
  • ➖ Couples source identity to provider implementation details rather than entity metadata
2. Allow explicit per-entity source in YAML
  • ➕ Full author control; can override edge cases
  • ➖ Easy to drift/lie vs actual on-disk origin
  • ➖ Adds authoring burden and validation requirements; undermines “derived from layout” guarantee

Recommendation: Current approach (derive from on-disk layout and always stamp an annotation) is the most robust for multi-image ingestion: it’s automatic, consistent, and easy for downstream consumers to query. Provider/location-only encoding was considered but would make UI attribution more brittle; manual YAML configuration was dismissed due to drift risk and extra complexity.

Files changed (45) +344 / -37 · 31 not counted

Enhancement (2) +46 / -5
BaseEntityProvider.tsDerive and stamp catalog-source annotation during entity ingestion +45/-5

Derive and stamp catalog-source annotation during entity ingestion

• Introduces 'deriveCatalogSource()' and a 'DEFAULT_CATALOG_SOURCE' constant, updates entity annotation logic to include 'extensions.backstage.io/catalog-source' based on the entity file path, and threads 'extensionsRoot' through 'getEntities'. Adds an info log reporting how many entities were applied.

workspaces/extensions/plugins/catalog-backend-module-extensions/src/providers/BaseEntityProvider.ts

annotations.tsAdd CATALOG_SOURCE to ExtensionsAnnotation enum +1/-0

Add CATALOG_SOURCE to ExtensionsAnnotation enum

• Adds 'extensions.backstage.io/catalog-source' as a first-class constant for shared use across providers, tests, and consumers.

workspaces/extensions/plugins/extensions-common/src/annotations.ts

Tests (2) +197 / -1
playwright.config.tsWait for provider import log before starting e2e tests +5/-1

Wait for provider import log before starting e2e tests

• Updates Playwright webServer configuration to wait for a specific stdout log indicating entities were applied to the catalog (and implicitly that plugins were loaded).

workspaces/extensions/playwright.config.ts

BaseEntityProvider.test.tsAdd tests for catalog source derivation and annotation stamping +192/-0

Add tests for catalog source derivation and annotation stamping

• Adds focused unit tests for 'deriveCatalogSource' across primary and extra source paths and integration tests asserting 'CATALOG_SOURCE' is applied and preserved under collision policy.

workspaces/extensions/plugins/catalog-backend-module-extensions/src/providers/BaseEntityProvider.test.ts

Documentation (2) +42 / -0
plugins.mdDocument catalog-source annotation semantics +15/-0

Document catalog-source annotation semantics

• Adds documentation for 'extensions.backstage.io/catalog-source', including how values are derived from 'catalog-entities/' vs 'extra/<name>/catalog-entities/' and guidance to not set it manually.

workspaces/extensions/docs/catalog/plugins.md

README.mdDocument multi-source directory layout and source derivation +27/-0

Document multi-source directory layout and source derivation

• Adds documentation describing the 'extra/<name>/catalog-entities' layout and the automatic derivation of the 'catalog-source' annotation for downstream attribution.

workspaces/extensions/plugins/catalog-backend-module-extensions/README.md

Other (39) +59 / -31
khaki-points-mate.mdAdd changeset for minor version bumps +6/-0

Add changeset for minor version bumps

• Introduces a changeset to publish minor updates for the extensions catalog backend module and extensions-common due to the new catalog-source annotation behavior.

workspaces/extensions/.changeset/khaki-points-mate.md

app-config.yamlHarden local auth and update catalog/extensions example wiring +16/-28

Harden local auth and update catalog/extensions example wiring

• Removes insecure auth-related flags, reformats catalog location allow-list, and updates locations to load a new org definition. Also enables loading example YAMLs via 'extensions.directory' so entities pass through the extensions catalog module/provider path.

workspaces/extensions/app-config.yaml

3scale.yamlRelocate community plugin example into extra/community source tree not counted

Relocate community plugin example into extra/community source tree

• Moves/places a community plugin entity example under the multi-source 'extra/community' layout so it is ingested with an appropriate derived catalog-source.

workspaces/extensions/examples/extra/community/3scale.yaml

acr.yamlRelocate community plugin example into extra/community source tree not counted

Relocate community plugin example into extra/community source tree

• Moves/places a community plugin entity example under the multi-source 'extra/community' layout so it is ingested with an appropriate derived catalog-source.

workspaces/extensions/examples/extra/community/acr.yaml

backstage-community-plugin-3scale-backend.yamlRelocate community package example into extra/community source tree not counted

Relocate community package example into extra/community source tree

• Moves/places a community package entity example under the multi-source 'extra/community' layout for catalog-source attribution.

workspaces/extensions/examples/extra/community/backstage-community-plugin-3scale-backend.yaml

backstage-community-plugin-acr.yamlRelocate community package example into extra/community source tree not counted

Relocate community package example into extra/community source tree

• Moves/places a community package entity example under the multi-source 'extra/community' layout for catalog-source attribution.

workspaces/extensions/examples/extra/community/backstage-community-plugin-acr.yaml

backstage-community-plugin-catalog-backend-module-keycloak.yamlRelocate community package example into extra/community source tree not counted

Relocate community package example into extra/community source tree

• Moves/places a community package entity example under the multi-source 'extra/community' layout for catalog-source attribution.

workspaces/extensions/examples/extra/community/backstage-community-plugin-catalog-backend-module-keycloak.yaml

backstage-community-plugin-quay.yamlRelocate community package example into extra/community source tree not counted

Relocate community package example into extra/community source tree

• Moves/places a community package entity example under the multi-source 'extra/community' layout for catalog-source attribution.

workspaces/extensions/examples/extra/community/backstage-community-plugin-quay.yaml

backstage-community-plugin-tekton.yamlRelocate community package example into extra/community source tree not counted

Relocate community package example into extra/community source tree

• Moves/places a community package entity example under the multi-source 'extra/community' layout for catalog-source attribution.

workspaces/extensions/examples/extra/community/backstage-community-plugin-tekton.yaml

backstage-community-plugin-topology.yamlRelocate community package example into extra/community source tree not counted

Relocate community package example into extra/community source tree

• Moves/places a community package entity example under the multi-source 'extra/community' layout for catalog-source attribution.

workspaces/extensions/examples/extra/community/backstage-community-plugin-topology.yaml

keycloak.yamlRelocate community plugin example into extra/community source tree not counted

Relocate community plugin example into extra/community source tree

• Moves/places a community plugin entity example under the multi-source 'extra/community' layout so it is ingested with an appropriate derived catalog-source.

workspaces/extensions/examples/extra/community/keycloak.yaml

quay.yamlRelocate community plugin example into extra/community source tree not counted

Relocate community plugin example into extra/community source tree

• Moves/places a community plugin entity example under the multi-source 'extra/community' layout so it is ingested with an appropriate derived catalog-source.

workspaces/extensions/examples/extra/community/quay.yaml

tekton.yamlRelocate community plugin example into extra/community source tree not counted

Relocate community plugin example into extra/community source tree

• Moves/places a community plugin entity example under the multi-source 'extra/community' layout so it is ingested with an appropriate derived catalog-source.

workspaces/extensions/examples/extra/community/tekton.yaml

topology.yamlRelocate community plugin example into extra/community source tree not counted

Relocate community plugin example into extra/community source tree

• Moves/places a community plugin entity example under the multi-source 'extra/community' layout so it is ingested with an appropriate derived catalog-source.

workspaces/extensions/examples/extra/community/topology.yaml

bulk-import.yamlRelocate Red Hat plugin example into extra/redhat source tree not counted

Relocate Red Hat plugin example into extra/redhat source tree

• Moves/places a Red Hat plugin entity example under the multi-source 'extra/redhat' layout so it is ingested with an appropriate derived catalog-source.

workspaces/extensions/examples/extra/redhat/bulk-import.yaml

extensions.yamlRelocate Red Hat plugin example into extra/redhat source tree not counted

Relocate Red Hat plugin example into extra/redhat source tree

• Moves/places a Red Hat plugin entity example under the multi-source 'extra/redhat' layout so it is ingested with an appropriate derived catalog-source.

workspaces/extensions/examples/extra/redhat/extensions.yaml

red-hat-developer-hub-backstage-plugin-bulk-import-backend.yamlRelocate Red Hat package example into extra/redhat source tree not counted

Relocate Red Hat package example into extra/redhat source tree

• Moves/places a Red Hat package entity example under the multi-source 'extra/redhat' layout for catalog-source attribution.

workspaces/extensions/examples/extra/redhat/red-hat-developer-hub-backstage-plugin-bulk-import-backend.yaml

red-hat-developer-hub-backstage-plugin-bulk-import.yamlRelocate Red Hat package example into extra/redhat source tree not counted

Relocate Red Hat package example into extra/redhat source tree

• Moves/places a Red Hat package entity example under the multi-source 'extra/redhat' layout for catalog-source attribution.

workspaces/extensions/examples/extra/redhat/red-hat-developer-hub-backstage-plugin-bulk-import.yaml

red-hat-developer-hub-backstage-plugin-extensions-backend.yamlRelocate Red Hat package example into extra/redhat source tree not counted

Relocate Red Hat package example into extra/redhat source tree

• Moves/places a Red Hat package entity example under the multi-source 'extra/redhat' layout for catalog-source attribution.

workspaces/extensions/examples/extra/redhat/red-hat-developer-hub-backstage-plugin-extensions-backend.yaml

red-hat-developer-hub-backstage-plugin-extensions.yamlRelocate Red Hat package example into extra/redhat source tree not counted

Relocate Red Hat package example into extra/redhat source tree

• Moves/places a Red Hat package entity example under the multi-source 'extra/redhat' layout for catalog-source attribution.

workspaces/extensions/examples/extra/redhat/red-hat-developer-hub-backstage-plugin-extensions.yaml

org.yamlAdd guest user/group org entities for local catalog +28/-0

Add guest user/group org entities for local catalog

• Adds a simple org definition containing a guest user and groups used by local configuration and permission examples.

workspaces/extensions/examples/org.yaml

no-icon-no-description.yamlKeep other-tests plugin example YAML under extensions directory not counted

Keep other-tests plugin example YAML under extensions directory

• Retains/positions additional test plugin YAML examples under the extensions directory so they are ingested through the extensions catalog provider path.

workspaces/extensions/examples/other-tests/no-icon-no-description.yaml

pre-installed-false.yamlKeep other-tests plugin example YAML under extensions directory not counted

Keep other-tests plugin example YAML under extensions directory

• Retains/positions additional test plugin YAML examples under the extensions directory so they are ingested through the extensions catalog provider path.

workspaces/extensions/examples/other-tests/pre-installed-false.yaml

pre-installed-true.yamlKeep other-tests plugin example YAML under extensions directory not counted

Keep other-tests plugin example YAML under extensions directory

• Retains/positions additional test plugin YAML examples under the extensions directory so they are ingested through the extensions catalog provider path.

workspaces/extensions/examples/other-tests/pre-installed-true.yaml

pre-installed-undefined.yamlKeep other-tests plugin example YAML under extensions directory not counted

Keep other-tests plugin example YAML under extensions directory

• Retains/positions additional test plugin YAML examples under the extensions directory so they are ingested through the extensions catalog provider path.

workspaces/extensions/examples/other-tests/pre-installed-undefined.yaml

search.yamlKeep other-tests plugin example YAML under extensions directory not counted

Keep other-tests plugin example YAML under extensions directory

• Retains/positions additional test plugin YAML examples under the extensions directory so they are ingested through the extensions catalog provider path.

workspaces/extensions/examples/other-tests/search.yaml

support-community.yamlKeep other-tests plugin example YAML under extensions directory not counted

Keep other-tests plugin example YAML under extensions directory

• Retains/positions additional test plugin YAML examples under the extensions directory so they are ingested through the extensions catalog provider path.

workspaces/extensions/examples/other-tests/support-community.yaml

support-dev-preview.yamlKeep other-tests plugin example YAML under extensions directory not counted

Keep other-tests plugin example YAML under extensions directory

• Retains/positions additional test plugin YAML examples under the extensions directory so they are ingested through the extensions catalog provider path.

workspaces/extensions/examples/other-tests/support-dev-preview.yaml

support-generally-available.yamlKeep other-tests plugin example YAML under extensions directory not counted

Keep other-tests plugin example YAML under extensions directory

• Retains/positions additional test plugin YAML examples under the extensions directory so they are ingested through the extensions catalog provider path.

workspaces/extensions/examples/other-tests/support-generally-available.yaml

support-none.yamlKeep other-tests plugin example YAML under extensions directory not counted

Keep other-tests plugin example YAML under extensions directory

• Retains/positions additional test plugin YAML examples under the extensions directory so they are ingested through the extensions catalog provider path.

workspaces/extensions/examples/other-tests/support-none.yaml

support-string.yamlKeep other-tests plugin example YAML under extensions directory not counted

Keep other-tests plugin example YAML under extensions directory

• Retains/positions additional test plugin YAML examples under the extensions directory so they are ingested through the extensions catalog provider path.

workspaces/extensions/examples/other-tests/support-string.yaml

support-tech-preview.yamlKeep other-tests plugin example YAML under extensions directory not counted

Keep other-tests plugin example YAML under extensions directory

• Retains/positions additional test plugin YAML examples under the extensions directory so they are ingested through the extensions catalog provider path.

workspaces/extensions/examples/other-tests/support-tech-preview.yaml

support-undefined.yamlKeep other-tests plugin example YAML under extensions directory not counted

Keep other-tests plugin example YAML under extensions directory

• Retains/positions additional test plugin YAML examples under the extensions directory so they are ingested through the extensions catalog provider path.

workspaces/extensions/examples/other-tests/support-undefined.yaml

support-unknown-level.yamlKeep other-tests plugin example YAML under extensions directory not counted

Keep other-tests plugin example YAML under extensions directory

• Retains/positions additional test plugin YAML examples under the extensions directory so they are ingested through the extensions catalog provider path.

workspaces/extensions/examples/other-tests/support-unknown-level.yaml

package.jsonAdd @backstage/cli-defaults devDependency +1/-0

Add @backstage/cli-defaults devDependency

• Adds '@backstage/cli-defaults' to remove warnings/ensure default CLI config when running extension workspace tests and tooling.

workspaces/extensions/package.json

report.api.mdUpdate API report for new BaseEntityProvider surface +3/-1

Update API report for new BaseEntityProvider surface

• Updates the generated API report to include the new 'DEFAULT_CATALOG_SOURCE', 'deriveCatalogSource', and updated 'getEntities' signature.

workspaces/extensions/plugins/catalog-backend-module-extensions/report.api.md

module.tsAdjust scheduled task frequency for extensions catalog module +2/-2

Adjust scheduled task frequency for extensions catalog module

• Changes provider/processor scheduled task runners from every 30 minutes to hourly execution.

workspaces/extensions/plugins/catalog-backend-module-extensions/src/module.ts

report.api.mdUpdate API report for new ExtensionsAnnotation member +2/-0

Update API report for new ExtensionsAnnotation member

• Updates the generated API report to include the new 'ExtensionsAnnotation.CATALOG_SOURCE' enum value.

workspaces/extensions/plugins/extensions-common/report.api.md

yarn.lockLockfile update for added cli-defaults dependency +1/-0

Lockfile update for added cli-defaults dependency

• Updates the workspace lockfile to include '@backstage/cli-defaults' resolution and dependency metadata.

workspaces/extensions/yarn.lock

@codecov

codecov Bot commented Jul 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 86.66667% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 57.35%. Comparing base (70f61da) to head (45748ce).
⚠️ Report is 3 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #3944   +/-   ##
=======================================
  Coverage   57.35%   57.35%           
=======================================
  Files        2384     2384           
  Lines       95608    95617    +9     
  Branches    26699    26708    +9     
=======================================
+ Hits        54832    54841    +9     
  Misses      39238    39238           
  Partials     1538     1538           
Flag Coverage Δ *Carryforward flag
adoption-insights 84.54% <ø> (ø) Carriedforward from 49a903a
ai-integrations 69.26% <ø> (ø) Carriedforward from 49a903a
app-defaults 69.79% <ø> (ø) Carriedforward from 49a903a
augment 46.67% <ø> (ø) Carriedforward from 49a903a
boost 75.89% <ø> (ø) Carriedforward from 49a903a
bulk-import 72.61% <ø> (ø) Carriedforward from 49a903a
cost-management 13.55% <ø> (ø) Carriedforward from 49a903a
dcm 60.72% <ø> (ø) Carriedforward from 49a903a
extensions 56.38% <86.66%> (+0.10%) ⬆️
global-floating-action-button 71.18% <ø> (ø) Carriedforward from 49a903a
global-header 62.19% <ø> (ø) Carriedforward from 49a903a
homepage 47.58% <ø> (ø) Carriedforward from 49a903a
install-dynamic-plugins 56.77% <ø> (ø) Carriedforward from 49a903a
intelligent-assistant 74.05% <ø> (ø) Carriedforward from 49a903a
konflux 91.98% <ø> (ø) Carriedforward from 49a903a
lightspeed 69.02% <ø> (ø) Carriedforward from 49a903a
mcp-integrations 83.40% <ø> (ø) Carriedforward from 49a903a
orchestrator 62.67% <ø> (ø) Carriedforward from 49a903a
quickstart 65.18% <ø> (ø) Carriedforward from 49a903a
sandbox 79.56% <ø> (ø) Carriedforward from 49a903a
scorecard 82.66% <ø> (ø) Carriedforward from 49a903a
theme 83.85% <ø> (ø) Carriedforward from 49a903a
translations 5.12% <ø> (ø) Carriedforward from 49a903a
x2a 79.31% <ø> (ø) Carriedforward from 49a903a

*This pull request uses carry forward flags. Click here to find out more.


Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 70f61da...45748ce. Read the comment docs.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@rhdh-qodo-merge

rhdh-qodo-merge Bot commented Jul 23, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (1) 🔗 Cross-repo conflicts (2) 📜 Skill insights (0)

Context used
⚠️ Tickets: not configured — ticket URL found in PR but could not be fetched — check ticket provider credentials
✅ Compliance rules (platform): 11 rules
✅ Cross-repo context
  Explored: repo: redhat-developer/rhdh (sha: d090bd1a)
  Explored: repo: redhat-developer/rhdh-operator (sha: cde4968e)
  Explored: repo: redhat-developer/rhdh-local (sha: 2ae9e8c8)
  Not relevant to this PR: redhat-developer/rhdh-chart

Grey Divider


Action required

1. webServer missing backend url 📘 Rule violation ≡ Correctness
Description
The updated Playwright webServer entry in workspaces/extensions/playwright.config.ts no longer
declares a supported readiness target (url or port) for the backend and instead introduces a
non-standard wait.stdout, so Playwright may not actually wait for the correct service to be ready.
This can cause flaky or failing e2e runs by starting tests too early or validating the wrong
endpoint even though baseURL still points to http://localhost:3000.
Code

workspaces/extensions/playwright.config.ts[R37-47]

    : [
        {
          command: startCommand,
-          port: 3000,
          reuseExistingServer: false,
          cwd: __dirname,
+          wait: {
+            // wait for this message and expect 10+ loaded plugins.
+            stdout:
+              /extensions-plugin-provider applied [1-9]\d+ entities to the catalog/,
+          },
        },
Relevance

⭐⭐⭐ High

E2E readiness flakiness risk; Playwright config reliability fixes are typically accepted.

PR-#3249

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Compliance ID 2672 requires the Playwright project baseURL to point to the frontend port while the
webServer readiness check (url or backend port) targets the backend port (typically 7007).
In the Extensions workspace config, the modified webServer section includes neither a url nor a
port and instead uses wait.stdout, while baseURL remains http://localhost:3000; compared to
other workspaces in the repo that use Playwright’s supported port/url readiness options and do
not use a nested wait object, this inconsistency indicates the backend-port readiness requirement
is not being met and the readiness gating may be ignored or ineffective.

Rule 2672: Playwright project baseURL must be the frontend port, webServer readiness URL must be the backend port
workspaces/extensions/playwright.config.ts[35-47]
workspaces/extensions/playwright.config.ts[35-63]
workspaces/homepage/playwright.config.ts[39-60]
workspaces/bulk-import/playwright.config.ts[38-48]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Restore a supported Playwright `webServer` readiness mechanism so e2e runs reliably wait for the correct service to be ready, and ensure the readiness check targets the backend port as required (rather than relying on a non-standard `wait: { stdout: ... }` nesting).

## Issue Context
- The Extensions workspace Playwright config currently has `baseURL` set to the frontend (`http://localhost:3000`), which is correct.
- Compliance ID 2672 requires that the `webServer` readiness check (`url` or backend `port`) targets the backend port (typically `7007`).
- The current `webServer` entry no longer specifies `port` or `url` and instead introduces `wait.stdout`, which is not the standard config shape used elsewhere in this repo and is likely ignored or rejected.
- Other workspaces in this repo use Playwright’s supported readiness options (`port` or `url`) and do not use a nested `wait` object.
- If log-based waiting is still desired, use Playwright’s supported top-level `stdout` option on the `webServer` entry (not nested under `wait`) and consider loosening the regex so it doesn’t depend on `>= 10` entities.

## Fix Focus Areas
- workspaces/extensions/playwright.config.ts[35-63]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

2. Provider refresh interval changed 🔗 Cross-repo conflict ☼ Reliability
Description
This PR changes the default scheduled refresh frequency for the Extensions catalog providers from 30
minutes to 1 hour; since redhat-developer/rhdh consumes this module via its dynamic wrapper,
upgrading to the new version will increase the time it takes for newly extracted catalog entities
under /extensions to appear in RHDH.
Code

workspaces/extensions/plugins/catalog-backend-module-extensions/src/module.ts[R63-70]

        const taskRunner = scheduler.createScheduledTaskRunner({
-          frequency: { minutes: 30 },
+          frequency: { hours: 1 },
          timeout: { minutes: 10 },
        });
        const delayedTaskRunner = scheduler.createScheduledTaskRunner({
-          frequency: { minutes: 30 },
+          frequency: { hours: 1 },
          timeout: { minutes: 10 },
          initialDelay: { seconds: 20 },
Relevance

⭐⭐ Medium

Behavioral default change; no clear precedent whether team prefers 30m vs 1h refresh cadence.

PR-#2897

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The PR changes the scheduler frequency in the module; RHDH’s wrapper re-exports this module, so the
behavior change applies once RHDH updates to the new module version.

workspaces/extensions/plugins/catalog-backend-module-extensions/src/module.ts[62-71]
External repo: redhat-developer/rhdh, dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-catalog-backend-module-extensions-dynamic/src/index.ts [1]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The Extensions catalog providers’ scheduled refresh interval changed from 30 minutes to 1 hour, which impacts RHDH deployments after upgrading.

## Issue Context
RHDH embeds/exports this module via a dynamic wrapper package.

## Fix Focus Areas
- workspaces/extensions/plugins/catalog-backend-module-extensions/src/module.ts[start_line-end_line]
- /cross_repos/rhdh/dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-catalog-backend-module-extensions-dynamic/src/index.ts[start_line-end_line]

Consider making the interval configurable or updating downstream docs/release notes to set expectations.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. RHDH not consuming new annotation 🔗 Cross-repo conflict ☼ Reliability
Description
This PR adds an always-set extensions.backstage.io/catalog-source annotation and bumps the
involved packages, but redhat-developer/rhdh currently pins
@red-hat-developer-hub/backstage-plugin-catalog-backend-module-extensions and
@red-hat-developer-hub/backstage-plugin-extensions-common to 0.18.0 in its dynamic wrapper, so
RHDH won’t get the new behavior until it updates those pins (and rebuilds/re-exports the wrapper
artifact).
Code

workspaces/extensions/plugins/catalog-backend-module-extensions/src/providers/BaseEntityProvider.ts[R82-97]

+  static deriveCatalogSource(filePath: string, extensionsRoot: string): string {
+    const relative = path.relative(extensionsRoot, filePath);
+    const [first, second] = relative.split(path.sep);
+    return first === 'extra' && second
+      ? second
+      : BaseEntityProvider.DEFAULT_CATALOG_SOURCE;
+  }
+
+  private addProviderAnnotations(
+    entity: T,
+    filePath: string,
+    extensionsRoot: string,
+  ): T {
    return {
      ...entity,
      metadata: {
Relevance

⭐ Low

Similar cross-repo “downstream wrapper pins; needs follow-up bump” note was previously rejected as
out-of-scope.

PR-#3896

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR adds/sets the new annotation in BaseEntityProvider and declares a minor bump via changeset;
RHDH’s wrapper is pinned to 0.18.0 so it cannot pick up the new behavior without a coordinated
dependency bump.

workspaces/extensions/plugins/catalog-backend-module-extensions/src/providers/BaseEntityProvider.ts[65-107]
workspaces/extensions/.changeset/khaki-points-mate.md[1-4]
workspaces/extensions/plugins/catalog-backend-module-extensions/package.json[1-6]
External repo: redhat-developer/rhdh, dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-catalog-backend-module-extensions-dynamic/package.json [34-41]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
RHDH is pinned to older versions of the extensions catalog backend module and extensions-common, so it will not receive the new `extensions.backstage.io/catalog-source` annotation behavior until it updates.

## Issue Context
This PR introduces a new annotation emitted by `BaseEntityProvider` and includes a changeset indicating a minor release for the impacted packages.

## Fix Focus Areas
- dynamic-plugins/wrappers/red-hat-developer-hub-backstage-plugin-catalog-backend-module-extensions-dynamic/package.json[start_line-end_line]
- (and if applicable) other rhdh wrapper packages embedding `@red-hat-developer-hub/backstage-plugin-extensions-common`
- Coordinate release: ensure rhdh consumes the new published versions from this PR

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

@rhdh-qodo-merge rhdh-qodo-merge Bot added documentation Improvements or additions to documentation enhancement New feature or request Tests Bug fix labels Jul 23, 2026
…L parse error

Signed-off-by: Hope Hadfield <hhadfiel@redhat.com>
@hopehadfield
hopehadfield force-pushed the add-source-metadata branch from dfca187 to 45748ce Compare July 23, 2026 21:26
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug fix documentation Improvements or additions to documentation enhancement New feature or request Tests workspace/extensions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants