From 128beacfccdc769ec9d2454e6e4279691bdc3eed Mon Sep 17 00:00:00 2001 From: David Hasani Date: Fri, 9 May 2025 10:37:52 -0700 Subject: [PATCH 01/21] copy JAR --- ...-065d979a-e921-4252-a9a7-f0c2079015f3.json | 4 + plugins/amazonq/build.gradle.kts | 6 + .../controller/CodeTransformChatController.kt | 26 +- .../ideMaven/MavenRunnerUtils.kt | 271 +++++++----------- .../ideMaven/TransformMavenRunner.kt | 2 +- .../model/CodeModernizerSessionContext.kt | 32 +-- .../codemodernizer/model/ZipManifest.kt | 2 +- .../utils/CodeTransformApiUtils.kt | 13 +- .../CodeWhispererCodeModernizerUtilsTest.kt | 12 +- plugins/amazonq/contrib/QCT-Maven.jar | Bin 0 -> 148642 bytes .../resources/MessagesBundle.properties | 6 +- .../transformTests/TransformChatTest.kt | 13 +- 12 files changed, 167 insertions(+), 220 deletions(-) create mode 100644 .changes/next-release/feature-065d979a-e921-4252-a9a7-f0c2079015f3.json create mode 100644 plugins/amazonq/contrib/QCT-Maven.jar diff --git a/.changes/next-release/feature-065d979a-e921-4252-a9a7-f0c2079015f3.json b/.changes/next-release/feature-065d979a-e921-4252-a9a7-f0c2079015f3.json new file mode 100644 index 00000000000..ae117a79932 --- /dev/null +++ b/.changes/next-release/feature-065d979a-e921-4252-a9a7-f0c2079015f3.json @@ -0,0 +1,4 @@ +{ + "type" : "feature", + "description" : "/transform: run all builds client-side" +} \ No newline at end of file diff --git a/plugins/amazonq/build.gradle.kts b/plugins/amazonq/build.gradle.kts index 39bbdd368fa..8ea3fccdaec 100644 --- a/plugins/amazonq/build.gradle.kts +++ b/plugins/amazonq/build.gradle.kts @@ -26,6 +26,12 @@ val changelog = tasks.register("pluginChangeLog") { changeLogFile.value(layout.buildDirectory.file("changelog/change-notes.xml")) } +tasks.prepareSandbox { + from("contrib/QCT-Maven.jar") { + into("/plugin-amazonq/lib") + } +} + tasks.jar { dependsOn(changelog) from(changelog) { diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt index 735e0008a8f..ead5d6be49d 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt @@ -76,6 +76,7 @@ import software.aws.toolkits.jetbrains.services.codemodernizer.constants.buildTr import software.aws.toolkits.jetbrains.services.codemodernizer.constants.buildTransformStoppingChatContent import software.aws.toolkits.jetbrains.services.codemodernizer.constants.buildUserCancelledChatContent import software.aws.toolkits.jetbrains.services.codemodernizer.constants.buildUserHilSelection +import software.aws.toolkits.jetbrains.services.codemodernizer.constants.buildUserInputCustomDependencyVersionsChatContent import software.aws.toolkits.jetbrains.services.codemodernizer.constants.buildUserInputLanguageUpgradeChatContent import software.aws.toolkits.jetbrains.services.codemodernizer.constants.buildUserInputSQLConversionMetadataChatContent import software.aws.toolkits.jetbrains.services.codemodernizer.constants.buildUserInputSkipTestsFlagChatContent @@ -89,6 +90,7 @@ import software.aws.toolkits.jetbrains.services.codemodernizer.messages.Authenti import software.aws.toolkits.jetbrains.services.codemodernizer.messages.CodeTransformChatMessage import software.aws.toolkits.jetbrains.services.codemodernizer.messages.CodeTransformCommandMessage import software.aws.toolkits.jetbrains.services.codemodernizer.messages.IncomingCodeTransformMessage +import software.aws.toolkits.jetbrains.services.codemodernizer.model.CLIENT_SIDE_BUILD import software.aws.toolkits.jetbrains.services.codemodernizer.model.CodeModernizerArtifact import software.aws.toolkits.jetbrains.services.codemodernizer.model.CodeModernizerJobCompletedResult import software.aws.toolkits.jetbrains.services.codemodernizer.model.CodeTransformConversationState @@ -120,6 +122,10 @@ import software.aws.toolkits.jetbrains.services.codemodernizer.utils.validateSct import software.aws.toolkits.jetbrains.services.cwc.messages.ChatMessageType import software.aws.toolkits.resources.message import software.aws.toolkits.telemetry.CodeTransformPreValidationError +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.fileEditor.FileEditorManager +import com.intellij.testFramework.LightVirtualFile +import org.jetbrains.yaml.YAMLFileType class CodeTransformChatController( private val context: AmazonQAppInitContext, @@ -150,6 +156,7 @@ class CodeTransformChatController( if (objective == "language upgrade" || objective == "sql conversion") { telemetry.submitSelection(objective) } + broadcastQEvent(QFeatureEvent.INVOCATION) when (objective) { "language upgrade" -> this.handleLanguageUpgrade() "sql conversion" -> this.handleSQLConversion() @@ -412,14 +419,12 @@ class CodeTransformChatController( codeModernizerManager.codeTransformationSession?.let { it.sessionContext.customBuildCommand = customBuildCommand } - // TODO: add CLIENT_SIDE_BUILD below when releasing CSB - val transformCapabilities = listOf(EXPLAINABILITY_V1, SELECTIVE_TRANSFORMATION_V2) + val transformCapabilities = listOf(EXPLAINABILITY_V1, CLIENT_SIDE_BUILD, SELECTIVE_TRANSFORMATION_V2) codeModernizerManager.codeTransformationSession?.let { it.sessionContext.transformCapabilities = transformCapabilities codeModernizerManager.runLocalMavenBuild(context.project, it) } - // TODO: when releasing CSB, delete "runLocalMavenBuild" line above and uncomment line below - // promptForCustomYamlFile() + promptForCustomYamlFile() } override suspend fun processCodeTransformCustomDependencyVersions(message: IncomingCodeTransformMessage.CodeTransformConfirmCustomDependencyVersions) { @@ -461,36 +466,33 @@ class CodeTransformChatController( } } - // TODO: uncomment when releasing CSB -/* private suspend fun promptForCustomYamlFile() { codeTransformChatHelper.addNewMessage(buildUserInputCustomDependencyVersionsChatContent()) val sampleYAML = """ -name: "custom-dependency-management" +name: "dependency-upgrade" description: "Custom dependency version management for Java migration from JDK 8/11/17 to JDK 17/21" - dependencyManagement: dependencies: - identifier: "com.example:library1" targetVersion: "2.1.0" versionProperty: "library1.version" # Optional - originType: "FIRST_PARTY" # or "THIRD_PARTY" + originType: "FIRST_PARTY" # or "THIRD_PARTY" # Optional - identifier: "com.example:library2" targetVersion: "3.0.0" originType: "THIRD_PARTY" plugins: - - identifier: "com.example.plugin" + - identifier: "com.example:plugin" targetVersion: "1.2.0" versionProperty: "plugin.version" # Optional """.trimIndent() - val virtualFile = LightVirtualFile("sample-dependency-management.yaml", YAMLFileType.YML, sampleYAML) + val virtualFile = LightVirtualFile("sample-dependency-upgrade.yaml", YAMLFileType.YML, sampleYAML) virtualFile.isWritable = true ApplicationManager.getApplication().invokeLater { FileEditorManager.getInstance(context.project).openFile(virtualFile, true) } } -*/ + override suspend fun processCodeTransformContinueAction(message: IncomingCodeTransformMessage.CodeTransformContinue) { codeTransformChatHelper.addNewMessage(buildContinueTransformationChatContent()) promptForTargetJdkName(message.tabId) diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/ideMaven/MavenRunnerUtils.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/ideMaven/MavenRunnerUtils.kt index 35ecb95564e..a1358cc19c5 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/ideMaven/MavenRunnerUtils.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/ideMaven/MavenRunnerUtils.kt @@ -17,91 +17,35 @@ import org.jetbrains.idea.maven.execution.MavenRunnerSettings import org.slf4j.Logger import software.aws.toolkits.core.utils.error import software.aws.toolkits.core.utils.info +import software.aws.toolkits.jetbrains.AwsPlugin +import software.aws.toolkits.jetbrains.AwsToolkit import software.aws.toolkits.jetbrains.services.codemodernizer.CodeModernizerManager import software.aws.toolkits.jetbrains.services.codemodernizer.CodeTransformTelemetryManager import software.aws.toolkits.jetbrains.services.codemodernizer.model.CodeModernizerSessionContext import software.aws.toolkits.jetbrains.services.codemodernizer.model.MAVEN_BUILD_RUN_UNIT_TESTS import software.aws.toolkits.jetbrains.services.codemodernizer.model.MavenCopyCommandsResult import software.aws.toolkits.jetbrains.services.codemodernizer.model.MavenDependencyReportCommandsResult +import software.aws.toolkits.jetbrains.utils.notifyStickyInfo import software.aws.toolkits.telemetry.CodeTransformBuildCommand import software.aws.toolkits.telemetry.Result import java.io.File import java.nio.file.Files import java.nio.file.Path -fun runClientSideBuild(targetDir: VirtualFile, logger: Logger, project: Project): Pair { - // run mvn test-compile or mvn test - val transformMvnRunner = TransformMavenRunner(project) - val mvnSettings = MavenRunner.getInstance(project).settings.clone() - val buildRunnable = runClientSideBuild(targetDir, mvnSettings, transformMvnRunner, logger, project) - buildRunnable.await() - // write build output to a new text file and open it - val buildLogOutput = buildRunnable.getOutput().toString() - // first line is a long Maven String showing the build command; not useful or needed - val outputWithoutFirstLine = buildLogOutput.lines().drop(1).joinToString("\n") - val buildLogOutputFile = Files.createTempFile("build-logs-", ".txt") - Files.write(buildLogOutputFile, outputWithoutFirstLine.toByteArray()) - val buildLogOutputVirtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(buildLogOutputFile.toFile()) - runInEdt { - if (buildLogOutputVirtualFile != null) { - FileEditorManager.getInstance(project).openFile(buildLogOutputVirtualFile, true) - } - } - return buildRunnable.getExitCode() to buildRunnable.getOutput().toString() -} - -fun runHilMavenCopyDependency( - context: CodeModernizerSessionContext, - sourceFolder: File, - destinationDir: File, - logBuilder: StringBuilder, - logger: Logger, - project: Project, -): MavenCopyCommandsResult { - logger.info { "Executing IntelliJ bundled Maven" } - try { - // Create shared parameters - val transformMvnRunner = TransformMavenRunner(project) - context.mavenRunnerQueue.add(transformMvnRunner) - val mvnSettings = MavenRunner.getInstance(project).settings.clone() // clone required to avoid editing user settings - - // run copy dependencies - val copyDependenciesRunnable = - runMavenCopyDependencies(sourceFolder, logBuilder, mvnSettings, transformMvnRunner, destinationDir.toPath(), logger) - copyDependenciesRunnable.await() - logBuilder.appendLine(copyDependenciesRunnable.getOutput()) - if (copyDependenciesRunnable.isComplete()) { - val successMsg = "IntelliJ IDEA bundled Maven copy-dependencies executed successfully" - logger.info { successMsg } - logBuilder.appendLine(successMsg) - } else if (copyDependenciesRunnable.isTerminated()) { - return MavenCopyCommandsResult.Cancelled - } - } catch (t: Throwable) { - logger.error(t) { "IntelliJ bundled Maven copy-dependencies failed" } - return MavenCopyCommandsResult.Failure - } - // When all commands executed successfully, show the transformation hub - return MavenCopyCommandsResult.Success(destinationDir) -} - fun runMavenCopyCommands( context: CodeModernizerSessionContext, sourceFolder: File, logBuilder: StringBuilder, logger: Logger, project: Project, - shouldSkipTests: Boolean, ): MavenCopyCommandsResult { val currentTimestamp = System.currentTimeMillis() val destinationDir = Files.createTempDirectory("transformation_dependencies_temp_$currentTimestamp") val telemetry = CodeTransformTelemetryManager.getInstance(project) var telemetryErrorMessage = "" var telemetryLocalBuildResult = Result.Succeeded - logger.info { "Executing IntelliJ bundled Maven" } try { - // Create shared parameters val transformMvnRunner = TransformMavenRunner(project) context.mavenRunnerQueue.add(transformMvnRunner) val mvnSettings = MavenRunner.getInstance(project).settings.clone() // clone required to avoid editing user settings @@ -111,108 +55,96 @@ fun runMavenCopyCommands( val sdk = moduleSdk ?: ProjectRootManager.getInstance(project).projectSdk // edge case: module SDK and project SDK are null, and Maven Runner Settings is using the null project SDK, so Maven Runner will definitely fail if (sdk == null && mvnSettings.jreName == "#USE_PROJECT_JDK") return MavenCopyCommandsResult.NoJdk - - // run copy dependencies - val copyDependenciesRunnable = - runMavenCopyDependencies(sourceFolder, logBuilder, mvnSettings, transformMvnRunner, destinationDir, logger) - copyDependenciesRunnable.await() - logBuilder.appendLine(copyDependenciesRunnable.getOutput()) - if (copyDependenciesRunnable.isComplete()) { - val successMsg = "IntelliJ IDEA bundled Maven copy-dependencies executed successfully" + // run clean test-compile with Maven JAR + val jarRunnable = runMavenJar(sourceFolder, logBuilder, mvnSettings, transformMvnRunner, destinationDir, logger) + jarRunnable.await() + val output = jarRunnable.getOutput()?.lowercase()?.replace("elasticgumby", "QCT") + logBuilder.appendLine(output) + if (jarRunnable.isComplete()) { + val successMsg = "IntelliJ bundled Maven JAR executed successfully" logger.info { successMsg } logBuilder.appendLine(successMsg) - } else if (copyDependenciesRunnable.isTerminated()) { + } else if (jarRunnable.isTerminated()) { telemetryLocalBuildResult = Result.Cancelled return MavenCopyCommandsResult.Cancelled } else { - telemetryErrorMessage += "Maven Copy: bundled Maven failed. " - } - - // Run clean - val cleanRunnable = runMavenClean(sourceFolder, logBuilder, mvnSettings, transformMvnRunner, logger, destinationDir) - cleanRunnable.await() - logBuilder.appendLine(cleanRunnable.getOutput()) - if (cleanRunnable.isComplete()) { - val successMsg = "IntelliJ bundled Maven clean executed successfully" - logger.info { successMsg } - logBuilder.appendLine(successMsg) - } else if (cleanRunnable.isTerminated()) { - telemetryLocalBuildResult = Result.Cancelled - return MavenCopyCommandsResult.Cancelled - } else { - telemetryErrorMessage += "Maven Clean: bundled Maven failed." - - telemetryLocalBuildResult = Result.Failed - return MavenCopyCommandsResult.Failure - } - - // Run install - val installRunnable = runMavenInstall(sourceFolder, logBuilder, mvnSettings, transformMvnRunner, logger, destinationDir, shouldSkipTests) - installRunnable.await() - logBuilder.appendLine(installRunnable.getOutput()) - if (installRunnable.isComplete()) { - val successMsg = "IntelliJ bundled Maven install executed successfully" - logger.info { successMsg } - logBuilder.appendLine(successMsg) - } else if (installRunnable.isTerminated()) { - telemetryLocalBuildResult = Result.Cancelled - return MavenCopyCommandsResult.Cancelled - } else { - telemetryErrorMessage += "Maven Install: bundled Maven failed." - + telemetryErrorMessage += "Maven JAR: bundled Maven failed." telemetryLocalBuildResult = Result.Failed return MavenCopyCommandsResult.Failure } } catch (t: Throwable) { - val errorMessage = "IntelliJ bundled Maven executed failed: ${t.message}" + val error = t.message?.lowercase()?.replace("elasticgumby", "QCT") + val errorMessage = "IntelliJ bundled Maven JAR executed failed: $error" logger.error(t) { errorMessage } telemetryErrorMessage = errorMessage telemetryLocalBuildResult = Result.Failed return MavenCopyCommandsResult.Failure } finally { - // emit telemetry telemetry.localBuildProject(CodeTransformBuildCommand.IDEBundledMaven, telemetryLocalBuildResult, telemetryErrorMessage) } - // When all commands executed successfully, show the transformation hub return MavenCopyCommandsResult.Success(destinationDir.toFile()) } -private fun runMavenCopyDependencies( +private fun runMavenJar( sourceFolder: File, - buildlogBuilder: StringBuilder, + logBuilder: StringBuilder, mvnSettings: MavenRunnerSettings, transformMavenRunner: TransformMavenRunner, destinationDir: Path, logger: Logger, ): TransformRunnable { - buildlogBuilder.appendLine("Command Run: IntelliJ IDEA bundled Maven dependency:copy-dependencies") - val copyCommandList = listOf( - "dependency:copy-dependencies", - "-DoutputDirectory=$destinationDir", - "-Dmdep.useRepositoryLayout=true", - "-Dmdep.copyPom=true", - "-Dmdep.addParentPoms=true", + logBuilder.appendLine("Command Run: IntelliJ IDEA bundled Maven JAR") + val jarPath = AwsToolkit.PLUGINS_INFO[AwsPlugin.Q]?.path?.resolve("lib/QCT-Maven.jar") + + notifyStickyInfo("found jarPath", "jarPath = $jarPath") + + val commandList = listOf( + "-Dmaven.ext.class.path=${jarPath}", + "-Dcom.amazon.aws.developer.transform.jobDirectory=$destinationDir", + "clean", + "test-compile" ) - val copyParams = MavenRunnerParameters( + val jarParams = MavenRunnerParameters( false, sourceFolder.absolutePath, null, - copyCommandList, + commandList, emptyList(), null ) - val copyTransformRunnable = TransformRunnable() + val jarRunnable = TransformRunnable() runInEdt { try { - transformMavenRunner.run(copyParams, mvnSettings, copyTransformRunnable) + transformMavenRunner.run(jarParams, mvnSettings, jarRunnable) } catch (t: Throwable) { - val error = "Maven Copy: Unexpected error when executing bundled Maven copy dependencies" - copyTransformRunnable.setExitCode(Integer.MIN_VALUE) // to stop looking for the exitCode + val error = "Maven JAR: Unexpected error when executing bundled Maven JAR" + jarRunnable.setExitCode(Integer.MIN_VALUE) // to stop looking for the exitCode logger.info(t) { error } - buildlogBuilder.appendLine("IntelliJ bundled Maven copy dependencies failed: ${t.message}") + logBuilder.appendLine("IntelliJ bundled Maven JAR failed: ${t.message}") } } - return copyTransformRunnable + return jarRunnable +} + +fun runClientSideBuild(targetDir: VirtualFile, logger: Logger, project: Project): Pair { + // run mvn test-compile or mvn test + val transformMvnRunner = TransformMavenRunner(project) + val mvnSettings = MavenRunner.getInstance(project).settings.clone() + val buildRunnable = runClientSideBuild(targetDir, mvnSettings, transformMvnRunner, logger, project) + buildRunnable.await() + // write build output to a new text file and open it + val buildLogOutput = buildRunnable.getOutput().toString() + // first line is a long Maven String showing the build command; not useful or needed + val outputWithoutFirstLine = buildLogOutput.lines().drop(1).joinToString("\n") + val buildLogOutputFile = Files.createTempFile("build-logs-", ".txt") + Files.write(buildLogOutputFile, outputWithoutFirstLine.toByteArray()) + val buildLogOutputVirtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(buildLogOutputFile.toFile()) + runInEdt { + if (buildLogOutputVirtualFile != null) { + FileEditorManager.getInstance(project).openFile(buildLogOutputVirtualFile, true) + } + } + return buildRunnable.getExitCode() to buildRunnable.getOutput().toString() } private fun runClientSideBuild( @@ -245,70 +177,79 @@ private fun runClientSideBuild( return buildTransformRunnable } -private fun runMavenClean( +// TODO: all functions below are for HIL; consider removing once client-side build released + +fun runHilMavenCopyDependency( + context: CodeModernizerSessionContext, sourceFolder: File, - buildlogBuilder: StringBuilder, - mvnSettings: MavenRunnerSettings, - transformMavenRunner: TransformMavenRunner, + destinationDir: File, + logBuilder: StringBuilder, logger: Logger, - destinationDir: Path, -): TransformRunnable { - buildlogBuilder.appendLine("Command Run: IntelliJ IDEA bundled Maven clean") - val cleanParams = MavenRunnerParameters( - false, - sourceFolder.absolutePath, - null, - listOf("-Dmaven.repo.local=$destinationDir", "clean"), - null, - null - ) - val cleanTransformRunnable = TransformRunnable() - runInEdt { - try { - transformMavenRunner.run(cleanParams, mvnSettings, cleanTransformRunnable) - } catch (t: Throwable) { - logger.error { "Maven Clean: Unexpected error when executing bundled Maven clean" } - cleanTransformRunnable.setExitCode(Integer.MIN_VALUE) // to stop looking for the exitCode - buildlogBuilder.appendLine("IntelliJ bundled Maven clean failed: ${t.message}") + project: Project, +): MavenCopyCommandsResult { + logger.info { "Executing IntelliJ bundled Maven" } + try { + // Create shared parameters + val transformMvnRunner = TransformMavenRunner(project) + context.mavenRunnerQueue.add(transformMvnRunner) + val mvnSettings = MavenRunner.getInstance(project).settings.clone() // clone required to avoid editing user settings + + // run copy dependencies + val copyDependenciesRunnable = + runMavenCopyDependencies(sourceFolder, logBuilder, mvnSettings, transformMvnRunner, destinationDir.toPath(), logger) + copyDependenciesRunnable.await() + logBuilder.appendLine(copyDependenciesRunnable.getOutput()) + if (copyDependenciesRunnable.isComplete()) { + val successMsg = "IntelliJ IDEA bundled Maven copy-dependencies executed successfully" + logger.info { successMsg } + logBuilder.appendLine(successMsg) + } else if (copyDependenciesRunnable.isTerminated()) { + return MavenCopyCommandsResult.Cancelled } + } catch (t: Throwable) { + logger.error(t) { "IntelliJ bundled Maven copy-dependencies failed" } + return MavenCopyCommandsResult.Failure } - return cleanTransformRunnable + // When all commands executed successfully, show the transformation hub + return MavenCopyCommandsResult.Success(destinationDir) } -private fun runMavenInstall( +private fun runMavenCopyDependencies( sourceFolder: File, logBuilder: StringBuilder, mvnSettings: MavenRunnerSettings, transformMavenRunner: TransformMavenRunner, - logger: Logger, destinationDir: Path, - shouldSkipTests: Boolean, + logger: Logger, ): TransformRunnable { - logBuilder.appendLine("Command Run: IntelliJ IDEA bundled Maven install") - val flags = if (shouldSkipTests) { - listOf("-Dmaven.repo.local=$destinationDir", "install", "-DskipTests") - } else { - listOf("-Dmaven.repo.local=$destinationDir", "install") - } - val installParams = MavenRunnerParameters( + logBuilder.appendLine("Command Run: IntelliJ IDEA bundled Maven dependency:copy-dependencies") + val copyCommandList = listOf( + "dependency:copy-dependencies", + "-DoutputDirectory=$destinationDir", + "-Dmdep.useRepositoryLayout=true", + "-Dmdep.copyPom=true", + "-Dmdep.addParentPoms=true", + ) + val copyParams = MavenRunnerParameters( false, sourceFolder.absolutePath, null, - flags, - null, + copyCommandList, + emptyList(), null ) - val installTransformRunnable = TransformRunnable() + val copyTransformRunnable = TransformRunnable() runInEdt { try { - transformMavenRunner.run(installParams, mvnSettings, installTransformRunnable) + transformMavenRunner.run(copyParams, mvnSettings, copyTransformRunnable) } catch (t: Throwable) { - logger.error(t) { "Maven Install: Unexpected error when executing bundled Maven install" } - installTransformRunnable.setExitCode(Integer.MIN_VALUE) // to stop looking for the exitCode - logBuilder.appendLine("IntelliJ bundled Maven install failed: ${t.message}") + val error = "Maven Copy: Unexpected error when executing bundled Maven copy dependencies" + copyTransformRunnable.setExitCode(Integer.MIN_VALUE) // to stop looking for the exitCode + logger.info(t) { error } + logBuilder.appendLine("IntelliJ bundled Maven copy dependencies failed: ${t.message}") } } - return installTransformRunnable + return copyTransformRunnable } private fun runMavenDependencyUpdatesReport( diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/ideMaven/TransformMavenRunner.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/ideMaven/TransformMavenRunner.kt index 4590c529793..338d465aca8 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/ideMaven/TransformMavenRunner.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/ideMaven/TransformMavenRunner.kt @@ -38,7 +38,7 @@ class TransformMavenRunner(val project: Project) { override fun onTextAvailable(event: ProcessEvent, outputType: Key<*>) { // IntelliJ includes some unneeded lines in stdout; exclude those from build logs - if (!event.text.startsWith("[IJ]")) { + if (!event.text.startsWith("[IJ]") && !event.text.startsWith("Progress (")) { output += event.text } } diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerSessionContext.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerSessionContext.kt index 0f567285a09..8acfe8d72b6 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerSessionContext.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerSessionContext.kt @@ -28,6 +28,7 @@ import software.aws.toolkits.jetbrains.services.codemodernizer.toolwindow.CodeMo import software.aws.toolkits.jetbrains.services.codemodernizer.utils.getPathToHilArtifactPomFolder import software.aws.toolkits.jetbrains.services.codemodernizer.utils.getPathToHilDependenciesRootDir import software.aws.toolkits.jetbrains.services.codemodernizer.utils.getPathToHilUploadZip +import software.aws.toolkits.jetbrains.utils.notifyStickyInfo import software.aws.toolkits.resources.message import java.io.File import java.io.IOException @@ -44,8 +45,7 @@ import kotlin.io.path.pathString const val MANIFEST_PATH = "manifest.json" const val ZIP_SOURCES_PATH = "sources" const val ZIP_DEPENDENCIES_PATH = "dependencies" -const val BUILD_LOG_PATH = "build-logs.txt" -const val CUSTOM_DEPENDENCY_VERSIONS_FILE_PATH = "custom-upgrades.yaml" +const val CUSTOM_DEPENDENCY_VERSIONS_FILE_PATH = "dependency_upgrade.yml" const val UPLOAD_ZIP_MANIFEST_VERSION = "1.0" const val HIL_1P_UPGRADE_CAPABILITY = "HIL_1pDependency_VersionUpgrade" const val EXPLAINABILITY_V1 = "EXPLAINABILITY_V1" @@ -111,8 +111,7 @@ data class CodeModernizerSessionContext( fun executeMavenCopyCommands(sourceFolder: File, buildLogBuilder: StringBuilder): MavenCopyCommandsResult { if (isDisposed) return MavenCopyCommandsResult.Cancelled - val shouldSkipTests = customBuildCommand == MAVEN_BUILD_SKIP_UNIT_TESTS - return runMavenCopyCommands(this, sourceFolder, buildLogBuilder, LOG, project, shouldSkipTests) + return runMavenCopyCommands(this, sourceFolder, buildLogBuilder, LOG, project) } private fun executeHilMavenCopyDependency(sourceFolder: File, destinationFolder: File, buildLogBuilder: StringBuilder) = runHilMavenCopyDependency( @@ -210,7 +209,6 @@ data class CodeModernizerSessionContext( fun createZipWithModuleFiles(copyResult: MavenCopyCommandsResult?): ZipCreationResult { val root = configurationFile?.parent val sourceFolder = File(root?.path) - val buildLogBuilder = StringBuilder("Starting Build Log...\n") val depDirectory = if (copyResult is MavenCopyCommandsResult.Success) { showTransformationHub() copyResult.dependencyDirectory @@ -249,6 +247,9 @@ data class CodeModernizerSessionContext( ) ) } + if (customDependencyVersionsFile != null) { + manifest.dependencyUpgradeConfigFile = CUSTOM_DEPENDENCY_VERSIONS_FILE_PATH + } mapper.writeValueAsString(manifest) .byteInputStream() .use { @@ -259,14 +260,13 @@ data class CodeModernizerSessionContext( if (depDirectory != null) { dependencyFiles.forEach { depFile -> val relativePath = File(depFile.path).relativeTo(depDirectory) - val paddedPath = depSources.resolve(relativePath) - var paddedPathString = paddedPath.toPath().toString() + var relativePathString = relativePath.toPath().toString() // Convert Windows file path to work on Linux if (File.separatorChar != '/') { - paddedPathString = paddedPathString.replace('\\', '/') + relativePathString = relativePathString.replace('\\', '/') } depFile.inputStream().use { - zip.putNextEntry(paddedPathString, it) + zip.putNextEntry(relativePathString, it) } } } @@ -274,10 +274,13 @@ data class CodeModernizerSessionContext( LOG.info { "Dependency files size = ${dependencyFiles.sumOf { it.length().toInt() }}" } // 3) Custom YAML file - // TODO: where to put this? VS Code puts it in custom-upgrades/dependency-versions.yaml; here we put it at the root if (customDependencyVersionsFile != null) { + var yamlPath = "$ZIP_SOURCES_PATH/$CUSTOM_DEPENDENCY_VERSIONS_FILE_PATH" + if (File.separatorChar != '/') { + yamlPath = yamlPath.replace('\\', '/') + } customDependencyVersionsFile?.inputStream?.use { - zip.putNextEntry(Path(CUSTOM_DEPENDENCY_VERSIONS_FILE_PATH).toString(), it) + zip.putNextEntry(yamlPath, it) } } @@ -286,7 +289,6 @@ data class CodeModernizerSessionContext( val relativePath = File(file.path).relativeTo(sourceFolder) val paddedPath = zipSources.resolve(relativePath) var paddedPathString = paddedPath.toPath().toString() - // Convert Windows file path to work on Linux if (File.separatorChar != '/') { paddedPathString = paddedPathString.replace('\\', '/') } @@ -301,12 +303,8 @@ data class CodeModernizerSessionContext( } LOG.info { "Source code files size = ${files?.sumOf { it.length.toInt() }}" } - - // 5) Initial Maven copy-deps / install build log - buildLogBuilder.toString().byteInputStream().use { - zip.putNextEntry(Path(BUILD_LOG_PATH).toString(), it) - } }.toFile() + notifyStickyInfo("created ZIP at", outputFile.path) // depDirectory should never be null if (depDirectory != null) ZipCreationResult.Succeeded(outputFile) else ZipCreationResult.Missing1P(outputFile) } catch (e: NoSuchFileException) { diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/ZipManifest.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/ZipManifest.kt index 4dd20e630d0..2d3a4633c6a 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/ZipManifest.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/ZipManifest.kt @@ -7,7 +7,6 @@ package software.aws.toolkits.jetbrains.services.codemodernizer.model data class ZipManifest( val sourcesRoot: String = ZIP_SOURCES_PATH, val dependenciesRoot: String = ZIP_DEPENDENCIES_PATH, - val buildLogs: String = BUILD_LOG_PATH, val version: String = UPLOAD_ZIP_MANIFEST_VERSION, val hilCapabilities: List = listOf(HIL_1P_UPGRADE_CAPABILITY), // TODO: add CLIENT_SIDE_BUILD to transformCapabilities when releasing CSB @@ -15,6 +14,7 @@ data class ZipManifest( val noInteractiveMode: Boolean = true, val customBuildCommand: String = MAVEN_BUILD_RUN_UNIT_TESTS, val requestedConversions: RequestedConversions? = null, // only used for SQL conversions for now + var dependencyUpgradeConfigFile: String? = null, ) data class RequestedConversions( diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/utils/CodeTransformApiUtils.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/utils/CodeTransformApiUtils.kt index f3b424d8e3c..94e57287ba9 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/utils/CodeTransformApiUtils.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/utils/CodeTransformApiUtils.kt @@ -66,8 +66,6 @@ data class PollingResult( val transformationPlan: TransformationPlan?, ) -private const val IS_CLIENT_SIDE_BUILD_ENABLED = false - /** * Wrapper around [waitUntil] that polls the API DescribeMigrationJob to check the migration job status. */ @@ -121,8 +119,7 @@ suspend fun JobId.pollTransformationStatusAndPlan( delay(sleepDurationMillis) newPlan = clientAdaptor.getCodeModernizationPlan(this).transformationPlan() } - // TODO: remove flag when releasing CSB - if (IS_CLIENT_SIDE_BUILD_ENABLED && newStatus == TransformationStatus.TRANSFORMING && newPlan != null) { + if (newStatus == TransformationStatus.TRANSFORMING && newPlan != null) { attemptLocalBuild(newPlan, this, project) } if (newStatus != state) { @@ -224,6 +221,7 @@ suspend fun processClientInstructions(clientInstructionsPath: Path, jobId: JobId "Error applying intermediate diff.patch for job ${jobId.id} and artifact $artifactId located at " + "$clientInstructionsPath: $e" } + throw e } finally { runWriteAction { ModuleManager.getInstance(project).disposeModule(tempModule) @@ -244,10 +242,14 @@ suspend fun processClientInstructions(clientInstructionsPath: Path, jobId: JobId CodeModernizerManager.getInstance(project).codeTransformationSession?.uploadPayload(uploadZip, uploadContext) getLogger().info { "Upload succeeded; about to call ResumeTransformation for job ${jobId.id} and artifact $artifactId now" } CodeModernizerManager.getInstance(project).codeTransformationSession?.resumeTransformation() + getLogger().info { "ResumeTransformation succeeded for job ${jobId.id}" } + } catch (e: Exception) { + getLogger().error { "Upload / resume job failed for job ${jobId.id} and artifact $artifactId: $e" } + throw e } finally { uploadZip.deleteRecursively() copyOfProjectSources.toFile().deleteRecursively() - getLogger().info { "Deleted copy of project sources and client-side build upload ZIP" } + getLogger().info { "Deleted uploadZip and copyOfProjectSources" } } // switch back to Transformation Hub view runInEdt { @@ -262,6 +264,7 @@ suspend fun downloadClientInstructions(jobId: JobId, artifactId: String, project val downloadBytes = client.downloadExportResultArchive(jobId, artifactId) val downloadZipPath = zipToPath(downloadBytes, exportZipPath.toPath()).first.toAbsolutePath() unzipFile(downloadZipPath, exportZipPath.toPath()) + downloadZipPath.toFile().deleteRecursively() return exportZipPath.toPath().resolve("diff.patch") } diff --git a/plugins/amazonq/codetransform/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codemodernizer/CodeWhispererCodeModernizerUtilsTest.kt b/plugins/amazonq/codetransform/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codemodernizer/CodeWhispererCodeModernizerUtilsTest.kt index a257245a23c..38335097869 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codemodernizer/CodeWhispererCodeModernizerUtilsTest.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codemodernizer/CodeWhispererCodeModernizerUtilsTest.kt @@ -397,7 +397,7 @@ class CodeWhispererCodeModernizerUtilsTest : CodeWhispererCodeModernizerTestBase @Test fun `WHEN validateCustomVersionsFile on fully valid yaml file THEN passes validation`() { - val sampleFileContents = """name: "custom-dependency-management" + val sampleFileContents = """name: "dependency-upgrade" description: "Custom dependency version management for Java migration from JDK 8/11/17 to JDK 17/21" dependencyManagement: dependencies: @@ -406,7 +406,7 @@ dependencyManagement: versionProperty: "library1.version" originType: "FIRST_PARTY" plugins: - - identifier: "com.example.plugin" + - identifier: "com.example:plugin" targetVersion: "1.2.0" versionProperty: "plugin.version" """.trimIndent() @@ -418,7 +418,7 @@ dependencyManagement: @Test fun `WHEN validateCustomVersionsFile on invalid yaml file THEN fails validation`() { - val sampleFileContents = """name: "custom-dependency-management" + val sampleFileContents = """name: "dependency-upgrade" description: "Custom dependency version management for Java migration from JDK 8/11/17 to JDK 17/21" invalidKey: dependencies: @@ -427,7 +427,7 @@ invalidKey: versionProperty: "library1.version" originType: "FIRST_PARTY" plugins: - - identifier: "com.example.plugin" + - identifier: "com.example:plugin" targetVersion: "1.2.0" versionProperty: "plugin.version" """.trimIndent() @@ -439,7 +439,7 @@ invalidKey: @Test fun `WHEN validateCustomVersionsFile on non-yaml file THEN fails validation`() { - val sampleFileContents = """name: "custom-dependency-management" + val sampleFileContents = """name: "dependency-upgrade" description: "Custom dependency version management for Java migration from JDK 8/11/17 to JDK 17/21" dependencyManagement: dependencies: @@ -448,7 +448,7 @@ dependencyManagement: versionProperty: "library1.version" originType: "FIRST_PARTY" plugins: - - identifier: "com.example.plugin" + - identifier: "com.example:plugin" targetVersion: "1.2.0" versionProperty: "plugin.version" """.trimIndent() diff --git a/plugins/amazonq/contrib/QCT-Maven.jar b/plugins/amazonq/contrib/QCT-Maven.jar new file mode 100644 index 0000000000000000000000000000000000000000..1d134b2918651cdca6b67e40fde2abdfa0f88441 GIT binary patch literal 148642 zcmb@t1#o0Rk|iiAF_f5@nVDHCF*7U0%*@QpQi++FnVA_%%*;^Is<&rnrf25X?#%96 z#<$3@=l(Mz-8~}RU&u>=f}sEbK|%tR1{P=neP1B|xP4zx-%UnTS&&vzR*W7LNdDh} zL_P(Y^}Zli*xvxm@AfVJA3zyFSxGTbC1pApv3r@x327->x;Z#0TB_;EnFd9MMdm+; zdxs$ZMcKFfzdsf1yKiJ`{ofw=pE2K_y4OX(f?i4$jTgGU1Cul&H15+A+^C82FVLxsM4b7GZK53q^FC=#J9?`M2mV#GT}PF9hMy zgCf3u{Nt@1RgjJ0;d80kYw5No-RYd3-Cr+vaJ`t?5<~%JAdH~)jffAG3o;g*ixrx# zGMm~eg8GF3 zdOPw7qa6li0P2P-?b$qew>W+-4WD8QRZaB6?nIyW2A>ybTH91 zcTDG7U(-l{JK=NJ7W)YVK)&MMJl&^pnow4PHI8LepG0$CGf!XbkIfkd8)wS zvM?0pUS`^ak5z*Jcr5fqFg=BRiEA~sUGWwBCN_5srCvv1qbz%J1(UktTJHyaFc9B$jl?Tn%UV!ALO0@AjK+uHtT2HS&1twF9bC3W#Yk})_<%FI#+B~I zaViPdaB2-8I#!1mI8vw%oHT=p>W@3ZLiu$HM0JXgy9eXlVf{UT3mMZY9OIrm*@=~n z(3k|)R4NQxMydL4b*0NFtfE$Us)1<<(D>~91~25CYiGm)crz422ehgHaRhK* zGfXcB_Lqo8svUhQ+^>jH3uQ)%>S5*TJ$NRFd+X~l_SI4JK1%PLltiF}`IX=Xj@aGb z{}G1%;c9LlcM7TaKtS|TKtOW;f4a!OxrH{Am-5mQ|M9f(w(%V#A+T{ADUtr@c(FhL zMUbCAi9Sf5Uqs><7&sa8LORq>l+*~Rt(InsD%A?nDiteM5{d|^zNRXbj#3q^4l_&3 zjT!I#_utRk(k2OGLYBV#Q=9KsUB@||(_cB4yxvC>U9msstTq(r6pa@~tChex(@a8$ zu*Z1}VqFVrDyJHT&}p<*aiT?ew$-a1EIz9EY(v@qXq|=+e(3tHB1bWD9=!*Cu7Z$h z^)-s2b5bf1r^;#+GUG0U=Gtb?Y~bC81^~dv!1Y)n;1ewa=~b`aH9P2`6B=NOmtdRg zskWO`Rg4wb;8rNaOAwPLSpM2UF+>9)R1|cNj!RHn3_y7+6f^1r5=|pZV3j}tyu_$j z(Z=OZA?xEj);X7Xxu%wlljt`hglTY>)>F8EZNDA#C=E}eU9#U{jF6aOM#*^sKwI*K z7Fv_&C{P^cEJ~Q8$r%T~1Zx_HT87Z$aHaBs^cz`G%&E6fEOakoF(SFOSwc3kqL)r3 zutr#za0{e0I8v6b^)oc}bIAWd*-%)9iGK9Kp)S1f&6|NJ$zG4pjh7U#WE3vUv7}SZ zU?98+1FAm#YOIRLn-SmFYVnmsGrX4{JDj1Tp#|rZvt#l=inZmnP@z}CC}=2|WTYVC zYB?<|Rx+R!gOv*v>SRfk$5{Xp71A7ZcOu@jpOAw;M}X3_LC6H1xTa>!ie($j*b;Mi z!e9_##wgRo&f;Bok?D$B%YyOxqEw&uXG} z+NcUwRk2v<*#6^NfA7%L4_3XkREM=zO&kE>!k}mnd`AL?R z?vy%>j56Gh`%2qgOTW4Y<6!_0y#dZ%hjbl)G9kh<;~E3OFsyFQ5tcD{%Me4%&IhYH zc*+J*v3?La_u4QF(bJ)(Za!&DZr;5Dj~*e0NtkMOFNQ{(aLJx7Y|w8Gni!IlW}>CQ z$X}DDM~R+}!S;?)t|?t7YXJdSIngdA_So-BsEwQ^%uJj%<#GszSk#m@e@e)mY!@hj zIVEbdF~HQP!c1s5Yun~N!RFEtO3eW8MC%JS4XkM?rQxdIJ>=3MY{;&Y-|U+zsc>r7 zoGc-R{*8QV?nFE3ICJ;*q(8ZHB$c%#x-!d7>i3o+0weiexsCy4{m3$)2booEiuD`p z!Y;IzN&`r?J-&qIKHLQLnfNX)NkB zC$A54pg7y(rle9ccWLjMfT0e&tfr3i0(?1tBAb1c-|;T;!vO)f3sG=qS@g21D$Z;I zixY!ES0~P9QUQS?C4GK321W`MVLHT~?1@@?g`Lm+2vqoIJbR4+g$lJ4c@Ssp(_E`@kd;K{bYY?ul)+xx; zGp_T%7mIfD{RxMl%!v7Btrs4Rkw(U*N>eXs%kgQNuif^nUCG zzJH3y^@Fte7fz2Iv_b>XkP_u{d5@3>Tg`a7au?`NMK_J1Hn|J~I6V6rog;(BQk~yW z|6-xH^TMw9Uot~4(vusOj`Z>()oajVM@1&-!#2BtTy~>Y^-2qlLjhWa zNZ#qQKV`lk5GCJs{i%-Okk&@xH(gT_`ShuRA*fh+<;!;ce+~G%fR)TS6sQ^QO`}sX z;!6R2#mnL^kV~f{HDJo6n-m4h<6keMS=>94XA#FJcSwjWWfvJkXiPuGcG9M)kK4T zY2F?AW1yv#dy!=4w!9~wnHajS*gp`gIoMS{P3$y%$a7z;YQrLJ<=)ed6Xg{wk5hDS zHV_$TSkSvRWVBj!tDYTuU=PY@an*z+vkH^SuZbR^(iBW8Bb$j?<$Md4Q)=HmEq+^Q z9DA~L5>8M?S;68vCDAdx01lfBe_`xd#gfFMaZCv!k81Jb;}s(trm&E)k~}`u%^zl0 zl14unYr32T%OcjzTgBdd0fP=rKIP%p`@-g|$j1wt4jqm3iaYpBP}xKJokX-Ta;xi| z6>%=)OB@aNE5{AbtF$^?PQ^Ws*!I~&NB|>(O$*0-;opN+I7K&qen0(e9z77cKyPyT zIFfbbKKtw_0joxHvb~TzmbxvXld=`{tiio*VKUJ)H{JYuMKL@sq`v_DvN`nlpvqQL01&m)@%fj}oq1 z=EM63szvy^$#H50)0QtN5-5K|!dlSYr1#QJH}f<*zmg}lJ5yH7y~?Lc!U@&?@~{06 zNV>-sN;F1Jsa?bOn@HVSIrj>&qE(XaE0VT%Xh;@G5*y&F=~=pFg*87#OKgtRf<&80 z)pR@$8}_Qr#ir@eX)l7i52VctyEqZA?UhhWMS!Xj7IG>`+y#C-s1z~E^895Xa20Og z!yG_Q+^mOjO$hg=c3N*g%$Q6J7OzGbYs~a-T>f95uxB+2nuE0I%g!HGQp%7Mt7nW< zT*Qj7s-QHMXto7@!we<^ir_4KiROy?$hgp%&VYM?aRJ~|h_#U8#(*TgSAk1bDVJ=>**85s>oXflgSGy%@h@(ID?B#SD7B>#0}E z?Vh>k5#j|9246P#|f5}4O+UDRkF;=`PXVW)1rV|2!|~0$2_z0omd|a!fH*KE-r;XYKPyQe1h<0o-@e*axptI z{}w|Rv*g{~enyG4lf&OPjK-I1E5Q(mnUOpDP!a>ruv||Kjt?s#R>0+>(kag28LCB> zJN;-x@e|iz!$M-V_VA`437%GZ(a8S2e@u!OZjjpS21PI(@v1Bmi7)aQ;ah!A|MG)k zJ1`Er#ne!6UBD-NsTWG`AeF^O<5=&uW_5CvU;RXQ5OYzOr2qdgp_PHQZ%q{xvpVr{%>U@O2w& zdZ_5tosRRRrLFK5yZ!_>`->_v=E7fuv=BM?Yg-+aAvY2r>!W7;>RK$LS40DmqD2SD z;Q3TK_JxWy+JiWs$c@~YDx&cj7?WsVr3P}m6K4>vi(vraEu6({g2Apht2e{+Elv#O zH`QbsG;^(;=k=wWrbe8sE#ph0zp@LT(4HVwmQ--HB8`zO_El~mx zJ+V5ZgWC?`$8f5opgbg4=*b2zE^LSVTr7*zgl7i*1Ya=cT7pb#G28h$RTgJ|G&B!p zVu6BF#7-v-DTWK&SIQ_2C+smW2T=$rB^ezICJk4IC^ZV%eS~Ut2m5x5=j+3 zbZs}O!uy0`q;gR)8ccn8+Au;`{-=c&sIZ)p6kLCo)OGY{DSt}Xy>e4^O4;GhSyefG z=7k8tp@Xgy*b{pvm5PeC^65n{tc7NzfcT3Maxtx{#ig-w-SWs!KLyI)smp7RG-tlH zshUNqmgNd+mSB~{3DtrPj~VE5S$XO0^70X0Z7kBPeZ>_`yiEK!B}d97#VFH1oL-4m zz3vr{TLu-BV+icJxpdUd52q5Emyn@^%7}nsQ8aU0spzd7%dC#_Z^uh2RLitEfvZli ze65V=02P`gcO}cG0P?yZ^JdUJIH{g)2hq#%vyAe$M`}w|`l=93hj&956J;LrNo1CD z(^l9CRT|Bn*7ojlhoy+O;z#OpwaUtJy(O?7i>^;34i;j57;s_61qS9RNv(S1eO%}W z@rMU#x`yg7L>Z9iWc8qv+F|^MrM~btqKZinD;t^7b0`)MBA-(&gv+{UAFGxRYN!6y zjRoirjU8f@v5ApA7Bu$1$5LT6h+qhFe8fNcFvUoPo(fk=F%~uy`697CxJx-;fLuLm zY*WQbz8s)Zr#`|UDJ{7siHF0AeC!e#Li}tTHzf`cj?M`dUXDSbCfF(ok8W+mE=r#a9cryWyKxPvPFS~hv@n3RD&lQTO2}m7rIWbo?zj8y%dr`@#{T#RjEpOjH{;Auzf7m$_rY13PB~B#in=NrNQ1_EclS2}=5U zfOFb;_n7D3zj)Hpc6@7Vf!`=k{LZ^MrBcP;BjS? z(zWmTsW>$0WA}y`y0a}48O47&LB{mwH4hO0Qv9{CdGGjEE;zK1W}56ef%c+CP^1$> z6`}k7{;FQYMCV#qPy)u@uJ|McCmhNkBCoC9tt(SHMgVxuHBsBwcr^BAEmtbZLHuIjh+SzoSAB+2D4CZ0ZgQfY$v;;;-_g1rB>jwZ3vsctnv z{@?|-+aoZ*NqI~<@=S?F(F{+jIku~iL^?bw3T=|;a{0u#M;CI4NI*hBx`YWE@3N|NVpZB#D1K=X^4r*)u5^XS$X_3Jb zplEo*&sh7Kjrt6&O`RCbF;6Upw?K6EQL-P7k5l-#j9eAu=N&oA5>=e* zYqYDPZ)RLXno^*D_HfO7sWxdX_MyexwRL(#eiVrD7%Htmc=S1*ZQg}{r6V#1{oXy0jqz19rhvRJLRxBf)VS`<~QGd7; zLcN#RKaKX~q6e=RbxLgPQC*!gpdD&mIKei~rrCg-w=ulBDV^x?bOX^6#P&XJ0ZSnK z7mv|aEGlCuWz&-`ozXHrJSCB*FU5}@+7x?z6A$kNRbyP}HtTCGx9zakvg8rB>H!P{ zE-Z-DrxG6A8*$(W8~>SHlr+QI>qBQtKXl0oIeMlFA|pazF-uxp0gsZXeonnf(wa;a z_yMI$&PZ8H(HG@2Ti9_9A^*D97P802@O4IN7N$Tg1aF_czz*T|Z@sklR8~|^qB5AT zvtvL+Ifjo$Qw8mjp-y(SZUNmpx%H^U6Jl{sM0FqhOk-OczD|#8jvP)g- zWSU}4n6KbkTyNQV!KBz>3JzXKnmtZS^HTb~tael5#Kll>q*~baGC#pV28~bTnB_9> z-l1n(l6y;&TqkNrw!Jd3+AFNu+`-cGq+L83t~(m;YGil7iTg4i*O*zPAw_K87OGkg zGdd45?pQiQy5aUfz42()D?=QnEK7Ax?gZAu?_&`PdTUY8^Hj_u%%&(*(3YR#s-WWp zkxL?W9_9g~ODGn5j}MioE1u<3z?ziY1f|rvJdg#kp$Np>TFo?o8NDlaT9G^VnDHTq zODh{xTDq9`OuO;o&k>z-&Kp-_SDcOValxTHcbx~;8p52cgGExw*bXDsmeohYP+Fk~q5e z->(M*Ojit0j@*&92)Nm^pemyI_)D3C*E<=gEFfp_xu9+jbe}UYS#rwa5z@TS;Kavk z8|K3%!Wt8!hF%II_{EZ85w=ZcDjVigLa4~5Nn{5IYs|t463>=I$&yU8RXeQ|9YwJp2pP7Icyi|lMCruDMavTCsgF4GV0-wz16oN^zCp5|u%DkGmbYvw z^W4hfz7Paoz^z@O6;Cx_KVwPR5!6;N>>x`m4d4d%-j|#WcLj?Cy_LLS-YkXWZ>*hp zU6B2w2p)ednX~8`T{^zj%x$Z(W2pWWa~M+-E+$$cqjB1kjXlDurk(W07m63&R6#=T zrzI`^Ieuy5i8m8KFld6GOSGvXh4w1O92cUF*?wkz4OkLBQv7!YuKUhS<$EkY7VadQ{0l{6A-1eUW&u_W>1O>gH z>6tPXOiE#AH2^FJe8QNFfY`<+O;5=x8k$cVFqvLh=SO_lAV@hE?$ane+XX zc*0CoJY$a5+vL|B^n*);8n~29^#FivZOE-H51u^&-yW9j#A-VKc#(hYh&EXui*N_I zKGOC8c|7OHlc4)Y;Q=YOSj`Q#Yuv^obY#BgRpQNWWFeHt|B@#@)SmD71_hMBz;3U| zBL~5cL!XuG9;A`w#<}VZUem?y87?PU6`a5&svRnK3`nm1jZPDOwP)zer12sE7)Con zyc`j{^&+d{ZdNgANaGBxcM@#HY91cg7CsvKhXME~%knLPAR6h*UkqRV5_^odtl_u;ylZVF|j+?U@5NTHCB+ z>t#pu>F=hG2U!w+$A4>xN9!GnF(2JbuWAHAaXv zV1P9dAA|q_*w;30yo*A%U{TmI$zs6f?0ueNk}Hj5$1umE11&I}*C>`#W+qU2A$37J zzBM5ZtDvsC+;66XucACVD9vrpY$2*0ery0aUnwH>XSJnwMImB4Zb*B&;ko@?dGC^u2%=X_;ka1n0_@W`?(CKeCVQy z7$V&*NOnEBpGl%G{$*0(TY-u0a{pWx2_q#qmz=wbEPiy0P?_wiN$pGFZA$(%3Q0}v zf}2557P~b&z~pAWM>~6}I=&CTnagZW_gfUTGf;K6C46SMiZhi6a-HrV+v$g%z|J1b zscLsv&QatkyBDQRFQD@FFl1U2QIJ<=VCfPPO~-EoVF}mFT;Q|n48n}_6nZ`1h45-z zf%10|`<-_CzX^ zFq_yy*vKz}kT3x$4pWu8<5qe5{b&4FRa%oN5`p9IFi32It+?wSw5`{*M9a`p ztDVQtoNvq+~cNwL0EqNPB{AF z}ieUmkUe{?&t z^-%_={s~e6pKe|Biz|7{VqfAH^SViM^w79D+3~y+6mAi=Z^K-z>S0o^N*}$(mUe?@ z`x0*WMva)%1YCtda}3R?;(o`XLbk=YPtI%^bYCan;dX1JC{WRO1T-DKi!^O-p+>nx@Orq@eH zIM1TsloPP@6sZJZH3|P#REeun+?89d5TC;g0vVXrQBsg8jeGiK47gKe~gga|ieQLFTWP3)-LKB0h z+AXOQt{#+<8}8+w%##f-2#_$(Q|=F-t={(&6Q2N^z2j4~Pgd{P9TELow5{pudE5`Y z$s=^97Kd3K3liyl1*eh>>E}}O2T+w?JIW1a9U0=!<)ltM<;Cxd4(nB_3$e%{tirU) z2t@cT#Jia_TuXQo)!L`!FtiXLnJdcdnpiqxo{PGTS-F3N_TJ+-6qhjAY0M+D4?x4EACw)* zE;-22r?ZfuI)`E=5d3tf${W@|i=Py#h}hWhTqZ{xRhE;YfCibtDYmdsQeIdSXPtpB z%zzVCni|e4FNQAH09m3LQb!e&3!o~`%K&^8S>$l@EYV0-WE_W9XNY>M1ajP%4p;uh zwgs*iI75GV{!#N*o)r+PkfhHJUKv&dg* z`XwFpsb}~wFnB_~d?IyrKiD9AYsv=TYXGdWWKQ5T0oFpaW*ly;Xj&6zURM-zE+w!m zu}w4eC&-__K>vdS@DD1|ciI2n*+W0S`~S{avajDiyWkPlKt&sS(!NLx)>j#0eLLqyGO@93s0-ESgRc%~{<4L@P>IqEle;_fti+UA^ z8B0B{`R|`_;uC9h3T)b!-p(HGOdmX$sLoP{4eZ?wD*E*w@UVc7%^@le5;(gaIcOp} zL3N+E7Woe#{$tvJA`=z9zxlsU8{~K2!obqN!O7rXSV;dB2ltVt!=5%J(il2~Mr*V9M_&EJLx z`+m-6U`W&v2J@BHq7wZ~pdLdxA@;6$1ND%7zATPpi!3ysHt)EiKPxZUi83ZMKJV>k zF1WToo_XtJ2=}OW`Y`_`JaphzfJat{a%gfgJTL>1v&!O&I74o)sR{^fHIG6ml!I=4^OL!MO06bR*N}$ zXb%p!KgzF~a-kM?$Swt?E6=6$6~71F_r+C7z)+i+g`A!s2U7!yKsKFKMZi^(d9iJH zIm1FFi8Y(Vo3!CqEwuka3pq-*X9lf)ZDXDlRZ4*|yVb&|tnE_vRsevqgEK%!4HsBA zeQ#8-027M?z5aAIDx+OkBofTr(v!+m7+>dL683n7ZIP-k%K~QK0!sX8@^xDwlP#RJ zZc9nbpkv+7eXWkgh1xM7cX!Z?Jx*9e28z$wsfDss#~Yx*x?wl#_}@Ukh!`s3$rdJc4UNacW@RAqR9#9 z!d!;JiEF{^!&9s;pOO`7OH-2NnNCq&N1q{Jd6-O)8x3x}M`A-k!^t?pOE%tXp2b;( zQF{yeuQeeZ# ze)Pu;I!b|w4QjbcvYKkS6apEo5iH6iW?n=0#PL%Uwdl%e(u5hmQlsbnZNpkZPW0>3yjWVN zL|Xy1R#j0WY*XL?u)gV-oiS(iyu9fFT~}YrLHoz}p@49jHs#miPH=E=f4yIW_~~5E z>Dor};ZpkD$7cEQiU~wZtX;6~mY_!gfG3&|k|n2~ndNtJ3vY<&oH(;Hgyi%bl~jX( z<4CahPoI6V0T!}WJB*nHiVkqM??8g4zU4W6|8oov!y{nz4tX#YU-07GEo^XBSOQ`0 z6>_XcC=L^z^G~~boRu>$I%lF3#$zwN`=sHmo)AU>uqNa0Wq=Rbk$ZF@EWf+ITj8hJ z+se=0C7|#^Iil0V)&O+k+yjP1%TNJ@OfdoH;Jjf3|NQM(KQ6QoDjbkUs@oX*Qp`6) z)xGNz6N+1)@hPB)lY%feT-!LG$r<3p12fiX4ebIIycOQ^@0Yn)(=nsRkD#$_Xsg7h z7Rh(x`?Q&S6ZobE82X*k&sI1TkQx*0~tX9U~r60&VliQ2ES$r?mAl zhT(C`tX%VzPaRPq<#m@hEN4@@H4VEqVHP%uyL8(oAC+U=IQD=7a0bc91q zZjcqs=|@$Pl~0Q5^|`hb$R*L9i!G2nP}rbE8?Y;X6Yt?0HZ)CdxghTrEpJa~C+=k4 z9qR2eqz`3->jmKJpcco?iZ5stxXjcO4=_bzW+`9SBQo%>{}QkZg`WnIzv;1-F#lY) z{!hUE-+}ml$5uJRfABv48C;W9wH!A@P(GL0U-J{BHf9AV^WcVL7g`1UP)f{^R)8}} z;G3`|{6d-M+w*YjkK^N51?vZQJ>JIbX958LZEz zT!t2A$=m>hp*{-tF*KK%8FqMY{uIk*SFV?~Ig`mh6p@|DVKm`Yl@3W|i+w@1QRneB zKGW=W@-oa;#TL&uN5x1GYKU6MsKp?w=e+Y8zqgiBxHrx}RF*L}-?YFM>gN;gH1=d3 z1;`+aDI6A4QV8*eX zSCfAetjzpzL*^>JH6myBCKzuSxhVGEJu+MLS>|$cMGzbAxYBW3aW?L(;TL^@e|iJ5 z+L59U=7@nzMi?UAR^7TQEHAtPMBlkE(zv7>Pz~xfqhsip3)P&rQ?;`B8SrNr?C9z{ zk)k+uRF&HVb7Y*AkSpi?RxtSx4_UL4fX{x^*ooAoGlKMS(@SfAOA@-&ZeAQ&&sms%a=PRABmIU54ZS|nA=qzlADOpjtu*bTxUIoC#*+VTL@ulAW zFfryC1TLcO#Kq9X`N?fnq_p&x`igp7T|jr3){D{zj~!sgf>HgE3FYbN;w0J-r0`Zw zDNDn3Zp>m&Avo#=R=zG3I88zoJ}bR29R!facg_g?&Y=c~ICm*hEn`;4DCYm&IE$A_YIZsEghk$_saL@&VDsP`RdC=i*;M&Wyl21K&|;33 z_e!)4m6+la13SPDygvTZJThs~uW>>!<_vOv+p&;#w|S)bLQ?7z%>5en*aymPxxkZ1r=adv;Q+tdt__r)b~G;?*Fk>BVK(L`U4IGB>hd{NB^%|wO`+xyMM-! zA~h{1WEB+N1+{sm8(O^n*7o0L=B@-F4QM6F?2#EL; zZo_RAyg)1jlm}ZP4_okk-VReOUoYnmIbDkr(=#_%{CzIQHaR_a9H)7oH#Z``vbhm} zsQ;uQm4+0M-tcq^+z|Cifzcy(3fV>dQ3+Uq)FpQd{38?40=Z4*7W#*yuLJBFF^j}Yn88fDZi3OLlY3KdlF_@L`rWbq4uhie z+*E;yK58m6vq{8V>&+7j3K~_)CF@&cqN%iygm|cUSIlGgA?j(-6pDDD=oGkG*7jn| zhLBR&Vk^5)x95R@hZ@ZZPz%X}a28fXqtd$;_D?ph*u3@yFKAEtVpG6=Jw5b)7truI0 ziOpDJarUHYaA&u?Ab}}m;6f2&UuTcM)&&s?2CIXt45YuBkOmbhKrO2)k-^d;nW^n1 znv5GNlH{p3>cJ@Kw33cOsp&)wk60GWTWi{OizS(H_{CVv+0}Z0-bHpa*(oz3aVf6< zU9+oq?Fi8N#f{o`q12bC(0tFdg(9Kp3CL7oU`U z+jgI*Uw5bb)#k|OiEBZw5t<}Ir81S8;2kgD#(d1#c95?fBh?u<<5VWNk~|j;Mccn@ z;;+~1ltEx$B@gwGu zB0k7&4<(+>XH)s7m6uX)H!NdDdT0z(Nry6fai*iXlqvgOI}KZCW}s#!y|Z2+rN-lc zP~4yPi{@aRyI^86+n63veG}cvIcW>R#N{ZmD&zU2xkAdNUm++)1hon<>}7=365(N4 zjqa$1zuMJdY_4iwWEtXDIeu_QVZrTwp}0hrW)LKsTMr=Pmn1!v(Lu#>;VAA|;J47F z(5H7k6lL!7U7K{&Y7|&nGOp2+Qe#^D(M0efA9%hAgmtdX(ocr9G{Eiiz_jrL$FvDT z!?X!t3vj_~7Jv{efn^s?h1J?c!))$z3BUzwnaCBO7YxhQ1BU|#U<6PIN{4V<#0!QR zU_SNhFm1v;kJ`~+B<}jS`TZdb00o19f=9#|rdkdCTD{OZ^2Z0fK=};&1HmoM9}^=< zOG!byBq}p;Rqk6O!^d!h_Ng;ciF$2YC;@W1y*BDIu8vkEV+r~6|Wp;bMe^`bFvB=Skjye9PN4(!<(+JTIY+Q(T7nlWKJ zH≫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 clza@#Oq8$s0hN48dW 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 Project Structure > Platform Settings > SDKs.', { timeout: 5000 }) -*/ - // TODO: delete errorMessage below, and uncomment the above when releasing CSB - const errorMessage = await page.waitForSelector('text/Sorry, I couldn\'t run the Maven clean install command', { - timeout: 5000 - }) console.log('Error message:', await errorMessage.evaluate(el => el.textContent)) } } finally { @@ -155,10 +150,8 @@ class TransformChatTest { "Choose a module to transform", "Choose the target code version", "Skip tests form appeared: true", - "couldn't run the Maven clean install command" - // TODO: delete line above, and uncomment lines below when releasing CSB - // "I could not find \"dummy-target-jdk-name-here\"", - // "Custom dependency versions file form appeared: true", + "Custom dependency versions file form appeared: true", + "I could not find \"dummy-target-jdk-name-here\"" ) } } From d0c758b35f376dabcc5a8bbeb92b0857e259c58c Mon Sep 17 00:00:00 2001 From: David Hasani Date: Fri, 9 May 2025 10:41:36 -0700 Subject: [PATCH 02/21] remove notify --- .../codemodernizer/model/CodeModernizerSessionContext.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerSessionContext.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerSessionContext.kt index 8acfe8d72b6..398760b467f 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerSessionContext.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerSessionContext.kt @@ -28,7 +28,6 @@ import software.aws.toolkits.jetbrains.services.codemodernizer.toolwindow.CodeMo import software.aws.toolkits.jetbrains.services.codemodernizer.utils.getPathToHilArtifactPomFolder import software.aws.toolkits.jetbrains.services.codemodernizer.utils.getPathToHilDependenciesRootDir import software.aws.toolkits.jetbrains.services.codemodernizer.utils.getPathToHilUploadZip -import software.aws.toolkits.jetbrains.utils.notifyStickyInfo import software.aws.toolkits.resources.message import java.io.File import java.io.IOException @@ -304,7 +303,6 @@ data class CodeModernizerSessionContext( LOG.info { "Source code files size = ${files?.sumOf { it.length.toInt() }}" } }.toFile() - notifyStickyInfo("created ZIP at", outputFile.path) // depDirectory should never be null if (depDirectory != null) ZipCreationResult.Succeeded(outputFile) else ZipCreationResult.Missing1P(outputFile) } catch (e: NoSuchFileException) { From dd8bc0d8996b674035f9df5150fcc1d72d668ccc Mon Sep 17 00:00:00 2001 From: David Hasani Date: Fri, 9 May 2025 10:42:32 -0700 Subject: [PATCH 03/21] remove other notify --- .../services/codemodernizer/ideMaven/MavenRunnerUtils.kt | 3 --- 1 file changed, 3 deletions(-) diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/ideMaven/MavenRunnerUtils.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/ideMaven/MavenRunnerUtils.kt index a1358cc19c5..1aaafa1512c 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/ideMaven/MavenRunnerUtils.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/ideMaven/MavenRunnerUtils.kt @@ -25,7 +25,6 @@ import software.aws.toolkits.jetbrains.services.codemodernizer.model.CodeModerni import software.aws.toolkits.jetbrains.services.codemodernizer.model.MAVEN_BUILD_RUN_UNIT_TESTS import software.aws.toolkits.jetbrains.services.codemodernizer.model.MavenCopyCommandsResult import software.aws.toolkits.jetbrains.services.codemodernizer.model.MavenDependencyReportCommandsResult -import software.aws.toolkits.jetbrains.utils.notifyStickyInfo import software.aws.toolkits.telemetry.CodeTransformBuildCommand import software.aws.toolkits.telemetry.Result import java.io.File @@ -96,8 +95,6 @@ private fun runMavenJar( logBuilder.appendLine("Command Run: IntelliJ IDEA bundled Maven JAR") val jarPath = AwsToolkit.PLUGINS_INFO[AwsPlugin.Q]?.path?.resolve("lib/QCT-Maven.jar") - notifyStickyInfo("found jarPath", "jarPath = $jarPath") - val commandList = listOf( "-Dmaven.ext.class.path=${jarPath}", "-Dcom.amazon.aws.developer.transform.jobDirectory=$destinationDir", From 0f741221fa23bdf645356d1342e63dc9c6291930 Mon Sep 17 00:00:00 2001 From: David Hasani Date: Fri, 9 May 2025 11:43:26 -0700 Subject: [PATCH 04/21] fix detekt and test --- .../controller/CodeTransformChatController.kt | 8 ++++---- .../services/codemodernizer/ideMaven/MavenRunnerUtils.kt | 2 +- .../CodeWhispererCodeModernizerSessionTest.kt | 8 +------- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt index ead5d6be49d..52238bd4f1a 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt @@ -4,17 +4,21 @@ package software.aws.toolkits.jetbrains.services.codemodernizer.controller import com.intellij.ide.BrowserUtil +import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.application.runInEdt import com.intellij.openapi.fileChooser.FileChooser import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory +import com.intellij.openapi.fileEditor.FileEditorManager import com.intellij.openapi.module.ModuleUtil import com.intellij.openapi.projectRoots.JavaSdkVersion import com.intellij.openapi.projectRoots.ProjectJdkTable import com.intellij.openapi.util.io.FileUtil.createTempDirectory import com.intellij.openapi.vfs.VirtualFile +import com.intellij.testFramework.LightVirtualFile import kotlinx.coroutines.delay import kotlinx.coroutines.runBlocking import kotlinx.coroutines.withContext +import org.jetbrains.yaml.YAMLFileType import software.amazon.awssdk.services.codewhispererstreaming.model.TransformationDownloadArtifactType import software.aws.toolkits.core.utils.debug import software.aws.toolkits.core.utils.error @@ -122,10 +126,6 @@ import software.aws.toolkits.jetbrains.services.codemodernizer.utils.validateSct import software.aws.toolkits.jetbrains.services.cwc.messages.ChatMessageType import software.aws.toolkits.resources.message import software.aws.toolkits.telemetry.CodeTransformPreValidationError -import com.intellij.openapi.application.ApplicationManager -import com.intellij.openapi.fileEditor.FileEditorManager -import com.intellij.testFramework.LightVirtualFile -import org.jetbrains.yaml.YAMLFileType class CodeTransformChatController( private val context: AmazonQAppInitContext, diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/ideMaven/MavenRunnerUtils.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/ideMaven/MavenRunnerUtils.kt index 1aaafa1512c..f99e7546d4c 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/ideMaven/MavenRunnerUtils.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/ideMaven/MavenRunnerUtils.kt @@ -96,7 +96,7 @@ private fun runMavenJar( val jarPath = AwsToolkit.PLUGINS_INFO[AwsPlugin.Q]?.path?.resolve("lib/QCT-Maven.jar") val commandList = listOf( - "-Dmaven.ext.class.path=${jarPath}", + "-Dmaven.ext.class.path=$jarPath", "-Dcom.amazon.aws.developer.transform.jobDirectory=$destinationDir", "clean", "test-compile" diff --git a/plugins/amazonq/codetransform/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codemodernizer/CodeWhispererCodeModernizerSessionTest.kt b/plugins/amazonq/codetransform/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codemodernizer/CodeWhispererCodeModernizerSessionTest.kt index ab7242be2ea..7b35e4448c0 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codemodernizer/CodeWhispererCodeModernizerSessionTest.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codemodernizer/CodeWhispererCodeModernizerSessionTest.kt @@ -168,12 +168,11 @@ class CodeWhispererCodeModernizerSessionTest : CodeWhispererCodeModernizerTestBa assertThat(fileContent).contains("\"noInteractiveMode\":true") } Path("sources/src/tmp.txt") -> assertThat(fileContent).isEqualTo(fileText) - Path("build-logs.txt") -> assertThat(fileContent).isNotNull() else -> fail("Unexpected entry in zip file: $entry") } } zipFile.close() - assert(numEntries == 3) + assert(numEntries == 2) } } @@ -207,7 +206,6 @@ class CodeWhispererCodeModernizerSessionTest : CodeWhispererCodeModernizerTestBa Path("manifest.json") -> assertThat(fileContent).isNotNull() Path("sources/src/tmp.java") -> assertThat(fileContent).isEqualTo(fileText) Path("sources/pom.xml") -> assertThat(fileContent).isEqualTo(fileText) - Path("build-logs.txt") -> assertThat(fileContent).isNotNull() else -> fail("Unexpected entry in zip file: $entry") } } @@ -244,7 +242,6 @@ class CodeWhispererCodeModernizerSessionTest : CodeWhispererCodeModernizerTestBa Path("manifest.json") -> assertThat(fileContent).isNotNull() Path("sources/src/tmp.java") -> assertThat(fileContent).isEqualTo(fileText) Path("sources/pom.xml") -> assertThat(fileContent).isEqualTo(fileText) - Path("build-logs.txt") -> assertThat(fileContent).isNotNull() else -> fail("Unexpected entry in zip file: $entry") } } @@ -284,7 +281,6 @@ class CodeWhispererCodeModernizerSessionTest : CodeWhispererCodeModernizerTestBa Path("sources/pom.xml") -> assertThat(fileContent).isEqualTo("pom.xml") Path("sources/someModule/src/helloworld.java") -> assertThat(fileContent).isEqualTo("someModule/src/helloworld.java") Path("sources/someModule/pom.xml") -> assertThat(fileContent).isEqualTo("someModule/pom.xml") - Path("build-logs.txt") -> assertThat(fileContent).isNotNull() else -> fail("Unexpected entry in zip file: $entry") } } @@ -324,7 +320,6 @@ class CodeWhispererCodeModernizerSessionTest : CodeWhispererCodeModernizerTestBa Path("sources/pom.xml") -> assertThat(fileContent).isEqualTo("pom.xml") Path("sources/someModule/src/helloworld.java") -> assertThat(fileContent).isEqualTo("someModule\\src\\helloworld.java") Path("sources/someModule/pom.xml") -> assertThat(fileContent).isEqualTo("someModule\\pom.xml") - Path("build-logs.txt") -> assertThat(fileContent).isNotNull() else -> fail("Unexpected entry in zip file: $entry") } } @@ -362,7 +357,6 @@ class CodeWhispererCodeModernizerSessionTest : CodeWhispererCodeModernizerTestBa Path("sources/pom.xml") -> assertThat(fileContent).isEqualTo("pom.xml") Path("sources/src/tmp.java") -> assertThat(fileContent).isEqualTo("src/tmp.java") Path("sources/someModule/pom.xml") -> assertThat(fileContent).isEqualTo("someModule/pom.xml") - Path("build-logs.txt") -> assertThat(fileContent).isNotNull() else -> throw AssertionError("Unexpected entry in zip file: $entry") } } From fa7e08e4107f2ca64c59f0410bf52bfe6ef7d4cf Mon Sep 17 00:00:00 2001 From: David Hasani Date: Tue, 20 May 2025 15:28:23 -0700 Subject: [PATCH 05/21] resolve conflicts --- .../codemodernizer/controller/CodeTransformChatController.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt index 52238bd4f1a..df062219092 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt @@ -422,7 +422,6 @@ class CodeTransformChatController( val transformCapabilities = listOf(EXPLAINABILITY_V1, CLIENT_SIDE_BUILD, SELECTIVE_TRANSFORMATION_V2) codeModernizerManager.codeTransformationSession?.let { it.sessionContext.transformCapabilities = transformCapabilities - codeModernizerManager.runLocalMavenBuild(context.project, it) } promptForCustomYamlFile() } From f59049bb1464969e489943ef00ecc1ea0434a6bc Mon Sep 17 00:00:00 2001 From: David Hasani Date: Thu, 5 Jun 2025 14:54:51 -0700 Subject: [PATCH 06/21] add check for empty diff --- .../codemodernizer/constants/CodeTransformChatItems.kt | 8 ++++---- .../controller/CodeTransformChatController.kt | 4 ++-- .../codemodernizer/model/CodeModernizerSessionContext.kt | 1 + .../services/codemodernizer/model/ZipManifest.kt | 8 ++++---- .../codemodernizer/utils/CodeTransformApiUtils.kt | 8 ++++++-- .../codemodernizer/utils/CodeTransformFileUtils.kt | 3 ++- .../aws/toolkits/resources/MessagesBundle.properties | 4 ++++ 7 files changed, 23 insertions(+), 13 deletions(-) diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/constants/CodeTransformChatItems.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/constants/CodeTransformChatItems.kt index 9baf422c500..314427f96f0 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/constants/CodeTransformChatItems.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/constants/CodeTransformChatItems.kt @@ -348,7 +348,7 @@ fun buildUserInputSQLConversionMetadataChatContent() = CodeTransformChatMessageC ) fun buildUserInputCustomDependencyVersionsChatContent() = CodeTransformChatMessageContent( - message = "Optionally, provide a .YAML file which specifies custom dependency versions you want Q to upgrade to.", + message = message("codemodernizer.chat.message.custom_dependency_upgrades_prompt"), buttons = listOf( confirmCustomDependencyVersionsButton, continueTransformationButton, @@ -368,7 +368,7 @@ fun buildInvalidTargetJdkNameChatContent(jdkName: String) = CodeTransformChatMes ) fun buildCustomDependencyVersionsFileValidChatContent() = CodeTransformChatMessageContent( - message = "I received your .yaml file and will upload it to Q.", + message = message("codemodernizer.chat.message.custom_dependency_upgrades_valid"), type = CodeTransformChatMessageType.FinalizedAnswer, ) @@ -415,7 +415,7 @@ fun buildSQLMetadataValidationErrorChatContent(errorReason: String) = CodeTransf fun buildCustomDependencyVersionsFileInvalidChatContent() = CodeTransformChatMessageContent( type = CodeTransformChatMessageType.FinalizedAnswer, - message = "The file you uploaded does not follow the format of the sample YAML file provided.", + message = message("codemodernizer.chat.message.custom_dependency_upgrades_invalid"), ) fun buildUserCancelledChatContent() = CodeTransformChatMessageContent( @@ -455,7 +455,7 @@ fun buildUserLanguageUpgradeSelectionSummaryChatContent(moduleName: String, targ fun buildContinueTransformationChatContent() = CodeTransformChatMessageContent( type = CodeTransformChatMessageType.FinalizedAnswer, - message = "Ok, I will continue without this information.", + message = message("codemodernizer.chat.message.custom_dependency_upgrades_continue"), ) fun buildCompileLocalInProgressChatContent() = CodeTransformChatMessageContent( diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt index df062219092..00eff7b1d58 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt @@ -475,7 +475,7 @@ dependencyManagement: - identifier: "com.example:library1" targetVersion: "2.1.0" versionProperty: "library1.version" # Optional - originType: "FIRST_PARTY" # or "THIRD_PARTY" # Optional + originType: "FIRST_PARTY" # or "THIRD_PARTY" - identifier: "com.example:library2" targetVersion: "3.0.0" originType: "THIRD_PARTY" @@ -485,7 +485,7 @@ dependencyManagement: versionProperty: "plugin.version" # Optional """.trimIndent() - val virtualFile = LightVirtualFile("sample-dependency-upgrade.yaml", YAMLFileType.YML, sampleYAML) + val virtualFile = LightVirtualFile("dependency_upgrade.yml", YAMLFileType.YML, sampleYAML) virtualFile.isWritable = true ApplicationManager.getApplication().invokeLater { FileEditorManager.getInstance(context.project).openFile(virtualFile, true) diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerSessionContext.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerSessionContext.kt index 398760b467f..4b732809e02 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerSessionContext.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerSessionContext.kt @@ -44,6 +44,7 @@ import kotlin.io.path.pathString const val MANIFEST_PATH = "manifest.json" const val ZIP_SOURCES_PATH = "sources" const val ZIP_DEPENDENCIES_PATH = "dependencies" +const val COMPILATIONS_JSON_FILE = "compilations.json" const val CUSTOM_DEPENDENCY_VERSIONS_FILE_PATH = "dependency_upgrade.yml" const val UPLOAD_ZIP_MANIFEST_VERSION = "1.0" const val HIL_1P_UPGRADE_CAPABILITY = "HIL_1pDependency_VersionUpgrade" diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/ZipManifest.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/ZipManifest.kt index 2d3a4633c6a..46d762d3631 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/ZipManifest.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/ZipManifest.kt @@ -3,18 +3,18 @@ package software.aws.toolkits.jetbrains.services.codemodernizer.model -// TODO: include custom yaml file path in manifest.json? data class ZipManifest( val sourcesRoot: String = ZIP_SOURCES_PATH, val dependenciesRoot: String = ZIP_DEPENDENCIES_PATH, val version: String = UPLOAD_ZIP_MANIFEST_VERSION, val hilCapabilities: List = listOf(HIL_1P_UPGRADE_CAPABILITY), - // TODO: add CLIENT_SIDE_BUILD to transformCapabilities when releasing CSB - val transformCapabilities: List = listOf(EXPLAINABILITY_V1, SELECTIVE_TRANSFORMATION_V2), - val noInteractiveMode: Boolean = true, + val transformCapabilities: List = listOf(EXPLAINABILITY_V1, CLIENT_SIDE_BUILD, SELECTIVE_TRANSFORMATION_V2), val customBuildCommand: String = MAVEN_BUILD_RUN_UNIT_TESTS, val requestedConversions: RequestedConversions? = null, // only used for SQL conversions for now var dependencyUpgradeConfigFile: String? = null, + // TODO: make sure the below 2 keys don't mess up SQL conversions when present + val noInteractiveMode: Boolean = true, + val compilationsJsonFile: String = COMPILATIONS_JSON_FILE ) data class RequestedConversions( diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/utils/CodeTransformApiUtils.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/utils/CodeTransformApiUtils.kt index 94e57287ba9..2d4bceba5dd 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/utils/CodeTransformApiUtils.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/utils/CodeTransformApiUtils.kt @@ -170,8 +170,12 @@ suspend fun attemptLocalBuild(plan: TransformationPlan, jobId: JobId, project: P if (artifactId != null) { val clientInstructionsPath = downloadClientInstructions(jobId, artifactId, project) getLogger().info { "Downloaded client instructions for job ${jobId.id} and artifact $artifactId at: $clientInstructionsPath" } - processClientInstructions(clientInstructionsPath, jobId, artifactId, project) - getLogger().info { "Finished processing client instructions for job ${jobId.id} and artifact $artifactId" } + if (clientInstructionsPath.toFile().readText().trim().isNotEmpty()) { + processClientInstructions(clientInstructionsPath, jobId, artifactId, project) + getLogger().info { "Finished processing client instructions for job ${jobId.id} and artifact $artifactId" } + } else { + getLogger().info { "Client instructions for job ${jobId.id} and artifact $artifactId is empty; skipping client-side build" } + } } } diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/utils/CodeTransformFileUtils.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/utils/CodeTransformFileUtils.kt index ea19a954342..f5b97786c30 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/utils/CodeTransformFileUtils.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/utils/CodeTransformFileUtils.kt @@ -197,7 +197,8 @@ fun parseXmlDependenciesReport(pathToXmlDependency: Path): DependencyUpdatesRepo } fun validateCustomVersionsFile(file: VirtualFile): Boolean { - if (!file.name.lowercase().endsWith(".yaml")) { + val validFileEndings = listOf("yaml", "yml") + if (!validFileEndings.any { file.name.lowercase().endsWith(it) }) { getLogger().error { "Custom versions file is not a YAML file: ${file.name}" } return false } diff --git a/plugins/core/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties b/plugins/core/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties index 1a4cd4d1b1a..ce55254d2a4 100644 --- a/plugins/core/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties +++ b/plugins/core/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties @@ -646,6 +646,10 @@ codemodernizer.chat.message.button.view_summary=View summary codemodernizer.chat.message.changes_applied=I applied the changes to your project. codemodernizer.chat.message.choose_objective=I can help you with the following tasks:\n- Upgrade your Java 8, Java 11, and Java 17 codebases to Java 17 or Java 21.\n- Upgrade Java 17 or Java 21 code with up-to-date libraries and other dependencies.\n- Convert embedded SQL code for Oracle to PostgreSQL database migrations in AWS DMS.\n\nWhat would you like to do? You can enter "language upgrade" or "sql conversion". codemodernizer.chat.message.choose_objective_placeholder=Enter "language upgrade" or "sql conversion" +codemodernizer.chat.message.custom_dependency_upgrades_continue=Ok, I will continue the transformation without additional dependency upgrade information. +codemodernizer.chat.message.custom_dependency_upgrades_prompt=Would you like to provide a dependency upgrade file? You can specify first and third party dependencies and their versions in a YAML file, and I will upgrade them during the transformation. For an example dependency upgrade file, see the [documentation](https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/code-transformation.html#dependency-upgrade-file). +codemodernizer.chat.message.custom_dependency_upgrades_invalid=I wasn't able to parse the dependency upgrade file. Check that it's configured properly and try again. For an example of the required dependency upgrade file format, see the [documentation](https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/code-transformation.html#dependency-upgrade-file). +codemodernizer.chat.message.custom_dependency_upgrades_valid=The dependency upgrade file looks good. I will use this information to upgrade the dependencies you specified. codemodernizer.chat.message.download_failed_client_instructions_expired=Your transformation is not available anymore. Your code and transformation summary are deleted 24 hours after the transformation completes. Please try starting the transformation again. codemodernizer.chat.message.download_failed_invalid_artifact=Sorry, I was unable to find your {0}. Artifacts are deleted after 24 hours. Please try starting the transformation again. codemodernizer.chat.message.download_failed_other=Sorry, I ran into an issue while trying to download your {0}. Please try again. {1} From 6f7c365d97357d0a2ceae021a9fc6c297a71eb38 Mon Sep 17 00:00:00 2001 From: David Hasani Date: Fri, 13 Jun 2025 13:14:31 -0700 Subject: [PATCH 07/21] rebase --- .../codemodernizer/controller/CodeTransformChatController.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt index 00eff7b1d58..f033d140bb9 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt @@ -156,7 +156,6 @@ class CodeTransformChatController( if (objective == "language upgrade" || objective == "sql conversion") { telemetry.submitSelection(objective) } - broadcastQEvent(QFeatureEvent.INVOCATION) when (objective) { "language upgrade" -> this.handleLanguageUpgrade() "sql conversion" -> this.handleSQLConversion() From 1ea253c53eacd1ddfff834c5f63988ce154da5a0 Mon Sep 17 00:00:00 2001 From: David Hasani Date: Mon, 16 Jun 2025 19:08:57 -0700 Subject: [PATCH 08/21] update JAR --- plugins/amazonq/build.gradle.kts | 2 +- .../ideMaven/MavenRunnerUtils.kt | 2 +- .../{QCT-Maven.jar => QCT-Maven-6-16.jar} | Bin 148642 -> 150250 bytes 3 files changed, 2 insertions(+), 2 deletions(-) rename plugins/amazonq/contrib/{QCT-Maven.jar => QCT-Maven-6-16.jar} (86%) diff --git a/plugins/amazonq/build.gradle.kts b/plugins/amazonq/build.gradle.kts index 8ea3fccdaec..83b0e5ffdfd 100644 --- a/plugins/amazonq/build.gradle.kts +++ b/plugins/amazonq/build.gradle.kts @@ -27,7 +27,7 @@ val changelog = tasks.register("pluginChangeLog") { } tasks.prepareSandbox { - from("contrib/QCT-Maven.jar") { + from("contrib/QCT-Maven-6-16.jar") { into("/plugin-amazonq/lib") } } diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/ideMaven/MavenRunnerUtils.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/ideMaven/MavenRunnerUtils.kt index f99e7546d4c..5f24806cc16 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/ideMaven/MavenRunnerUtils.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/ideMaven/MavenRunnerUtils.kt @@ -93,7 +93,7 @@ private fun runMavenJar( logger: Logger, ): TransformRunnable { logBuilder.appendLine("Command Run: IntelliJ IDEA bundled Maven JAR") - val jarPath = AwsToolkit.PLUGINS_INFO[AwsPlugin.Q]?.path?.resolve("lib/QCT-Maven.jar") + val jarPath = AwsToolkit.PLUGINS_INFO[AwsPlugin.Q]?.path?.resolve("lib/QCT-Maven-6-16.jar") val commandList = listOf( "-Dmaven.ext.class.path=$jarPath", diff --git a/plugins/amazonq/contrib/QCT-Maven.jar b/plugins/amazonq/contrib/QCT-Maven-6-16.jar similarity index 86% rename from plugins/amazonq/contrib/QCT-Maven.jar rename to plugins/amazonq/contrib/QCT-Maven-6-16.jar index 1d134b2918651cdca6b67e40fde2abdfa0f88441..bdc734b4d7b60a2436ea58f275e81c284ad1bcad 100644 GIT binary patch delta 12693 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 delta 11012 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 u0097> Date: Tue, 17 Jun 2025 12:28:06 -0700 Subject: [PATCH 09/21] always resume even on empty diff --- .../model/CodeModernizerSessionContext.kt | 1 - .../utils/CodeTransformApiUtils.kt | 82 +++++++++---------- 2 files changed, 40 insertions(+), 43 deletions(-) diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerSessionContext.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerSessionContext.kt index 4b732809e02..4465e3d763e 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerSessionContext.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerSessionContext.kt @@ -234,7 +234,6 @@ data class CodeModernizerSessionContext( } val zipSources = File(ZIP_SOURCES_PATH) - val depSources = File(ZIP_DEPENDENCIES_PATH) val outputFile = createTemporaryZipFile { zip -> // 1) Manifest file var manifest = ZipManifest(transformCapabilities = transformCapabilities, customBuildCommand = customBuildCommand) diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/utils/CodeTransformApiUtils.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/utils/CodeTransformApiUtils.kt index 2d4bceba5dd..c9ded4c3aad 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/utils/CodeTransformApiUtils.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/utils/CodeTransformApiUtils.kt @@ -170,12 +170,8 @@ suspend fun attemptLocalBuild(plan: TransformationPlan, jobId: JobId, project: P if (artifactId != null) { val clientInstructionsPath = downloadClientInstructions(jobId, artifactId, project) getLogger().info { "Downloaded client instructions for job ${jobId.id} and artifact $artifactId at: $clientInstructionsPath" } - if (clientInstructionsPath.toFile().readText().trim().isNotEmpty()) { - processClientInstructions(clientInstructionsPath, jobId, artifactId, project) - getLogger().info { "Finished processing client instructions for job ${jobId.id} and artifact $artifactId" } - } else { - getLogger().info { "Client instructions for job ${jobId.id} and artifact $artifactId is empty; skipping client-side build" } - } + processClientInstructions(clientInstructionsPath, jobId, artifactId, project) + getLogger().info { "Finished processing client instructions for job ${jobId.id} and artifact $artifactId" } } } @@ -190,45 +186,47 @@ suspend fun processClientInstructions(clientInstructionsPath: Path, jobId: JobId val targetDir = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(copyOfProjectSources.toFile()) ?: throw RuntimeException("Cannot find copy of project sources directory") - withContext(EDT) { - runWriteAction { - // create temp module with project copy so that we can apply diff.patch - val modifiableModel = ModuleManager.getInstance(project).getModifiableModel() - val tempModule = modifiableModel.newModule( - Paths.get(targetDir.path).resolve("temp.iml").toString(), - JavaModuleType.getModuleType().id - ) + if (clientInstructionsPath.toFile().readText().trim().isNotEmpty()) { + withContext(EDT) { + runWriteAction { + // create temp module with project copy so that we can apply diff.patch + val modifiableModel = ModuleManager.getInstance(project).getModifiableModel() + val tempModule = modifiableModel.newModule( + Paths.get(targetDir.path).resolve("temp.iml").toString(), + JavaModuleType.getModuleType().id + ) - try { - val moduleModel = ModuleRootManager.getInstance(tempModule).modifiableModel - moduleModel.addContentEntry(targetDir.url) - moduleModel.commit() - modifiableModel.commit() + try { + val moduleModel = ModuleRootManager.getInstance(tempModule).modifiableModel + moduleModel.addContentEntry(targetDir.url) + moduleModel.commit() + modifiableModel.commit() - // apply diff.patch - val patchReader = PatchReader(clientInstructionsPath) - patchReader.parseAllPatches() - PatchApplier( - project, - targetDir, - patchReader.allPatches, - null, - null - ).execute() - getLogger().info { "Successfully applied patch file at $clientInstructionsPath" } + // apply diff.patch + val patchReader = PatchReader(clientInstructionsPath) + patchReader.parseAllPatches() + PatchApplier( + project, + targetDir, + patchReader.allPatches, + null, + null + ).execute() + getLogger().info { "Successfully applied patch file at $clientInstructionsPath" } - val virtualFile = LocalFileSystem.getInstance().findFileByIoFile(clientInstructionsPath.toFile()) - ?: throw RuntimeException("Cannot find patch file at $clientInstructionsPath") - FileEditorManager.getInstance(project).openFile(virtualFile, true) - } catch (e: Exception) { - getLogger().error { - "Error applying intermediate diff.patch for job ${jobId.id} and artifact $artifactId located at " + - "$clientInstructionsPath: $e" - } - throw e - } finally { - runWriteAction { - ModuleManager.getInstance(project).disposeModule(tempModule) + val virtualFile = LocalFileSystem.getInstance().findFileByIoFile(clientInstructionsPath.toFile()) + ?: throw RuntimeException("Cannot find patch file at $clientInstructionsPath") + FileEditorManager.getInstance(project).openFile(virtualFile, true) + } catch (e: Exception) { + getLogger().error { + "Error applying intermediate diff.patch for job ${jobId.id} and artifact $artifactId located at " + + "$clientInstructionsPath: $e" + } + throw e + } finally { + runWriteAction { + ModuleManager.getInstance(project).disposeModule(tempModule) + } } } } From cbd8ad64e8a1be5c3624f913407db77d02834b49 Mon Sep 17 00:00:00 2001 From: David Hasani Date: Thu, 19 Jun 2025 16:20:13 -0700 Subject: [PATCH 10/21] poll correctly --- .../services/codemodernizer/CodeModernizerSession.kt | 4 ++-- .../controller/CodeTransformChatController.kt | 7 ++++--- .../codemodernizer/model/CodeModernizerSessionContext.kt | 1 + .../services/codemodernizer/model/ZipManifest.kt | 2 +- .../services/codemodernizer/state/CodeModernizerState.kt | 7 +++++-- .../codemodernizer/utils/CodeTransformApiUtils.kt | 6 +++++- .../CodeWhispererCodeModernizerSessionTest.kt | 9 ++++++++- .../aws/toolkits/resources/MessagesBundle.properties | 8 ++++---- 8 files changed, 30 insertions(+), 14 deletions(-) diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/CodeModernizerSession.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/CodeModernizerSession.kt index cab313282b7..7533259fd6d 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/CodeModernizerSession.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/CodeModernizerSession.kt @@ -72,8 +72,6 @@ import java.util.concurrent.atomic.AtomicBoolean import javax.net.ssl.SSLHandshakeException const val MAX_ZIP_SIZE = 2000000000 // 2GB -const val EXPLAINABILITY_V1 = "EXPLAINABILITY_V1" -const val SELECTIVE_TRANSFORMATION_V2 = "SELECTIVE_TRANSFORMATION_V2" // constants for handling SDKClientException const val CONNECTION_REFUSED_ERROR: String = "Connection refused" @@ -554,6 +552,8 @@ class CodeModernizerSession( else -> { LOG.error(e) { e.message.toString() } + LOG.info { "Stopping transformation job [$jobId] due to unexpected error." } + stopTransformation(jobId.id) CodeModernizerJobCompletedResult.RetryableFailure( jobId, message("codemodernizer.notification.info.modernize_failed.connection_failed", e.message.orEmpty()), diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt index f033d140bb9..07493468bd1 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt @@ -32,10 +32,8 @@ import software.aws.toolkits.jetbrains.services.codemodernizer.ArtifactHandler import software.aws.toolkits.jetbrains.services.codemodernizer.CodeModernizerManager import software.aws.toolkits.jetbrains.services.codemodernizer.CodeModernizerManager.Companion.LOG import software.aws.toolkits.jetbrains.services.codemodernizer.CodeTransformTelemetryManager -import software.aws.toolkits.jetbrains.services.codemodernizer.EXPLAINABILITY_V1 import software.aws.toolkits.jetbrains.services.codemodernizer.HilTelemetryMetaData import software.aws.toolkits.jetbrains.services.codemodernizer.InboundAppMessagesHandler -import software.aws.toolkits.jetbrains.services.codemodernizer.SELECTIVE_TRANSFORMATION_V2 import software.aws.toolkits.jetbrains.services.codemodernizer.client.GumbyClient import software.aws.toolkits.jetbrains.services.codemodernizer.commands.CodeTransformActionMessage import software.aws.toolkits.jetbrains.services.codemodernizer.commands.CodeTransformCommand @@ -103,6 +101,9 @@ import software.aws.toolkits.jetbrains.services.codemodernizer.model.CodeTransfo import software.aws.toolkits.jetbrains.services.codemodernizer.model.CustomerSelection import software.aws.toolkits.jetbrains.services.codemodernizer.model.DownloadArtifactResult import software.aws.toolkits.jetbrains.services.codemodernizer.model.DownloadFailureReason +import software.aws.toolkits.jetbrains.services.codemodernizer.model.EXPLAINABILITY_V1 +import software.aws.toolkits.jetbrains.services.codemodernizer.model.IDE +import software.aws.toolkits.jetbrains.services.codemodernizer.model.SELECTIVE_TRANSFORMATION_V2 import software.aws.toolkits.jetbrains.services.codemodernizer.model.InvalidTelemetryReason import software.aws.toolkits.jetbrains.services.codemodernizer.model.JobId import software.aws.toolkits.jetbrains.services.codemodernizer.model.MAVEN_BUILD_RUN_UNIT_TESTS @@ -418,7 +419,7 @@ class CodeTransformChatController( codeModernizerManager.codeTransformationSession?.let { it.sessionContext.customBuildCommand = customBuildCommand } - val transformCapabilities = listOf(EXPLAINABILITY_V1, CLIENT_SIDE_BUILD, SELECTIVE_TRANSFORMATION_V2) + val transformCapabilities = listOf(EXPLAINABILITY_V1, CLIENT_SIDE_BUILD, SELECTIVE_TRANSFORMATION_V2, IDE) codeModernizerManager.codeTransformationSession?.let { it.sessionContext.transformCapabilities = transformCapabilities } diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerSessionContext.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerSessionContext.kt index 4465e3d763e..a4665de5d67 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerSessionContext.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerSessionContext.kt @@ -50,6 +50,7 @@ const val UPLOAD_ZIP_MANIFEST_VERSION = "1.0" const val HIL_1P_UPGRADE_CAPABILITY = "HIL_1pDependency_VersionUpgrade" const val EXPLAINABILITY_V1 = "EXPLAINABILITY_V1" const val SELECTIVE_TRANSFORMATION_V2 = "SELECTIVE_TRANSFORMATION_V2" +const val IDE = "IDE" const val CLIENT_SIDE_BUILD = "CLIENT_SIDE_BUILD" const val MAVEN_CONFIGURATION_FILE_NAME = "pom.xml" const val MAVEN_BUILD_RUN_UNIT_TESTS = "clean test" diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/ZipManifest.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/ZipManifest.kt index 46d762d3631..089477b766b 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/ZipManifest.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/ZipManifest.kt @@ -8,7 +8,7 @@ data class ZipManifest( val dependenciesRoot: String = ZIP_DEPENDENCIES_PATH, val version: String = UPLOAD_ZIP_MANIFEST_VERSION, val hilCapabilities: List = listOf(HIL_1P_UPGRADE_CAPABILITY), - val transformCapabilities: List = listOf(EXPLAINABILITY_V1, CLIENT_SIDE_BUILD, SELECTIVE_TRANSFORMATION_V2), + val transformCapabilities: List = listOf(EXPLAINABILITY_V1, CLIENT_SIDE_BUILD, SELECTIVE_TRANSFORMATION_V2, IDE), val customBuildCommand: String = MAVEN_BUILD_RUN_UNIT_TESTS, val requestedConversions: RequestedConversions? = null, // only used for SQL conversions for now var dependencyUpgradeConfigFile: String? = null, diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/state/CodeModernizerState.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/state/CodeModernizerState.kt index 9c4f4727962..d509d944aeb 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/state/CodeModernizerState.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/state/CodeModernizerState.kt @@ -7,10 +7,13 @@ import com.intellij.openapi.components.BaseState import com.intellij.openapi.project.Project import com.intellij.openapi.projectRoots.JavaSdkVersion import com.intellij.util.xmlb.annotations.Property -import software.aws.toolkits.jetbrains.services.codemodernizer.EXPLAINABILITY_V1 +import software.aws.toolkits.jetbrains.services.codemodernizer.model.CLIENT_SIDE_BUILD import software.aws.toolkits.jetbrains.services.codemodernizer.model.CodeModernizerSessionContext +import software.aws.toolkits.jetbrains.services.codemodernizer.model.EXPLAINABILITY_V1 +import software.aws.toolkits.jetbrains.services.codemodernizer.model.IDE import software.aws.toolkits.jetbrains.services.codemodernizer.model.JobId import software.aws.toolkits.jetbrains.services.codemodernizer.model.MAVEN_BUILD_RUN_UNIT_TESTS +import software.aws.toolkits.jetbrains.services.codemodernizer.model.SELECTIVE_TRANSFORMATION_V2 import software.aws.toolkits.jetbrains.services.codemodernizer.utils.toVirtualFile enum class JobDetails { @@ -67,7 +70,7 @@ class CodeModernizerState : BaseState() { configurationFile, sourceJavaSdkVersion, targetJavaSdkVersion, - listOf(EXPLAINABILITY_V1), // default to one diff + listOf(EXPLAINABILITY_V1, SELECTIVE_TRANSFORMATION_V2, CLIENT_SIDE_BUILD, IDE), lastJobContext[JobDetails.CUSTOM_BUILD_COMMAND] ?: MAVEN_BUILD_RUN_UNIT_TESTS // default to running unit tests ) } diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/utils/CodeTransformApiUtils.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/utils/CodeTransformApiUtils.kt index c9ded4c3aad..d1057d7b86f 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/utils/CodeTransformApiUtils.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/utils/CodeTransformApiUtils.kt @@ -86,6 +86,7 @@ suspend fun JobId.pollTransformationStatusAndPlan( var transformationResponse: GetTransformationResponse? = null var transformationPlan: TransformationPlan? = null var didSleepOnce = false + var hasSeenTransforming = false val maxRefreshes = 10 var numRefreshes = 0 @@ -114,12 +115,15 @@ suspend fun JobId.pollTransformationStatusAndPlan( if (isDisposed.get()) throw AlreadyDisposedException("The invoker is disposed.") transformationResponse = clientAdaptor.getCodeModernizationJob(this.id) val newStatus = transformationResponse?.transformationJob()?.status() ?: throw RuntimeException("Unable to get job status") + if (newStatus == TransformationStatus.TRANSFORMING) { + hasSeenTransforming = true + } var newPlan: TransformationPlan? = null if (newStatus in STATES_WHERE_PLAN_EXIST && transformType != CodeTransformType.SQL_CONVERSION) { // no plan for SQL conversions delay(sleepDurationMillis) newPlan = clientAdaptor.getCodeModernizationPlan(this).transformationPlan() } - if (newStatus == TransformationStatus.TRANSFORMING && newPlan != null) { + if (hasSeenTransforming && newPlan != null) { attemptLocalBuild(newPlan, this, project) } if (newStatus != state) { diff --git a/plugins/amazonq/codetransform/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codemodernizer/CodeWhispererCodeModernizerSessionTest.kt b/plugins/amazonq/codetransform/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codemodernizer/CodeWhispererCodeModernizerSessionTest.kt index 7b35e4448c0..cca45b5d79f 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codemodernizer/CodeWhispererCodeModernizerSessionTest.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/tst/software/aws/toolkits/jetbrains/services/codemodernizer/CodeWhispererCodeModernizerSessionTest.kt @@ -49,13 +49,17 @@ import software.amazon.awssdk.services.codewhispererruntime.model.Transformation import software.amazon.awssdk.services.codewhispererruntime.model.UploadContext import software.amazon.awssdk.services.ssooidc.model.SsoOidcException import software.aws.toolkits.jetbrains.core.credentials.sso.bearer.BearerTokenAuthState +import software.aws.toolkits.jetbrains.services.codemodernizer.model.CLIENT_SIDE_BUILD import software.aws.toolkits.jetbrains.services.codemodernizer.model.CodeModernizerJobCompletedResult import software.aws.toolkits.jetbrains.services.codemodernizer.model.CodeModernizerSessionContext import software.aws.toolkits.jetbrains.services.codemodernizer.model.CodeModernizerStartJobResult import software.aws.toolkits.jetbrains.services.codemodernizer.model.CodeTransformHilDownloadArtifact import software.aws.toolkits.jetbrains.services.codemodernizer.model.CodeTransformType +import software.aws.toolkits.jetbrains.services.codemodernizer.model.EXPLAINABILITY_V1 +import software.aws.toolkits.jetbrains.services.codemodernizer.model.IDE import software.aws.toolkits.jetbrains.services.codemodernizer.model.MAVEN_BUILD_SKIP_UNIT_TESTS import software.aws.toolkits.jetbrains.services.codemodernizer.model.MavenCopyCommandsResult +import software.aws.toolkits.jetbrains.services.codemodernizer.model.SELECTIVE_TRANSFORMATION_V2 import software.aws.toolkits.jetbrains.services.codemodernizer.model.UploadFailureReason import software.aws.toolkits.jetbrains.services.codemodernizer.model.ZipCreationResult import software.aws.toolkits.jetbrains.services.codewhisperer.service.CodeWhispererService @@ -146,7 +150,7 @@ class CodeWhispererCodeModernizerSessionTest : CodeWhispererCodeModernizerTestBa root.children[0], JavaSdkVersion.JDK_1_8, JavaSdkVersion.JDK_11, - listOf(EXPLAINABILITY_V1, SELECTIVE_TRANSFORMATION_V2), + listOf(EXPLAINABILITY_V1, SELECTIVE_TRANSFORMATION_V2, CLIENT_SIDE_BUILD, IDE), MAVEN_BUILD_SKIP_UNIT_TESTS ) val mockFile = mock(File::class.java) @@ -164,7 +168,10 @@ class CodeWhispererCodeModernizerSessionTest : CodeWhispererCodeModernizerTestBa Path("manifest.json") -> { assertThat(fileContent).isNotNull() assertThat(fileContent).contains(MAVEN_BUILD_SKIP_UNIT_TESTS) + assertThat(fileContent).contains(EXPLAINABILITY_V1) assertThat(fileContent).contains(SELECTIVE_TRANSFORMATION_V2) + assertThat(fileContent).contains(CLIENT_SIDE_BUILD) + assertThat(fileContent).contains(IDE) assertThat(fileContent).contains("\"noInteractiveMode\":true") } Path("sources/src/tmp.txt") -> assertThat(fileContent).isEqualTo(fileText) diff --git a/plugins/core/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties b/plugins/core/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties index ce55254d2a4..6d93eed39f2 100644 --- a/plugins/core/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties +++ b/plugins/core/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties @@ -647,7 +647,7 @@ codemodernizer.chat.message.changes_applied=I applied the changes to your projec codemodernizer.chat.message.choose_objective=I can help you with the following tasks:\n- Upgrade your Java 8, Java 11, and Java 17 codebases to Java 17 or Java 21.\n- Upgrade Java 17 or Java 21 code with up-to-date libraries and other dependencies.\n- Convert embedded SQL code for Oracle to PostgreSQL database migrations in AWS DMS.\n\nWhat would you like to do? You can enter "language upgrade" or "sql conversion". codemodernizer.chat.message.choose_objective_placeholder=Enter "language upgrade" or "sql conversion" codemodernizer.chat.message.custom_dependency_upgrades_continue=Ok, I will continue the transformation without additional dependency upgrade information. -codemodernizer.chat.message.custom_dependency_upgrades_prompt=Would you like to provide a dependency upgrade file? You can specify first and third party dependencies and their versions in a YAML file, and I will upgrade them during the transformation. For an example dependency upgrade file, see the [documentation](https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/code-transformation.html#dependency-upgrade-file). +codemodernizer.chat.message.custom_dependency_upgrades_prompt=Would you like to provide a dependency upgrade file? You can specify first-party dependencies to upgrade in a YAML file, and I will upgrade them during the JDK upgrade (for example, Java 8 to 17). You can initiate a separate transformation (17 to 17 or 21 to 21) after the initial JDK upgrade to transform third-party dependencies.\n\nWithout a YAML file, I can perform a minimum JDK upgrade, and then you can initiate a separate transformation to upgrade all third-party dependencies as part of a maximum transformation. For an example dependency upgrade file, see the [documentation](https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/code-transformation.html#dependency-upgrade-file). codemodernizer.chat.message.custom_dependency_upgrades_invalid=I wasn't able to parse the dependency upgrade file. Check that it's configured properly and try again. For an example of the required dependency upgrade file format, see the [documentation](https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/code-transformation.html#dependency-upgrade-file). codemodernizer.chat.message.custom_dependency_upgrades_valid=The dependency upgrade file looks good. I will use this information to upgrade the dependencies you specified. codemodernizer.chat.message.download_failed_client_instructions_expired=Your transformation is not available anymore. Your code and transformation summary are deleted 24 hours after the transformation completes. Please try starting the transformation again. @@ -684,8 +684,8 @@ codemodernizer.chat.message.result.fail=Sorry, I ran into an issue during the tr codemodernizer.chat.message.result.fail_initial_build=I am having trouble building your project in the secure build environment and couldn't complete the transformation. codemodernizer.chat.message.result.fail_initial_build_no_build_log=I am having trouble building your project in the secure build environment: {0}. codemodernizer.chat.message.result.fail_with_known_reason=Sorry, I couldn''t complete the transformation. {0} -codemodernizer.chat.message.result.partially_success=I transformed part of your code. You can review the diff to see my proposed changes and accept or reject them. The transformation summary has details about the files I updated and the errors that prevented a complete transformation. After successfully building in Java 17 or 21, an additional transformation is required to upgrade your libraries and dependencies. Choose the same source code version and target code version (for example, 17 to 17) to do this. -codemodernizer.chat.message.result.success=I successfully completed your transformation. You can review the diff to see my proposed changes and accept or reject them. The transformation summary has details about the changes I am proposing. After successfully building in Java 17 or 21, an additional transformation is required to upgrade your libraries and dependencies. Choose the same source code version and target code version (for example, 17 to 17) to do this. +codemodernizer.chat.message.result.partially_success=I transformed part of your code. You can review the diff to see my proposed changes and accept or reject them. The transformation summary has details about the files I updated and the errors that prevented a complete transformation. After successfully transforming to Java 17 or 21, an additional transformation is required to upgrade your libraries and dependencies. Choose the same source code version and target code version (for example, 17 to 17) to do this. +codemodernizer.chat.message.result.success=I successfully completed your transformation. You can review the diff to see my proposed changes and accept or reject them. The transformation summary has details about the changes I am proposing. After successfully transforming to Java 17 or 21, an additional transformation is required to upgrade your libraries and dependencies. Choose the same source code version and target code version (for example, 17 to 17) to do this. codemodernizer.chat.message.result.zip_too_large=Sorry, your project size exceeds the Amazon Q Code Transformation upload limit of 2GB. codemodernizer.chat.message.resume_ongoing=I'm still transforming your code. It can take 10 to 30 minutes to upgrade your code, depending on the size of your module. To monitor progress, go to the Transformation Hub. codemodernizer.chat.message.skip_tests=I will build generated code in your local environment, not on the server side. For information on how I scan code to reduce security risks associated with building the code in your local environment, see the [Amazon Q Developer documentation](https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/code-transformation.html#java-local-builds).\n\nI will build your project using `mvn clean test` by default. If you would like me to build your project without running unit tests, I will use `mvn clean test-compile`. @@ -706,7 +706,7 @@ codemodernizer.chat.message.upload_failed_other=Sorry, I was unable to upload yo codemodernizer.chat.message.upload_failed_ssl_error=Sorry, I was unable to upload your project. This might have been caused by your IDE not trusting the certificate of your HTTP proxy. Ensure all certificates for your proxy client have been configured in your IDE, and then retry transformation. codemodernizer.chat.message.upload_failed_url_expired=Sorry, I couldn't upload your project to begin the transformation. The Amazon S3 pre-signed URL used to upload your code expired after 30 minutes. This might have been caused by delays introduced by intermediate services in your network infrastructure.\n\nCheck your network configuration for services that might be causing delays. If the issue persists, you might need to allow list the following Amazon S3 bucket: 'amazonq-code-transformation-us-east-1-c6160f047e0.s3.amazonaws.com'. codemodernizer.chat.message.validation.check_eligible_modules=Checking for eligible modules... -codemodernizer.chat.message.validation.check_passed=I can upgrade your Java module. To start the transformation, I need some information from you. Choose the module you want to upgrade and the target code version to upgrade to. Then, choose **Confirm**.\n\nIf you do not see the module you want to transform, you might need to configure your project so that I can find it. Go to File and choose Project Structure. In the Projects tab, set the correct project JDK and language level. In the Modules tab, set the correct module JDK and language level.\n\nAfter successfully building in Java 17 or 21, an additional transformation is required to upgrade your libraries and dependencies. Choose the same source code version and target code version (for example, 17 to 17) to do this. +codemodernizer.chat.message.validation.check_passed=I can upgrade your Java module. To start the transformation, I need some information from you. Choose the module you want to upgrade and the target code version to upgrade to. Then, choose **Confirm**.\n\nIf you do not see the module you want to transform, you might need to configure your project so that I can find it. Go to File and choose Project Structure. In the Projects tab, set the correct project JDK and language level. In the Modules tab, set the correct module JDK and language level.\n\nAfter successfully transforming to Java 17 or 21, an additional transformation is required to upgrade your libraries and dependencies. Choose the same source code version and target code version (for example, 17 to 17) to do this. codemodernizer.chat.message.validation.error.downgrade_attempt=I can't transform a project from Java 21 to Java 17, but I can upgrade Java 21 code with up-to-date libraries and other dependencies. Try again with a supported language upgrade. codemodernizer.chat.message.validation.error.invalid_sct=It looks like the .sct file you provided isn't valid. Make sure that you've uploaded the .zip file you retrieved from your schema conversion in AWS DMS. codemodernizer.chat.message.validation.error.invalid_source_db=I can only convert SQL for migrations from an Oracle source database. The provided .sct file indicates another source database for this migration. From 66444863d658255c8d0c8b5bf48b5bbeb1aadd35 Mon Sep 17 00:00:00 2001 From: David Hasani Date: Thu, 19 Jun 2025 20:13:11 -0700 Subject: [PATCH 11/21] text update --- .../codemodernizer/constants/CodeTransformChatItems.kt | 2 +- .../codemodernizer/controller/CodeTransformChatController.kt | 2 +- .../jetbrains/services/codemodernizer/model/ZipManifest.kt | 3 +-- .../services/codemodernizer/utils/CodeTransformApiUtils.kt | 1 + .../software/aws/toolkits/resources/MessagesBundle.properties | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/constants/CodeTransformChatItems.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/constants/CodeTransformChatItems.kt index 314427f96f0..bab116949c0 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/constants/CodeTransformChatItems.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/constants/CodeTransformChatItems.kt @@ -348,7 +348,7 @@ fun buildUserInputSQLConversionMetadataChatContent() = CodeTransformChatMessageC ) fun buildUserInputCustomDependencyVersionsChatContent() = CodeTransformChatMessageContent( - message = message("codemodernizer.chat.message.custom_dependency_upgrades_prompt"), + message = message("codemodernizer.chat.message.custom_dependency_upgrades_prompt"), buttons = listOf( confirmCustomDependencyVersionsButton, continueTransformationButton, diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt index 07493468bd1..3a5f509021a 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt @@ -103,13 +103,13 @@ import software.aws.toolkits.jetbrains.services.codemodernizer.model.DownloadArt import software.aws.toolkits.jetbrains.services.codemodernizer.model.DownloadFailureReason import software.aws.toolkits.jetbrains.services.codemodernizer.model.EXPLAINABILITY_V1 import software.aws.toolkits.jetbrains.services.codemodernizer.model.IDE -import software.aws.toolkits.jetbrains.services.codemodernizer.model.SELECTIVE_TRANSFORMATION_V2 import software.aws.toolkits.jetbrains.services.codemodernizer.model.InvalidTelemetryReason import software.aws.toolkits.jetbrains.services.codemodernizer.model.JobId import software.aws.toolkits.jetbrains.services.codemodernizer.model.MAVEN_BUILD_RUN_UNIT_TESTS import software.aws.toolkits.jetbrains.services.codemodernizer.model.MAVEN_BUILD_SKIP_UNIT_TESTS import software.aws.toolkits.jetbrains.services.codemodernizer.model.MavenCopyCommandsResult import software.aws.toolkits.jetbrains.services.codemodernizer.model.MavenDependencyReportCommandsResult +import software.aws.toolkits.jetbrains.services.codemodernizer.model.SELECTIVE_TRANSFORMATION_V2 import software.aws.toolkits.jetbrains.services.codemodernizer.model.UploadFailureReason import software.aws.toolkits.jetbrains.services.codemodernizer.model.ValidationResult import software.aws.toolkits.jetbrains.services.codemodernizer.panels.managers.CodeModernizerBottomWindowPanelManager diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/ZipManifest.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/ZipManifest.kt index 089477b766b..4ad61c8476b 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/ZipManifest.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/ZipManifest.kt @@ -12,9 +12,8 @@ data class ZipManifest( val customBuildCommand: String = MAVEN_BUILD_RUN_UNIT_TESTS, val requestedConversions: RequestedConversions? = null, // only used for SQL conversions for now var dependencyUpgradeConfigFile: String? = null, - // TODO: make sure the below 2 keys don't mess up SQL conversions when present val noInteractiveMode: Boolean = true, - val compilationsJsonFile: String = COMPILATIONS_JSON_FILE + val compilationsJsonFile: String = COMPILATIONS_JSON_FILE, ) data class RequestedConversions( diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/utils/CodeTransformApiUtils.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/utils/CodeTransformApiUtils.kt index d1057d7b86f..0b4f4a40cca 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/utils/CodeTransformApiUtils.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/utils/CodeTransformApiUtils.kt @@ -123,6 +123,7 @@ suspend fun JobId.pollTransformationStatusAndPlan( delay(sleepDurationMillis) newPlan = clientAdaptor.getCodeModernizationPlan(this).transformationPlan() } + // TODO: handle case where PlannerAgent may request mvn dependency:tree; not needed for now if (hasSeenTransforming && newPlan != null) { attemptLocalBuild(newPlan, this, project) } diff --git a/plugins/core/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties b/plugins/core/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties index 6d93eed39f2..38784981980 100644 --- a/plugins/core/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties +++ b/plugins/core/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties @@ -706,7 +706,7 @@ codemodernizer.chat.message.upload_failed_other=Sorry, I was unable to upload yo codemodernizer.chat.message.upload_failed_ssl_error=Sorry, I was unable to upload your project. This might have been caused by your IDE not trusting the certificate of your HTTP proxy. Ensure all certificates for your proxy client have been configured in your IDE, and then retry transformation. codemodernizer.chat.message.upload_failed_url_expired=Sorry, I couldn't upload your project to begin the transformation. The Amazon S3 pre-signed URL used to upload your code expired after 30 minutes. This might have been caused by delays introduced by intermediate services in your network infrastructure.\n\nCheck your network configuration for services that might be causing delays. If the issue persists, you might need to allow list the following Amazon S3 bucket: 'amazonq-code-transformation-us-east-1-c6160f047e0.s3.amazonaws.com'. codemodernizer.chat.message.validation.check_eligible_modules=Checking for eligible modules... -codemodernizer.chat.message.validation.check_passed=I can upgrade your Java module. To start the transformation, I need some information from you. Choose the module you want to upgrade and the target code version to upgrade to. Then, choose **Confirm**.\n\nIf you do not see the module you want to transform, you might need to configure your project so that I can find it. Go to File and choose Project Structure. In the Projects tab, set the correct project JDK and language level. In the Modules tab, set the correct module JDK and language level.\n\nAfter successfully transforming to Java 17 or 21, an additional transformation is required to upgrade your libraries and dependencies. Choose the same source code version and target code version (for example, 17 to 17) to do this. +codemodernizer.chat.message.validation.check_passed=I can upgrade your Java module. To start the transformation, I need some information from you. Choose the module you want to upgrade and the target code version to upgrade to. Then, choose **Confirm**.\n\nIf you do not see the module you want to transform, you might need to configure your project so that I can find it. Go to File and choose Project Structure. In the Projects tab, set the correct project JDK and language level. In the Modules tab, set the correct module JDK and language level.\n\nAfter successfully transforming to Java 17 or 21, an additional transformation is required to upgrade your libraries and dependencies. Choose the same source code version and target code version (for example, 17 to 17) to do this.\n\nI will perform the transformation based on your project's requests, descriptions, and content. To maintain security, avoid including external, unvetted artifacts in your project repository prior to starting the transformation and always validate transformed code for both functionality and security. By pressing Confirm, you agree to these terms. codemodernizer.chat.message.validation.error.downgrade_attempt=I can't transform a project from Java 21 to Java 17, but I can upgrade Java 21 code with up-to-date libraries and other dependencies. Try again with a supported language upgrade. codemodernizer.chat.message.validation.error.invalid_sct=It looks like the .sct file you provided isn't valid. Make sure that you've uploaded the .zip file you retrieved from your schema conversion in AWS DMS. codemodernizer.chat.message.validation.error.invalid_source_db=I can only convert SQL for migrations from an Oracle source database. The provided .sct file indicates another source database for this migration. From 1c3271aed1c01ddf6670377056bbccfc6031bfc4 Mon Sep 17 00:00:00 2001 From: David Hasani Date: Thu, 19 Jun 2025 20:59:08 -0700 Subject: [PATCH 12/21] fix detekt --- .../services/codemodernizer/utils/CodeTransformApiUtils.kt | 2 +- .../software/aws/toolkits/resources/MessagesBundle.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/utils/CodeTransformApiUtils.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/utils/CodeTransformApiUtils.kt index 0b4f4a40cca..8800481a12a 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/utils/CodeTransformApiUtils.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/utils/CodeTransformApiUtils.kt @@ -119,7 +119,7 @@ suspend fun JobId.pollTransformationStatusAndPlan( hasSeenTransforming = true } var newPlan: TransformationPlan? = null - if (newStatus in STATES_WHERE_PLAN_EXIST && transformType != CodeTransformType.SQL_CONVERSION) { // no plan for SQL conversions + if (hasSeenTransforming && transformType != CodeTransformType.SQL_CONVERSION) { // no plan for SQL conversions delay(sleepDurationMillis) newPlan = clientAdaptor.getCodeModernizationPlan(this).transformationPlan() } diff --git a/plugins/core/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties b/plugins/core/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties index 38784981980..1c22360b846 100644 --- a/plugins/core/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties +++ b/plugins/core/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties @@ -647,8 +647,8 @@ codemodernizer.chat.message.changes_applied=I applied the changes to your projec codemodernizer.chat.message.choose_objective=I can help you with the following tasks:\n- Upgrade your Java 8, Java 11, and Java 17 codebases to Java 17 or Java 21.\n- Upgrade Java 17 or Java 21 code with up-to-date libraries and other dependencies.\n- Convert embedded SQL code for Oracle to PostgreSQL database migrations in AWS DMS.\n\nWhat would you like to do? You can enter "language upgrade" or "sql conversion". codemodernizer.chat.message.choose_objective_placeholder=Enter "language upgrade" or "sql conversion" codemodernizer.chat.message.custom_dependency_upgrades_continue=Ok, I will continue the transformation without additional dependency upgrade information. -codemodernizer.chat.message.custom_dependency_upgrades_prompt=Would you like to provide a dependency upgrade file? You can specify first-party dependencies to upgrade in a YAML file, and I will upgrade them during the JDK upgrade (for example, Java 8 to 17). You can initiate a separate transformation (17 to 17 or 21 to 21) after the initial JDK upgrade to transform third-party dependencies.\n\nWithout a YAML file, I can perform a minimum JDK upgrade, and then you can initiate a separate transformation to upgrade all third-party dependencies as part of a maximum transformation. For an example dependency upgrade file, see the [documentation](https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/code-transformation.html#dependency-upgrade-file). codemodernizer.chat.message.custom_dependency_upgrades_invalid=I wasn't able to parse the dependency upgrade file. Check that it's configured properly and try again. For an example of the required dependency upgrade file format, see the [documentation](https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/code-transformation.html#dependency-upgrade-file). +codemodernizer.chat.message.custom_dependency_upgrades_prompt=Would you like to provide a dependency upgrade file? You can specify first-party dependencies to upgrade in a YAML file, and I will upgrade them during the JDK upgrade (for example, Java 8 to 17). You can initiate a separate transformation (17 to 17 or 21 to 21) after the initial JDK upgrade to transform third-party dependencies.\n\nWithout a YAML file, I can perform a minimum JDK upgrade, and then you can initiate a separate transformation to upgrade all third-party dependencies as part of a maximum transformation. For an example dependency upgrade file, see the [documentation](https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/code-transformation.html#dependency-upgrade-file). codemodernizer.chat.message.custom_dependency_upgrades_valid=The dependency upgrade file looks good. I will use this information to upgrade the dependencies you specified. codemodernizer.chat.message.download_failed_client_instructions_expired=Your transformation is not available anymore. Your code and transformation summary are deleted 24 hours after the transformation completes. Please try starting the transformation again. codemodernizer.chat.message.download_failed_invalid_artifact=Sorry, I was unable to find your {0}. Artifacts are deleted after 24 hours. Please try starting the transformation again. From 3240d294fdf4692ddedfd956b510b5f0b5d86320 Mon Sep 17 00:00:00 2001 From: David Hasani Date: Thu, 19 Jun 2025 21:19:37 -0700 Subject: [PATCH 13/21] zip sql metadata correctly --- .../codemodernizer/model/CodeModernizerSessionContext.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerSessionContext.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerSessionContext.kt index a4665de5d67..004d5325df3 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerSessionContext.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerSessionContext.kt @@ -261,6 +261,10 @@ data class CodeModernizerSessionContext( dependencyFiles.forEach { depFile -> val relativePath = File(depFile.path).relativeTo(depDirectory) var relativePathString = relativePath.toPath().toString() + if (copyResult == null) { + // null copyResult means doing a SQL conversion; put metadata under dependencies folder + relativePathString = File(ZIP_DEPENDENCIES_PATH).resolve(relativePath).toPath().toString() + } // Convert Windows file path to work on Linux if (File.separatorChar != '/') { relativePathString = relativePathString.replace('\\', '/') From a60edff32096fdcaa0c2a5bbda3d5f1aa7130a32 Mon Sep 17 00:00:00 2001 From: David Hasani Date: Fri, 20 Jun 2025 11:06:56 -0700 Subject: [PATCH 14/21] update text --- .../software/aws/toolkits/resources/MessagesBundle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/core/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties b/plugins/core/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties index 1c22360b846..45c4caea56b 100644 --- a/plugins/core/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties +++ b/plugins/core/resources/resources/software/aws/toolkits/resources/MessagesBundle.properties @@ -706,7 +706,7 @@ codemodernizer.chat.message.upload_failed_other=Sorry, I was unable to upload yo codemodernizer.chat.message.upload_failed_ssl_error=Sorry, I was unable to upload your project. This might have been caused by your IDE not trusting the certificate of your HTTP proxy. Ensure all certificates for your proxy client have been configured in your IDE, and then retry transformation. codemodernizer.chat.message.upload_failed_url_expired=Sorry, I couldn't upload your project to begin the transformation. The Amazon S3 pre-signed URL used to upload your code expired after 30 minutes. This might have been caused by delays introduced by intermediate services in your network infrastructure.\n\nCheck your network configuration for services that might be causing delays. If the issue persists, you might need to allow list the following Amazon S3 bucket: 'amazonq-code-transformation-us-east-1-c6160f047e0.s3.amazonaws.com'. codemodernizer.chat.message.validation.check_eligible_modules=Checking for eligible modules... -codemodernizer.chat.message.validation.check_passed=I can upgrade your Java module. To start the transformation, I need some information from you. Choose the module you want to upgrade and the target code version to upgrade to. Then, choose **Confirm**.\n\nIf you do not see the module you want to transform, you might need to configure your project so that I can find it. Go to File and choose Project Structure. In the Projects tab, set the correct project JDK and language level. In the Modules tab, set the correct module JDK and language level.\n\nAfter successfully transforming to Java 17 or 21, an additional transformation is required to upgrade your libraries and dependencies. Choose the same source code version and target code version (for example, 17 to 17) to do this.\n\nI will perform the transformation based on your project's requests, descriptions, and content. To maintain security, avoid including external, unvetted artifacts in your project repository prior to starting the transformation and always validate transformed code for both functionality and security. By pressing Confirm, you agree to these terms. +codemodernizer.chat.message.validation.check_passed=I can upgrade your Java module. To start the transformation, I need some information from you. Choose the module you want to upgrade and the target code version to upgrade to. Then, choose **Confirm**.\n\nIf you do not see the module you want to transform, you might need to configure your project so that I can find it. Go to File and choose Project Structure. In the Projects tab, set the correct project JDK and language level. In the Modules tab, set the correct module JDK and language level.\n\nAfter successfully transforming to Java 17 or 21, an additional transformation is required to upgrade your libraries and dependencies. Choose the same source code version and target code version (for example, 17 to 17) to do this.\n\nI will perform the transformation based on your project's requests, descriptions, and content. To maintain security, avoid including external, unvetted artifacts in your project repository prior to starting the transformation and always validate transformed code for both functionality and security. codemodernizer.chat.message.validation.error.downgrade_attempt=I can't transform a project from Java 21 to Java 17, but I can upgrade Java 21 code with up-to-date libraries and other dependencies. Try again with a supported language upgrade. codemodernizer.chat.message.validation.error.invalid_sct=It looks like the .sct file you provided isn't valid. Make sure that you've uploaded the .zip file you retrieved from your schema conversion in AWS DMS. codemodernizer.chat.message.validation.error.invalid_source_db=I can only convert SQL for migrations from an Oracle source database. The provided .sct file indicates another source database for this migration. From fc15be87e7a87028270283f05c62e216d145434b Mon Sep 17 00:00:00 2001 From: David Hasani Date: Fri, 20 Jun 2025 11:54:28 -0700 Subject: [PATCH 15/21] fix timeout issue --- .../services/codemodernizer/utils/CodeTransformApiUtils.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/utils/CodeTransformApiUtils.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/utils/CodeTransformApiUtils.kt index 8800481a12a..de8785b5c94 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/utils/CodeTransformApiUtils.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/utils/CodeTransformApiUtils.kt @@ -252,7 +252,12 @@ suspend fun processClientInstructions(clientInstructionsPath: Path, jobId: JobId getLogger().info { "ResumeTransformation succeeded for job ${jobId.id}" } } catch (e: Exception) { getLogger().error { "Upload / resume job failed for job ${jobId.id} and artifact $artifactId: $e" } - throw e + if (e.message?.contains("find a step in desired state:AWAITING_CLIENT_ACTION") == true) { + getLogger().info { "Resuming job after server-side timeout" } + CodeModernizerManager.getInstance(project).codeTransformationSession?.resumeTransformation() + } else { + throw e + } } finally { uploadZip.deleteRecursively() copyOfProjectSources.toFile().deleteRecursively() From 1e701e05b7a627650ae9b520509c1ad0264aeaa4 Mon Sep 17 00:00:00 2001 From: David Hasani Date: Fri, 20 Jun 2025 19:01:28 -0700 Subject: [PATCH 16/21] handle Windows --- .../codemodernizer/model/CodeModernizerSessionContext.kt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerSessionContext.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerSessionContext.kt index 004d5325df3..f45c6fc2749 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerSessionContext.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerSessionContext.kt @@ -260,6 +260,13 @@ data class CodeModernizerSessionContext( if (depDirectory != null) { dependencyFiles.forEach { depFile -> val relativePath = File(depFile.path).relativeTo(depDirectory) + if (depFile.path.contains("compilations.json")) { + if (File.separatorChar != '/') { + var content = depFile.readText() + content = content.replace("\\\\", "/") + depFile.writeText(content) + } + } var relativePathString = relativePath.toPath().toString() if (copyResult == null) { // null copyResult means doing a SQL conversion; put metadata under dependencies folder From 87fac4a5214d3f267b68394cb450bb1e52d5abc0 Mon Sep 17 00:00:00 2001 From: David Hasani Date: Fri, 20 Jun 2025 19:04:20 -0700 Subject: [PATCH 17/21] refactor --- .../model/CodeModernizerSessionContext.kt | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerSessionContext.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerSessionContext.kt index f45c6fc2749..058b47c3800 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerSessionContext.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/CodeModernizerSessionContext.kt @@ -260,12 +260,10 @@ data class CodeModernizerSessionContext( if (depDirectory != null) { dependencyFiles.forEach { depFile -> val relativePath = File(depFile.path).relativeTo(depDirectory) - if (depFile.path.contains("compilations.json")) { - if (File.separatorChar != '/') { - var content = depFile.readText() - content = content.replace("\\\\", "/") - depFile.writeText(content) - } + if (depFile.path.contains("compilations.json") && File.separatorChar != '/') { + var content = depFile.readText() + content = content.replace("\\\\", "/") + depFile.writeText(content) } var relativePathString = relativePath.toPath().toString() if (copyResult == null) { From fbb545c9bdaf9c9978a792e4d83675d3c91ac4eb Mon Sep 17 00:00:00 2001 From: David Hasani Date: Mon, 23 Jun 2025 10:43:57 -0700 Subject: [PATCH 18/21] remove IDE capability --- .../codemodernizer/controller/CodeTransformChatController.kt | 2 +- .../jetbrains/services/codemodernizer/model/ZipManifest.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt index 3a5f509021a..9ece59c7c3c 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt @@ -419,7 +419,7 @@ class CodeTransformChatController( codeModernizerManager.codeTransformationSession?.let { it.sessionContext.customBuildCommand = customBuildCommand } - val transformCapabilities = listOf(EXPLAINABILITY_V1, CLIENT_SIDE_BUILD, SELECTIVE_TRANSFORMATION_V2, IDE) + val transformCapabilities = listOf(EXPLAINABILITY_V1, CLIENT_SIDE_BUILD, SELECTIVE_TRANSFORMATION_V2) codeModernizerManager.codeTransformationSession?.let { it.sessionContext.transformCapabilities = transformCapabilities } diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/ZipManifest.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/ZipManifest.kt index 4ad61c8476b..eb7cbe54812 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/ZipManifest.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/model/ZipManifest.kt @@ -8,7 +8,7 @@ data class ZipManifest( val dependenciesRoot: String = ZIP_DEPENDENCIES_PATH, val version: String = UPLOAD_ZIP_MANIFEST_VERSION, val hilCapabilities: List = listOf(HIL_1P_UPGRADE_CAPABILITY), - val transformCapabilities: List = listOf(EXPLAINABILITY_V1, CLIENT_SIDE_BUILD, SELECTIVE_TRANSFORMATION_V2, IDE), + val transformCapabilities: List = listOf(EXPLAINABILITY_V1, CLIENT_SIDE_BUILD, SELECTIVE_TRANSFORMATION_V2), val customBuildCommand: String = MAVEN_BUILD_RUN_UNIT_TESTS, val requestedConversions: RequestedConversions? = null, // only used for SQL conversions for now var dependencyUpgradeConfigFile: String? = null, From 67c45ac5767e22f97c7967d98d5cba15083e5fe0 Mon Sep 17 00:00:00 2001 From: David Hasani Date: Mon, 23 Jun 2025 10:45:53 -0700 Subject: [PATCH 19/21] remove IDE capability everywhere --- .../codemodernizer/controller/CodeTransformChatController.kt | 1 - .../services/codemodernizer/state/CodeModernizerState.kt | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt index 9ece59c7c3c..3c9709f9fef 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/controller/CodeTransformChatController.kt @@ -102,7 +102,6 @@ import software.aws.toolkits.jetbrains.services.codemodernizer.model.CustomerSel import software.aws.toolkits.jetbrains.services.codemodernizer.model.DownloadArtifactResult import software.aws.toolkits.jetbrains.services.codemodernizer.model.DownloadFailureReason import software.aws.toolkits.jetbrains.services.codemodernizer.model.EXPLAINABILITY_V1 -import software.aws.toolkits.jetbrains.services.codemodernizer.model.IDE import software.aws.toolkits.jetbrains.services.codemodernizer.model.InvalidTelemetryReason import software.aws.toolkits.jetbrains.services.codemodernizer.model.JobId import software.aws.toolkits.jetbrains.services.codemodernizer.model.MAVEN_BUILD_RUN_UNIT_TESTS diff --git a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/state/CodeModernizerState.kt b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/state/CodeModernizerState.kt index d509d944aeb..2c8f30975e6 100644 --- a/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/state/CodeModernizerState.kt +++ b/plugins/amazonq/codetransform/jetbrains-community/src/software/aws/toolkits/jetbrains/services/codemodernizer/state/CodeModernizerState.kt @@ -10,7 +10,6 @@ import com.intellij.util.xmlb.annotations.Property import software.aws.toolkits.jetbrains.services.codemodernizer.model.CLIENT_SIDE_BUILD import software.aws.toolkits.jetbrains.services.codemodernizer.model.CodeModernizerSessionContext import software.aws.toolkits.jetbrains.services.codemodernizer.model.EXPLAINABILITY_V1 -import software.aws.toolkits.jetbrains.services.codemodernizer.model.IDE import software.aws.toolkits.jetbrains.services.codemodernizer.model.JobId import software.aws.toolkits.jetbrains.services.codemodernizer.model.MAVEN_BUILD_RUN_UNIT_TESTS import software.aws.toolkits.jetbrains.services.codemodernizer.model.SELECTIVE_TRANSFORMATION_V2 @@ -70,7 +69,7 @@ class CodeModernizerState : BaseState() { configurationFile, sourceJavaSdkVersion, targetJavaSdkVersion, - listOf(EXPLAINABILITY_V1, SELECTIVE_TRANSFORMATION_V2, CLIENT_SIDE_BUILD, IDE), + listOf(EXPLAINABILITY_V1, SELECTIVE_TRANSFORMATION_V2, CLIENT_SIDE_BUILD), lastJobContext[JobDetails.CUSTOM_BUILD_COMMAND] ?: MAVEN_BUILD_RUN_UNIT_TESTS // default to running unit tests ) } From 7429e6ab36cbca21a6a8a4fe1f8404c97e69a937 Mon Sep 17 00:00:00 2001 From: David Hasani Date: Mon, 23 Jun 2025 11:09:36 -0700 Subject: [PATCH 20/21] address comment --- plugins/amazonq/build.gradle.kts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/plugins/amazonq/build.gradle.kts b/plugins/amazonq/build.gradle.kts index 83b0e5ffdfd..5888aa500b4 100644 --- a/plugins/amazonq/build.gradle.kts +++ b/plugins/amazonq/build.gradle.kts @@ -26,12 +26,6 @@ val changelog = tasks.register("pluginChangeLog") { changeLogFile.value(layout.buildDirectory.file("changelog/change-notes.xml")) } -tasks.prepareSandbox { - from("contrib/QCT-Maven-6-16.jar") { - into("/plugin-amazonq/lib") - } -} - tasks.jar { dependsOn(changelog) from(changelog) { @@ -139,6 +133,9 @@ val prepareBundledFlare by tasks.registering(Copy::class) { } tasks.withType().configureEach { + from("contrib/QCT-Maven-6-16.jar") { + into("/plugin-amazonq/lib") + } intoChild(intellijPlatform.projectName.map { "$it/flare" }) .from(prepareBundledFlare) } From bc34ade229e35e7aed42f8045a3d2b4ae48252d7 Mon Sep 17 00:00:00 2001 From: David <60020664+dhasani23@users.noreply.github.com> Date: Mon, 23 Jun 2025 12:55:04 -0700 Subject: [PATCH 21/21] Update plugins/amazonq/build.gradle.kts Co-authored-by: Richard Li <742829+rli@users.noreply.github.com> --- plugins/amazonq/build.gradle.kts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/plugins/amazonq/build.gradle.kts b/plugins/amazonq/build.gradle.kts index 5888aa500b4..67c5f08033e 100644 --- a/plugins/amazonq/build.gradle.kts +++ b/plugins/amazonq/build.gradle.kts @@ -133,9 +133,8 @@ val prepareBundledFlare by tasks.registering(Copy::class) { } tasks.withType().configureEach { - from("contrib/QCT-Maven-6-16.jar") { - into("/plugin-amazonq/lib") - } + intoChild(intellijPlatform.projectName.map { "$it/lib" }) + .from(file("contrib/QCT-Maven-6-16.jar")) intoChild(intellijPlatform.projectName.map { "$it/flare" }) .from(prepareBundledFlare) }