Skip to content

feat(releases): replace readiness version dropdown with 3-tier selector - #1521

Open
deekay2310 wants to merge 1 commit into
red-hat-data-services:mainfrom
deekay2310:feat/readiness-multi-select-filter
Open

feat(releases): replace readiness version dropdown with 3-tier selector#1521
deekay2310 wants to merge 1 commit into
red-hat-data-services:mainfrom
deekay2310:feat/readiness-multi-select-filter

Conversation

@deekay2310

@deekay2310 deekay2310 commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Replaces the static single-select version dropdown in the Release Readiness dashboard with the same 3-tier selector modal used by the Capacity Commitment report (family: multi-select, version: single-select, phase: multi-select)
  • Adds phase tabs so users can view multiple milestones (EA1, EA2, GA) side by side
  • Generalizes useReleaseSelector with a fetchReleases option for custom data sources (backward-compatible — existing Capacity Commitment usage unchanged)
  • Adds URL param + localStorage persistence for the selection

Closes RHOAIENG-85414

Changes

File What
useReleaseSelector.js Export parseReleaseId, add fetchReleases option
release-readiness/routes.js Return releases array in /versions response
useReleaseReadiness.js Add fetchMetrics and fetchReadinessReleases
ReleaseReadinessDirector.vue New selector modal, phase tabs, selection watcher

Test plan

  • Open Release Readiness dashboard — "Select Release" button appears instead of dropdown
  • Click "Select Release" — modal shows family/version/phase tiers
  • Select a family, version, and phase — Apply loads readiness data
  • Select multiple phases — tabs appear, switching tabs loads correct phase data
  • Refresh page — selection restored from URL params
  • Verify Capacity Commitment report still works (no regression from useReleaseSelector change)
  • Build passes (npm run build)
  • Lint passes (npm run lint)

🤖 Generated with Claude Code

Overhaul the Release Readiness dashboard version filter to use the same
family/version/phase selector pattern as the Capacity Commitment report.
Families and phases are multi-select (inclusive), version is single-select.
Phase tabs allow viewing multiple milestones (EA1, EA2, GA) side by side.

Generalizes useReleaseSelector with a fetchReleases option so consumers
can provide custom data sources. The readiness dashboard feeds parsed
version filenames through this composable instead of the registry API.

Closes RHOAIENG-85414

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Claude finished @deekay2310's task in 3m 43s —— View job


PR Review: feat(releases): replace readiness version dropdown with 3-tier selector

Read-only review (fork PR) — no autofixes applied.

  • Gather PR diff and review instructions
  • Read changed files for full context
  • Check against project hard constraints (AGENTS.md)
  • Apply review checklist (.github/instructions/review.instructions.md)
  • Post review findings

Issues Found

1. Bug — Double-load on mount (inline comment)
ReleaseReadinessDirector.vue lines 589–595: restoreSelection() mutates reactive selection state, which triggers the watch (lines 637–645) to call loadSelectedPhases(). But onMounted also calls loadSelectedPhases() explicitly on the next line. Both execute concurrently, doubling API calls and causing a second pass that resets selectedComponents/selectedPhases. Fix: remove the explicit call from onMounted and rely on the watcher.

2. Potential correctness issue — Release ID format mismatch (inline comment)
routes.js line 93: Release IDs are raw filenames (minus .json). parseReleaseId() expects the pattern {family}-{version}[.{phase}] (e.g. rhoai-2.20.ea1). If readiness files were uploaded with display-style names (e.g. "RHOAI 2.20 EA1"RHOAI_2.20_EA1), parsing returns null and the 3-tier selector shows nothing. Verify actual filenames match, or add a normalization step.

3. OpenAPI annotation incomplete (inline comment)
The /versions response now includes a releases array, but the @openapi annotation (line 40) still only describes versions and default_version.

