Skip to content

Commit b31764a

Browse files
committed
Add meaningful error codes for telemetry
1 parent 4235561 commit b31764a

File tree

6 files changed

+61
-6
lines changed

6 files changed

+61
-6
lines changed

packages/core/src/shared/sam/build.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ export async function runBuild(arg?: TreeNode): Promise<SamBuildResult> {
236236
} catch (error) {
237237
throw ToolkitError.chain(error, 'Failed to build SAM template', {
238238
details: { ...resolveBuildArgConflict(buildFlags) },
239+
code: error instanceof ToolkitError ? error.code : undefined,
239240
})
240241
}
241242
}

packages/core/src/shared/sam/deploy.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,10 @@ export async function runDeploy(arg: any, wizardParams?: DeployParams): Promise<
392392
throw error
393393
}
394394
} catch (error) {
395-
throw ToolkitError.chain(error, 'Failed to deploy SAM template', { details: { ...deployFlags } })
395+
throw ToolkitError.chain(error, 'Failed to deploy SAM template', {
396+
details: { ...deployFlags },
397+
code: error instanceof ToolkitError ? error.code : undefined,
398+
})
396399
}
397400
return {
398401
isSuccess: true,

packages/core/src/shared/sam/processTerminal.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,29 @@ import { CancellationError } from '../utilities/timeoutUtils'
1212
import { getLogger } from '../logger'
1313
import { removeAnsi } from '../utilities/textUtilities'
1414
import { isAutomation } from '../vscode/env'
15+
import { getSamCliErrorMessage, SamCliErrorTypes } from './utils'
1516

1617
let oldTerminal: ProcessTerminal | undefined
1718
export async function runInTerminal(proc: ChildProcess, cmd: string) {
1819
const handleResult = (result?: ChildProcessResult) => {
1920
if (result && result.exitCode !== 0) {
20-
const message = `sam ${cmd} exited with a non-zero exit code: ${result.exitCode}`
21+
const defaultMessage = `sam ${cmd} exited with a non-zero exit code: ${result.exitCode}`
2122
if (result.stderr.includes('is up to date')) {
22-
throw ToolkitError.chain(result.error, message, {
23+
throw ToolkitError.chain(result.error, defaultMessage, {
2324
code: 'NoUpdateExitCode',
2425
})
2526
}
26-
throw ToolkitError.chain(result.error, message, {
27+
for (const errorType in SamCliErrorTypes) {
28+
const errorMessage = getSamCliErrorMessage(result.stderr)
29+
if (errorMessage.includes(SamCliErrorTypes[errorType as keyof typeof SamCliErrorTypes])) {
30+
throw ToolkitError.chain(result.error, errorMessage, {
31+
code: errorType,
32+
})
33+
}
34+
}
35+
36+
// If no specific error matched, throw the default non-zero exit code error.
37+
throw ToolkitError.chain(result.error, defaultMessage, {
2738
code: 'NonZeroExitCode',
2839
})
2940
}

packages/core/src/shared/sam/sync.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -661,7 +661,10 @@ export async function runSync(
661661
isSuccess: true,
662662
}
663663
} catch (err) {
664-
throw ToolkitError.chain(err, 'Failed to sync SAM application', { details: { ...params } })
664+
throw ToolkitError.chain(err, 'Failed to sync SAM application', {
665+
details: { ...params },
666+
code: err instanceof ToolkitError ? err.code : undefined,
667+
})
665668
}
666669
})
667670
}

packages/core/src/shared/sam/utils.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,22 @@ export async function getSamCliPathAndVersion() {
8383

8484
return { path: samCliPath, parsedVersion }
8585
}
86+
87+
export function getSamCliErrorMessage(stderr: string): string {
88+
// Split the stderr string by newline, filter out empty lines, and get the last line
89+
const lines = stderr
90+
.trim()
91+
.split('\n')
92+
.filter((line) => line.trim() !== '')
93+
return lines[lines.length - 1]
94+
}
95+
96+
export enum SamCliErrorTypes {
97+
DockerUnreachable = 'Docker is unreachable.',
98+
ResolveS3AndS3Set = 'Cannot use both --resolve-s3 and --s3-bucket parameters in non-guided deployments.',
99+
DeployStackStatusMissing = 'Was not able to find a stack with the name:',
100+
DeployStackOutPutFailed = 'Failed to get outputs from stack',
101+
DeployBucketRequired = 'Templates with a size greater than 51,200 bytes must be deployed via an S3 Bucket.',
102+
NoUpdate = 'is up to date',
103+
ChangeSetEmpty = 'No changes to deploy. Stack is up to date',
104+
}

packages/core/src/test/shared/sam/utils.test.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,13 @@
66
import * as vscode from 'vscode'
77
import assert from 'assert'
88
import sinon from 'sinon'
9-
import { getProjectRootUri, getProjectRoot, getSource, isDotnetRuntime } from '../../../shared/sam/utils'
9+
import {
10+
getProjectRootUri,
11+
getProjectRoot,
12+
getSource,
13+
isDotnetRuntime,
14+
getSamCliErrorMessage,
15+
} from '../../../shared/sam/utils'
1016
import { TemplateItem } from '../../../shared/sam/sync'
1117
import { RegionNode } from '../../../awsexplorer/regionNode'
1218
import { Region } from '../../../shared/regions/endpoints'
@@ -148,4 +154,16 @@ describe('SAM utils', async function () {
148154
})
149155
})
150156
})
157+
158+
describe('gets the SAM CLI error from stderr', async function () {
159+
it('returns the error message', async function () {
160+
const stderr =
161+
'Starting Build use cache\nStarting Build inside a container\nCache is invalid, running build and copying resources for following functions (ResizerFunction)\nBuilding codeuri: /Users/mbfreder/TestApp/JavaSamApp/serverless-patterns/s3lambda-resizing-python/src runtime: python3.12 metadata: {} architecture: x86_64 functions: ResizerFunction\nError: Docker is unreachable. Docker needs to be running to build inside a container.'
162+
const response = getSamCliErrorMessage(stderr)
163+
assert.deepStrictEqual(
164+
response,
165+
'Error: Docker is unreachable. Docker needs to be running to build inside a container.'
166+
)
167+
})
168+
})
151169
})

0 commit comments

Comments
 (0)