Skip to content

Commit ad8ef31

Browse files
committed
PR fixes: refactoring, syntax changes
1 parent 2f9891e commit ad8ef31

File tree

7 files changed

+109
-141
lines changed

7 files changed

+109
-141
lines changed

packages/core/src/amazonqGumby/activation.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,13 @@ export async function activate(context: ExtContext) {
7272
)
7373
}),
7474

75+
Commands.register(
76+
'aws.amazonq.transformationHub.updateContent',
77+
async (button, startTime, historyFileUpdated) => {
78+
await transformationHubViewProvider.updateContent(button, startTime, historyFileUpdated)
79+
}
80+
),
81+
7582
workspaceChangeEvent
7683
)
7784
}

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

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -192,12 +192,7 @@ export class GumbyController {
192192
private async transformInitiated(message: any) {
193193
// check if any jobs potentially still in progress on backend
194194
const history = readHistoryFile()
195-
let numInProgress = 0
196-
history.forEach((job) => {
197-
if (job.status === 'FAILED') {
198-
numInProgress += 1
199-
}
200-
})
195+
const numInProgress = history.filter((job) => job.status === 'FAILED').length
201196
this.messenger.sendViewHistoryMessage(message.tabID, numInProgress)
202197
if (transformByQState.isRefreshInProgress()) {
203198
this.messenger.sendMessage(CodeWhispererConstants.refreshInProgressChatMessage, message.tabID, 'ai-prompt')

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

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -749,15 +749,14 @@ export async function postTransformationJob() {
749749
})
750750
}
751751

752+
// delete original upload ZIP at very end of transformation
753+
fs.rmSync(transformByQState.getPayloadFilePath(), { force: true })
754+
752755
if (
753756
transformByQState.isSucceeded() ||
754757
transformByQState.isPartiallySucceeded() ||
755758
transformByQState.isCancelled()
756759
) {
757-
if (transformByQState.getPayloadFilePath()) {
758-
// delete original upload ZIP at very end of transformation
759-
fs.rmSync(transformByQState.getPayloadFilePath(), { force: true })
760-
}
761760
// delete the copy of the upload ZIP
762761
fs.rmSync(path.join(transformByQState.getJobHistoryPath(), 'zipped-code.zip'), { force: true })
763762
// delete transformation job metadata file (no longer needed)
@@ -801,7 +800,7 @@ export async function postTransformationJob() {
801800
]
802801

803802
const jobDetails = fields.join('\t') + '\n'
804-
fs.writeFileSync(historyLogFilePath, jobDetails, { flag: 'a' })
803+
fs.writeFileSync(historyLogFilePath, jobDetails, { flag: 'a' }) // 'a' flag used to append to file
805804
await vscode.commands.executeCommand(
806805
'aws.amazonq.transformationHub.updateContent',
807806
'job history',

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

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -812,7 +812,8 @@ export const viewHistoryMessage = (numInProgress: number) =>
812812
: 'View previous transformations run from the IDE'
813813

814814
export const transformationHistoryTableDescription =
815-
'This table lists the most recent jobs that you have run in the past 30 days. To open the diff patch and summary files, click the provided links. Jobs with a status of FAILED may still be in progress. Resume them within 12 hours of starting the job to get an updated job status and artifacts. Click the refresh icon to do so. The diff patch and summary will appear once they are available.'
815+
'This table lists the most recent jobs that you have run in the past 30 days. To open the diff patch and summary files, click the provided links. To get an updated job status, click the refresh icon. The diff patch and summary will appear once they are available.<br><br>' +
816+
'Jobs with a status of FAILED may still be in progress. Resume these jobs within 12 hours of starting the job to get an updated job status and artifacts.'
816817

817818
export const refreshErrorChatMessage =
818819
"Sorry, I couldn't refresh the job. Please try again or start a new transformation."
@@ -935,3 +936,13 @@ export const predictionTrackerDefaultConfig = {
935936
}
936937

937938
export const findingsSuffix = '_codeReviewFindings'
939+
940+
export interface HistoryObject {
941+
startTime: string
942+
projectName: string
943+
status: string
944+
duration: string
945+
diffPath: string
946+
summaryPath: string
947+
jobId: string
948+
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1157,6 +1157,7 @@ export class TransformByQState {
11571157
this.buildLog = ''
11581158
this.customBuildCommand = ''
11591159
this.intervalId = undefined
1160+
this.jobHistoryPath = ''
11601161
}
11611162
}
11621163

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

Lines changed: 77 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -26,36 +26,19 @@ import { startInterval, pollTransformationStatusUntilComplete } from '../../comm
2626
import { CodeTransformTelemetryState } from '../../../amazonqGumby/telemetry/codeTransformTelemetryState'
2727
import { convertToTimeString, isWithin30Days } from '../../../shared/datetime'
2828
import { AuthUtil } from '../../util/authUtil'
29-
import fs from 'fs'
29+
import fs from 'fs' // eslint-disable-line no-restricted-imports
3030
import path from 'path'
3131
import os from 'os'
3232
import { ChatSessionManager } from '../../../amazonqGumby/chat/storages/chatSession'
3333
import { setMaven } from './transformFileHandler'
3434

35-
interface HistoryObject {
36-
startTime: string
37-
projectName: string
38-
status: string
39-
duration: string
40-
diffPath: string
41-
summaryPath: string
42-
jobId: string
43-
}
44-
4535
export class TransformationHubViewProvider implements vscode.WebviewViewProvider {
4636
public static readonly viewType = 'aws.amazonq.transformationHub'
4737
private _view?: vscode.WebviewView
4838
private lastClickedButton: string = ''
4939
private _extensionUri: vscode.Uri = globals.context.extensionUri
50-
private transformationHistory: HistoryObject[] = []
51-
constructor() {
52-
vscode.commands.registerCommand(
53-
'aws.amazonq.transformationHub.updateContent',
54-
(button: 'job history' | 'plan progress', startTime?: number, historyFileUpdated?: boolean) => {
55-
return this.updateContent(button, startTime, historyFileUpdated)
56-
}
57-
)
58-
}
40+
private transformationHistory: CodeWhispererConstants.HistoryObject[] = []
41+
constructor() {}
5942
static #instance: TransformationHubViewProvider
6043

6144
public async updateContent(
@@ -101,13 +84,13 @@ export class TransformationHubViewProvider implements vscode.WebviewViewProvider
10184
this._view.webview.onDidReceiveMessage((message) => {
10285
switch (message.command) {
10386
case 'refreshJob':
104-
this.refreshJob(message.jobId, message.currentStatus, message.projectName)
87+
void this.refreshJob(message.jobId, message.currentStatus, message.projectName)
10588
break
10689
case 'openSummaryPreview':
107-
vscode.commands.executeCommand('markdown.showPreview', vscode.Uri.file(message.filePath))
90+
void vscode.commands.executeCommand('markdown.showPreview', vscode.Uri.file(message.filePath))
10891
break
10992
case 'openDiffFile':
110-
vscode.commands.executeCommand('vscode.open', vscode.Uri.file(message.filePath))
93+
void vscode.commands.executeCommand('vscode.open', vscode.Uri.file(message.filePath))
11194
break
11295
}
11396
})
@@ -132,7 +115,7 @@ export class TransformationHubViewProvider implements vscode.WebviewViewProvider
132115
}
133116

134117
private showJobHistory(): string {
135-
const jobsToDisplay: HistoryObject[] = [...this.transformationHistory]
118+
const jobsToDisplay: CodeWhispererConstants.HistoryObject[] = [...this.transformationHistory]
136119
if (transformByQState.isRunning()) {
137120
const current = sessionJobHistory[transformByQState.getJobId()]
138121
jobsToDisplay.unshift({
@@ -202,7 +185,7 @@ export class TransformationHubViewProvider implements vscode.WebviewViewProvider
202185
</html>`
203186
}
204187

205-
private getTableMarkup(history: HistoryObject[]) {
188+
private getTableMarkup(history: CodeWhispererConstants.HistoryObject[]) {
206189
return `
207190
<style>
208191
.refresh-btn {
@@ -286,16 +269,16 @@ export class TransformationHubViewProvider implements vscode.WebviewViewProvider
286269
transformationJobId: jobId,
287270
profileArn: undefined,
288271
})
289-
status = response.transformationJob.status!
272+
status = response.transformationJob.status ?? currentStatus
290273
if (response.transformationJob.endExecutionTime && response.transformationJob.creationTime) {
291274
duration = convertToTimeString(
292275
response.transformationJob.endExecutionTime.getTime() -
293276
response.transformationJob.creationTime.getTime()
294277
)
295278
}
296279

297-
getLogger().info(
298-
'Code Transformation: Job Id: %s\nFetched status: %s\nDuration: %s',
280+
getLogger().debug(
281+
'Code Transformation: Job refresh - Fetched status for job id: %s\n{Status: %s; Duration: %s}',
299282
jobId,
300283
status,
301284
duration
@@ -333,94 +316,34 @@ export class TransformationHubViewProvider implements vscode.WebviewViewProvider
333316
}
334317
transformByQState.setRefreshInProgress(true)
335318
const messenger = transformByQState.getChatMessenger()
336-
if (messenger) {
337-
messenger.sendJobRefreshInProgressMessage(ChatSessionManager.Instance.getSession().tabID!, jobId)
338-
}
319+
const tabID = ChatSessionManager.Instance.getSession().tabID
320+
messenger?.sendJobRefreshInProgressMessage(tabID!, jobId)
321+
void this.updateContent('job history') // refreshing the table disables all jobs' refresh buttons while this one is resuming
339322

340-
// set state to prepare to resume job
341-
transformByQState.setJobId(jobId)
342-
transformByQState.setPolledJobStatus(status)
323+
// resume job and bring to completion
343324
try {
344-
transformByQState.setJobHistoryPath(path.join(os.homedir(), '.aws', 'transform', projectName, jobId))
345-
const metadataFile = fs.readFileSync(path.join(transformByQState.getJobHistoryPath(), 'metadata.txt'), {
346-
encoding: 'utf8',
347-
flag: 'r',
348-
})
349-
const metadata = metadataFile.split('\t')
350-
transformByQState.setTransformationType(metadata[1] as TransformationType)
351-
transformByQState.setSourceJDKVersion(metadata[2] as JDKVersion)
352-
transformByQState.setTargetJDKVersion(metadata[3] as JDKVersion)
353-
transformByQState.setCustomDependencyVersionFilePath(metadata[4])
354-
transformByQState.setPayloadFilePath(
355-
path.join(os.homedir(), '.aws', 'transform', projectName, jobId, 'zipped-code.zip')
356-
)
357-
setMaven()
358-
transformByQState.setCustomBuildCommand(metadata[5])
359-
transformByQState.setTargetJavaHome(metadata[6])
360-
transformByQState.setProjectPath(metadata[7])
361-
transformByQState.setStartTime(metadata[8])
325+
status = await this.resumeJob(jobId, projectName, status)
362326
} catch (e: any) {
363-
// reaching this means there was most likely a problem with the metadata file
364-
getLogger().error('Code Transformation: Error setting job state: %s', (e as Error).message)
327+
getLogger().error('Code Transformation: Error resuming job (id: %s): %s', jobId, (e as Error).message)
365328
transformByQState.setJobDefaults()
366-
if (messenger) {
367-
messenger.sendJobFinishedMessage(
368-
ChatSessionManager.Instance.getSession().tabID!,
369-
CodeWhispererConstants.refreshErrorChatMessage
370-
)
371-
}
329+
messenger?.sendJobFinishedMessage(tabID!, CodeWhispererConstants.refreshErrorChatMessage)
372330
void vscode.window.showErrorMessage(CodeWhispererConstants.refreshErrorNotification(jobId))
331+
void this.updateContent('job history')
373332
return
374333
}
375334

376-
// resume polling job
377-
try {
378-
this.updateContent('job history') // refreshing the table disables all jobs' refresh buttons while this one is polling
379-
status = await pollTransformationStatusUntilComplete(
380-
jobId,
381-
AuthUtil.instance.regionProfileManager.activeRegionProfile
382-
)
383-
if (
384-
CodeWhispererConstants.validStatesForCheckingDownloadUrl.includes(status) &&
385-
!CodeWhispererConstants.failureStates.includes(status)
386-
) {
387-
duration = convertToTimeString(
388-
new Date().getTime() - new Date(transformByQState.getStartTime()).getTime()
389-
)
390-
jobHistoryPath = await this.retrieveArtifacts(jobId, projectName)
391-
// delete payload and metadata files
392-
if (transformByQState.getPayloadFilePath()) {
393-
fs.rmSync(transformByQState.getPayloadFilePath(), { force: true })
394-
}
395-
fs.rmSync(path.join(transformByQState.getJobHistoryPath(), 'metadata.txt'), { force: true })
396-
// delete temporary build logs file
397-
const logFilePath = path.join(os.tmpdir(), 'build-logs.txt')
398-
if (fs.existsSync(logFilePath)) {
399-
fs.rmSync(logFilePath, { force: true })
400-
}
401-
}
402-
} catch (e: any) {
403-
getLogger().error('Code Transformation: Error resuming job (id: %s): %s', jobId, (e as Error).message)
404-
transformByQState.setJobDefaults()
405-
if (messenger) {
406-
messenger.sendJobFinishedMessage(
407-
ChatSessionManager.Instance.getSession().tabID!,
408-
CodeWhispererConstants.refreshErrorChatMessage
409-
)
410-
}
411-
void vscode.window.showErrorMessage(CodeWhispererConstants.refreshErrorNotification(jobId))
412-
this.updateContent('job history') // re-enable refresh buttons
413-
return
335+
// download artifacts if available
336+
if (
337+
CodeWhispererConstants.validStatesForCheckingDownloadUrl.includes(status) &&
338+
!CodeWhispererConstants.failureStates.includes(status)
339+
) {
340+
duration = convertToTimeString(Date.now() - new Date(transformByQState.getStartTime()).getTime())
341+
jobHistoryPath = await this.retrieveArtifacts(jobId, projectName)
414342
}
415343

416344
// reset state
417345
transformByQState.setJobDefaults()
418-
if (messenger) {
419-
messenger.sendJobFinishedMessage(
420-
ChatSessionManager.Instance.getSession().tabID!,
421-
CodeWhispererConstants.refreshCompletedChatMessage
422-
)
423-
}
346+
messenger?.sendJobFinishedMessage(tabID!, CodeWhispererConstants.refreshCompletedChatMessage)
424347
} else {
425348
// FAILED or STOPPED job
426349
getLogger().info('Code Transformation: No artifacts available to download (job status = %s)', status)
@@ -472,10 +395,8 @@ export class TransformationHubViewProvider implements vscode.WebviewViewProvider
472395
} catch (error) {
473396
jobHistoryPath = ''
474397
} finally {
475-
if (fs.existsSync(resultsPath)) {
476-
fs.rmSync(resultsPath, { recursive: true, force: true })
477-
}
478-
getLogger().info('Code Transformation: Deleted temporary extraction directory')
398+
// delete temporary extraction directory
399+
fs.rmSync(resultsPath, { recursive: true, force: true })
479400
}
480401
}
481402
return jobHistoryPath
@@ -489,7 +410,7 @@ export class TransformationHubViewProvider implements vscode.WebviewViewProvider
489410
const jobs = historyFile.split('\n')
490411
jobs.shift() // removes headers
491412
if (jobs.length > 0) {
492-
jobs.forEach((job) => {
413+
for (const job of jobs) {
493414
if (job) {
494415
const jobInfo = job.split('\t')
495416
// startTime: jobInfo[0], projectName: jobInfo[1], status: jobInfo[2], duration: jobInfo[3], diffPath: jobInfo[4], summaryPath: jobInfo[5], jobId: jobInfo[6]
@@ -506,7 +427,7 @@ export class TransformationHubViewProvider implements vscode.WebviewViewProvider
506427
}
507428
history.push(jobInfo)
508429
}
509-
})
430+
}
510431
}
511432
}
512433
if (history.length > 0) {
@@ -520,6 +441,50 @@ export class TransformationHubViewProvider implements vscode.WebviewViewProvider
520441
}
521442
}
522443

444+
private async resumeJob(jobId: string, projectName: string, status: string) {
445+
// set state to prepare to resume job
446+
await this.setupTransformationState(jobId, projectName, status)
447+
// resume polling the job
448+
return await this.pollAndCompleteTransformation(jobId)
449+
}
450+
451+
private async setupTransformationState(jobId: string, projectName: string, status: string) {
452+
transformByQState.setJobId(jobId)
453+
transformByQState.setPolledJobStatus(status)
454+
transformByQState.setJobHistoryPath(path.join(os.homedir(), '.aws', 'transform', projectName, jobId))
455+
const metadataFile = fs.readFileSync(path.join(transformByQState.getJobHistoryPath(), 'metadata.txt'), {
456+
encoding: 'utf8',
457+
flag: 'r',
458+
})
459+
const metadata = metadataFile.split('\t')
460+
transformByQState.setTransformationType(metadata[1] as TransformationType)
461+
transformByQState.setSourceJDKVersion(metadata[2] as JDKVersion)
462+
transformByQState.setTargetJDKVersion(metadata[3] as JDKVersion)
463+
transformByQState.setCustomDependencyVersionFilePath(metadata[4])
464+
transformByQState.setPayloadFilePath(
465+
path.join(os.homedir(), '.aws', 'transform', projectName, jobId, 'zipped-code.zip')
466+
)
467+
setMaven()
468+
transformByQState.setCustomBuildCommand(metadata[5])
469+
transformByQState.setTargetJavaHome(metadata[6])
470+
transformByQState.setProjectPath(metadata[7])
471+
transformByQState.setStartTime(metadata[8])
472+
}
473+
474+
private async pollAndCompleteTransformation(jobId: string) {
475+
const status = await pollTransformationStatusUntilComplete(
476+
jobId,
477+
AuthUtil.instance.regionProfileManager.activeRegionProfile
478+
)
479+
// delete payload and metadata files
480+
fs.rmSync(transformByQState.getPayloadFilePath(), { force: true })
481+
fs.rmSync(path.join(transformByQState.getJobHistoryPath(), 'metadata.txt'), { force: true })
482+
// delete temporary build logs file
483+
const logFilePath = path.join(os.tmpdir(), 'build-logs.txt')
484+
fs.rmSync(logFilePath, { force: true })
485+
return status
486+
}
487+
523488
private generateTransformationStepMarkup(
524489
name: string,
525490
startTime: Date | undefined,
@@ -928,8 +893,8 @@ export class TransformationHubViewProvider implements vscode.WebviewViewProvider
928893
}
929894
}
930895

931-
export function readHistoryFile(): HistoryObject[] {
932-
const history: HistoryObject[] = []
896+
export function readHistoryFile(): CodeWhispererConstants.HistoryObject[] {
897+
const history: CodeWhispererConstants.HistoryObject[] = []
933898
const jobHistoryFilePath = path.join(os.homedir(), '.aws', 'transform', 'transformation_history.tsv')
934899
if (fs.existsSync(jobHistoryFilePath)) {
935900
const historyFile = fs.readFileSync(jobHistoryFilePath, { encoding: 'utf8', flag: 'r' })

0 commit comments

Comments
 (0)