Skip to content

Commit 5be8447

Browse files
committed
feat(amazonq): skip registering run command log file
1 parent 9f805be commit 5be8447

File tree

3 files changed

+168
-0
lines changed

3 files changed

+168
-0
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type": "Feature",
3+
"description": "Save user command execution logs to plugin output."
4+
}

packages/core/src/amazonq/session/sessionState.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import { prepareRepoData, getDeletedFileInfos, registerNewFiles, PrepareRepoData
2929
import { uploadCode } from '../util/upload'
3030

3131
export const EmptyCodeGenID = 'EMPTY_CURRENT_CODE_GENERATION_ID'
32+
export const RunCommandLogFileName = '.amazonq/dev/run_command.log'
3233

3334
export interface BaseMessenger {
3435
sendAnswer(params: any): void
@@ -103,6 +104,16 @@ export abstract class CodeGenBase {
103104
case CodeGenerationStatus.COMPLETE: {
104105
const { newFileContents, deletedFiles, references } =
105106
await this.config.proxyClient.exportResultArchive(this.conversationId)
107+
108+
const logFileInfo = newFileContents.find(
109+
(file: { zipFilePath: string; fileContent: string }) =>
110+
file.zipFilePath === RunCommandLogFileName
111+
)
112+
if (logFileInfo) {
113+
getLogger().info(`sessionState: Run Command logs, ${logFileInfo.fileContent}`)
114+
newFileContents.splice(newFileContents.indexOf(logFileInfo), 1)
115+
}
116+
106117
const newFileInfo = registerNewFiles(
107118
fs,
108119
newFileContents,
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
/*!
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import * as vscode from 'vscode'
7+
import sinon from 'sinon'
8+
import { CodeGenBase } from '../../../amazonq/session/sessionState'
9+
import { RunCommandLogFileName } from '../../../amazonq/session/sessionState'
10+
import assert from 'assert'
11+
import * as workspaceUtils from '../../../shared/utilities/workspaceUtils'
12+
import { TelemetryHelper } from '../../../amazonq/util/telemetryHelper'
13+
import { assertLogsContain } from '../../globalSetup.test'
14+
15+
describe('CodeGenBase generateCode log file handling', () => {
16+
class TestCodeGen extends CodeGenBase {
17+
public generatedFiles: any[] = []
18+
constructor(config: any, tabID: string) {
19+
super(config, tabID)
20+
}
21+
protected handleProgress(_messenger: any): void {
22+
// No-op for test.
23+
}
24+
protected getScheme(): string {
25+
return 'file'
26+
}
27+
protected getTimeoutErrorCode(): string {
28+
return 'test_timeout'
29+
}
30+
protected handleGenerationComplete(_messenger: any, newFileInfo: any[]): void {
31+
this.generatedFiles = newFileInfo
32+
}
33+
protected handleError(_messenger: any, _codegenResult: any): Error {
34+
throw new Error('handleError called')
35+
}
36+
}
37+
38+
let fakeProxyClient: any
39+
let testConfig: any
40+
let fsMock: any
41+
let messengerMock: any
42+
let testAction: any
43+
44+
beforeEach(async () => {
45+
const ret = {
46+
testworkspacefolder: {
47+
uri: vscode.Uri.file('/path/to/testworkspacefolder'),
48+
name: 'testworkspacefolder',
49+
index: 0,
50+
},
51+
}
52+
sinon.stub(workspaceUtils, 'getWorkspaceFoldersByPrefixes').returns(ret)
53+
54+
fakeProxyClient = {
55+
getCodeGeneration: sinon.stub().resolves({
56+
codeGenerationStatus: { status: 'Complete' },
57+
codeGenerationRemainingIterationCount: 0,
58+
codeGenerationTotalIterationCount: 1,
59+
}),
60+
exportResultArchive: sinon.stub(),
61+
}
62+
63+
testConfig = {
64+
conversationId: 'conv_test',
65+
uploadId: 'upload_test',
66+
workspaceRoots: ['/path/to/testworkspacefolder'],
67+
proxyClient: fakeProxyClient,
68+
}
69+
70+
fsMock = {
71+
writeFile: sinon.stub().resolves(),
72+
registerProvider: sinon.stub().resolves(),
73+
}
74+
75+
messengerMock = { sendAnswer: sinon.spy() }
76+
77+
testAction = {
78+
fs: fsMock,
79+
messenger: messengerMock,
80+
tokenSource: {
81+
token: {
82+
isCancellationRequested: false,
83+
onCancellationRequested: () => {},
84+
},
85+
},
86+
}
87+
})
88+
89+
afterEach(() => {
90+
sinon.restore()
91+
})
92+
93+
const runGenerateCode = async (codeGenerationId: string) => {
94+
const testCodeGen = new TestCodeGen(testConfig, 'tab1')
95+
return await testCodeGen.generateCode({
96+
messenger: messengerMock,
97+
fs: fsMock,
98+
codeGenerationId,
99+
telemetry: new TelemetryHelper(),
100+
workspaceFolders: [testConfig.workspaceRoots[0]],
101+
action: testAction,
102+
})
103+
}
104+
105+
const createExpectedNewFile = (fileObj: { zipFilePath: string; fileContent: string }) => ({
106+
zipFilePath: fileObj.zipFilePath,
107+
fileContent: fileObj.fileContent,
108+
changeApplied: false,
109+
rejected: false,
110+
relativePath: fileObj.zipFilePath,
111+
virtualMemoryUri: vscode.Uri.file(`/upload_test/${fileObj.zipFilePath}`),
112+
workspaceFolder: {
113+
index: 0,
114+
name: 'testworkspacefolder',
115+
uri: vscode.Uri.file('/path/to/testworkspacefolder'),
116+
},
117+
})
118+
119+
it('adds the log content to logger if present and excludes it from new files', async () => {
120+
const logFileInfo = {
121+
zipFilePath: RunCommandLogFileName,
122+
fileContent: 'Log content',
123+
}
124+
const otherFile = { zipFilePath: 'other.ts', fileContent: 'other content' }
125+
fakeProxyClient.exportResultArchive.resolves({
126+
newFileContents: [logFileInfo, otherFile],
127+
deletedFiles: [],
128+
references: [],
129+
})
130+
const result = await runGenerateCode('codegen1')
131+
132+
assertLogsContain(`sessionState: Run Command logs, Log content`, false, 'info')
133+
134+
const expectedNewFile = createExpectedNewFile(otherFile)
135+
assert.deepStrictEqual(result.newFiles[0].fileContent, expectedNewFile.fileContent)
136+
})
137+
138+
it('skips log file handling if log file is not present', async () => {
139+
const file1 = { zipFilePath: 'file1.ts', fileContent: 'content1' }
140+
fakeProxyClient.exportResultArchive.resolves({
141+
newFileContents: [file1],
142+
deletedFiles: [],
143+
references: [],
144+
})
145+
146+
const result = await runGenerateCode('codegen2')
147+
148+
assert.throws(() => assertLogsContain(`sessionState: Run Command logs, Log content`, false, 'info'))
149+
150+
const expectedNewFile = createExpectedNewFile(file1)
151+
assert.deepStrictEqual(result.newFiles[0].fileContent, expectedNewFile.fileContent)
152+
})
153+
})

0 commit comments

Comments
 (0)