diff --git a/.changes/next-release/bugfix-bc83a934-5f3d-49d1-9e81-4390229ea052.json b/.changes/next-release/bugfix-bc83a934-5f3d-49d1-9e81-4390229ea052.json new file mode 100644 index 00000000000..76b7984dfac --- /dev/null +++ b/.changes/next-release/bugfix-bc83a934-5f3d-49d1-9e81-4390229ea052.json @@ -0,0 +1,4 @@ +{ + "type" : "bugfix", + "description" : "/transform: validate YAML dependency file for required fields" +} \ No newline at end of file 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 e5af1ff428c..d7329f0bacd 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 @@ -419,9 +419,9 @@ fun buildSQLMetadataValidationErrorChatContent(errorReason: String) = CodeTransf message = errorReason, ) -fun buildCustomDependencyVersionsFileInvalidChatContent() = CodeTransformChatMessageContent( +fun buildCustomDependencyVersionsFileInvalidChatContent(missingKey: String) = CodeTransformChatMessageContent( type = CodeTransformChatMessageType.FinalizedAnswer, - message = message("codemodernizer.chat.message.custom_dependency_upgrades_invalid"), + message = message("codemodernizer.chat.message.custom_dependency_upgrades_invalid", missingKey), ) fun buildUserCancelledChatContent() = 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 1629b0acc27..9d8e948e6bd 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 @@ -432,9 +432,9 @@ class CodeTransformChatController( val descriptor = FileChooserDescriptorFactory.createSingleFileDescriptor() .withDescription("Select .yaml file") val selectedFile = FileChooser.chooseFile(descriptor, null, null) ?: return@withContext - val isValid = validateCustomVersionsFile(selectedFile) - if (!isValid) { - codeTransformChatHelper.updateLastPendingMessage(buildCustomDependencyVersionsFileInvalidChatContent()) + val missingKey = validateCustomVersionsFile(selectedFile) + if (missingKey != null) { + codeTransformChatHelper.updateLastPendingMessage(buildCustomDependencyVersionsFileInvalidChatContent(missingKey)) codeTransformChatHelper.addNewMessage(buildStartNewTransformFollowup()) return@withContext } 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 f5b97786c30..4f925f142e8 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 @@ -196,21 +196,22 @@ fun parseXmlDependenciesReport(pathToXmlDependency: Path): DependencyUpdatesRepo return report } -fun validateCustomVersionsFile(file: VirtualFile): Boolean { +// return the first missing key in the custom versions file, or null if all required keys are present +fun validateCustomVersionsFile(file: VirtualFile): String? { 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 + return message("codemodernizer.chat.message.custom_dependency_upgrades_invalid_not_yaml") } val fileContents = file.readText() - val requiredKeys = listOf("dependencyManagement:", "identifier:", "targetVersion:") + val requiredKeys = listOf("dependencyManagement", "identifier", "targetVersion", "originType") for (key in requiredKeys) { if (!fileContents.contains(key)) { getLogger().error { "Missing yaml key: $key" } - return false + return key } } - return true + return null } fun validateSctMetadata(sctFile: File?): SqlMetadataValidationResult { 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 2699ddc6178..16090b13437 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 @@ -411,8 +411,8 @@ dependencyManagement: """.trimIndent() val virtualFile = LightVirtualFile("test-valid.yaml", YAMLFileType.YML, sampleFileContents) - val isValidFile = validateCustomVersionsFile(virtualFile) - assertThat(isValidFile).isTrue() + val missingKey = validateCustomVersionsFile(virtualFile) + assertThat(missingKey).isNull() } @Test @@ -432,8 +432,8 @@ invalidKey: """.trimIndent() val virtualFile = LightVirtualFile("test-invalid.yaml", YAMLFileType.YML, sampleFileContents) - val isValidFile = validateCustomVersionsFile(virtualFile) - assertThat(isValidFile).isFalse() + val missingKey = validateCustomVersionsFile(virtualFile) + assertThat(missingKey).isEqualTo("dependencyManagement") } @Test @@ -454,7 +454,27 @@ dependencyManagement: val virtualFile = LightVirtualFile("test-invalid-file-type.txt", sampleFileContents) val isValidFile = validateCustomVersionsFile(virtualFile) - assertThat(isValidFile).isFalse() + assertThat(isValidFile).isEqualTo(message("codemodernizer.chat.message.custom_dependency_upgrades_invalid_not_yaml")) + } + + @Test + fun `WHEN validateCustomVersionsFile on yaml file missing originType THEN fails validation`() { + val sampleFileContents = """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" + plugins: + - identifier: "com.example:plugin" + targetVersion: "1.2.0" + versionProperty: "plugin.version" + """.trimIndent() + + val virtualFile = LightVirtualFile("sample.yaml", sampleFileContents) + val missingKey = validateCustomVersionsFile(virtualFile) + assertThat(missingKey).isEqualTo("originType") } @Test 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 46236427ae9..3593f378159 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,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_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_invalid=The dependency upgrade file provided is missing required field `{0}`. Check that it is 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_invalid_not_yaml=Provided file is not a YAML/YML file codemodernizer.chat.message.custom_dependency_upgrades_prompt_jdk_upgrade=Would you like to provide a dependency upgrade file? You can specify first party dependencies and their versions in a YAML file, and I will upgrade them during the JDK upgrade 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_library_upgrade=Would you like to provide a dependency upgrade file? You can specify third party dependencies and their versions in a YAML file, and I will only upgrade these dependencies during the library upgrade 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.