Skip to content

Commit f8b2217

Browse files
authored
Merge pull request #5451 from Shopify/dlm-app-version-create-mutation-variables
Update mutation variables for AppVersionCreate
2 parents 275033c + 8d20719 commit f8b2217

File tree

5 files changed

+223
-54
lines changed

5 files changed

+223
-54
lines changed

packages/app/src/cli/api/graphql/app-management/generated/create-app-version.ts

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ import {TypedDocumentNode as DocumentNode} from '@graphql-typed-document-node/co
66

77
export type CreateAppVersionMutationVariables = Types.Exact<{
88
appId: Types.Scalars['ID']['input']
9-
appSource: Types.AppSourceInput
10-
name: Types.Scalars['String']['input']
9+
version: Types.AppVersionInput
1110
metadata?: Types.InputMaybe<Types.VersionMetadataInput>
1211
}>
1312

@@ -49,13 +48,8 @@ export const CreateAppVersion = {
4948
},
5049
{
5150
kind: 'VariableDefinition',
52-
variable: {kind: 'Variable', name: {kind: 'Name', value: 'appSource'}},
53-
type: {kind: 'NonNullType', type: {kind: 'NamedType', name: {kind: 'Name', value: 'AppSourceInput'}}},
54-
},
55-
{
56-
kind: 'VariableDefinition',
57-
variable: {kind: 'Variable', name: {kind: 'Name', value: 'name'}},
58-
type: {kind: 'NonNullType', type: {kind: 'NamedType', name: {kind: 'Name', value: 'String'}}},
51+
variable: {kind: 'Variable', name: {kind: 'Name', value: 'version'}},
52+
type: {kind: 'NonNullType', type: {kind: 'NamedType', name: {kind: 'Name', value: 'AppVersionInput'}}},
5953
},
6054
{
6155
kind: 'VariableDefinition',
@@ -77,13 +71,8 @@ export const CreateAppVersion = {
7771
},
7872
{
7973
kind: 'Argument',
80-
name: {kind: 'Name', value: 'appSource'},
81-
value: {kind: 'Variable', name: {kind: 'Name', value: 'appSource'}},
82-
},
83-
{
84-
kind: 'Argument',
85-
name: {kind: 'Name', value: 'name'},
86-
value: {kind: 'Variable', name: {kind: 'Name', value: 'name'}},
74+
name: {kind: 'Name', value: 'version'},
75+
value: {kind: 'Variable', name: {kind: 'Name', value: 'version'}},
8776
},
8877
{
8978
kind: 'Argument',

packages/app/src/cli/api/graphql/app-management/generated/types.d.ts

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -47,28 +47,6 @@ export type Scalars = {
4747
URL: {input: string; output: string}
4848
}
4949

50-
/** The input fields for an app module. */
51-
export type AppModuleInput = {
52-
/** Configuration for the module. */
53-
config: Scalars['JSON']['input']
54-
/** Human-readable identifier for the module. */
55-
handle?: InputMaybe<Scalars['String']['input']>
56-
/** Identifier for the module's specification. */
57-
specificationIdentifier: Scalars['String']['input']
58-
/** The location where the module will be surfaced. */
59-
target?: InputMaybe<Scalars['String']['input']>
60-
/** User-specified identifier for the module, unique to the app. */
61-
uid?: InputMaybe<Scalars['String']['input']>
62-
}
63-
64-
/** The input fields for data and configuration that represent an app. */
65-
export type AppSourceInput = {
66-
/** Modules that make up the app. */
67-
appModules: AppModuleInput[]
68-
/** URL for app assets. */
69-
assetsUrl?: InputMaybe<Scalars['URL']['input']>
70-
}
71-
7250
/** The input fields used to create a new app version. */
7351
export type AppVersionInput = {
7452
/** The manifest from which to create the app version. */

packages/app/src/cli/api/graphql/app-management/queries/create-app-version.graphql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
mutation CreateAppVersion($appId: ID!, $appSource: AppSourceInput!, $name: String!, $metadata: VersionMetadataInput) {
2-
appVersionCreate(appId: $appId, appSource: $appSource, name: $name, metadata: $metadata) {
1+
mutation CreateAppVersion($appId: ID!, $version: AppVersionInput!, $metadata: VersionMetadataInput) {
2+
appVersionCreate(appId: $appId, version: $version, metadata: $metadata) {
33
version {
44
id
55
appModules {

packages/app/src/cli/utilities/developer-platform-client/app-management-client.test.ts

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {AvailableTopicsQuery} from '../../api/graphql/webhooks/generated/availab
2020
import {CliTesting, CliTestingMutation} from '../../api/graphql/webhooks/generated/cli-testing.js'
2121
import {SendSampleWebhookVariables} from '../../services/webhook/request-sample.js'
2222
import {CreateApp} from '../../api/graphql/app-management/generated/create-app.js'
23+
import {BrandingSpecIdentifier} from '../../models/extensions/specifications/app_config_branding.js'
2324
import {describe, expect, test, vi} from 'vitest'
2425
import {CLI_KIT_VERSION} from '@shopify/cli-kit/common/version'
2526
import {fetch} from '@shopify/cli-kit/node/http'
@@ -558,3 +559,198 @@ describe('sendSampleWebhook', () => {
558559
expect(result.sendSampleWebhook.userErrors).toEqual([{message: 'Invalid api_version', fields: []}])
559560
})
560561
})
562+
563+
describe('deploy', () => {
564+
// Given
565+
const client = new AppManagementClient()
566+
client.token = () => Promise.resolve('token')
567+
568+
test('creates version with correct metadata and modules', async () => {
569+
// Given
570+
const versionTag = '1.0.0'
571+
const message = 'Test deploy'
572+
const commitReference = 'https://github.com/org/repo/commit/123'
573+
const appModules = [
574+
{
575+
uid: 'branding',
576+
config: JSON.stringify({name: 'Test App'}),
577+
handle: 'test-app',
578+
specificationIdentifier: BrandingSpecIdentifier,
579+
context: 'unused-context',
580+
},
581+
]
582+
583+
const mockResponse = {
584+
appVersionCreate: {
585+
version: {
586+
id: 'gid://shopify/Version/1',
587+
metadata: {
588+
versionTag,
589+
message,
590+
sourceControlUrl: commitReference,
591+
},
592+
appModules: [
593+
{
594+
uuid: 'some_uuid',
595+
},
596+
],
597+
},
598+
userErrors: [],
599+
},
600+
}
601+
vi.mocked(appManagementRequestDoc).mockResolvedValueOnce(mockResponse)
602+
603+
// When
604+
await client.deploy({
605+
apiKey: 'api-key',
606+
appId: 'gid://shopify/App/123',
607+
name: 'Test App',
608+
appModules,
609+
organizationId: 'gid://shopify/Organization/123',
610+
versionTag,
611+
message,
612+
commitReference,
613+
skipPublish: true,
614+
})
615+
616+
// Then
617+
expect(appManagementRequestDoc).toHaveBeenCalledWith('gid://shopify/Organization/123', expect.anything(), 'token', {
618+
appId: 'gid://shopify/App/123',
619+
version: {
620+
source: {
621+
name: 'Test App',
622+
modules: [
623+
{
624+
uid: 'branding',
625+
type: BrandingSpecIdentifier,
626+
handle: 'test-app',
627+
config: {name: 'Test App'},
628+
},
629+
],
630+
},
631+
},
632+
metadata: {
633+
versionTag,
634+
message,
635+
sourceControlUrl: commitReference,
636+
},
637+
})
638+
})
639+
640+
test('uses bundleUrl when provided instead of modules', async () => {
641+
// Given
642+
const bundleUrl = 'https://storage.test/bundle.zip'
643+
const mockResponse = {
644+
appVersionCreate: {
645+
version: {
646+
id: 'gid://shopify/Version/1',
647+
metadata: {},
648+
appModules: [],
649+
},
650+
userErrors: [],
651+
},
652+
}
653+
vi.mocked(appManagementRequestDoc).mockResolvedValueOnce(mockResponse)
654+
655+
// When
656+
await client.deploy({
657+
apiKey: 'api-key',
658+
appId: 'gid://shopify/App/123',
659+
name: 'Test App',
660+
organizationId: 'gid://shopify/Organization/123',
661+
bundleUrl,
662+
versionTag: '1.0.0',
663+
skipPublish: true,
664+
})
665+
666+
// Then
667+
expect(appManagementRequestDoc).toHaveBeenCalledWith('gid://shopify/Organization/123', expect.anything(), 'token', {
668+
appId: 'gid://shopify/App/123',
669+
version: {
670+
sourceUrl: bundleUrl,
671+
},
672+
metadata: expect.any(Object),
673+
})
674+
})
675+
676+
test('updates name from branding module if present', async () => {
677+
// Given
678+
const appModules = [
679+
{
680+
uuid: 'branding',
681+
config: JSON.stringify({name: 'Updated App Name'}),
682+
handle: 'branding',
683+
specificationIdentifier: BrandingSpecIdentifier,
684+
context: 'unused-context',
685+
},
686+
]
687+
const mockResponse = {
688+
appVersionCreate: {
689+
version: {
690+
id: 'gid://shopify/Version/1',
691+
metadata: {},
692+
appModules: [],
693+
},
694+
userErrors: [],
695+
},
696+
}
697+
vi.mocked(appManagementRequestDoc).mockResolvedValueOnce(mockResponse)
698+
699+
// When
700+
await client.deploy({
701+
apiKey: 'api-key',
702+
appId: 'gid://shopify/App/123',
703+
name: 'Original Name',
704+
appModules,
705+
organizationId: 'gid://shopify/Organization/123',
706+
versionTag: '1.0.0',
707+
skipPublish: true,
708+
})
709+
710+
// Then
711+
expect(appManagementRequestDoc).toHaveBeenCalledWith(
712+
'gid://shopify/Organization/123',
713+
expect.anything(),
714+
'token',
715+
expect.objectContaining({
716+
version: {
717+
source: {
718+
name: 'Updated App Name',
719+
modules: expect.any(Array),
720+
},
721+
},
722+
}),
723+
)
724+
})
725+
726+
test('handles version creation errors', async () => {
727+
// Given
728+
const mockResponse = {
729+
appVersionCreate: {
730+
version: null,
731+
userErrors: [
732+
{
733+
field: ['version'],
734+
message: 'Invalid version',
735+
details: [],
736+
},
737+
],
738+
},
739+
}
740+
vi.mocked(appManagementRequestDoc).mockResolvedValueOnce(mockResponse)
741+
742+
// When
743+
const result = await client.deploy({
744+
apiKey: 'api-key',
745+
appId: 'gid://shopify/App/123',
746+
name: 'Test App',
747+
organizationId: 'gid://shopify/Organization/123',
748+
versionTag: '1.0.0',
749+
skipPublish: true,
750+
})
751+
752+
// Then
753+
expect(result.appDeploy.userErrors).toHaveLength(1)
754+
expect(result.appDeploy.userErrors[0]?.message).toBe('Invalid version')
755+
})
756+
})

packages/app/src/cli/utilities/developer-platform-client/app-management-client.ts

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -589,22 +589,24 @@ export class AppManagementClient implements DeveloperPlatformClient {
589589
if (brandingModule) {
590590
updatedName = JSON.parse(brandingModule.config).name
591591
}
592-
592+
const metadata = {versionTag, message, sourceControlUrl: commitReference}
593+
const queryVersion: AppVersionSourceUrl | AppVersionSource = bundleUrl
594+
? {sourceUrl: bundleUrl}
595+
: {
596+
source: {
597+
name: updatedName,
598+
modules: (appModules ?? []).map((mod) => ({
599+
uid: mod.uid ?? mod.uuid ?? mod.handle,
600+
type: mod.specificationIdentifier,
601+
handle: mod.handle,
602+
config: JSON.parse(mod.config),
603+
})),
604+
},
605+
}
593606
const variables = {
594607
appId,
595-
name: updatedName,
596-
appSource: {
597-
assetsUrl: bundleUrl,
598-
appModules: (appModules ?? []).map((mod) => {
599-
return {
600-
uid: mod.uid ?? mod.uuid ?? mod.handle,
601-
specificationIdentifier: mod.specificationIdentifier,
602-
handle: mod.handle,
603-
config: JSON.parse(mod.config),
604-
}
605-
}),
606-
},
607-
metadata: {versionTag, message, sourceControlUrl: commitReference},
608+
version: queryVersion as unknown as JsonMapType,
609+
metadata,
608610
}
609611

610612
const result = await appManagementRequestDoc(organizationId, CreateAppVersion, await this.token(), variables)
@@ -921,6 +923,10 @@ interface AppVersionSource {
921923
}
922924
}
923925

926+
interface AppVersionSourceUrl {
927+
sourceUrl: string
928+
}
929+
924930
// this is a temporary solution for editions to support https://vault.shopify.io/gsd/projects/31406
925931
// read more here: https://vault.shopify.io/gsd/projects/31406
926932
const MAGIC_URL = 'https://shopify.dev/apps/default-app-home'

0 commit comments

Comments
 (0)