diff --git a/lib/manager/gradle/index.ts b/lib/manager/gradle/index.ts index b535adec707bad..2362cad7125acf 100644 --- a/lib/manager/gradle/index.ts +++ b/lib/manager/gradle/index.ts @@ -1,4 +1,4 @@ -import { exists } from 'fs-extra'; +import { access, constants, exists } from 'fs-extra'; import upath from 'upath'; import { exec } from '../../util/exec'; @@ -139,7 +139,10 @@ async function getGradleCommandLine( cwd: string ): Promise { let cmd: string; - const gradlewExists = await exists(upath.join(cwd, 'gradlew')); + const gradlewPath = upath.join(cwd, 'gradlew'); + const gradlewExists = await exists(gradlewPath); + const gradlewExecutable = gradlewExists && (await canExecute(gradlewPath)); + if (config.binarySource === 'docker') { cmd = `docker run --rm `; // istanbul ignore if @@ -148,6 +151,8 @@ async function getGradleCommandLine( } cmd += `-v ${cwd}:${cwd} -w ${cwd} `; cmd += `renovate/gradle gradle`; + } else if (gradlewExecutable) { + cmd = './gradlew'; } else if (gradlewExists) { cmd = 'sh gradlew'; } else { @@ -156,4 +161,13 @@ async function getGradleCommandLine( return cmd + ' ' + GRADLE_DEPENDENCY_REPORT_OPTIONS; } +async function canExecute(path: string): Promise { + try { + await access(path, constants.X_OK); + return true; + } catch { + return false; + } +} + export const language = 'java'; diff --git a/test/manager/gradle/index.spec.ts b/test/manager/gradle/index.spec.ts index 79b6f69d436ce8..56653c59d764f6 100644 --- a/test/manager/gradle/index.spec.ts +++ b/test/manager/gradle/index.spec.ts @@ -30,6 +30,7 @@ describe('manager/gradle', () => { fs.readFile.mockResolvedValue(updatesDependenciesReport as any); fs.mkdir.mockResolvedValue(); fs.exists.mockResolvedValue(true); + fs.access.mockResolvedValue(undefined); exec.mockResolvedValue({ stdout: 'gradle output', stderr: '' } as never); platform.getFile.mockResolvedValue('some content'); }); @@ -109,6 +110,19 @@ describe('manager/gradle', () => { it('should execute gradlew when available', async () => { await manager.extractAllPackageFiles(config, ['build.gradle']); + expect(exec.mock.calls[0][0]).toBe( + './gradlew --init-script renovate-plugin.gradle renovate' + ); + expect(exec.mock.calls[0][1]).toMatchObject({ + cwd: 'localDir', + timeout: 20000, + }); + }); + + it('should run gradlew through `sh` when available but not executable', async () => { + fs.access.mockRejectedValue(undefined); + await manager.extractAllPackageFiles(config, ['build.gradle']); + expect(exec.mock.calls[0][0]).toBe( 'sh gradlew --init-script renovate-plugin.gradle renovate' );