Skip to content

Commit 5824582

Browse files
authored
fix(amazonq): downloadExportResultAcrchive api not passed with profileArn and cause 400 error (aws#7022)
## Problem The CreateUploadUrl and StartTestGenerationJob requests succeeded with the profile ARN attached. However, the ExportResultArchive requests were made without this profile ARN, leading to inconsistent profile resolution between operations. ## Solution --- - Treat all work as PUBLIC. Private `feature/x` branches will not be squash-merged at release time. - Your code changes must meet the guidelines in [CONTRIBUTING.md](https://github.com/aws/aws-toolkit-vscode/blob/master/CONTRIBUTING.md#guidelines). - License: I confirm that my contribution is made under the terms of the Apache 2.0 license.
1 parent dd14b98 commit 5824582

File tree

11 files changed

+45
-13
lines changed

11 files changed

+45
-13
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type": "Bug Fix",
3+
"description": "Fix Q agents will fail for /transform /dev /test features if IdC kms key is configured with 400 error"
4+
}

packages/core/src/amazonqDoc/session/session.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,7 @@ export class Session {
313313
clientId: getClientId(globals.globalState),
314314
ideVersion: extensionVersion,
315315
},
316+
profileArn: AuthUtil.instance.regionProfileManager.activeRegionProfile?.arn,
316317
}
317318

318319
const response = await client.sendTelemetryEvent(params).promise()

packages/core/src/amazonqFeatureDev/client/featureDev.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,11 +244,13 @@ export class FeatureDevClient implements FeatureClient {
244244
}
245245

246246
public async exportResultArchive(conversationId: string) {
247+
const profile = AuthUtil.instance.regionProfileManager.activeRegionProfile
247248
try {
248249
const streamingClient = await createCodeWhispererChatStreamingClient()
249250
const params = {
250251
exportId: conversationId,
251252
exportIntent: 'TASK_ASSIST',
253+
profileArn: profile?.arn,
252254
} satisfies ExportResultArchiveCommandInput
253255
getLogger().debug(`Executing exportResultArchive with %O`, params)
254256
const archiveResponse = await streamingClient.exportResultArchive(params)

packages/core/src/codewhisperer/client/codewhisperer.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@ export class DefaultCodeWhispererClient {
252252
clientId: getClientId(globals.globalState),
253253
ideVersion: extensionVersion,
254254
},
255+
profileArn: AuthUtil.instance.regionProfileManager.activeRegionProfile?.arn,
255256
}
256257
if (!AuthUtil.instance.isValidEnterpriseSsoInUse() && !globals.telemetry.telemetryEnabled) {
257258
return

packages/core/src/codewhisperer/commands/startTestGeneration.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ export async function startTestGenerationProcess(
7272
let artifactMap: ArtifactMap = {}
7373
const uploadStartTime = performance.now()
7474
try {
75-
artifactMap = await getPresignedUrlAndUploadTestGen(zipMetadata)
75+
artifactMap = await getPresignedUrlAndUploadTestGen(zipMetadata, profile)
7676
} finally {
7777
const outputLogPath = path.join(testGenerationLogsDir, 'output.log')
7878
if (await fs.existsFile(outputLogPath)) {

packages/core/src/codewhisperer/commands/startTransformByQ.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ export async function preTransformationUploadCode() {
269269
})
270270

271271
transformByQState.setPayloadFilePath(payloadFilePath)
272-
uploadId = await uploadPayload(payloadFilePath)
272+
uploadId = await uploadPayload(payloadFilePath, AuthUtil.instance.regionProfileManager.activeRegionProfile)
273273
telemetry.record({ codeTransformJobId: uploadId }) // uploadId is re-used as jobId
274274
})
275275
} catch (err) {
@@ -457,7 +457,7 @@ export async function finishHumanInTheLoop(selectedDependency?: string) {
457457
}),
458458
})
459459

