Skip to content

Commit 76086bc

Browse files
authored
Merge pull request #6239 from Shopify/08-11-handle_uid_mis-matches_post-migration
Handle UID mis-matches post-migration
2 parents 80909e4 + 6fee23e commit 76086bc

File tree

3 files changed

+39
-10
lines changed

3 files changed

+39
-10
lines changed

packages/app/src/cli/services/context/breakdown-extensions.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,13 @@ async function resolveRemoteExtensionIdentifiersBreakdown(
362362
const version = activeAppVersion || (await developerPlatformClient.activeAppVersion(remoteApp))
363363
if (!version) return
364364

365-
const extensionIdentifiersBreakdown = loadExtensionsIdentifiersBreakdown(version, localRegistration, toCreate, specs)
365+
const extensionIdentifiersBreakdown = loadExtensionsIdentifiersBreakdown(
366+
version,
367+
localRegistration,
368+
toCreate,
369+
specs,
370+
developerPlatformClient,
371+
)
366372

367373
const dashboardOnlyFinal = dashboardOnly.filter(
368374
(dashboardOnly) =>
@@ -384,13 +390,24 @@ function loadExtensionsIdentifiersBreakdown(
384390
localRegistration: IdentifiersExtensions,
385391
toCreate: LocalSource[],
386392
specs: ExtensionSpecification[],
393+
developerPlatformClient: DeveloperPlatformClient,
387394
) {
388395
const extensionModules = activeAppVersion?.appModuleVersions.filter(
389396
(ext) => extensionTypeStrategy(specs, ext.specification?.identifier) === 'uuid',
390397
)
391398

399+
// In AppManagement, matching has to be via UID, but we acccept UUID matches if the UID is empty (migration pending)
400+
// In Partners, we keep the legacy match of only UUID.
392401
function moduleHasUUIDorUID(module: AppModuleVersion, identifier: string) {
393-
return module.registrationUuid === identifier || module.registrationId === identifier
402+
const UuidMatch = module.registrationUuid === identifier
403+
const UidMatch = module.registrationId === identifier
404+
const pendingMigration = module.registrationId.length === 0
405+
406+
if (developerPlatformClient.supportsAtomicDeployments) {
407+
return UidMatch || (pendingMigration && UuidMatch)
408+
} else {
409+
return UuidMatch
410+
}
394411
}
395412

396413
const allExistingExtensions = Object.entries(localRegistration)

packages/app/src/cli/services/context/id-matching.test.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -780,9 +780,10 @@ describe('automaticMatchmaking: with Atomic Deployments enabled', () => {
780780

781781
test('creates the missing extension when there is a remote one', async () => {
782782
// When
783+
const registrationA = {...REGISTRATION_A, id: ''}
783784
const got = await automaticMatchmaking(
784785
[EXTENSION_A, EXTENSION_A_2],
785-
[REGISTRATION_A],
786+
[registrationA],
786787
{'extension-a': 'UUID_A'},
787788
testDeveloperPlatformClient({supportsAtomicDeployments: true}),
788789
)
@@ -805,16 +806,21 @@ describe('outputAddedIDs', () => {
805806
vi.mocked(outputInfo).mockClear()
806807

807808
// Extension B has a valid UID
808-
REGISTRATION_B.id = EXTENSION_B.uid
809+
// Extension C is marked as toCreate because we only try to match by UID (because it has a real one)
810+
const registrationA = {...REGISTRATION_A, id: ''}
811+
const registrationB = {...REGISTRATION_B, id: EXTENSION_B.uid}
812+
const registrationC = {...REGISTRATION_C}
813+
const registrationD = {...REGISTRATION_D, id: ''}
809814

810815
// When: Extensions are matched by UUID (not by UID)
811-
await automaticMatchmaking(
812-
[EXTENSION_A, EXTENSION_B, EXTENSION_C],
813-
[REGISTRATION_A, REGISTRATION_B, REGISTRATION_C],
816+
const result = await automaticMatchmaking(
817+
[EXTENSION_A, EXTENSION_B, EXTENSION_C, EXTENSION_D],
818+
[registrationA, registrationB, registrationC, registrationD],
814819
{
815820
'extension-a': 'UUID_A',
816821
'extension-b': 'UUID_B',
817822
'extension-c': 'UUID_C',
823+
'extension-d': 'UUID_D',
818824
},
819825
testDeveloperPlatformClient({supportsAtomicDeployments: true}),
820826
)
@@ -823,10 +829,13 @@ describe('outputAddedIDs', () => {
823829
expect(outputInfo).toHaveBeenCalledWith('Generating extension IDs\n')
824830
expect(outputInfo).toHaveBeenCalledWith(expect.stringContaining('\x1B[36mextension-a\x1B[39m | Added ID: UUID_A'))
825831
expect(outputInfo).not.toHaveBeenCalledWith(expect.stringContaining('Added ID: UUID_B'))
826-
expect(outputInfo).toHaveBeenCalledWith(expect.stringContaining('\x1B[35mextension-c\x1B[39m | Added ID: UUID_C'))
832+
expect(outputInfo).not.toHaveBeenCalledWith(expect.stringContaining('Added ID: UUID_C'))
833+
expect(outputInfo).toHaveBeenCalledWith(expect.stringContaining('\x1B[35mextension-d\x1B[39m | Added ID: UUID_D'))
827834
expect(outputInfo).toHaveBeenCalledWith('\n')
828835

829836
// Verify it was called 4 times total (header + 2 extensions + footer)
830837
expect(outputInfo).toHaveBeenCalledTimes(4)
838+
839+
expect(result.toCreate).toEqual([EXTENSION_C])
831840
})
832841
})

packages/app/src/cli/services/context/id-matching.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,23 +86,26 @@ function matchByUIDandUUID(
8686
const matchedByUUID: IdentifiersExtensions = {}
8787

8888
// First, try to match by UID, then by UUID.
89+
// But only accept a UUID match if the ID for the remote source is empty, meaning is still pending migration.
8990
local.forEach((localSource) => {
9091
const matchByUID = remote.find((remoteSource) => remoteSource.id === localSource.uid)
9192
const matchByUUID = remote.find((remoteSource) => remoteSource.uuid === ids[localSource.localIdentifier])
9293

9394
if (matchByUID) {
9495
matchedByUID[localSource.localIdentifier] = matchByUID.id
95-
} else if (matchByUUID) {
96+
} else if (matchByUUID && matchByUUID.id.length === 0) {
9697
matchedByUUID[localSource.localIdentifier] = matchByUUID.uuid
9798
} else {
9899
pendingLocal.push(localSource)
99100
}
100101
})
101102

103+
// Remote source with a valid UID is not pending, shouldn't be tried to be matched by name/type.
102104
const pendingRemote = remote.filter(
103105
(remoteSource) =>
104106
!Object.values(matchedByUUID).includes(remoteSource.uuid) &&
105-
!Object.values(matchedByUID).includes(remoteSource.id),
107+
!Object.values(matchedByUID).includes(remoteSource.id) &&
108+
remoteSource.id.length === 0,
106109
)
107110

108111
// Then, try to match by name and type as a last resort.

0 commit comments

Comments
 (0)