Skip to content

Commit 2aed15e

Browse files
Merge master into feature/model-selection
2 parents fde7892 + 593815a commit 2aed15e

File tree

4 files changed

+78
-15
lines changed

4 files changed

+78
-15
lines changed

packages/core/src/amazonqGumby/chat/controller/controller.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -580,11 +580,11 @@ export class GumbyController {
580580
return
581581
}
582582
const fileContents = await fs.readFileText(fileUri[0].fsPath)
583-
const missingKey = await validateCustomVersionsFile(fileContents)
583+
const errorMessage = validateCustomVersionsFile(fileContents)
584584

585-
if (missingKey) {
585+
if (errorMessage) {
586586
this.messenger.sendMessage(
587-
CodeWhispererConstants.invalidCustomVersionsFileMessage(missingKey),
587+
CodeWhispererConstants.invalidCustomVersionsFileMessage(errorMessage),
588588
message.tabID,
589589
'ai-prompt'
590590
)

packages/core/src/codewhisperer/models/constants.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -588,8 +588,8 @@ export const invalidMetadataFileUnsupportedSourceDB =
588588
export const invalidMetadataFileUnsupportedTargetDB =
589589
'I can only convert SQL for migrations to Aurora PostgreSQL or Amazon RDS for PostgreSQL target databases. The provided .sct file indicates another target database for this migration.'
590590

591-
export const invalidCustomVersionsFileMessage = (missingKey: string) =>
592-
`The dependency upgrade file provided is missing required field \`${missingKey}\`. 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).`
591+
export const invalidCustomVersionsFileMessage = (errorMessage: string) =>
592+
`The dependency upgrade file provided is malformed: ${errorMessage}. 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).`
593593

594594
export const invalidMetadataFileErrorParsing =
595595
"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."

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

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import * as vscode from 'vscode'
77
import * as path from 'path'
88
import * as os from 'os'
9+
import * as YAML from 'js-yaml'
910
import xml2js = require('xml2js')
1011
import * as CodeWhispererConstants from '../../models/constants'
1112
import { existsSync, readFileSync, writeFileSync } from 'fs' // eslint-disable-line no-restricted-imports
@@ -119,15 +120,52 @@ export async function parseBuildFile() {
119120
return undefined
120121
}
121122

122-
// return the first missing key in the custom versions file, or undefined if all required keys are present
123-
export async function validateCustomVersionsFile(fileContents: string) {
123+
// return an error message, or undefined if YAML file is valid
124+
export function validateCustomVersionsFile(fileContents: string) {
124125
const requiredKeys = ['dependencyManagement', 'identifier', 'targetVersion', 'originType']
125126
for (const key of requiredKeys) {
126127
if (!fileContents.includes(key)) {
127128
getLogger().info(`CodeTransformation: .YAML file is missing required key: ${key}`)
128-
return key
129+
return `Missing required key: \`${key}\``
129130
}
130131
}
132+
try {
133+
const yaml = YAML.load(fileContents) as any
134+
const dependencies = yaml?.dependencyManagement?.dependencies || []
135+
const plugins = yaml?.dependencyManagement?.plugins || []
136+
const dependenciesAndPlugins = dependencies.concat(plugins)
137+
138+
if (dependenciesAndPlugins.length === 0) {
139+
getLogger().info('CodeTransformation: .YAML file must contain at least dependencies or plugins')
140+
return `YAML file must contain at least \`dependencies\` or \`plugins\` under \`dependencyManagement\``
141+
}
142+
for (const item of dependenciesAndPlugins) {
143+
const errorMessage = validateItem(item)
144+
if (errorMessage) {
145+
return errorMessage
146+
}
147+
}
148+
return undefined
149+
} catch (err: any) {
150+
getLogger().info(`CodeTransformation: Invalid YAML format: ${err.message}`)
151+
return `Invalid YAML format: ${err.message}`
152+
}
153+
}
154+
155+
// return an error message, or undefined if item is valid
156+
function validateItem(item: any, validOriginTypes: string[] = ['FIRST_PARTY', 'THIRD_PARTY']) {
157+
if (!/^[^\s:]+:[^\s:]+$/.test(item.identifier)) {
158+
getLogger().info(`CodeTransformation: Invalid identifier format: ${item.identifier}`)
159+
return `Invalid identifier format: \`${item.identifier}\`. Must be in format \`groupId:artifactId\` without spaces`
160+
}
161+
if (!validOriginTypes.includes(item.originType)) {
162+
getLogger().info(`CodeTransformation: Invalid originType: ${item.originType}`)
163+
return `Invalid originType: \`${item.originType}\`. Must be either \`FIRST_PARTY\` or \`THIRD_PARTY\``
164+
}
165+
if (!item.targetVersion?.trim()) {
166+
getLogger().info(`CodeTransformation: Missing targetVersion in: ${item.identifier}`)
167+
return `Missing \`targetVersion\` in: \`${item.identifier}\``
168+
}
131169
return undefined
132170
}
133171

packages/core/src/test/codewhisperer/commands/transformByQ.test.ts

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ dependencyManagement:
6767
plugins:
6868
- identifier: "com.example:plugin"
6969
targetVersion: "1.2.0"
70-
versionProperty: "plugin.version" # Optional`
70+
versionProperty: "plugin.version" # Optional
71+
originType: "FIRST_PARTY" # or "THIRD_PARTY"`
7172

7273
const validSctFile = `<?xml version="1.0" encoding="UTF-8"?>
7374
<tree>
@@ -570,15 +571,39 @@ dependencyManagement:
570571
assert.strictEqual(expectedWarning, warningMessage)
571572
})
572573

573-
it(`WHEN validateCustomVersionsFile on fully valid .yaml file THEN passes validation`, async function () {
574-
const missingKey = await validateCustomVersionsFile(validCustomVersionsFile)
575-
assert.strictEqual(missingKey, undefined)
574+
it(`WHEN validateCustomVersionsFile on fully valid .yaml file THEN passes validation`, function () {
575+
const errorMessage = validateCustomVersionsFile(validCustomVersionsFile)
576+
assert.strictEqual(errorMessage, undefined)
576577
})
577578

578-
it(`WHEN validateCustomVersionsFile on invalid .yaml file THEN fails validation`, async function () {
579+
it(`WHEN validateCustomVersionsFile on .yaml file with missing key THEN fails validation`, function () {
579580
const invalidFile = validCustomVersionsFile.replace('dependencyManagement', 'invalidKey')
580-
const missingKey = await validateCustomVersionsFile(invalidFile)
581-
assert.strictEqual(missingKey, 'dependencyManagement')
581+
const errorMessage = validateCustomVersionsFile(invalidFile)
582+
assert.strictEqual(errorMessage, `Missing required key: \`dependencyManagement\``)
583+
})
584+
585+
it(`WHEN validateCustomVersionsFile on .yaml file with invalid identifier format THEN fails validation`, function () {
586+
const invalidFile = validCustomVersionsFile.replace('com.example:library1', 'com.example-library1')
587+
const errorMessage = validateCustomVersionsFile(invalidFile)
588+
assert.strictEqual(
589+
errorMessage,
590+
`Invalid identifier format: \`com.example-library1\`. Must be in format \`groupId:artifactId\` without spaces`
591+
)
592+
})
593+
594+
it(`WHEN validateCustomVersionsFile on .yaml file with invalid originType THEN fails validation`, function () {
595+
const invalidFile = validCustomVersionsFile.replace('FIRST_PARTY', 'INVALID_TYPE')
596+
const errorMessage = validateCustomVersionsFile(invalidFile)
597+
assert.strictEqual(
598+
errorMessage,
599+
`Invalid originType: \`INVALID_TYPE\`. Must be either \`FIRST_PARTY\` or \`THIRD_PARTY\``
600+
)
601+
})
602+
603+
it(`WHEN validateCustomVersionsFile on .yaml file with missing targetVersion THEN fails validation`, function () {
604+
const invalidFile = validCustomVersionsFile.replace('targetVersion: "2.1.0"', '')
605+
const errorMessage = validateCustomVersionsFile(invalidFile)
606+
assert.strictEqual(errorMessage, `Missing \`targetVersion\` in: \`com.example:library1\``)
582607
})
583608

584609
it(`WHEN validateMetadataFile on fully valid .sct file THEN passes validation`, async function () {

0 commit comments

Comments
 (0)