diff --git a/lib/modules/manager/gradle-wrapper/artifacts.spec.ts b/lib/modules/manager/gradle-wrapper/artifacts.spec.ts index e05c33037d2bdd..2f9cee7a784f9a 100644 --- a/lib/modules/manager/gradle-wrapper/artifacts.spec.ts +++ b/lib/modules/manager/gradle-wrapper/artifacts.spec.ts @@ -275,4 +275,53 @@ describe('modules/manager/gradle-wrapper/artifacts', () => { ]); expect(execSnapshots).toBeEmptyArray(); }); + + it('handles gradle-wrapper in subdirectory', async () => { + const execSnapshots = mockExecAll(); + git.getRepoStatus.mockResolvedValue( + partial({ + modified: [ + 'sub/gradle/wrapper/gradle-wrapper.properties', + 'sub/gradlew', + 'sub/gradlew.bat', + ], + }) + ); + + const res = await updateArtifacts({ + packageFileName: 'sub/gradle/wrapper/gradle-wrapper.properties', + updatedDeps: [], + newPackageFileContent: Fixtures.get( + 'expectedFiles/gradle/wrapper/gradle-wrapper.properties' + ), + config: { ...config, newValue: '6.3' }, + }); + + expect(res).toEqual( + [ + 'sub/gradle/wrapper/gradle-wrapper.properties', + 'sub/gradlew', + 'sub/gradlew.bat', + ].map((fileProjectPath) => ({ + file: { + type: 'addition', + path: fileProjectPath, + contents: 'test', + }, + })) + ); + expect(execSnapshots).toMatchObject([ + { + cmd: './gradlew wrapper --gradle-distribution-url https://services.gradle.org/distributions/gradle-6.3-bin.zip', + options: { + cwd: '/tmp/github/some/repo/sub', + encoding: 'utf-8', + env: { + GRADLE_OPTS: + '-Dorg.gradle.parallel=true -Dorg.gradle.configureondemand=true -Dorg.gradle.daemon=false -Dorg.gradle.caching=false', + }, + }, + }, + ]); + }); }); diff --git a/lib/modules/manager/gradle-wrapper/artifacts.ts b/lib/modules/manager/gradle-wrapper/artifacts.ts index 0fe7f16f9e6031..442531e996c093 100644 --- a/lib/modules/manager/gradle-wrapper/artifacts.ts +++ b/lib/modules/manager/gradle-wrapper/artifacts.ts @@ -1,5 +1,6 @@ import is from '@sindresorhus/is'; import { quote } from 'shlex'; +import { dirname, join } from 'upath'; import { TEMPORARY_ERROR } from '../../../constants/error-messages'; import { logger } from '../../../logger'; import { exec } from '../../../util/exec'; @@ -10,7 +11,12 @@ import type { StatusResult } from '../../../util/git/types'; import { Http } from '../../../util/http'; import { newlineRegex } from '../../../util/regex'; import type { UpdateArtifact, UpdateArtifactsResult } from '../types'; -import { extraEnv, getJavaConstraint, prepareGradleCommand } from './utils'; +import { + extraEnv, + getJavaConstraint, + gradleWrapperFileName, + prepareGradleCommand, +} from './utils'; const http = new Http('gradle-wrapper'); @@ -55,7 +61,10 @@ export async function updateArtifacts({ }: UpdateArtifact): Promise { try { logger.debug({ updatedDeps }, 'gradle-wrapper.updateArtifacts()'); - let cmd = await prepareGradleCommand(); + const localGradleDir = join(dirname(packageFileName), '../../'); + const gradlewFile = join(localGradleDir, gradleWrapperFileName()); + + let cmd = await prepareGradleCommand(gradlewFile); if (!cmd) { logger.info('No gradlew found - skipping Artifacts update'); return null; @@ -81,6 +90,7 @@ export async function updateArtifacts({ } logger.debug(`Updating gradle wrapper: "${cmd}"`); const execOptions: ExecOptions = { + cwdFile: gradlewFile, docker: { image: 'sidecar', }, diff --git a/lib/modules/manager/gradle-wrapper/util.spec.ts b/lib/modules/manager/gradle-wrapper/util.spec.ts index 13fffb6b2c14e7..1feed75ae9a4c4 100644 --- a/lib/modules/manager/gradle-wrapper/util.spec.ts +++ b/lib/modules/manager/gradle-wrapper/util.spec.ts @@ -69,7 +69,7 @@ describe('modules/manager/gradle-wrapper/util', () => { mode: 0o550, }) ); - expect(await prepareGradleCommand()).toBe('./gradlew'); + expect(await prepareGradleCommand('./gradlew')).toBe('./gradlew'); }); it('returns null', async () => { @@ -78,7 +78,7 @@ describe('modules/manager/gradle-wrapper/util', () => { isFile: () => false, }) ); - expect(await prepareGradleCommand()).toBeNull(); + expect(await prepareGradleCommand('./gradlew')).toBeNull(); }); }); }); diff --git a/lib/modules/manager/gradle-wrapper/utils.ts b/lib/modules/manager/gradle-wrapper/utils.ts index 14c6ffcc812b65..430b0d4a226d45 100644 --- a/lib/modules/manager/gradle-wrapper/utils.ts +++ b/lib/modules/manager/gradle-wrapper/utils.ts @@ -21,8 +21,9 @@ export function gradleWrapperFileName(): string { return './gradlew'; } -export async function prepareGradleCommand(): Promise { - const gradlewFile = gradleWrapperFileName(); +export async function prepareGradleCommand( + gradlewFile: string +): Promise { const gradlewStat = await statLocalFile(gradlewFile); if (gradlewStat?.isFile() === true) { // if the file is not executable by others @@ -30,7 +31,7 @@ export async function prepareGradleCommand(): Promise { // add the execution permission to the owner, group and others await chmodLocalFile(gradlewFile, gradlewStat.mode | 0o111); } - return gradlewFile; + return gradleWrapperFileName(); } /* eslint-enable no-bitwise */ return null;