4. Manual edit in auto-generated file (inline comment)
platform/view-owners/owners.js is auto-generated — the added team-tracker/reports/allocation entry will be overwritten on next regeneration. Use data/view-owner-overrides.json instead. This change is also unrelated to the PR's feature scope.

⚠️ Missing Integration Test Warning

This PR modifies module views (ReleaseReadinessDirector.vue) and server routes (release-readiness/routes.js) but includes no corresponding integration test updates in tests/integration/releases.spec.js. Per the review policy, please add integration tests that verify:

  • The readiness report loads with the new selector modal
  • The selector modal opens, accepts selections, and loads data
  • Phase tabs render and switch correctly when multiple phases are selected

What looks good

  • Clean reuse of the existing useReleaseSelector composable via the fetchReleases option — backward compatible with Capacity Commitment and Program Hygiene reports
  • Multi-phase data loading with phaseDataMap and tab switching is well-structured
  • URL param + localStorage persistence follows established patterns
  • The parseReleaseId export is a reasonable API surface change

Comment on lines 589 to 595
onMounted(async () => {
await loadVersions()
if (versions.value.length > 0) {
const initial = defaultVersion.value || versions.value[0]
selectedVersion.value = initial
await loadMetrics(initial)
if (data.value && data.value.component_readiness) {
selectedComponents.value = [...(data.value.component_readiness.all_components || [])]
}
await fetchRegistry()
restoreSelection()
if (hasSelection.value) {
await loadSelectedPhases()
}
})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Double-load on mount. restoreSelection() mutates selection, which triggers the watch below (lines 637–645). But the very next line also calls loadSelectedPhases() explicitly. Both run concurrently, doubling API calls and causing a second pass that resets selectedComponents / selectedPhases.

Fix: remove the explicit loadSelectedPhases() from onMounted and let the watcher handle it, or add { flush: 'post' } to the watch and guard with a flag.

Suggested change
onMounted(async () => {
await loadVersions()
if (versions.value.length > 0) {
const initial = defaultVersion.value || versions.value[0]
selectedVersion.value = initial
await loadMetrics(initial)
if (data.value && data.value.component_readiness) {
selectedComponents.value = [...(data.value.component_readiness.all_components || [])]
}
await fetchRegistry()
restoreSelection()
if (hasSelection.value) {
await loadSelectedPhases()
}
})
await fetchRegistry()
restoreSelection()

.map(f => f.replace('.json', ''));

const versions = rawNames.map(n => n.replace(/_/g, ' '));
const releases = rawNames.map(name => ({ id: name, state: 'active' }));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential format mismatch: parseReleaseId() expects IDs matching ^([a-z]+)-(\d+\.\d+)(?:\.(ea\d?))?$ (e.g. rhoai-2.20.ea1). Here, release IDs are raw filenames (minus .json). If files were uploaded with display-style version names (e.g. "RHOAI 2.20 EA1"), sanitizeFilename produces RHOAI_2.20_EA1 — which parseReleaseId can't parse, making the 3-tier selector empty.

Please verify the actual filenames on disk match the {family}-{version}[.{phase}] convention, or add a normalization step here (e.g. lowercase + replace underscores with hyphens).

const defaultVersion = findUpcomingVersion(versions, storage);

res.json({ versions, default_version: defaultVersion });
res.json({ versions, releases, default_version: defaultVersion });

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OpenAPI description out of date. The response now includes a releases array alongside versions and default_version. The @openapi annotation (line 40) should be updated to reflect the new field:

description: Object with versions array, releases array, and default_version

'releases/reports/tv-fv-delta': 'Dimitri Saridakis',

// team-tracker > reports
'team-tracker/reports/allocation': 'Alex Corvin',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Manual edit in auto-generated file. This file's header says "DO NOT EDIT MANUALLY — regenerated by scripts/update-view-owners.js". This entry will be overwritten on the next regeneration. If this is intentional, add the override to data/view-owner-overrides.json instead (which the script merges in).

Also, this change is unrelated to the readiness selector feature — consider splitting it into its own PR.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant