Skip to content

Commit c50c7a6

Browse files
Merge staging into feature/starling
2 parents ca73db4 + f896178 commit c50c7a6

File tree

13 files changed

+140
-119
lines changed

13 files changed

+140
-119
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": "Use MDE endpoint set by environment variable"
4+
}

.github/workflows/release.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ jobs:
6969
echo "tagname=$TAG_NAME" >> $GITHUB_OUTPUT
7070
echo "version=$(grep -m 1 version package.json | grep -o '[0-9][^\"]\+' | sed 's/-SNAPSHOT//')" >> $GITHUB_OUTPUT
7171
echo 'changes<<EOF' >> $GITHUB_OUTPUT
72-
head -14 CHANGELOG.md >> $GITHUB_OUTPUT
72+
cat CHANGELOG.md | perl -ne 'BEGIN{$/="\n\n"} print; exit if $. == 2' >> $GITHUB_OUTPUT
7373
echo 'EOF' >> $GITHUB_OUTPUT
7474
7575
publish:
@@ -83,6 +83,9 @@ jobs:
8383
FEAT_NAME: ${{ needs.package.outputs.feature }}
8484
TAG_NAME: ${{ needs.package.outputs.tagname }}
8585
AWS_TOOLKIT_VERSION: ${{ needs.package.outputs.version }}
86+
# Used in release_notes.md
87+
BRANCH: ${{ github.ref_name }}
88+
# Used in release_notes.md
8689
AWS_TOOLKIT_CHANGES: ${{ needs.package.outputs.changes }}
8790
permissions:
8891
contents: write

.github/workflows/release_notes.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
_This is an **unsupported preview build** of AWS Toolkit, for testing new features._
1+
_This is an **unsupported preview build** of the `${BRANCH}` branch of AWS Toolkit._
22

33
# Install
44

@@ -8,3 +8,7 @@ _This is an **unsupported preview build** of AWS Toolkit, for testing new featur
88
# Changes
99

1010
${AWS_TOOLKIT_CHANGES}
11+
12+
## Previous changes
13+
14+
- See [CHANGELOG.md](CHANGELOG.md)

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4352,7 +4352,7 @@
43524352
"@aws-sdk/shared-ini-file-loader": "^3.46.0",
43534353
"@aws-sdk/smithy-client": "^3.46.0",
43544354
"@aws-sdk/util-arn-parser": "^3.46.0",
4355-
"@aws/mynah-ui-chat": "npm:@aws/[email protected].5",
4355+
"@aws/mynah-ui-chat": "npm:@aws/[email protected].9",
43564356
"@gerhobbelt/gitignore-parser": "^0.2.0-9",
43574357
"@iarna/toml": "^2.2.5",
43584358
"@vscode/debugprotocol": "^1.57.0",

src/codewhisperer/commands/startSecurityScan.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ export async function startSecurityScan(
183183
codeScanTelemetryEntry.codewhispererCodeScanTotalIssues = total
184184
codeScanTelemetryEntry.codewhispererCodeScanIssuesWithFixes = withFixes
185185
throwIfCancelled()
186-
getLogger().verbose(`Security scan totally found ${total} issues.`)
186+
getLogger().verbose(`Security scan totally found ${total} issues. ${withFixes} of them have fixes.`)
187187
if (isCloud9()) {
188188
securityPanelViewProvider.addLines(securityRecommendationCollection, editor)
189189
vscode.commands.executeCommand('workbench.view.extension.aws-codewhisperer-security-panel')
@@ -235,8 +235,7 @@ export async function emitCodeScanTelemetry(editor: vscode.TextEditor, codeScanT
235235
)
236236
codeScanTelemetryEntry.codewhispererCodeScanProjectBytes = projectSize
237237
}
238-
// TODO: should be removed. Added this to pass tests
239-
telemetry.codewhisperer_securityScan.emit({ ...codeScanTelemetryEntry, codewhispererCodeScanIssuesWithFixes: 1 })
238+
telemetry.codewhisperer_securityScan.emit(codeScanTelemetryEntry)
240239
}
241240

242241
export function errorPromptHelper(error: Error) {

src/codewhisperer/commands/startTransformByQ.ts

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ import {
2020
pollTransformationJob,
2121
convertToTimeString,
2222
convertDateToTimestamp,
23-
getValidModules,
23+
getOpenProjects,
24+
validateProjectSelection,
2425
} from '../service/transformByQHandler'
2526
import { QuickPickItem } from 'vscode'
2627
import { MultiStepInputFlowController } from '../../shared//multiStepInputFlowController'
@@ -59,51 +60,58 @@ interface UserInputState {
5960
totalSteps: number
6061
targetLanguage: QuickPickItem
6162
targetVersion: QuickPickItem
62-
module: QuickPickItem
63+
project: QuickPickItem
6364
}
6465

65-
async function collectInputs(validModules: vscode.QuickPickItem[] | undefined) {
66+
async function collectInputs(validProjects: vscode.QuickPickItem[] | undefined) {
6667
// const targetLanguages: QuickPickItem[] = CodeWhispererConstants.targetLanguages.map(label => ({ label }))
6768
const state = {} as Partial<UserInputState>
6869
// only supporting target language of Java and target version of JDK17 for now, so skip to pickModule prompt
6970
transformByQState.setTargetJDKVersionToJDK17()
70-
await MultiStepInputFlowController.run(input => pickModule(input, state, validModules))
71+
await MultiStepInputFlowController.run(input => pickProject(input, state, validProjects))
7172
// await MultiStepInputFlowController.run(input => pickTargetLanguage(input, state, targetLanguages, validModules))
7273
return state as UserInputState
7374
}
7475

75-
async function pickModule(
76+
async function pickProject(
7677
input: MultiStepInputFlowController,
7778
state: Partial<UserInputState>,
78-
validModules: vscode.QuickPickItem[] | undefined
79+
validProjects: vscode.QuickPickItem[] | undefined
7980
) {
8081
const pick = await input.showQuickPick({
8182
title: CodeWhispererConstants.transformByQWindowTitle,
8283
step: DropdownStep.STEP_1,
8384
totalSteps: DropdownStep.STEP_1,
8485
placeholder: CodeWhispererConstants.selectModulePrompt,
85-
items: validModules!,
86+
items: validProjects!,
8687
shouldResume: () => Promise.resolve(true),
8788
ignoreFocusOut: false,
8889
})
89-
state.module = pick
90-
transformByQState.setModuleName(he.encode(state.module.label)) // encode to avoid HTML injection risk
90+
state.project = pick
91+
transformByQState.setProjectName(he.encode(state.project.label)) // encode to avoid HTML injection risk
9192
}
9293

9394
export async function startTransformByQ() {
9495
await telemetry.amazonq_codeTransformInvoke.run(async span => {
9596
span.record({ codeTransform_SessionId: codeTransformTelemetryState.getSessionId() })
96-
let validModules: vscode.QuickPickItem[] | undefined
97+
98+
let openProjects: vscode.QuickPickItem[] = []
9799
try {
98-
validModules = await getValidModules()
100+
openProjects = await getOpenProjects()
99101
} catch (err) {
100-
getLogger().error('Failed to get valid modules: ', err)
102+
getLogger().error('Failed to get open projects: ', err)
101103
throw err
102104
}
105+
const state = await collectInputs(openProjects)
103106

104-
span.record({ codeTransform_SourceJavaVersion: transformByQState.getSourceJDKVersion() })
107+
try {
108+
await validateProjectSelection(state.project)
109+
} catch (err) {
110+
getLogger().error('Selected project is not Java 8, not Java 11, or does not use Maven', err)
111+
throw err
112+
}
105113

106-
const state = await collectInputs(validModules)
114+
span.record({ codeTransform_SourceJavaVersion: transformByQState.getSourceJDKVersion() })
107115

108116
const selection = await vscode.window.showWarningMessage(
109117
CodeWhispererConstants.dependencyDisclaimer,
@@ -116,7 +124,7 @@ export async function startTransformByQ() {
116124
}
117125

118126
transformByQState.setToRunning()
119-
transformByQState.setModulePath(state.module.description!)
127+
transformByQState.setProjectPath(state.project.description!)
120128
sessionPlanProgress['uploadCode'] = StepProgress.Pending
121129
sessionPlanProgress['buildCode'] = StepProgress.Pending
122130
sessionPlanProgress['transformCode'] = StepProgress.Pending
@@ -146,7 +154,7 @@ export async function startTransformByQ() {
146154
throwIfCancelled()
147155
try {
148156
// TODO: we want to track zip failures separately from uploadPayload failures
149-
const payloadFileName = await zipCode(state.module.description!)
157+
const payloadFileName = await zipCode(state.project.description!)
150158
await vscode.commands.executeCommand('aws.amazonq.refresh') // so that button updates
151159
uploadId = await uploadPayload(payloadFileName)
152160
} catch (error) {
@@ -277,11 +285,11 @@ export async function startTransformByQ() {
277285
vscode.commands.executeCommand('setContext', 'gumby.isTransformAvailable', true)
278286
const durationInMs = new Date().getTime() - startTime.getTime()
279287

280-
if (state.module) {
288+
if (state.project) {
281289
sessionJobHistory = processHistory(
282290
sessionJobHistory,
283291
convertDateToTimestamp(startTime),
284-
transformByQState.getModuleName(),
292+
transformByQState.getProjectName(),
285293
transformByQState.getStatus(),
286294
convertToTimeString(durationInMs),
287295
transformByQState.getJobId()

src/codewhisperer/models/model.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -256,8 +256,8 @@ export class ZipManifest {
256256
export class TransformByQState {
257257
private transformByQState: TransformByQStatus = TransformByQStatus.NotStarted
258258

259-
private moduleName: string = ''
260-
private modulePath: string = ''
259+
private projectName: string = ''
260+
private projectPath: string = ''
261261

262262
private jobId: string = ''
263263

@@ -296,12 +296,12 @@ export class TransformByQState {
296296
return this.transformByQState === TransformByQStatus.PartiallySucceeded
297297
}
298298

299-
public getModuleName() {
300-
return this.moduleName
299+
public getProjectName() {
300+
return this.projectName
301301
}
302302

303-
public getModulePath() {
304-
return this.modulePath
303+
public getProjectPath() {
304+
return this.projectPath
305305
}
306306

307307
public getJobId() {
@@ -360,12 +360,12 @@ export class TransformByQState {
360360
this.transformByQState = TransformByQStatus.PartiallySucceeded
361361
}
362362

363-
public setModuleName(name: string) {
364-
this.moduleName = name
363+
public setProjectName(name: string) {
364+
this.projectName = name
365365
}
366366

367-
public setModulePath(path: string) {
368-
this.modulePath = path
367+
public setProjectPath(path: string) {
368+
this.projectPath = path
369369
}
370370

371371
public setJobId(id: string) {

src/codewhisperer/service/transformByQHandler.ts

Lines changed: 58 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -57,75 +57,70 @@ export function throwIfCancelled() {
5757
}
5858
}
5959

60-
/*
61-
* This function searches for a .class file in each opened module. Then it runs javap on the found .class file to get the JDK version
62-
* for the file, and sets the version in the state variable. Only JDK8 and JDK11 are supported.
63-
*/
64-
export async function getValidModules() {
60+
export async function getOpenProjects() {
6561
const folders = vscode.workspace.workspaceFolders
66-
const validModules: vscode.QuickPickItem[] = []
6762
if (folders === undefined) {
6863
vscode.window.showErrorMessage(CodeWhispererConstants.noSupportedJavaProjectsFoundMessage, { modal: true })
69-
throw Error('No Java projects found since no projects are open')
64+
throw new ToolkitError('No Java projects found since no projects are open', { code: 'NoOpenProjects' })
7065
}
71-
let containsSupportedJava = false // workspace must contain Java 8 or Java 11 code for this to be true
72-
let containsPomXml = false // workspace must contain a 'pom.xml' file for this to be true
73-
let failureReason = 'NoJavaProjectsAvailable'
66+
const openProjects: vscode.QuickPickItem[] = []
7467
for (const folder of folders) {
75-
const compiledJavaFiles = await vscode.workspace.findFiles(
76-
new vscode.RelativePattern(folder, '**/*.class'),
77-
'**/node_modules/**',
78-
1
79-
)
80-
if (compiledJavaFiles.length < 1) {
81-
continue
82-
}
83-
const classFilePath = compiledJavaFiles[0].fsPath
84-
const baseCommand = 'javap'
85-
const args = ['-v', classFilePath]
86-
const spawnResult = spawnSync(baseCommand, args, { shell: false, encoding: 'utf-8' })
87-
88-
if (spawnResult.error || spawnResult.status !== 0) {
89-
failureReason = 'CouldNotRunJavaCommand'
90-
continue // if cannot get Java version, move on to other projects in workspace
91-
}
92-
const majorVersionIndex = spawnResult.stdout.indexOf('major version: ')
93-
const javaVersion = spawnResult.stdout.slice(majorVersionIndex + 15, majorVersionIndex + 17).trim()
94-
if (javaVersion === CodeWhispererConstants.JDK8VersionNumber) {
95-
transformByQState.setSourceJDKVersionToJDK8()
96-
containsSupportedJava = true
97-
} else if (javaVersion === CodeWhispererConstants.JDK11VersionNumber) {
98-
transformByQState.setSourceJDKVersionToJDK11()
99-
containsSupportedJava = true
100-
} else {
101-
continue
102-
}
103-
const buildFile = await vscode.workspace.findFiles(
104-
new vscode.RelativePattern(folder, '**/pom.xml'), // only supporting projects with a pom.xml for now
105-
'**/node_modules/**',
106-
1
107-
)
108-
if (buildFile.length < 1) {
109-
checkIfGradle(folder)
110-
continue
111-
} else {
112-
containsPomXml = true
113-
}
114-
validModules.push({ label: folder.name, description: folder.uri.fsPath })
68+
openProjects.push({
69+
label: folder.name,
70+
description: folder.uri.fsPath,
71+
})
72+
}
73+
return openProjects
74+
}
75+
76+
/*
77+
* This function searches for a .class file in the selected project. Then it runs javap on the found .class file to get the JDK version
78+
* for the project, and sets the version in the state variable. Only JDK8 and JDK11 are supported. It also ensure a pom.xml file is found,
79+
* since only the Maven build system is supported for now.
80+
*/
81+
export async function validateProjectSelection(project: vscode.QuickPickItem) {
82+
const projectPath = project.description
83+
const compiledJavaFiles = await vscode.workspace.findFiles(
84+
new vscode.RelativePattern(projectPath!, '**/*.class'),
85+
'**/node_modules/**',
86+
1
87+
)
88+
if (compiledJavaFiles.length < 1) {
89+
vscode.window.showErrorMessage(CodeWhispererConstants.noSupportedJavaProjectsFoundMessage, { modal: true })
90+
throw new ToolkitError('No Java projects found', { code: 'NoJavaProjectsAvailable' })
11591
}
116-
if (!containsSupportedJava) {
92+
const classFilePath = compiledJavaFiles[0].fsPath
93+
const baseCommand = 'javap'
94+
const args = ['-v', classFilePath]
95+
const spawnResult = spawnSync(baseCommand, args, { shell: false, encoding: 'utf-8' })
96+
97+
if (spawnResult.error || spawnResult.status !== 0) {
11798
vscode.window.showErrorMessage(CodeWhispererConstants.noSupportedJavaProjectsFoundMessage, { modal: true })
118-
throw new ToolkitError('No Java projects found', { code: failureReason })
99+
throw new ToolkitError('Unable to determine Java version', { code: 'CannotDetermineJavaVersion' })
119100
}
120-
if (!containsPomXml) {
121-
vscode.window.showErrorMessage(CodeWhispererConstants.noPomXmlFoundMessage, { modal: true })
122-
throw new ToolkitError('No build file found', { code: 'CouldNotFindPomXml' })
101+
const majorVersionIndex = spawnResult.stdout.indexOf('major version: ')
102+
const javaVersion = spawnResult.stdout.slice(majorVersionIndex + 15, majorVersionIndex + 17).trim()
103+
if (javaVersion === CodeWhispererConstants.JDK8VersionNumber) {
104+
transformByQState.setSourceJDKVersionToJDK8()
105+
} else if (javaVersion === CodeWhispererConstants.JDK11VersionNumber) {
106+
transformByQState.setSourceJDKVersionToJDK11()
123107
} else {
124-
telemetry.amazonq_codeTransformInvoke.record({
125-
codeTransform_ProjectType: 'maven',
126-
})
108+
vscode.window.showErrorMessage(CodeWhispererConstants.noSupportedJavaProjectsFoundMessage, { modal: true })
109+
throw new ToolkitError('Project selected is not Java 8 or Java 11', { code: 'UnsupportedJavaVersion' })
127110
}
128-
return validModules
111+
const buildFile = await vscode.workspace.findFiles(
112+
new vscode.RelativePattern(projectPath!, '**/pom.xml'),
113+
'**/node_modules/**',
114+
1
115+
)
116+
if (buildFile.length < 1) {
117+
await checkIfGradle(projectPath!)
118+
vscode.window.showErrorMessage(CodeWhispererConstants.noPomXmlFoundMessage, { modal: true })
119+
throw new ToolkitError('No valid Maven build file found', { code: 'CouldNotFindPomXml' })
120+
}
121+
telemetry.amazonq_codeTransformInvoke.record({
122+
codeTransform_ProjectType: 'maven',
123+
})
129124
}
130125

131126
export function getSha256(fileName: string) {
@@ -384,14 +379,14 @@ export async function pollTransformationJob(jobId: string, validStates: string[]
384379
return status
385380
}
386381

387-
async function checkIfGradle(folder: vscode.WorkspaceFolder) {
388-
const gradleBuildFiles = await vscode.workspace.findFiles(
389-
new vscode.RelativePattern(folder, '**/build.gradle'),
382+
async function checkIfGradle(projectPath: string) {
383+
const gradleBuildFile = await vscode.workspace.findFiles(
384+
new vscode.RelativePattern(projectPath, '**/build.gradle'),
390385
'**/node_modules/**',
391386
1
392387
)
393388

394-
if (gradleBuildFiles.length > 1) {
389+
if (gradleBuildFile.length > 0) {
395390
telemetry.amazonq_codeTransformInvoke.record({
396391
codeTransform_ProjectType: 'gradle',
397392
})

0 commit comments

Comments
 (0)