Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions packages/app/src/cli/models/app/identifiers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,7 @@ describe('getAppIdentifiers', () => {
})

// Then
expect(got.app).toEqual('FOO')
expect((got.extensions ?? {})['test-ui-extension']).toEqual('BAR')
expect(got['test-ui-extension']).toEqual('BAR')
})
})

Expand All @@ -229,8 +228,7 @@ describe('getAppIdentifiers', () => {
)

// Then
expect(got.app).toEqual('FOO')
expect((got.extensions ?? {})['test-ui-extension']).toEqual('BAR')
expect(got['test-ui-extension']).toEqual('BAR')
})
})
})
12 changes: 7 additions & 5 deletions packages/app/src/cli/models/app/identifiers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ export interface ExtensionUuidsByLocalIdentifier {
[localIdentifier: string]: string
}

export interface DeployIdentifiers {
appModuleUuids: ExtensionUuidsByLocalIdentifier
appModuleRegistrationIds: ExtensionUuidsByLocalIdentifier
}

type UuidOnlyIdentifiers = Omit<Identifiers, 'extensionIds' | 'extensionsNonUuidManaged'>
type UpdateAppIdentifiersCommand = 'dev' | 'deploy' | 'release' | 'import-extensions'
interface UpdateAppIdentifiersOptions {
Expand Down Expand Up @@ -95,7 +100,7 @@ interface GetAppIdentifiersOptions {
export function getAppIdentifiers(
{app}: GetAppIdentifiersOptions,
systemEnvironment = process.env,
): Partial<UuidOnlyIdentifiers> {
): ExtensionUuidsByLocalIdentifier {
const envVariables = {
...app.dotenv?.variables,
...(systemEnvironment as {[variable: string]: string}),
Expand All @@ -108,8 +113,5 @@ export function getAppIdentifiers(
}
app.allExtensions.forEach(processExtension)

return {
app: envVariables[app.idEnvironmentVariableName],
extensions: extensionsIdentifiers,
}
return extensionsIdentifiers
}
2 changes: 1 addition & 1 deletion packages/app/src/cli/services/context.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ beforeAll(async () => {
})

beforeEach(async () => {
vi.mocked(getAppIdentifiers).mockReturnValue({app: undefined})
vi.mocked(getAppIdentifiers).mockReturnValue({})
vi.mocked(selectOrganizationPrompt).mockResolvedValue(ORG1)
vi.mocked(selectOrCreateApp).mockResolvedValue(APP1)
vi.mocked(selectStore).mockResolvedValue(STORE1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ export function configExtensionsIdentifiersReleaseBreakdown({
return buildConfigExtensionIdentifiersBreakdown(versionConfig, activeConfig)
}

function buildConfigExtensionIdentifiersBreakdown(
export function buildConfigExtensionIdentifiersBreakdown(
localConfig: {[key: string]: unknown},
remoteConfig: {[key: string]: unknown},
): ConfigExtensionIdentifiersBreakdown | undefined {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import {EnsureDeploymentIdsPresenceOptions, RemoteSource} from './identifiers.js'
import {extensionMigrationPrompt} from './prompts.js'
import {migrateFlowExtensions} from '../dev/migrate-flow-extension.js'
import {migrateExtensionsToUIExtension} from '../dev/migrate-to-ui-extension.js'
import {
AdminLinkModulesMap,
FlowModulesMap,
getModulesToMigrate,
MarketingModulesMap,
migrateAppModules,
UIModulesMap,
} from '../dev/migrate-app-module.js'
import {DeveloperPlatformClient} from '../../utilities/developer-platform-client.js'
import {PartnersClient} from '../../utilities/developer-platform-client/partners-client.js'
import {AbortSilentError} from '@shopify/cli-kit/node/error'

/** Returns a fresh active app version when migrations changed remote modules. */
export async function activeAppVersionAfterMigrations(options: EnsureDeploymentIdsPresenceOptions) {
const didMigrateExtensions = await migrateExtensionsIfNeeded(options)
return didMigrateExtensions
? options.developerPlatformClient.activeAppVersion(options.remoteApp)
: options.activeAppVersion
}

/** Runs supported legacy extension migrations before deploy classification. */
async function migrateExtensionsIfNeeded(options: EnsureDeploymentIdsPresenceOptions) {
const {app, appId, developerPlatformClient, envIdentifiers, remoteApp} = options
const registrations = await developerPlatformClient.appExtensionRegistrations(remoteApp, options.activeAppVersion)
const localExtensions = app.allExtensions
const identifiers = envIdentifiers
const remoteExtensions = registrations.app.extensionRegistrations
const dashboardExtensions = registrations.app.dashboardManagedExtensionRegistrations
const migrationClient = PartnersClient.getInstance()

let didMigrate = false
let migratedRemoteExtensions = remoteExtensions

const uiExtensionsToMigrate = getModulesToMigrate(
localExtensions,
migratedRemoteExtensions,
identifiers,
UIModulesMap,
)
if (uiExtensionsToMigrate.length > 0) {
const confirmedMigration = await extensionMigrationPrompt(uiExtensionsToMigrate)
if (!confirmedMigration) throw new AbortSilentError()
migratedRemoteExtensions = await migrateExtensionsToUIExtension({
extensionsToMigrate: uiExtensionsToMigrate,
appId,
remoteExtensions: migratedRemoteExtensions,
migrationClient,
})
didMigrate = true
}

const dashboardMigrations = [
{typesMap: FlowModulesMap, migrate: migrateFlowExtensions},
migrationGroup(MarketingModulesMap, 'marketing_activity'),
migrationGroup(AdminLinkModulesMap, 'admin_link'),
]

for (const migration of dashboardMigrations) {
const extensionsToMigrate = getModulesToMigrate(
localExtensions,
dashboardExtensions,
identifiers,
migration.typesMap,
)
if (extensionsToMigrate.length === 0) continue

// eslint-disable-next-line no-await-in-loop
const confirmedMigration = await extensionMigrationPrompt(extensionsToMigrate, false)
if (!confirmedMigration) throw new AbortSilentError()

// eslint-disable-next-line no-await-in-loop
const newRemoteExtensions = await migration.migrate({
extensionsToMigrate,
appId,
remoteExtensions: dashboardExtensions,
migrationClient,
})
migratedRemoteExtensions = migratedRemoteExtensions.concat(newRemoteExtensions)
didMigrate = true
}

return didMigrate
}

/** Adapts app-module migrations to the shared dashboard migration loop. */
function migrationGroup(typesMap: {[key: string]: string[]}, type: string) {
return {
typesMap,
migrate: (options: {
extensionsToMigrate: Parameters<typeof migrateAppModules>[0]['extensionsToMigrate']
appId: string
remoteExtensions: RemoteSource[]
migrationClient: DeveloperPlatformClient
}) => migrateAppModules({...options, type}),
}
}
Loading
Loading