Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Display field for app management errors #5368

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
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
2 changes: 1 addition & 1 deletion packages/app/src/cli/api/graphql/app_deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export interface AppDeploySchema {
message: string
}[]
}[]
}
} | null
userErrors: {
field?: string[] | null
message: string
Expand Down
7 changes: 4 additions & 3 deletions packages/app/src/cli/services/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {joinPath, dirname} from '@shopify/cli-kit/node/path'
import {outputNewline, outputInfo, formatPackageManagerCommand} from '@shopify/cli-kit/node/output'
import {useThemebundling} from '@shopify/cli-kit/node/context/local'
import {getArrayRejectingUndefined} from '@shopify/cli-kit/common/array'
import type {Task} from '@shopify/cli-kit/node/ui'
import type {InlineToken, Task} from '@shopify/cli-kit/node/ui'

export interface DeployOptions {
/** The app to be built and uploaded */
Expand Down Expand Up @@ -160,8 +160,9 @@ async function outputCompletionMessage({
release: boolean
uploadExtensionsBundleResult: UploadExtensionsBundleOutput
}) {
const linkAndMessage = [
{link: {label: uploadExtensionsBundleResult.versionTag ?? 'version', url: uploadExtensionsBundleResult.location}},
const {location} = uploadExtensionsBundleResult
const linkAndMessage: InlineToken[] = [
...(location ? [{link: {label: uploadExtensionsBundleResult.versionTag ?? 'version', url: location}}] : []),
uploadExtensionsBundleResult.message ? `\n${uploadExtensionsBundleResult.message}` : '',
]
if (release) {
Expand Down
24 changes: 15 additions & 9 deletions packages/app/src/cli/services/deploy/upload.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,20 +132,14 @@ describe('uploadExtensionsBundle', () => {
})
})

test("throws a specific error based on what is returned from partners when response doesn't include an app version", async () => {
test("throws a specific error based on what is returned from any backend when response doesn't include an app version", async () => {
await inTemporaryDirectory(async (tmpDir) => {
// Given
const errorResponse: AppDeploySchema = {
appDeploy: {
appVersion: {
uuid: 'uuid',
id: 1,
versionTag: 'version-tag',
location: 'location',
message: 'message',
appModuleVersions: [],
},
appVersion: null,
userErrors: [
// Partners style errors
{
message: 'Missing expected key(s).',
field: ['base'],
Expand Down Expand Up @@ -206,6 +200,13 @@ describe('uploadExtensionsBundle', () => {
},
],
},
// App Management style errors
{
message: 'is not allowed',
category: 'invalid',
field: ['customers_redact_url'],
details: [],
},
],
},
}
Expand Down Expand Up @@ -242,6 +243,11 @@ describe('uploadExtensionsBundle', () => {
} catch (error: any) {
expect(error.message).toEqual("Version couldn't be created.")
expect(error.customSections).toEqual([
// App Management error
{
body: 'customers_redact_url: is not allowed',
},
// Partners errors
{
title: 'amortizable-marketplace-ext',
body: [
Expand Down
35 changes: 22 additions & 13 deletions packages/app/src/cli/services/deploy/upload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ export interface UploadExtensionsBundleOutput {
validationErrors: UploadExtensionValidationError[]
versionTag?: string | null
message?: string | null
location: string
location: string | undefined
deployError?: string
}

Expand Down Expand Up @@ -179,17 +179,18 @@ export async function uploadExtensionsBundle(
}
}

const validationErrors = result.appDeploy.appVersion.appModuleVersions
.filter((ver) => ver.validationErrors.length > 0)
.map((ver) => {
return {uuid: ver.registrationUuid, errors: ver.validationErrors}
})
const validationErrors =
result.appDeploy.appVersion?.appModuleVersions
.filter((ver) => ver.validationErrors.length > 0)
.map((ver) => {
return {uuid: ver.registrationUuid, errors: ver.validationErrors}
}) ?? []

return {
validationErrors,
versionTag: result.appDeploy.appVersion.versionTag,
location: result.appDeploy.appVersion.location,
message: result.appDeploy.appVersion.message,
versionTag: result.appDeploy.appVersion?.versionTag,
location: result.appDeploy.appVersion?.location,
message: result.appDeploy.appVersion?.message,
deployError,
}
}
Expand Down Expand Up @@ -252,7 +253,8 @@ function generalErrorsSection(
if (errors.length === 1) {
return [
{
body: errors[0]?.message ?? '',
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
body: messageIncludingField(errors[0]!),
},
]
}
Expand All @@ -261,7 +263,7 @@ function generalErrorsSection(
{
body: {
list: {
items: errors.map((error) => error.message),
items: errors.map((error) => messageIncludingField(error)),
},
},
},
Expand All @@ -273,8 +275,7 @@ function generalErrorsSection(

function cliErrorsSections(errors: AppDeploySchema['appDeploy']['userErrors'], identifiers: IdentifiersExtensions) {
return errors.reduce<ErrorCustomSection[]>((sections, error) => {
const field = (error.field ?? ['unknown']).join('.').replace('extension_points', 'extensions.targeting')
const errorMessage = field === 'base' ? error.message : `${field}: ${error.message}`
const errorMessage = messageIncludingField(error, ['unknown'])

const remoteTitle = error.details.find((detail) => typeof detail.extension_title !== 'undefined')?.extension_title
const specificationIdentifier = error.details.find(
Expand Down Expand Up @@ -374,6 +375,14 @@ function partnersErrorsSections(errors: AppDeploySchema['appDeploy']['userErrors
})) as ErrorCustomSection[]
}

function messageIncludingField(
{field, message}: AppDeploySchema['appDeploy']['userErrors'][number],
defaultField: string[] = [],
): string {
const errorField = (field ?? defaultField).join('.').replace('extension_points', 'extensions.targeting')
return errorField === 'base' || errorField === '' ? message : `${errorField}: ${message}`
}

/**
* It generates a URL to upload an app bundle.
* @param apiKey - The application API key
Expand Down
2 changes: 1 addition & 1 deletion packages/eslint-plugin-cli/rules/no-inline-graphql.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ const knownFailures = {
'f48a44e2dae39f1b33ac685971740e3705f2754de5fdf1d6f1fbb3492bc62be2',
'packages/app/src/cli/api/graphql/app_active_version.ts':
'685d858cf3ad636fe8d771707715dd9a793e4aa4529f843eac3df625efd4d5be',
'packages/app/src/cli/api/graphql/app_deploy.ts': 'ff060a322caebf8722fc2f0e2e1cec08fbb861fb258af2417fc430006b2c903e',
'packages/app/src/cli/api/graphql/app_deploy.ts': 'f7eb5241cecb5e4a83597c045a4bc1fe76c7f4bf3783aadabc8d0eab9e32b441',
'packages/app/src/cli/api/graphql/app_release.ts': '3acace031157856c88dc57506d81364c084fb5ca66ab5c6ff59393ab5255846d',
'packages/app/src/cli/api/graphql/app_version_by_tag.ts':
'a3231389ceb20eec4cab51186678b032e52d8f3e4df3078ce1a33c8ae83ac7fa',
Expand Down
Loading