Skip to content

Commit c9d234b

Browse files
committed
Minor fixes and PR fixes
1 parent ba771da commit c9d234b

File tree

4 files changed

+89
-87
lines changed

4 files changed

+89
-87
lines changed

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

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import { AbsolutePathDetectedError } from '../../../amazonqGumby/errors'
1717
import { getLogger } from '../../../shared/logger/logger'
1818
import AdmZip from 'adm-zip'
1919
import { IManifestFile } from './humanInTheLoopManager'
20+
import { ExportResultArchiveStructure } from '../../../shared/utilities/download'
21+
import { isFileNotFoundError } from '../../../shared/errors'
2022

2123
export async function getDependenciesFolderInfo(): Promise<FolderInfo> {
2224
const dependencyFolderName = `${CodeWhispererConstants.dependencyFolderName}${globals.clock.Date.now()}`
@@ -348,3 +350,40 @@ export async function parseVersionsListFromPomFile(xmlString: string): Promise<I
348350

349351
return { latestVersion, majorVersions, minorVersions, status }
350352
}
353+
354+
/**
355+
* Saves a copy of the diff patch, summary, and build logs (if any) locally
356+
*
357+
* @param pathToArchiveDir path to the archive directory where the artifacts are unzipped
358+
* @param pathToDestinationDir destination directory (will create directories if path doesn't exist already)
359+
*/
360+
export async function copyArtifacts(pathToArchiveDir: string, pathToDestinationDir: string) {
361+
// create destination path if doesn't exist already
362+
// mkdir() will not raise an error if path exists
363+
await fs.mkdir(pathToDestinationDir)
364+
365+
const diffPath = path.join(pathToArchiveDir, ExportResultArchiveStructure.PathToDiffPatch)
366+
const summaryPath = path.join(pathToArchiveDir, ExportResultArchiveStructure.PathToSummary)
367+
368+
try {
369+
await fs.copy(diffPath, path.join(pathToDestinationDir, 'diff.patch'))
370+
// make summary directory if needed
371+
await fs.mkdir(path.join(pathToDestinationDir, 'summary'))
372+
await fs.copy(summaryPath, path.join(pathToDestinationDir, 'summary', 'summary.md'))
373+
} catch (error) {
374+
getLogger().error('Code Transformation: Error saving local copy of artifacts: %s', (error as Error).message)
375+
}
376+
377+
const buildLogsPath = path.join(path.dirname(summaryPath), 'buildCommandOutput.log')
378+
try {
379+
await fs.copy(buildLogsPath, path.join(pathToDestinationDir, 'summary', 'buildCommandOutput.log'))
380+
} catch (error) {
381+
// build logs won't exist for SQL conversions (not an error)
382+
if (!isFileNotFoundError(error)) {
383+
getLogger().error(
384+
'Code Transformation: Error saving local copy of build logs: %s',
385+
(error as Error).message
386+
)
387+
}
388+
}
389+
}

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

Lines changed: 5 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,12 @@ import * as CodeWhispererConstants from '../../models/constants'
1111
import { JDKVersion, TransformationType, transformByQState } from '../../models/model'
1212
import { getLogger } from '../../../shared/logger/logger'
1313
import { codeWhispererClient } from '../../../codewhisperer/client/codewhisperer'
14-
import { pollTransformationStatusUntilComplete } from '../../commands/startTransformByQ'
15-
import { downloadAndExtractResultArchive } from './transformApiHandler'
14+
import { downloadAndExtractResultArchive, pollTransformationJob } from './transformApiHandler'
1615
import { ChatSessionManager } from '../../../amazonqGumby/chat/storages/chatSession'
1716
import { AuthUtil } from '../../util/authUtil'
1817
import { setMaven } from './transformFileHandler'
1918
import { convertToTimeString, isWithin30Days } from '../../../shared/datetime'
20-
import { ExportResultArchiveStructure } from '../../../shared/utilities/download'
21-
import { isFileNotFoundError } from '../../../shared/errors'
19+
import { copyArtifacts } from './transformFileHandler'
2220

