Skip to content

boost: Implement VersionListCard with multi-version list and navigation #4028

Description

@rohitkrai03

Problem

Context: RHIDP-15167 (Entity Page Extensions), task 3.3

The VersionListCard entity card extension (plugins/boost/src/components/catalog/entity/VersionListCard.tsx) currently reads a single rhdh.io/ai-asset-version annotation and renders it as a badge with a "current" label. The entity-extensions spec requires it to list all versions of the same asset, highlight the current/recommended version, and let developers navigate between them.

AI assets in the catalog can have multiple version entities sharing the same logical asset identifier (e.g. code-review-skill at versions 1.0.0, 1.1.0, 1.2.0). The version list card should let developers see what versions exist and jump between them.

Expected behavior

The VersionListCard renders a list of all versions for the current AI asset, with navigation:

  1. Query versions — use the Backstage catalogApiRef to find all entities that share the same rhdh.io/ai-asset-name annotation (or metadata.name base name) and have different rhdh.io/ai-asset-version values. This identifies sibling version entities.
  2. Render list — show each version as a row with:
    • Version string (from rhdh.io/ai-asset-version annotation)
    • A "current" badge on the version matching the currently viewed entity
    • A "recommended" badge if the entity has a rhdh.io/ai-asset-recommended annotation set to true
  3. Navigation — clicking a non-current version row navigates to that version's catalog entity page using entityHref() from utils/entityHelpers.ts.
  4. Single version — if only one version exists (or no sibling entities found), show just the current version badge with no navigation affordance (same as current behavior).
  5. No version — if the entity lacks rhdh.io/ai-asset-version, return null.

Scope

  • Workspace: workspaces/boost
  • Package: @red-hat-developer-hub/backstage-plugin-boost (plugins/boost)

Files to modify

File Change
plugins/boost/src/components/catalog/entity/VersionListCard.tsx Replace single-badge rendering with a version list. Use useApi(catalogApiRef) to query sibling versions. Render each version as a clickable row (except current). Add "current" and "recommended" badges. Handle loading state while fetching siblings.
plugins/boost/src/translations/ref.ts Add i18n keys: catalog.card.versionRecommended, catalog.card.versionNavigate (aria label for version link).
fixtures/ai-catalog-fixtures.yaml Add a second version entity for one existing asset (e.g. code-review-skill at version 1.0.0 alongside the existing 1.2.0) so the multi-version behavior is exercisable in the dev app.

New file

File Content
plugins/boost/src/components/catalog/entity/VersionListCard.test.tsx Unit tests (see below).

Implementation details

Querying sibling versions

Use catalogApiRef.getEntities() with a filter on annotations:

const catalogApi = useApi(catalogApiRef);

const siblings = await catalogApi.getEntities({
  filter: {
    'metadata.annotations.rhdh.io/ai-asset-name': assetName,
  },
});

Where assetName is derived from the current entity's rhdh.io/ai-asset-name annotation or, if that's not set, from metadata.name. Sort the results by version string (semver-aware if possible, falling back to lexicographic).

Wrap this in a useEffect + useState pattern (or useAsync from react-use if available in the workspace) to handle loading state.

Rendering

  • Use BUI Card / CardHeader / CardBody structure (same as current).
  • Each version row: Flex align="center" gap="2" containing the version string, optional badges, and a navigation icon for non-current versions.
  • Current version: Badge size="small" with the "current" label.
  • Recommended version: Badge size="small" variant="success" or similar distinguishing style.
  • Non-current version rows: wrap in a clickable element (BUI Link or Button variant="link") pointing to entityHref(siblingEntity).
  • Loading: show a Skeleton or spinner while sibling query is in flight.
  • All text labels via useTranslation().

Fixture entities

Add a second version of code-review-skill to fixtures/ai-catalog-fixtures.yaml:

apiVersion: backstage.io/v1alpha1
kind: AiResource
metadata:
  name: code-review-skill-v1
  namespace: default
  description: Automated code review skill (legacy version)
  annotations:
    rhdh.io/ai-asset-category: skill
    rhdh.io/ai-asset-version: '1.0.0'
    rhdh.io/ai-asset-name: code-review-skill
    rhdh.io/ai-asset-source: github
spec:
  type: skill
  lifecycle: production
  owner: team-ai-platform
  location:
    type: git
    target: https://github.com/example/code-review-skill

Also add a rhdh.io/ai-asset-name: code-review-skill annotation to the existing code-review-skill entity if not already present.

Tests

Add VersionListCard.test.tsx following the AdoptionCard.test.tsx pattern.

  1. Single version — entity with one version renders the version badge and "current" label, no navigation links.
  2. Multiple versions — mock catalogApiRef.getEntities to return 3 sibling entities. Verify all versions render, current is marked, non-current have navigation links.
  3. Recommended badge — sibling with rhdh.io/ai-asset-recommended: 'true' shows the recommended badge.
  4. No version annotation — entity without rhdh.io/ai-asset-version returns null.
  5. Loading state — verify a loading indicator renders while the catalog query is in flight.
  6. Navigation link — clicking a non-current version triggers navigation to that entity's catalog page.

Notes

  • useApi and catalogApiRef are imported from @backstage/plugin-catalog-react. The catalogApiRef may need to be added to the plugin's dependencies if not already present.
  • The entityHref() helper already exists in utils/entityHelpers.ts and produces /catalog/:namespace/:kind/:name.
  • This card is registered as entity-card:boost/version-list in plugin.tsx with the isAiAsset filter. No registration changes needed.
  • If rhdh.io/ai-asset-name is not consistently set across fixture entities, fall back to metadata.name for sibling discovery. Document the annotation requirement.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions