From f671ef043b802ffd3a991797b09886add6918436 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isaac=20Rold=C3=A1n?= Date: Thu, 2 Apr 2026 13:32:27 +0200 Subject: [PATCH 1/3] Refactor extension module spec matching Co-authored-by: Claude Code --- .../app/src/cli/services/context/breakdown-extensions.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/app/src/cli/services/context/breakdown-extensions.ts b/packages/app/src/cli/services/context/breakdown-extensions.ts index 9d854e8339a..aad339444f5 100644 --- a/packages/app/src/cli/services/context/breakdown-extensions.ts +++ b/packages/app/src/cli/services/context/breakdown-extensions.ts @@ -348,7 +348,10 @@ function loadExtensionsIdentifiersBreakdown( developerPlatformClient: DeveloperPlatformClient, ) { const extensionModules = activeAppVersion?.appModuleVersions.filter((ext) => { - const spec = specs.find((spec) => spec.identifier === ext.specification?.identifier) + const spec = specs.find( + (spec) => + spec.identifier === ext.specification?.identifier || spec.externalIdentifier === ext.specification?.identifier, + ) return spec && !isAppConfigSpecification(spec) }) From b0fcbbdbb8e99a9b3754c0150aa2b48659ba7153 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isaac=20Rold=C3=A1n?= Date: Thu, 2 Apr 2026 13:36:16 +0200 Subject: [PATCH 2/3] Add regression test for external spec identifier matching Co-authored-by: Claude Code --- .../context/breakdown-extensions.test.ts | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/packages/app/src/cli/services/context/breakdown-extensions.test.ts b/packages/app/src/cli/services/context/breakdown-extensions.test.ts index a91a5d183c5..804242c7219 100644 --- a/packages/app/src/cli/services/context/breakdown-extensions.test.ts +++ b/packages/app/src/cli/services/context/breakdown-extensions.test.ts @@ -90,6 +90,21 @@ const MODULE_CLI_A_NO_UID: AppModuleVersion = { }, } +const MODULE_CLI_A_EXTERNAL_IDENTIFIER: AppModuleVersion = { + registrationId: 'A', + registrationUuid: 'UUID_A', + registrationTitle: 'Checkout post purchase', + type: 'checkout_post_purchase_external', + specification: { + identifier: 'checkout_post_purchase_external', + name: 'Post purchase UI extension', + experience: 'extension', + options: { + managementExperience: 'cli', + }, + }, +} + const MODULE_DASHBOARD_MIGRATED_CLI_A: AppModuleVersion = { registrationId: 'A', registrationUuid: 'UUID_A', @@ -567,6 +582,52 @@ describe('extensionsIdentifiersDeployBreakdown', () => { remoteExtensionsRegistrations: remoteExtensionRegistrations.app, }) }) + + test('and there is an active version with a module matching a local spec external identifier then cli extension should be unchanged', async () => { + // Given + const extensionsToConfirm = { + validMatches: {EXTENSION_A: 'UUID_A'}, + dashboardOnlyExtensions: [REGISTRATION_DASHBOARD_A], + extensionsToCreate: [EXTENSION_A_2], + didMigrateDashboardExtensions: false, + } + vi.mocked(ensureExtensionsIds).mockResolvedValue(extensionsToConfirm) + const remoteExtensionRegistrations = { + app: { + extensionRegistrations: [REGISTRATION_A], + configurationRegistrations: [], + dashboardManagedExtensionRegistrations: [REGISTRATION_DASHBOARD_A], + }, + } + const activeAppVersion = { + appModuleVersions: [MODULE_CONFIG_A, MODULE_DASHBOARD_A, MODULE_CLI_A_EXTERNAL_IDENTIFIER], + } + + const developerPlatformClient: DeveloperPlatformClient = testDeveloperPlatformClient({ + appExtensionRegistrations: (_app: MinimalAppIdentifiers) => Promise.resolve(remoteExtensionRegistrations), + }) + + // When + const result = await extensionsIdentifiersDeployBreakdown( + await options({uiExtensions, developerPlatformClient, activeAppVersion}), + ) + + // Then + expect(result).toEqual({ + extensionIdentifiersBreakdown: { + onlyRemote: [], + toCreate: [buildExtensionBreakdownInfo('extension-a-2', 'test-ui-extension-uid')], + toUpdate: [], + unchanged: [ + buildExtensionBreakdownInfo('EXTENSION_A', undefined), + buildDashboardBreakdownInfo('Dashboard A'), + ], + }, + extensionsToConfirm, + remoteExtensionsRegistrations: remoteExtensionRegistrations.app, + }) + }) + test('and there is an active version with matching dashboard migrated cli app modules then migrated extension should be returned in the to create', async () => { // Given const remoteExtensionRegistrations = { From d562fdc8d159d004b85bc6efe5e68b035e72f7ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Isaac=20Rold=C3=A1n?= Date: Thu, 2 Apr 2026 13:38:32 +0200 Subject: [PATCH 3/3] Simplify external identifier regression test Co-authored-by: Claude Code --- .../context/breakdown-extensions.test.ts | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/packages/app/src/cli/services/context/breakdown-extensions.test.ts b/packages/app/src/cli/services/context/breakdown-extensions.test.ts index 804242c7219..7ac6882d58c 100644 --- a/packages/app/src/cli/services/context/breakdown-extensions.test.ts +++ b/packages/app/src/cli/services/context/breakdown-extensions.test.ts @@ -587,8 +587,8 @@ describe('extensionsIdentifiersDeployBreakdown', () => { // Given const extensionsToConfirm = { validMatches: {EXTENSION_A: 'UUID_A'}, - dashboardOnlyExtensions: [REGISTRATION_DASHBOARD_A], - extensionsToCreate: [EXTENSION_A_2], + dashboardOnlyExtensions: [], + extensionsToCreate: [], didMigrateDashboardExtensions: false, } vi.mocked(ensureExtensionsIds).mockResolvedValue(extensionsToConfirm) @@ -596,11 +596,11 @@ describe('extensionsIdentifiersDeployBreakdown', () => { app: { extensionRegistrations: [REGISTRATION_A], configurationRegistrations: [], - dashboardManagedExtensionRegistrations: [REGISTRATION_DASHBOARD_A], + dashboardManagedExtensionRegistrations: [], }, } const activeAppVersion = { - appModuleVersions: [MODULE_CONFIG_A, MODULE_DASHBOARD_A, MODULE_CLI_A_EXTERNAL_IDENTIFIER], + appModuleVersions: [MODULE_CLI_A_EXTERNAL_IDENTIFIER], } const developerPlatformClient: DeveloperPlatformClient = testDeveloperPlatformClient({ @@ -609,19 +609,16 @@ describe('extensionsIdentifiersDeployBreakdown', () => { // When const result = await extensionsIdentifiersDeployBreakdown( - await options({uiExtensions, developerPlatformClient, activeAppVersion}), + await options({uiExtensions: [EXTENSION_A], developerPlatformClient, activeAppVersion}), ) // Then expect(result).toEqual({ extensionIdentifiersBreakdown: { onlyRemote: [], - toCreate: [buildExtensionBreakdownInfo('extension-a-2', 'test-ui-extension-uid')], + toCreate: [], toUpdate: [], - unchanged: [ - buildExtensionBreakdownInfo('EXTENSION_A', undefined), - buildDashboardBreakdownInfo('Dashboard A'), - ], + unchanged: [buildExtensionBreakdownInfo('EXTENSION_A', undefined)], }, extensionsToConfirm, remoteExtensionsRegistrations: remoteExtensionRegistrations.app,