460-
await uploadPayload(uploadResult.tempFilePath, {
460+
await uploadPayload(uploadResult.tempFilePath, profile, {
461461
transformationUploadContext: {
462462
jobId,
463463
uploadArtifactType: 'Dependencies',

packages/core/src/codewhisperer/service/testGenHandler.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import { randomUUID } from '../../shared/crypto'
3636
import { sleep } from '../../shared/utilities/timeoutUtils'
3737
import { tempDirPath } from '../../shared/filesystemUtilities'
3838
import fs from '../../shared/fs/fs'
39+
import { AuthUtil } from '../util/authUtil'
3940

4041
// TODO: Get TestFileName and Framework and to error message
4142
export function throwIfCancelled() {
@@ -45,7 +46,7 @@ export function throwIfCancelled() {
4546
}
4647
}
4748

48-
export async function getPresignedUrlAndUploadTestGen(zipMetadata: ZipMetadata) {
49+
export async function getPresignedUrlAndUploadTestGen(zipMetadata: ZipMetadata, profile: RegionProfile | undefined) {
4950
const logger = getLogger()
5051
if (zipMetadata.zipFilePath === '') {
5152
getLogger().error('Failed to create valid source zip')
@@ -55,6 +56,7 @@ export async function getPresignedUrlAndUploadTestGen(zipMetadata: ZipMetadata)
5556
contentMd5: getMd5(zipMetadata.zipFilePath),
5657
artifactType: 'SourceCode',
5758
uploadIntent: CodeWhispererConstants.testGenUploadIntent,
59+
profileArn: profile?.arn,
5860
}
5961
logger.verbose(`Prepare for uploading src context...`)
6062
const srcResp = await codeWhisperer.codeWhispererClient.createUploadUrl(srcReq).catch((err) => {
@@ -310,7 +312,8 @@ export async function downloadResultArchive(
310312
},
311313
},
312314
},
313-
pathToArchive
315+
pathToArchive,
316+
AuthUtil.instance.regionProfileManager.activeRegionProfile
314317
)
315318
} catch (e: any) {
316319
downloadErrorMessage = (e as Error).message

packages/core/src/codewhisperer/service/transformByQ/transformApiHandler.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ import { encodeHTML } from '../../../shared/utilities/textUtilities'
5151
import { convertToTimeString } from '../../../shared/datetime'
5252
import { getAuthType } from '../../../auth/utils'
5353
import { UserWrittenCodeTracker } from '../../tracker/userWrittenCodeTracker'
54+
import { AuthUtil } from '../../util/authUtil'
5455

5556
export function getSha256(buffer: Buffer) {
5657
const hasher = crypto.createHash('sha256')
@@ -193,7 +194,11 @@ export async function stopJob(jobId: string) {
193194
}
194195
}
195196

196-
export async function uploadPayload(payloadFileName: string, uploadContext?: UploadContext) {
197+
export async function uploadPayload(
198+
payloadFileName: string,
199+
profile: RegionProfile | undefined,
200+
uploadContext?: UploadContext
201+
) {
197202
const buffer = Buffer.from(await fs.readFileBytes(payloadFileName))
198203
const sha256 = getSha256(buffer)
199204

@@ -205,6 +210,7 @@ export async function uploadPayload(payloadFileName: string, uploadContext?: Upl
205210
contentChecksumType: CodeWhispererConstants.contentChecksumType,
206211
uploadIntent: CodeWhispererConstants.uploadIntent,
207212
uploadContext,
213+
profileArn: profile?.arn,
208214
})
209215
} catch (e: any) {
210216
const errorMessage = `Creating the upload URL failed due to: ${(e as Error).message}`
@@ -759,7 +765,8 @@ export async function downloadResultArchive(
759765
exportId: jobId,
760766
exportIntent: ExportIntent.TRANSFORMATION,
761767
},
762-
pathToArchive
768+
pathToArchive,
769+
AuthUtil.instance.regionProfileManager.activeRegionProfile
763770
)
764771
} catch (e: any) {
765772
getLogger().error(`CodeTransformation: ExportResultArchive error = %O`, e)

packages/core/src/codewhisperer/service/transformByQ/transformationResultsViewProvider.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import { ChatSessionManager } from '../../../amazonqGumby/chat/storages/chatSess
2727
import { setContext } from '../../../shared/vscode/setContext'
2828
import * as codeWhisperer from '../../client/codewhisperer'
2929
import { UserWrittenCodeTracker } from '../../tracker/userWrittenCodeTracker'
30+
import { AuthUtil } from '../../util/authUtil'
3031

3132
export abstract class ProposedChangeNode {
3233
abstract readonly resourcePath: string
@@ -403,7 +404,8 @@ export class ProposedTransformationExplorer {
403404
exportId: transformByQState.getJobId(),
404405
exportIntent: ExportIntent.TRANSFORMATION,
405406
},
406-
pathToArchive
407+
pathToArchive,
408+
AuthUtil.instance.regionProfileManager.activeRegionProfile
407409
)
408410

409411
getLogger().info('CodeTransformation: downloaded results successfully')

packages/core/src/shared/utilities/download.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import { CodeWhispererStreaming, ExportResultArchiveCommandInput } from '@amzn/codewhisperer-streaming'
77
import { ToolkitError } from '../errors'
88
import fs from '../fs/fs'
9+
import { RegionProfile } from '../../codewhisperer/models/model'
910

1011
/**
1112
* This class represents the structure of the archive returned by the ExportResultArchive endpoint
@@ -21,9 +22,10 @@ export class ExportResultArchiveStructure {
2122
export async function downloadExportResultArchive(
2223
cwStreamingClient: CodeWhispererStreaming,
2324
exportResultArchiveArgs: ExportResultArchiveCommandInput,
24-
toPath: string
25+
toPath: string,
26+
profile: RegionProfile | undefined
2527
) {
26-
const result = await cwStreamingClient.exportResultArchive(exportResultArchiveArgs)
28+
const result = await cwStreamingClient.exportResultArchive({ ...exportResultArchiveArgs, profileArn: profile?.arn })
2729

2830
const buffer = []
2931

0 commit comments

Comments
 (0)