Skip to content

Fix duplicate marketplace categories from case-sensitive displayName matching#7334

Open
pdelagrave wants to merge 1 commit intomainfrom
fix/case-insensitive-category-merge
Open

Fix duplicate marketplace categories from case-sensitive displayName matching#7334
pdelagrave wants to merge 1 commit intomainfrom
fix/case-insensitive-category-merge

Conversation

@pdelagrave
Copy link
Copy Markdown
Contributor

@pdelagrave pdelagrave commented Apr 9, 2026

Problem

Category.merge() and findOrCreateCategory() use case-sensitive equals() to match categories by displayName. When two entries define the same category with different casing, they are treated as distinct categories instead of being merged, resulting in duplicate category entries in the marketplace tree.

How this manifested

In rewrite-java, the recipes.csv is a combination of auto-generated entries and explicit entries from java-categories.yml. Three commits created the issue:

  1. 8fe912f4a -- auto-generated recipes.csv was added, with ClassDefinitionLength and MethodDefinitionLength under category "Ai" (title-cased from the org.openrewrite.java.ai package name)
  2. 4ce95cc5e -- added explicit rows for the same recipes with category "AI" (from java-categories.yml), but did not remove the original "Ai" rows
  3. e2b6e2afd (v8.75.7) -- removed the duplicate "Ai" rows, fixing the CSV

This means rewrite-java v8.75.6 shipped with both "Ai" and "AI" entries for the same recipes. Any marketplace that installed that version retains the stale duplicate data, and the case-sensitive equals() in merge() keeps both categories alive -- showing two "AI" entries in the UI.

Solution

Switch both Category.merge() and findOrCreateCategory() from equals() to equalsIgnoreCase() for displayName comparison. The first-seen casing is preserved as the canonical displayName. This prevents duplicate categories from arising regardless of casing inconsistencies in source data.

Two new tests cover:

  • mergeCategoriesCaseInsensitive: merging two marketplaces where one uses "AI" and the other "ai" produces a single category
  • installCategoriesCaseInsensitive: installing recipes from a single CSV with mixed casing produces a single category

…Name matching

Category.merge() and findOrCreateCategory() used equals() to match categories
by displayName, causing "AI" and "ai" to be treated as distinct categories.
This resulted in duplicate category entries on the marketplace page when
different recipe modules used different casing for the same category name
(e.g. rewrite-java uses "AI" while rewrite-ai uses "ai").

Switch both methods to equalsIgnoreCase() so categories with the same name
but different casing are properly merged. The first-seen casing is preserved.
@pdelagrave pdelagrave self-assigned this Apr 9, 2026
@github-project-automation github-project-automation bot moved this to In Progress in OpenRewrite Apr 9, 2026
@pdelagrave pdelagrave marked this pull request as ready for review April 9, 2026 19:08
@pdelagrave pdelagrave marked this pull request as draft April 9, 2026 19:09
@pdelagrave pdelagrave closed this Apr 9, 2026
@github-project-automation github-project-automation bot moved this from In Progress to Done in OpenRewrite Apr 9, 2026
@pdelagrave pdelagrave reopened this Apr 9, 2026
@github-project-automation github-project-automation bot moved this from Done to In Progress in OpenRewrite Apr 9, 2026
@pdelagrave pdelagrave marked this pull request as ready for review April 9, 2026 21:19
@github-project-automation github-project-automation bot moved this from In Progress to Ready to Review in OpenRewrite Apr 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Ready to Review

Development

Successfully merging this pull request may close these issues.

2 participants