Skip to content

Commit a3659a0

Browse files
author
David Hasani
committed
part 2 of dms
1 parent e7916fe commit a3659a0

File tree

10 files changed

+146
-73
lines changed

10 files changed

+146
-73
lines changed

packages/core/src/amazonqGumby/chat/controller/controller.ts

Lines changed: 50 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,9 @@ export class GumbyController {
346346
case ButtonActions.CONFIRM_SQL_CONVERSION_TRANSFORMATION_FORM:
347347
await this.handleUserSQLConversionProjectSelection(message)
348348
break
349+
case ButtonActions.SELECT_SQL_CONVERSION_METADATA_FILE:
350+
await this.processMetadataFile(message)
351+
break
349352
case ButtonActions.VIEW_TRANSFORMATION_HUB:
350353
await vscode.commands.executeCommand(GumbyCommands.FOCUS_TRANSFORMATION_HUB, CancelActionPositions.Chat)
351354
this.messenger.sendJobSubmittedMessage(message.tabID)
@@ -436,8 +439,8 @@ export class GumbyController {
436439
private async handleUserSQLConversionProjectSelection(message: any) {
437440
await telemetry.codeTransform_submitSelection.run(async () => {
438441
const pathToProject: string = message.formSelectedValues['GumbyTransformSQLConversionProjectForm']
439-
const toDB: DB = message.formSelectedValues['GumbyTransformDBToForm']
440442
const fromDB: DB = message.formSelectedValues['GumbyTransformDBFromForm']
443+
const toDB: DB = message.formSelectedValues['GumbyTransformDBToForm']
441444

442445
telemetry.record({
443446
codeTransformProjectId: pathToProject === undefined ? telemetryUndefined : getStringHash(pathToProject),
@@ -457,7 +460,7 @@ export class GumbyController {
457460
}
458461

459462
await processSQLConversionTransformFormInput(pathToProject, fromDB, toDB)
460-
await this.getMetadataFile(message)
463+
this.messenger.sendSelectSQLMetadataFileMessage(message.tabID)
461464
})
462465
}
463466

@@ -526,7 +529,47 @@ export class GumbyController {
526529
await this.prepareLanguageUpgradeProjectForSubmission(message)
527530
}
528531

529-
private async getMetadataFile(message: any | undefined = undefined) {
532+
private async validateMetadataFile(sctRulesData: any, message: any) {
533+
try {
534+
const sctRules = JSON.parse(sctRulesData)
535+
const sourceDB = sctRules['rules'][0]['locator']['sourceVendor'] as string
536+
const targetDB = sctRules['rules'][0]['locator']['targetVendor'] as string
537+
if (sourceDB.toUpperCase() !== DB.ORACLE) {
538+
this.messenger.sendJobFinishedMessage(
539+
message.tabID,
540+
CodeWhispererConstants.invalidMetadataFileUnsupportedSourceVendor(sourceDB)
541+
)
542+
return false
543+
} else if (
544+
targetDB.toUpperCase() !== DB.AURORA_POSTGRESQL &&
545+
targetDB.toUpperCase() !== DB.RDS_POSTGRESQL
546+
) {
547+
this.messenger.sendJobFinishedMessage(
548+
message.tabID,
549+
CodeWhispererConstants.invalidMetadataFileUnsupportedTargetVendor(targetDB)
550+
)
551+
return false
552+
} else if (targetDB.toUpperCase() !== transformByQState.getTargetDB()) {
553+
this.messenger.sendJobFinishedMessage(
554+
message.tabID,
555+
CodeWhispererConstants.invalidMetadataFileTargetVendorMismatch(
556+
targetDB,
557+
transformByQState.getTargetDB()!
558+
)
559+
)
560+
return false
561+
}
562+
} catch (e: any) {
563+
this.messenger.sendJobFinishedMessage(
564+
message.tabID,
565+
CodeWhispererConstants.invalidMetadataFileUnknownIssueParsing
566+
)
567+
return false
568+
}
569+
return true
570+
}
571+
572+
private async processMetadataFile(message: any) {
530573
const fileUri = await vscode.window.showOpenDialog({
531574
canSelectMany: false, // Allow only one file to be selected
532575
openLabel: 'Select', // Label for the open button
@@ -550,33 +593,12 @@ export class GumbyController {
550593
}
551594

552595
const sctRulesData = nodefs.readFileSync(path.join(pathToZip, pathToRules), 'utf8')
553-
try {
554-
const sctRules = JSON.parse(sctRulesData)
555-
const sourceDB = sctRules['rules'][0]['locator']['sourceVendor'] as string
556-
const targetDB = sctRules['rules'][0]['locator']['targetVendor'] as string
557-
if (sourceDB.toUpperCase() !== 'ORACLE') {
558-
this.messenger.sendJobFinishedMessage(
559-
message.tabID,
560-
CodeWhispererConstants.invalidMetadataFileUnsupportedSourceVendor(sourceDB)
561-
)
562-
return
563-
} else if (targetDB.toUpperCase() !== 'AURORA_POSTGRESQL') {
564-
// TO-DO: or !== 'AMAZON_RDS' or something like that
565-
this.messenger.sendJobFinishedMessage(
566-
message.tabID,
567-
CodeWhispererConstants.invalidMetadataFileUnsupportedTargetVendor(targetDB)
568-
)
569-
return
570-
}
571-
} catch (e: any) {
572-
this.messenger.sendJobFinishedMessage(
573-
message.tabID,
574-
CodeWhispererConstants.invalidMetadataFileUnknownIssueParsing
575-
)
596+
const isValidSctRulesData = await this.validateMetadataFile(sctRulesData, message)
597+
if (!isValidSctRulesData) {
576598
return
577599
}
578600

579-
transformByQState.setMetadataPathSQL(pathToZip)
601+
transformByQState.setMetadataPathSQL(fileUri[0].fsPath)
580602

581603
this.messenger.sendAsyncEventProgress(
582604
message.tabID,
@@ -586,7 +608,7 @@ export class GumbyController {
586608
)
587609
this.messenger.sendJobSubmittedMessage(message.tabID)
588610
this.sessionStorage.getSession().conversationState = ConversationState.JOB_SUBMITTED
589-
// await startTransformByQ()
611+
await startTransformByQ()
590612
}
591613

592614
private transformationFinished(data: { message: string | undefined; tabID: string }) {

packages/core/src/amazonqGumby/chat/controller/messenger/messenger.ts

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -268,11 +268,11 @@ export class Messenger {
268268
options: [
269269
{
270270
value: DB.ORACLE,
271-
label: DB.ORACLE,
271+
label: CodeWhispererConstants.oracleVendor,
272272
},
273273
{
274274
value: DB.OTHER,
275-
label: DB.OTHER,
275+
label: CodeWhispererConstants.otherVendor,
276276
},
277277
],
278278
})
@@ -284,12 +284,12 @@ export class Messenger {
284284
mandatory: true,
285285
options: [
286286
{
287-
value: DB.AMAZON_RDS,
288-
label: DB.AMAZON_RDS,
287+
value: DB.RDS_POSTGRESQL,
288+
label: CodeWhispererConstants.rdsTargetVendor,
289289
},
290290
{
291-
value: DB.AMAZON_AURORA,
292-
label: DB.AMAZON_AURORA,
291+
value: DB.AURORA_POSTGRESQL,
292+
label: CodeWhispererConstants.auroraTargetVendor,
293293
},
294294
],
295295
})
@@ -720,4 +720,26 @@ ${codeSnippet}
720720
)
721721
)
722722
}
723+
724+
public sendSelectSQLMetadataFileMessage(tabID: string) {
725+
const message = 'Please select your metadata ZIP file.'
726+
const buttons: ChatItemButton[] = []
727+
728+
buttons.push({
729+
keepCardAfterClick: true,
730+
text: 'Select metadata file',
731+
id: ButtonActions.SELECT_SQL_CONVERSION_METADATA_FILE,
732+
})
733+
734+
this.dispatcher.sendChatMessage(
735+
new ChatMessage(
736+
{
737+
message,
738+
messageType: 'ai-prompt',
739+
buttons,
740+
},
741+
tabID
742+
)
743+
)
744+
}
723745
}

packages/core/src/amazonqGumby/chat/controller/messenger/messengerUtils.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export enum ButtonActions {
1818
CANCEL_TRANSFORMATION_FORM = 'gumbyTransformFormCancel', // shared between Language Upgrade & SQL Conversion
1919
CONFIRM_SKIP_TESTS_FORM = 'gumbyTransformSkipTestsFormConfirm',
2020
CANCEL_SKIP_TESTS_FORM = 'gumbyTransformSkipTestsFormCancel',
21+
SELECT_SQL_CONVERSION_METADATA_FILE = 'gumbySQLConversionMetadataTransformFormConfirm',
2122
CONFIRM_DEPENDENCY_FORM = 'gumbyTransformDependencyFormConfirm',
2223
CANCEL_DEPENDENCY_FORM = 'gumbyTransformDependencyFormCancel',
2324
CONFIRM_JAVA_HOME_FORM = 'gumbyJavaHomeFormConfirm',

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

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -289,8 +289,9 @@ export async function preTransformationUploadCode() {
289289
// if the user chose to skip unit tests, add the custom build command here
290290
transformZipManifest.customBuildCommand = transformByQState.getCustomBuildCommand()
291291
const zipCodeResult = await zipCode({
292-
dependenciesFolder: transformByQState.getDependencyFolderInfo()!,
293-
modulePath: transformByQState.getProjectPath(),
292+
// dependenciesFolder will be undefined for SQL conversions since we don't compileProject
293+
dependenciesFolder: transformByQState.getDependencyFolderInfo(),
294+
projectPath: transformByQState.getProjectPath(),
294295
zipManifest: transformZipManifest,
295296
})
296297

@@ -735,20 +736,23 @@ export async function postTransformationJob() {
735736
const durationInMs = calculateTotalLatency(CodeTransformTelemetryState.instance.getStartTime())
736737
const resultStatusMessage = transformByQState.getStatus()
737738

738-
const versionInfo = await getVersionData()
739-
const mavenVersionInfoMessage = `${versionInfo[0]} (${transformByQState.getMavenName()})`
740-
const javaVersionInfoMessage = `${versionInfo[1]} (${transformByQState.getMavenName()})`
741-
742-
// Note: IntelliJ implementation of ResultStatusMessage includes additional metadata such as jobId.
743-
telemetry.codeTransform_totalRunTime.emit({
744-
buildSystemVersion: mavenVersionInfoMessage,
745-
codeTransformSessionId: CodeTransformTelemetryState.instance.getSessionId(),
746-
codeTransformResultStatusMessage: resultStatusMessage,
747-
codeTransformRunTimeLatency: durationInMs,
748-
codeTransformLocalJavaVersion: javaVersionInfoMessage,
749-
result: resultStatusMessage === TransformByQStatus.Succeeded ? MetadataResult.Pass : MetadataResult.Fail,
750-
reason: resultStatusMessage,
751-
})
739+
if (!transformByQState.getMetadataPathSQL()) {
740+
// the below is only applicable when user is doing a Java 8/11 language upgrade
741+
const versionInfo = await getVersionData()
742+
const mavenVersionInfoMessage = `${versionInfo[0]} (${transformByQState.getMavenName()})`
743+
const javaVersionInfoMessage = `${versionInfo[1]} (${transformByQState.getMavenName()})`
744+
745+
// Note: IntelliJ implementation of ResultStatusMessage includes additional metadata such as jobId.
746+
telemetry.codeTransform_totalRunTime.emit({
747+
buildSystemVersion: mavenVersionInfoMessage,
748+
codeTransformSessionId: CodeTransformTelemetryState.instance.getSessionId(),
749+
codeTransformResultStatusMessage: resultStatusMessage,
750+
codeTransformRunTimeLatency: durationInMs,
751+
codeTransformLocalJavaVersion: javaVersionInfoMessage,
752+
result: resultStatusMessage === TransformByQStatus.Succeeded ? MetadataResult.Pass : MetadataResult.Fail,
753+
reason: resultStatusMessage,
754+
})
755+
}
752756

753757
if (transformByQState.isSucceeded()) {
754758
void vscode.window.showInformationMessage(CodeWhispererConstants.jobCompletedNotification)
@@ -770,7 +774,7 @@ export async function postTransformationJob() {
770774
}
771775

772776
if (transformByQState.getPayloadFilePath() !== '') {
773-
fs.rmSync(transformByQState.getPayloadFilePath(), { recursive: true, force: true }) // delete ZIP if it exists
777+
// fs.rmSync(transformByQState.getPayloadFilePath(), { recursive: true, force: true }) // delete ZIP if it exists
774778
}
775779
}
776780

packages/core/src/codewhisperer/models/constants.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -504,13 +504,24 @@ export const invalidMetadataFileNoRulesJson =
504504
"Sorry, your metadata ZIP appears to be invalid; it does not contain an 'sct-rules.json' file."
505505

506506
export const invalidMetadataFileUnsupportedSourceVendor = (vendor: string) =>
507-
`Sorry, your metadata ZIP appears to be invalid; the source vendor is '${vendor}', but only Oracle is supported.`
507+
`Sorry, your metadata ZIP appears to be invalid; the source vendor is '${vendor}', but only 'Oracle' is supported.`
508508

509509
export const invalidMetadataFileUnsupportedTargetVendor = (vendor: string) =>
510-
`Sorry, your metadata ZIP appears to be invalid; the target vendor is '${vendor}', but only Amazon Aurora PostgreSQL and Amazon RDS for PostgreSQL are supported.`
510+
`Sorry, your metadata ZIP appears to be invalid; the target vendor is '${vendor}', but only 'Amazon Aurora PostgreSQL' and 'Amazon RDS for PostgreSQL' are supported.`
511+
512+
export const invalidMetadataFileTargetVendorMismatch = (foundVendor: string, selectedVendor: string) =>
513+
`Sorry, your metadata ZIP appears to be invalid; the target vendor is '${foundVendor}', but you previously selected a target vendor of '${selectedVendor}'.`
511514

512515
export const invalidMetadataFileUnknownIssueParsing =
513-
'Sorry, I had an issue parsing the metadata ZIP you provided; please make sure it is valid'
516+
'Sorry, I had an issue parsing the metadata ZIP you provided; please make sure it is valid.'
517+
518+
export const oracleVendor = 'Oracle'
519+
520+
export const otherVendor = 'Other'
521+
522+
export const auroraTargetVendor = 'Amazon Aurora PostgreSQL'
523+
524+
export const rdsTargetVendor = 'Amazon RDS for PostgreSQL'
514525

515526
export const failedToStartJobChatMessage =
516527
"Sorry, I couldn't begin the transformation. Please try starting the transformation again."

packages/core/src/codewhisperer/models/model.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -304,10 +304,10 @@ export enum JDKVersion {
304304
}
305305

306306
export enum DB {
307-
ORACLE = 'Oracle',
308-
AMAZON_RDS = 'Amazon RDS for PostgreSQL',
309-
AMAZON_AURORA = 'Amazon Aurora PostgreSQL',
310-
OTHER = 'Other',
307+
ORACLE = 'ORACLE',
308+
RDS_POSTGRESQL = 'RDS_POSTGRESQL', // TO-DO: these should all match what source/target vendor look like in sct-rules.json
309+
AURORA_POSTGRESQL = 'AURORA_POSTGRESQL',
310+
OTHER = 'OTHER',
311311
}
312312

313313
export enum BuildSystem {
@@ -324,6 +324,7 @@ export class ZipManifest {
324324
hilCapabilities: string[] = ['HIL_1pDependency_VersionUpgrade']
325325
transformCapabilities: string[] = ['EXPLAINABILITY_V1']
326326
customBuildCommand: string = 'clean test'
327+
sqlMetadataPath: string | undefined = undefined
327328
}
328329

329330
export interface IHilZipManifestParams {
@@ -703,6 +704,7 @@ export class TransformByQState {
703704
this.jobFailureErrorChatMessage = undefined
704705
this.jobFailureMetadata = ''
705706
this.payloadFilePath = ''
707+
this.metadataPathSQL = ''
706708
this.errorLog = ''
707709
this.customBuildCommand = ''
708710
this.intervalId = undefined

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

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -275,9 +275,9 @@ export function createZipManifest({ hilZipParams }: IZipManifestParams) {
275275
}
276276

277277
interface IZipCodeParams {
278-
dependenciesFolder: FolderInfo
278+
dependenciesFolder?: FolderInfo
279279
humanInTheLoopFlag?: boolean
280-
modulePath?: string
280+
projectPath?: string
281281
zipManifest: ZipManifest | HilZipManifest
282282
}
283283

@@ -287,40 +287,51 @@ interface ZipCodeResult {
287287
fileSize: number
288288
}
289289

290-
export async function zipCode({ dependenciesFolder, humanInTheLoopFlag, modulePath, zipManifest }: IZipCodeParams) {
290+
export async function zipCode({ dependenciesFolder, humanInTheLoopFlag, projectPath, zipManifest }: IZipCodeParams) {
291291
let tempFilePath = undefined
292292
let logFilePath = undefined
293293
let dependenciesCopied = false
294294
try {
295295
throwIfCancelled()
296296
const zip = new AdmZip()
297297

298-
// If no modulePath is passed in, we are not uploaded the source folder
299-
// NOTE: We only upload dependencies for human in the loop work
300-
if (modulePath) {
301-
const sourceFiles = getFilesRecursively(modulePath, false)
298+
// if no project Path is passed in, we are not uploaded the source folder
299+
// we only upload dependencies for human in the loop work
300+
if (projectPath) {
301+
const sourceFiles = getFilesRecursively(projectPath, false)
302302
let sourceFilesSize = 0
303303
for (const file of sourceFiles) {
304304
if (nodefs.statSync(file).isDirectory()) {
305305
getLogger().info('CodeTransformation: Skipping directory, likely a symlink')
306306
continue
307307
}
308-
const relativePath = path.relative(modulePath, file)
308+
const relativePath = path.relative(projectPath, file)
309309
const paddedPath = path.join('sources', relativePath)
310310
zip.addLocalFile(file, path.dirname(paddedPath))
311311
sourceFilesSize += (await nodefs.promises.stat(file)).size
312312
}
313313
getLogger().info(`CodeTransformation: source code files size = ${sourceFilesSize}`)
314314
}
315315

316+
if (transformByQState.getMetadataPathSQL()) {
317+
// user is doing a SQL conversion
318+
zip.addLocalFile(transformByQState.getMetadataPathSQL())
319+
// must be true here, since only other option is HilZipManifest (not used for SQL conversions)
320+
if (zipManifest instanceof ZipManifest) {
321+
zipManifest.sqlMetadataPath = path.basename(transformByQState.getMetadataPathSQL())
322+
}
323+
const sqlMetadataSize = (await nodefs.promises.stat(transformByQState.getMetadataPathSQL())).size
324+
getLogger().info(`CodeTransformation: SQL metadata file size = ${sqlMetadataSize}`)
325+
}
326+
316327
throwIfCancelled()
317328

318329
let dependencyFiles: string[] = []
319-
if (await fs.exists(dependenciesFolder.path)) {
330+
if (dependenciesFolder && await fs.exists(dependenciesFolder.path)) {
320331
dependencyFiles = getFilesRecursively(dependenciesFolder.path, true)
321332
}
322333

323-
if (dependencyFiles.length > 0) {
334+
if (dependenciesFolder && dependencyFiles.length > 0) {
324335
let dependencyFilesSize = 0
325336
for (const file of dependencyFiles) {
326337
if (isExcludedDependencyFile(file)) {
@@ -354,7 +365,7 @@ export async function zipCode({ dependenciesFolder, humanInTheLoopFlag, modulePa
354365

355366
tempFilePath = path.join(os.tmpdir(), 'zipped-code.zip')
356367
await fs.writeFile(tempFilePath, zip.toBuffer())
357-
if (await fs.exists(dependenciesFolder.path)) {
368+
if (dependenciesFolder && await fs.exists(dependenciesFolder.path)) {
358369
await fs.delete(dependenciesFolder.path, { recursive: true, force: true })
359370
}
360371
} catch (e: any) {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ export class TransformationHubViewProvider implements vscode.WebviewViewProvider
331331
activeStepId === 0
332332
)
333333
const buildMarkup =
334-
activeStepId >= 1
334+
activeStepId >= 1 && !transformByQState.getMetadataPathSQL() // for SQL conversions, don't show buildCode step
335335
? simpleStep(
336336
this.getProgressIconMarkup(jobPlanProgress['buildCode']),
337337
CodeWhispererConstants.buildCodeStepMessage,

0 commit comments

Comments
 (0)