Skip to content

Commit

Permalink
feat(gradle): Add basic Gradle Kotlin DSL support
Browse files Browse the repository at this point in the history
  • Loading branch information
ikesyo committed Jul 14, 2019
1 parent 7725faa commit f684ca7
Show file tree
Hide file tree
Showing 8 changed files with 212 additions and 6 deletions.
6 changes: 5 additions & 1 deletion lib/config/definitions.js
Original file line number Diff line number Diff line change
Expand Up @@ -1633,7 +1633,11 @@ const options = [
stage: 'package',
type: 'object',
default: {
fileMatch: ['\\.gradle$', '(^|/)gradle.properties$'],
fileMatch: [
'\\.gradle(\\.kts)?$',
'(^|/)gradle.properties$',
'(^|/)buildSrc/.*',
],
timeout: 300,
versionScheme: 'maven',
},
Expand Down
49 changes: 49 additions & 0 deletions lib/manager/gradle/build-gradle.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ function updateGradleVersion(buildGradleContent, dependency, newVersion) {
const updateFunctions = [
updateVersionStringFormat,
updateVersionMapFormat,
updateVersionKotlinNamedArgumentFormat,
updateVersionMapVariableFormat,
updateVersionKotlinNamedArgumentVariableFormat,
updateVersionStringVariableFormat,
updateVersionExpressionVariableFormat,
updateGlobalVariables,
Expand Down Expand Up @@ -43,6 +45,7 @@ function collectVersionVariables(dependencies, buildGradleContent) {
moduleStringVariableExpressionVersionFormatMatch(dependency),
moduleStringVariableInterpolationVersionFormatMatch(dependency),
moduleMapVariableVersionFormatMatch(dependency),
moduleKotlinNamedArgumentVariableVersionFormatMatch(dependency),
];

for (const regex of regexes) {
Expand Down Expand Up @@ -74,6 +77,18 @@ function updateVersionMapFormat(dependency, buildGradleContent, newVersion) {
return null;
}

function updateVersionKotlinNamedArgumentFormat(
dependency,
buildGradleContent,
newVersion
) {
const regex = moduleKotlinNamedArgumentVersionFormatMatch(dependency);
if (buildGradleContent.match(regex)) {
return buildGradleContent.replace(regex, `$1${newVersion}$2`);
}
return null;
}

function updateVersionMapVariableFormat(
dependency,
buildGradleContent,
Expand All @@ -90,6 +105,22 @@ function updateVersionMapVariableFormat(
return null;
}

function updateVersionKotlinNamedArgumentVariableFormat(
dependency,
buildGradleContent,
newVersion
) {
const regex = moduleKotlinNamedArgumentVariableVersionFormatMatch(dependency);
const match = buildGradleContent.match(regex);
if (match) {
return buildGradleContent.replace(
variableDefinitionFormatMatch(match[1]),
`$1${newVersion}$3`
);
}
return null;
}

function updateVersionStringVariableFormat(
dependency,
buildGradleContent,
Expand Down Expand Up @@ -169,6 +200,15 @@ function moduleMapVersionFormatMatch(dependency) {
);
}

function moduleKotlinNamedArgumentVersionFormatMatch(dependency) {
// prettier-ignore
return new RegExp(
`(group\\s*=\\s*["']${dependency.group}["']\\s*,\\s*` +
`name\\s*=\\s*["']${dependency.name}["']\\s*,\\s*` +
`version\\s*=\\s*["']).*?(["'])`
);
}

function moduleMapVariableVersionFormatMatch(dependency) {
// prettier-ignore
return new RegExp(
Expand All @@ -178,6 +218,15 @@ function moduleMapVariableVersionFormatMatch(dependency) {
);
}

function moduleKotlinNamedArgumentVariableVersionFormatMatch(dependency) {
// prettier-ignore
return new RegExp(
`group\\s*=\\s*["']${dependency.group}["']\\s*,\\s*` +
`name\\s*=\\s*["']${dependency.name}["']\\s*,\\s*` +
`version\\s*=\\s*([^\\s"']+?)[\\s\\),]`
);
}

function moduleStringVariableInterpolationVersionFormatMatch(dependency) {
return new RegExp(
`["']${dependency.group}:${dependency.name}:\\$([^{].*?)["']`
Expand Down
8 changes: 6 additions & 2 deletions lib/manager/gradle/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ const GRADLE_DEPENDENCY_REPORT_OPTIONS =
const TIMEOUT_CODE = 143;

async function extractAllPackageFiles(config, packageFiles) {
if (!packageFiles.some(packageFile => packageFile === 'build.gradle')) {
logger.warn('No root build.gradle found - skipping');
if (
!packageFiles.some(packageFile =>
['build.gradle', 'build.gradle.kts'].includes(packageFile)
)
) {
logger.warn('No root build.gradle nor build.gradle.kts found - skipping');
return null;
}
logger.info('Extracting dependencies from all gradle files');
Expand Down
6 changes: 5 additions & 1 deletion renovate-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1122,7 +1122,11 @@
"description": "Configuration object for build.gradle files",
"type": "object",
"default": {
"fileMatch": ["\\.gradle$", "(^|/)gradle.properties$"],
"fileMatch": [
"\\.gradle(\\.kts)?$",
"(^|/)gradle.properties$",
"(^|/)buildSrc/.*"
],
"timeout": 300,
"versionScheme": "maven"
},
Expand Down
79 changes: 79 additions & 0 deletions test/manager/gradle/__snapshots__/index.spec.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,85 @@ Array [
]
`;

exports[`manager/gradle extractPackageFile should return gradle.kts dependencies 1`] = `
Array [
Object {
"datasource": "maven",
"deps": Array [
Object {
"currentValue": null,
"depGroup": "org.springframework.boot",
"depName": "org.springframework.boot:spring-boot-starter-jersey",
"name": "spring-boot-starter-jersey",
"registryUrls": Array [
"https://repo.maven.apache.org/maven2/",
"https://jitpack.io",
],
},
Object {
"currentValue": "1.0-groovy-2.4",
"depGroup": "org.spockframework",
"depName": "org.spockframework:spock-core",
"name": "spock-core",
"registryUrls": Array [
"https://repo.maven.apache.org/maven2/",
"https://jitpack.io",
],
},
Object {
"currentValue": "3.1",
"depGroup": "cglib",
"depName": "cglib:cglib-nodep",
"name": "cglib-nodep",
"registryUrls": Array [
"https://repo.maven.apache.org/maven2/",
"https://jitpack.io",
],
},
],
"manager": "gradle",
"packageFile": "build.gradle.kts",
},
Object {
"datasource": "maven",
"deps": Array [
Object {
"currentValue": null,
"depGroup": "org.springframework.boot",
"depName": "org.springframework.boot:spring-boot-starter-jersey",
"name": "spring-boot-starter-jersey",
"registryUrls": Array [
"https://repo.maven.apache.org/maven2/",
"https://jitpack.io",
],
},
Object {
"currentValue": "1.0-groovy-2.4",
"depGroup": "org.spockframework",
"depName": "org.spockframework:spock-core",
"name": "spock-core",
"registryUrls": Array [
"https://repo.maven.apache.org/maven2/",
"https://jitpack.io",
],
},
Object {
"currentValue": "3.1",
"depGroup": "cglib",
"depName": "cglib:cglib-nodep",
"name": "cglib-nodep",
"registryUrls": Array [
"https://repo.maven.apache.org/maven2/",
"https://jitpack.io",
],
},
],
"manager": "gradle",
"packageFile": "subproject/build.gradle.kts",
},
]
`;

exports[`manager/gradle extractPackageFile should throw registry failure if gradle execution fails 1`] = `[Error: registry-failure]`;

exports[`manager/gradle extractPackageFile should use repositories only for current project 1`] = `
Expand Down
58 changes: 58 additions & 0 deletions test/manager/gradle/build-gradle.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,22 @@ describe('lib/manager/gradle/updateGradleVersion', () => {
);
});

it('returns a file updated if the version defined as a Kotlin keyword argument is found', () => {
const gradleFile = `compile(group = 'mysql' ,
name = 'mysql-connector-java',
version = '6.0.5')`;
const updatedGradleFile = gradle.updateGradleVersion(
gradleFile,
{ group: 'mysql', name: 'mysql-connector-java', version: '6.0.5' },
'7.0.0'
);
expect(updatedGradleFile).toEqual(
`compile(group = 'mysql' ,
name = 'mysql-connector-java',
version = '7.0.0')`
);
});

it('should returns a file updated if the version defined in a variable as a string is found', () => {
const gradleFile = `String mysqlVersion= "6.0.5"
runtime ( "mysql:mysql-connector-java:$mysqlVersion" )
Expand Down Expand Up @@ -130,6 +146,26 @@ describe('lib/manager/gradle/updateGradleVersion', () => {
);
});

it('should returns a file updated if the version defined in a variable as a Kotlin keyword argument is found', () => {
const gradleFile = `val mysqlVersion = "6.0.5"
compile(group = 'mysql' ,
name = 'mysql-connector-java',
version = mysqlVersion)
`;
const updatedGradleFile = gradle.updateGradleVersion(
gradleFile,
{ group: 'mysql', name: 'mysql-connector-java', version: '6.0.5' },
'7.0.0'
);
expect(updatedGradleFile).toEqual(
`val mysqlVersion = "7.0.0"
compile(group = 'mysql' ,
name = 'mysql-connector-java',
version = mysqlVersion)
`
);
});

it('should replace a external groovy variable assigned to a specific dependency', () => {
const gradleFile =
'runtime ( "mysql:mysql-connector-java:${mysqlVersion}" )'; // eslint-disable-line no-template-curly-in-string
Expand Down Expand Up @@ -192,6 +228,28 @@ describe('lib/manager/gradle/updateGradleVersion', () => {
expect(updatedGradleFile).toEqual('String mysqlVersion = "7.0.0"');
});

it('should replace a external variable assigned to a Kotlin keyword argument dependency', () => {
const gradleFile = `compile(group = 'mysql' ,
name = 'mysql-connector-java',
version = mysqlVersion)
`;
const mysqlDependency = {
group: 'mysql',
depGroup: 'mysql',
name: 'mysql-connector-java',
version: '6.0.5',
};
gradle.collectVersionVariables([mysqlDependency], gradleFile);

const gradleWithVersionFile = 'val mysqlVersion = "6.0.5"';
const updatedGradleFile = gradle.updateGradleVersion(
gradleWithVersionFile,
mysqlDependency,
'7.0.0'
);
expect(updatedGradleFile).toEqual('val mysqlVersion = "7.0.0"');
});

it('should replace a external variable assigned to a interpolated dependency', () => {
const gradleFile =
'runtime ( "mysql:mysql-connector-java:$mysqlVersion" )';
Expand Down
8 changes: 8 additions & 0 deletions test/manager/gradle/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ describe('manager/gradle', () => {
expect(dependencies).toMatchSnapshot();
});

it('should return gradle.kts dependencies', async () => {
const dependencies = await manager.extractAllPackageFiles(config, [
'build.gradle.kts',
'subproject/build.gradle.kts',
]);
expect(dependencies).toMatchSnapshot();
});

it('should return empty if there are no dependencies', async () => {
fs.readFile.mockReturnValue(
fsReal.readFileSync(
Expand Down
4 changes: 2 additions & 2 deletions website/docs/java.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ Renovate detects versions specified as string `'group:artifact:version'` and as

### File Support

Renovate can update `build.gradle` files in the root of the repository and any `*.gradle` file inside any subdirectory as multi-project configurations.
Renovate can update `build.gradle`/`build.gradle.kts` files in the root of the repository and any `*.gradle`/`*.gradle.kts` file inside any subdirectory as multi-project configurations.

Renovate does not support:

- Projects without a `build.gradle` file in the root of the repository.
- Projects without neither `build.gradle` nor `build.gradle.kts` file in the root of the repository.
- Android projects that requires extra configuration to run. (e.g. setting the android SDK)

### How It Works
Expand Down

0 comments on commit f684ca7

Please sign in to comment.