2321
export interface HistoryObject {
2422
startTime: string
@@ -111,43 +109,6 @@ export async function createMetadataFile(payloadFilePath: string, metadata: JobM
111109
return jobHistoryPath
112110
}
113111

114-
/**
115-
* Saves a copy of the diff patch, summary, and build logs (if any) locally
116-
*
117-
* @param pathToArchiveDir path to the archive directory where the artifacts are unzipped
118-
* @param pathToDestinationDir destination directory (will create directories if path doesn't exist already)
119-
*/
120-
export async function copyArtifacts(pathToArchiveDir: string, pathToDestinationDir: string) {
121-
// create destination path if doesn't exist already
122-
// mkdir() will not raise an error if path exists
123-
await fs.mkdir(pathToDestinationDir)
124-
125-
const diffPath = path.join(pathToArchiveDir, ExportResultArchiveStructure.PathToDiffPatch)
126-
const summaryPath = path.join(pathToArchiveDir, ExportResultArchiveStructure.PathToSummary)
127-
128-
try {
129-
await fs.copy(diffPath, path.join(pathToDestinationDir, 'diff.patch'))
130-
// make summary directory if needed
131-
await fs.mkdir(path.join(pathToDestinationDir, 'summary'))
132-
await fs.copy(summaryPath, path.join(pathToDestinationDir, 'summary', 'summary.md'))
133-
} catch (error) {
134-
getLogger().error('Code Transformation: Error saving local copy of artifacts: %s', (error as Error).message)
135-
}
136-
137-
const buildLogsPath = path.join(summaryPath, 'buildCommandOutput.log')
138-
try {
139-
await fs.copy(buildLogsPath, path.join(pathToDestinationDir, 'summary', 'buildCommandOutput.log'))
140-
} catch (error) {
141-
// build logs won't exist for SQL conversions (not an error)
142-
if (!isFileNotFoundError(error)) {
143-
getLogger().error(
144-
'Code Transformation: Error saving local copy of build logs: %s',
145-
(error as Error).message
146-
)
147-
}
148-
}
149-
}
150-
151112
/**
152113
* Writes job details to history file
153114
*
@@ -248,7 +209,7 @@ export async function refreshJob(jobId: string, currentStatus: string, projectNa
248209
getLogger().error('Code Transformation: Error fetching status (job id: %s): %s', jobId, errorMessage)
249210
if (errorMessage.includes('not authorized to make this call')) {
250211
// job not available on backend
251-
status = 'FAILED'
212+
status = 'FAILED' // won't allow retries for this job
252213
} else {
253214
// some other error (e.g. network error)
254215
return
@@ -418,8 +379,9 @@ async function setupTransformationState(jobId: string, projectName: string, stat
418379
}
419380

420381
async function pollAndCompleteTransformation(jobId: string) {
421-
const status = await pollTransformationStatusUntilComplete(
382+
const status = await pollTransformationJob(
422383
jobId,
384+
CodeWhispererConstants.validStatesForCheckingDownloadUrl,
423385
AuthUtil.instance.regionProfileManager.activeRegionProfile
424386
)
425387
await cleanupTempJobFiles(transformByQState.getJobHistoryPath(), status, transformByQState.getPayloadFilePath())

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import { setContext } from '../../../shared/vscode/setContext'
2222
import * as codeWhisperer from '../../client/codewhisperer'
2323
import { UserWrittenCodeTracker } from '../../tracker/userWrittenCodeTracker'
2424
import { AuthUtil } from '../../util/authUtil'
25-
import { copyArtifacts } from './transformationHistoryHandler'
25+
import { copyArtifacts } from './transformFileHandler'
2626

2727
export abstract class ProposedChangeNode {
2828
abstract readonly resourcePath: string

packages/core/src/test/amazonqGumby/transformationJobHistory.test.ts

Lines changed: 44 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,37 @@ import {
1515
readHistoryFile,
1616
writeToHistoryFile,
1717
createMetadataFile,
18-
copyArtifacts,
1918
cleanupTempJobFiles,
2019
refreshJob,
2120
JobMetadata,
2221
} from '../../codewhisperer/service/transformByQ/transformationHistoryHandler'
22+
import { copyArtifacts } from '../../codewhisperer/service/transformByQ/transformFileHandler'
2323
import * as transformApiHandler from '../../codewhisperer/service/transformByQ/transformApiHandler'
2424
import { ExportResultArchiveStructure } from '../../shared/utilities/download'
2525
import { JDKVersion, TransformationType } from '../../codewhisperer'
2626

2727
describe('Transformation History Handler', function () {
28+
function setupFileSystemMocks() {
29+
const createdFiles = new Map<string, string>()
30+
const createdDirs = new Set<string>()
31+
32+
// Mock file operations to track what gets created
33+
sinon.stub(fs, 'mkdir').callsFake(async (dirPath: any) => {
34+
createdDirs.add(dirPath.toString())
35+
})
36+
sinon.stub(fs, 'copy').callsFake(async (src: any, dest: any) => {
37+
createdFiles.set(dest.toString(), `copied from ${src.toString()}`)
38+
})
39+
sinon.stub(fs, 'writeFile').callsFake(async (filePath: any, content: any) => {
40+
createdFiles.set(filePath.toString(), content.toString())
41+
})
42+
sinon.stub(fs, 'delete').callsFake(async (filePath: any) => {
43+
createdFiles.delete(filePath.toString())
44+
})
45+
46+
return { createdFiles, createdDirs }
47+
}
48+
2849
afterEach(function () {
2950
sinon.restore()
3051
})
@@ -86,7 +107,7 @@ describe('Transformation History Handler', function () {
86107
assert(fileContent.includes('date\tproject_name\tstatus\tduration\tdiff_patch\tsummary\tjob_id\n'))
87108
assert(
88109
fileContent.includes(
89-
'01/01/25, 10:00 AM\ttest-project\tCOMPLETED\t5 min\t/job/path/diff.patch\t/job/path/summary/summary.md\tjob-123\n'
110+
`01/01/25, 10:00 AM\ttest-project\tCOMPLETED\t5 min\t${path.join('/job/path', 'diff.patch')}\t${path.join('/job/path', 'summary', 'summary.md')}\tjob-123\n`
90111
)
91112
)
92113
})
@@ -157,22 +178,9 @@ describe('Transformation History Handler', function () {
157178
}
158179

159180
beforeEach(function () {
160-
createdFiles = new Map()
161-
createdDirs = new Set()
162-
163-
// Mock file operations to track what gets created
164-
sinon.stub(fs, 'mkdir').callsFake(async (dirPath: any) => {
165-
createdDirs.add(dirPath.toString())
166-
})
167-
sinon.stub(fs, 'copy').callsFake(async (src: any, dest: any) => {
168-
createdFiles.set(dest.toString(), `copied from ${src.toString()}`)
169-
})
170-
sinon.stub(fs, 'writeFile').callsFake(async (filePath: any, content: any) => {
171-
createdFiles.set(filePath.toString(), content.toString())
172-
})
173-
sinon.stub(fs, 'delete').callsFake(async (filePath: any) => {
174-
createdFiles.delete(filePath.toString())
175-
})
181+
const mocks = setupFileSystemMocks()
182+
createdFiles = mocks.createdFiles
183+
createdDirs = mocks.createdDirs
176184
})
177185

178186
it('Creates job history directory and metadata files', async function () {
@@ -199,28 +207,28 @@ describe('Transformation History Handler', function () {
199207
// Pre-populate files that would exist
200208
createdFiles.set('/payload.zip', 'payload content')
201209
createdFiles.set(path.join(os.tmpdir(), 'build-logs.txt'), 'build logs')
202-
createdFiles.set('/job/path/metadata.json', 'metadata')
203-
createdFiles.set('/job/path/zipped-code.zip', 'zip content')
210+
createdFiles.set(path.join('/job/path', 'metadata.json'), 'metadata')
211+
createdFiles.set(path.join('/job/path', 'zipped-code.zip'), 'zip content')
204212

205213
await cleanupTempJobFiles('/job/path', 'COMPLETED', '/payload.zip')
206214

207215
// Verify files were deleted (no longer exist in createdFiles)
208216
assert(!createdFiles.has('/payload.zip'))
209217
assert(!createdFiles.has(path.join(os.tmpdir(), 'build-logs.txt')))
210-
assert(!createdFiles.has('/job/path/metadata.json'))
211-
assert(!createdFiles.has('/job/path/zipped-code.zip'))
218+
assert(!createdFiles.has(path.join('/job/path', 'metadata.json')))
219+
assert(!createdFiles.has(path.join('/job/path', 'zipped-code.zip')))
212220
})
213221

214222
it('Preserves metadata for failed jobs', async function () {
215223
// Pre-populate files that would exist
216-
createdFiles.set('/job/path/metadata.json', 'metadata')
217-
createdFiles.set('/job/path/zipped-code.zip', 'zip content')
224+
createdFiles.set(path.join('/job/path', 'metadata.json'), 'metadata')
225+
createdFiles.set(path.join('/job/path', 'zipped-code.zip'), 'zip content')
218226

219227
await cleanupTempJobFiles('/job/path', 'FAILED')
220228

221229
// Verify metadata files still exist (were NOT deleted)
222-
assert(createdFiles.has('/job/path/metadata.json'))
223-
assert(createdFiles.has('/job/path/zipped-code.zip'))
230+
assert(createdFiles.has(path.join('/job/path', 'metadata.json')))
231+
assert(createdFiles.has(path.join('/job/path', 'zipped-code.zip')))
224232
})
225233
})
226234

@@ -229,32 +237,25 @@ describe('Transformation History Handler', function () {
229237
let createdDirs: Set<string>
230238

231239
beforeEach(function () {
232-
createdFiles = new Map()
233-
createdDirs = new Set()
234-
235-
// Mock file operations to track what gets created
236-
sinon.stub(fs, 'mkdir').callsFake(async (dirPath: any) => {
237-
createdDirs.add(dirPath.toString())
238-
})
239-
sinon.stub(fs, 'copy').callsFake(async (src: any, dest: any) => {
240-
createdFiles.set(dest.toString(), `copied from ${src.toString()}`)
241-
})
240+
const mocks = setupFileSystemMocks()
241+
createdFiles = mocks.createdFiles
242+
createdDirs = mocks.createdDirs
242243
})
243244

244245
it('Copies diff patch and summary files to destination', async function () {
245-
await copyArtifacts('/archive/path', '/destination/path')
246+
await copyArtifacts(path.join('archive', 'path'), path.join('destination', 'path'))
246247

247248
// Verify directories were created
248-
assert(createdDirs.has('/destination/path'))
249-
assert(createdDirs.has('/destination/path/summary'))
249+
assert(createdDirs.has(path.join('destination', 'path')))
250+
assert(createdDirs.has(path.join('destination', 'path', 'summary')))
250251

251252
// Verify files were copied to correct locations
252-
assert(createdFiles.has('/destination/path/diff.patch'))
253-
assert(createdFiles.has('/destination/path/summary/summary.md'))
253+
assert(createdFiles.has(path.join('destination', 'path', 'diff.patch')))
254+
assert(createdFiles.has(path.join('destination', 'path', 'summary', 'summary.md')))
254255

255256
// Verify source paths are correct
256-
const diffSource = createdFiles.get('/destination/path/diff.patch')
257-
const summarySource = createdFiles.get('/destination/path/summary/summary.md')
257+
const diffSource = createdFiles.get(path.join('destination', 'path', 'diff.patch'))
258+
const summarySource = createdFiles.get(path.join('destination', 'path', 'summary', 'summary.md'))
258259
assert(diffSource?.includes(ExportResultArchiveStructure.PathToDiffPatch))
259260
assert(summarySource?.includes(ExportResultArchiveStructure.PathToSummary))
260261
})

0 commit comments

Comments
 (0)