Skip to content

Commit

Permalink
feat(gradle-wrapper): add support for gradle daemon JVM discovery (#3…
Browse files Browse the repository at this point in the history
…1319)

Co-authored-by: Rhys Arkins <[email protected]>
  • Loading branch information
Churro and rarkins committed Sep 15, 2024
1 parent 87fc69b commit 32a13f6
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 18 deletions.
3 changes: 2 additions & 1 deletion lib/modules/manager/gradle-wrapper/artifacts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,8 @@ export async function updateArtifacts({
{
toolName: 'java',
constraint:
config.constraints?.java ?? getJavaConstraint(config.currentValue),
config.constraints?.java ??
(await getJavaConstraint(config.currentValue, gradlewFile)),
},
],
};
Expand Down
57 changes: 44 additions & 13 deletions lib/modules/manager/gradle-wrapper/util.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import type { Stats } from 'node:fs';
import os from 'node:os';
import { codeBlock } from 'common-tags';
import { fs, partial } from '../../../../test/util';
import { GlobalConfig } from '../../../config/global';
import {
extractGradleVersion,
getJavaConstraint,
getJvmConfiguration,
gradleWrapperFileName,
prepareGradleCommand,
} from './utils';
Expand All @@ -16,34 +18,63 @@ describe('modules/manager/gradle-wrapper/util', () => {
beforeEach(() => GlobalConfig.reset());

describe('getJavaConstraint()', () => {
it('return ^8.0.0 for global mode', () => {
expect(getJavaConstraint('4')).toBe('^8.0.0');
it('return ^8.0.0 for global mode', async () => {
expect(await getJavaConstraint('4', '')).toBe('^8.0.0');
});

it('return ^11.0.0 for docker mode and undefined gradle', () => {
it('return ^11.0.0 for docker mode and undefined gradle', async () => {
GlobalConfig.set({ binarySource: 'docker' });
expect(getJavaConstraint('')).toBe('^11.0.0');
expect(await getJavaConstraint('', '')).toBe('^11.0.0');
});

it('return ^8.0.0 for docker gradle < 5', () => {
it('return ^8.0.0 for docker gradle < 5', async () => {
GlobalConfig.set({ binarySource: 'docker' });
expect(getJavaConstraint('4.9')).toBe('^8.0.0');
expect(await getJavaConstraint('4.9', '')).toBe('^8.0.0');
});

it('return ^11.0.0 for docker gradle >=5 && <7', () => {
it('return ^11.0.0 for docker gradle >=5 && <7', async () => {
GlobalConfig.set({ binarySource: 'docker' });
expect(getJavaConstraint('6.0')).toBe('^11.0.0');
expect(await getJavaConstraint('6.0', '')).toBe('^11.0.0');
});

it('return ^16.0.0 for docker gradle >= 7', () => {
it('return ^16.0.0 for docker gradle >= 7', async () => {
GlobalConfig.set({ binarySource: 'docker' });
expect(getJavaConstraint('7.0.1')).toBe('^16.0.0');
expect(await getJavaConstraint('7.0.1', '')).toBe('^16.0.0');
});

it('return ^17.0.0 for docker gradle >= 7.3', () => {
it('return ^17.0.0 for docker gradle >= 7.3', async () => {
GlobalConfig.set({ binarySource: 'docker' });
expect(getJavaConstraint('7.3.0')).toBe('^17.0.0');
expect(getJavaConstraint('8.0.1')).toBe('^17.0.0');
expect(await getJavaConstraint('7.3.0', '')).toBe('^17.0.0');
expect(await getJavaConstraint('8.0.1', '')).toBe('^17.0.0');
});

it('returns toolChainVersion constraint if daemon JVM configured', async () => {
const daemonJvm = codeBlock`
#This file is generated by updateDaemonJvm
toolchainVersion=999
`;
fs.readLocalFile.mockResolvedValue(daemonJvm);
expect(await getJavaConstraint('8.8', './gradlew')).toBe('^999.0.0');
});
});

describe('getJvmConfiguration', () => {
it('extracts toolChainVersion value', async () => {
const daemonJvm = codeBlock`
#This file is generated by updateDaemonJvm
toolchainVersion=21
`;
fs.readLocalFile.mockResolvedValue(daemonJvm);
expect(await getJvmConfiguration('')).toBe('21');
});

it('returns null if gradle-daemon-jvm.properties file not found', async () => {
fs.readLocalFile.mockResolvedValueOnce(null);
expect(await getJvmConfiguration('sub/gradlew')).toBeNull();
expect(fs.readLocalFile).toHaveBeenCalledWith(
'sub/gradle/gradle-daemon-jvm.properties',
'utf8',
);
});
});

Expand Down
43 changes: 40 additions & 3 deletions lib/modules/manager/gradle-wrapper/utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import os from 'node:os';
import { dirname, join } from 'upath';
import { GlobalConfig } from '../../../config/global';
import { logger } from '../../../logger';
import { chmodLocalFile, statLocalFile } from '../../../util/fs';
import { chmodLocalFile, readLocalFile, statLocalFile } from '../../../util/fs';
import { newlineRegex, regEx } from '../../../util/regex';
import gradleVersioning from '../../versioning/gradle';
import type { GradleVersionExtract } from './types';
Expand Down Expand Up @@ -41,13 +42,24 @@ export async function prepareGradleCommand(
* Find compatible java version for gradle.
* see https://docs.gradle.org/current/userguide/compatibility.html
* @param gradleVersion current gradle version
* @param gradlewFile path to gradle wrapper
* @returns A Java semver range
*/
export function getJavaConstraint(
export async function getJavaConstraint(
gradleVersion: string | null | undefined,
): string {
gradlewFile: string,
): Promise<string> {
const major = gradleVersion ? gradleVersioning.getMajor(gradleVersion) : null;
const minor = gradleVersion ? gradleVersioning.getMinor(gradleVersion) : null;

// https://docs.gradle.org/8.8/release-notes.html#daemon-toolchains
if (major && (major > 8 || (major === 8 && minor && minor >= 8))) {
const toolChainVersion = await getJvmConfiguration(gradlewFile);
if (toolChainVersion) {
return `^${toolChainVersion}.0.0`;
}
}

if (major && (major > 7 || (major >= 7 && minor && minor >= 3))) {
return '^17.0.0';
}
Expand All @@ -61,6 +73,31 @@ export function getJavaConstraint(
return '^11.0.0';
}

/**
* https://docs.gradle.org/current/userguide/gradle_daemon.html#sec:daemon_jvm_criteria
*/
export async function getJvmConfiguration(
gradlewFile: string,
): Promise<string | null> {
const daemonJvmFile = join(
dirname(gradlewFile),
'gradle/gradle-daemon-jvm.properties',
);
const daemonJvm = await readLocalFile(daemonJvmFile, 'utf8');
if (daemonJvm) {
const TOOLCHAIN_VERSION_REGEX = regEx(
'^(?:toolchainVersion\\s*=\\s*)(?<version>\\d+)$',
'm',
);
const toolChainMatch = TOOLCHAIN_VERSION_REGEX.exec(daemonJvm);
if (toolChainMatch?.groups) {
return toolChainMatch.groups.version;
}
}

return null;
}

// https://regex101.com/r/IcOs7P/1
const DISTRIBUTION_URL_REGEX = regEx(
'^(?:distributionUrl\\s*=\\s*)(?<url>\\S*-(?<version>\\d+\\.\\d+(?:\\.\\d+)?(?:-\\w+)*)-(?<type>bin|all)\\.zip)\\s*$',
Expand Down
5 changes: 4 additions & 1 deletion lib/modules/manager/gradle/artifacts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,10 @@ export async function updateArtifacts({
toolName: 'java',
constraint:
config.constraints?.java ??
getJavaConstraint(await getGradleVersion(gradlewFile)),
(await getJavaConstraint(
await getGradleVersion(gradlewFile),
gradlewFile,
)),
},
],
};
Expand Down

0 comments on commit 32a13f6

Please sign in to comment.