From e38bcefb99933586c9d697afcffc911417bf4696 Mon Sep 17 00:00:00 2001 From: Vincenzo Scamporlino Date: Mon, 30 Mar 2026 23:22:03 +0200 Subject: [PATCH] Fix template name collision between new and legacy frontend plugin templates The legacy frontend plugin template had the same name (`frontend-plugin`) as the new frontend plugin template, causing a conflict error when both were shown (e.g. when the frontend system could not be auto-detected). Rename the legacy template to `frontend-plugin-legacy` so both can coexist. Co-Authored-By: Claude Opus 4.6 (1M context) Signed-off-by: Vincenzo Scamporlino --- .changeset/angry-clouds-tell.md | 2 +- .../loadPortableTemplateConfig.test.ts | 34 +++++++------------ .../preparation/loadPortableTemplateConfig.ts | 2 -- .../portable-template.yaml | 2 +- 4 files changed, 14 insertions(+), 26 deletions(-) diff --git a/.changeset/angry-clouds-tell.md b/.changeset/angry-clouds-tell.md index c2da96699f..a01306d84a 100644 --- a/.changeset/angry-clouds-tell.md +++ b/.changeset/angry-clouds-tell.md @@ -2,4 +2,4 @@ '@backstage/cli-module-new': patch --- -Rename the legacy `frontend-plugin` to `legacy-frontend-plugin` +Rename the legacy `frontend-plugin` to `frontend-plugin-legacy` diff --git a/packages/cli-module-new/src/lib/preparation/loadPortableTemplateConfig.test.ts b/packages/cli-module-new/src/lib/preparation/loadPortableTemplateConfig.test.ts index 454ece648a..5333b05739 100644 --- a/packages/cli-module-new/src/lib/preparation/loadPortableTemplateConfig.test.ts +++ b/packages/cli-module-new/src/lib/preparation/loadPortableTemplateConfig.test.ts @@ -374,14 +374,14 @@ describe('loadPortableTemplateConfig', () => { }, node_modules: Object.fromEntries( defaultTemplates.map(t => { - // Match the real behavior: both frontend-plugin and legacy-frontend-plugin - // have the same template name "frontend-plugin" const name = t.endsWith('/legacy-frontend-plugin') - ? 'frontend-plugin' + ? 'frontend-plugin-legacy' : basename(t); return [ t, - { [TEMPLATE_FILE_NAME]: `name: ${name}\nrole: web-library\n` }, + { + [TEMPLATE_FILE_NAME]: `name: ${name}\nrole: web-library\n`, + }, ]; }), ), @@ -398,14 +398,7 @@ describe('loadPortableTemplateConfig', () => { expect(templateNames).toContain('frontend-plugin-module'); expect(templateNames).toContain('backend-plugin'); // Legacy template should be filtered out - expect(templateNames).not.toContain('legacy-frontend-plugin'); - - // The frontend-plugin in the list should be from the new template, not legacy - const frontendPlugin = config.templatePointers.find( - t => t.name === 'frontend-plugin', - ); - expect(frontendPlugin?.target).toContain('/frontend-plugin/'); - expect(frontendPlugin?.target).not.toContain('/legacy-frontend-plugin/'); + expect(templateNames).not.toContain('frontend-plugin-legacy'); }); it('should filter out new frontend templates for legacy frontend system apps', async () => { @@ -424,11 +417,13 @@ describe('loadPortableTemplateConfig', () => { node_modules: Object.fromEntries( defaultTemplates.map(t => { const name = t.endsWith('/legacy-frontend-plugin') - ? 'frontend-plugin' + ? 'frontend-plugin-legacy' : basename(t); return [ t, - { [TEMPLATE_FILE_NAME]: `name: ${name}\nrole: web-library\n` }, + { + [TEMPLATE_FILE_NAME]: `name: ${name}\nrole: web-library\n`, + }, ]; }), ), @@ -441,17 +436,12 @@ describe('loadPortableTemplateConfig', () => { expect(config.isUsingDefaultTemplates).toBe(true); const templateNames = config.templatePointers.map(t => t.name); - // Legacy template should be present (shown as "frontend-plugin") - expect(templateNames).toContain('frontend-plugin'); + // Legacy template should be present + expect(templateNames).toContain('frontend-plugin-legacy'); expect(templateNames).toContain('backend-plugin'); // New frontend templates should be filtered out + expect(templateNames).not.toContain('frontend-plugin'); expect(templateNames).not.toContain('frontend-plugin-module'); - - // The frontend-plugin in the list should be from the legacy template - const frontendPlugin = config.templatePointers.find( - t => t.name === 'frontend-plugin', - ); - expect(frontendPlugin?.target).toContain('/legacy-frontend-plugin/'); }); it('should not filter templates when using explicit configuration', async () => { diff --git a/packages/cli-module-new/src/lib/preparation/loadPortableTemplateConfig.ts b/packages/cli-module-new/src/lib/preparation/loadPortableTemplateConfig.ts index fd5a92bb91..f0fb8ea5ce 100644 --- a/packages/cli-module-new/src/lib/preparation/loadPortableTemplateConfig.ts +++ b/packages/cli-module-new/src/lib/preparation/loadPortableTemplateConfig.ts @@ -177,8 +177,6 @@ export async function loadPortableTemplateConfig( ); // Auto-filter frontend templates based on detected frontend system. - // This must happen before the conflict check since both the new and legacy - // frontend plugin templates have the same name, but only one will be shown. if (isUsingDefaultTemplates) { const frontendSystem = await detectFrontendSystem(basePath); templatePointerEntries = filterTemplateEntriesForFrontendSystem( diff --git a/packages/cli-module-new/templates/legacy-frontend-plugin/portable-template.yaml b/packages/cli-module-new/templates/legacy-frontend-plugin/portable-template.yaml index ec4bd338c6..9350418967 100644 --- a/packages/cli-module-new/templates/legacy-frontend-plugin/portable-template.yaml +++ b/packages/cli-module-new/templates/legacy-frontend-plugin/portable-template.yaml @@ -1,4 +1,4 @@ -name: legacy-frontend-plugin +name: frontend-plugin-legacy role: frontend-plugin description: A new frontend plugin (legacy system) values: