diff --git a/lib/modules/manager/gradle-wrapper/artifacts.spec.ts b/lib/modules/manager/gradle-wrapper/artifacts.spec.ts index 2f9cee7a784f9aeb86877c0fbaf620182d4010a3..75b91fea4f17c5757f6fa23c572de78d072d07ef 100644 --- a/lib/modules/manager/gradle-wrapper/artifacts.spec.ts +++ b/lib/modules/manager/gradle-wrapper/artifacts.spec.ts @@ -4,13 +4,21 @@ import { join } from 'upath'; import { envMock, mockExecAll } from '../../../../test/exec-util'; import { Fixtures } from '../../../../test/fixtures'; import * as httpMock from '../../../../test/http-mock'; -import { env, fs, git, mockedFunction, partial } from '../../../../test/util'; +import { + env, + fs, + git, + logger, + mockedFunction, + partial, +} from '../../../../test/util'; import { GlobalConfig } from '../../../config/global'; import type { RepoGlobalConfig } from '../../../config/types'; import { resetPrefetchedImages } from '../../../util/exec/docker'; import type { StatusResult } from '../../../util/git/types'; import { getPkgReleases } from '../../datasource'; import type { UpdateArtifactsConfig } from '../types'; +import { updateBuildFile } from './artifacts'; import { updateArtifacts } from '.'; jest.mock('../../../util/fs'); @@ -64,264 +72,342 @@ describe('modules/manager/gradle-wrapper/artifacts', () => { }); }); - it('replaces existing value', async () => { - const execSnapshots = mockExecAll(); - git.getRepoStatus.mockResolvedValue( - partial<StatusResult>({ - modified: [ + describe('updateArtifacts()', () => { + it('replaces existing value', async () => { + const execSnapshots = mockExecAll(); + git.getRepoStatus.mockResolvedValue( + partial<StatusResult>({ + modified: [ + 'gradle/wrapper/gradle-wrapper.properties', + 'gradlew', + 'gradlew.bat', + ], + }) + ); + + const res = await updateArtifacts({ + packageFileName: 'gradle/wrapper/gradle-wrapper.properties', + updatedDeps: [], + newPackageFileContent: Fixtures.get( + 'expectedFiles/gradle/wrapper/gradle-wrapper.properties' + ), + config: { ...config, newValue: '6.3' }, + }); + + expect(res).toEqual( + [ 'gradle/wrapper/gradle-wrapper.properties', 'gradlew', 'gradlew.bat', - ], - }) - ); - - const res = await updateArtifacts({ - packageFileName: 'gradle/wrapper/gradle-wrapper.properties', - updatedDeps: [], - newPackageFileContent: Fixtures.get( - 'expectedFiles/gradle/wrapper/gradle-wrapper.properties' - ), - config: { ...config, newValue: '6.3' }, - }); - - expect(res).toEqual( - [ - 'gradle/wrapper/gradle-wrapper.properties', - 'gradlew', - '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', - encoding: 'utf-8', - env: { - GRADLE_OPTS: - '-Dorg.gradle.parallel=true -Dorg.gradle.configureondemand=true -Dorg.gradle.daemon=false -Dorg.gradle.caching=false', + ].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', + encoding: 'utf-8', + env: { + GRADLE_OPTS: + '-Dorg.gradle.parallel=true -Dorg.gradle.configureondemand=true -Dorg.gradle.daemon=false -Dorg.gradle.caching=false', + }, }, }, - }, - ]); - }); + ]); + }); - it('gradlew not found', async () => { - const execSnapshots = mockExecAll(); - fs.statLocalFile.mockResolvedValue( - partial<Stats>({ - isFile: () => false, - mode: 0o555, - }) - ); + it('gradlew not found', async () => { + const execSnapshots = mockExecAll(); + fs.statLocalFile.mockResolvedValue( + partial<Stats>({ + isFile: () => false, + mode: 0o555, + }) + ); + + const result = await updateArtifacts({ + packageFileName: 'gradle/wrapper/gradle-wrapper.properties', + updatedDeps: [], + newPackageFileContent: '', + config: {}, + }); - const result = await updateArtifacts({ - packageFileName: 'gradle/wrapper/gradle-wrapper.properties', - updatedDeps: [], - newPackageFileContent: '', - config: {}, + expect(result).toBeNull(); + expect(execSnapshots).toBeEmptyArray(); }); - expect(result).toBeNull(); - expect(execSnapshots).toBeEmptyArray(); - }); + it('gradlew failed', async () => { + const execSnapshots = mockExecAll(new Error('failed')); + git.getRepoStatus.mockResolvedValueOnce( + partial<StatusResult>({ + modified: [], + }) + ); + const result = await updateArtifacts({ + packageFileName: 'gradle/wrapper/gradle-wrapper.properties', + updatedDeps: [], + newPackageFileContent: '', + config, + }); - it('gradlew failed', async () => { - const execSnapshots = mockExecAll(new Error('failed')); - git.getRepoStatus.mockResolvedValueOnce( - partial<StatusResult>({ - modified: [], - }) - ); - const result = await updateArtifacts({ - packageFileName: 'gradle/wrapper/gradle-wrapper.properties', - updatedDeps: [], - newPackageFileContent: '', - config, + expect(result).toBeEmptyArray(); + expect(execSnapshots).toMatchObject([ + { + cmd: './gradlew wrapper --gradle-version 5.6.4', + options: { cwd: '/tmp/github/some/repo' }, + }, + ]); }); - expect(result).toBeEmptyArray(); - expect(execSnapshots).toMatchObject([ - { - cmd: './gradlew wrapper --gradle-version 5.6.4', - options: { cwd: '/tmp/github/some/repo' }, - }, - ]); - }); - - it('updates distributionSha256Sum (docker)', async () => { - const execSnapshots = mockExecAll(); - httpMock - .scope('https://services.gradle.org') - .get('/distributions/gradle-6.3-bin.zip.sha256') - .reply( - 200, - '038794feef1f4745c6347107b6726279d1c824f3fc634b60f86ace1e9fbd1768' + it('updates distributionSha256Sum (docker)', async () => { + const execSnapshots = mockExecAll(); + httpMock + .scope('https://services.gradle.org') + .get('/distributions/gradle-6.3-bin.zip.sha256') + .reply( + 200, + '038794feef1f4745c6347107b6726279d1c824f3fc634b60f86ace1e9fbd1768' + ); + git.getRepoStatus.mockResolvedValueOnce( + partial<StatusResult>({ + modified: ['gradle/wrapper/gradle-wrapper.properties'], + }) ); - git.getRepoStatus.mockResolvedValueOnce( - partial<StatusResult>({ - modified: ['gradle/wrapper/gradle-wrapper.properties'], - }) - ); - GlobalConfig.set({ ...adminConfig, binarySource: 'docker' }); + GlobalConfig.set({ ...adminConfig, binarySource: 'docker' }); - const result = await updateArtifacts({ - packageFileName: 'gradle/wrapper/gradle-wrapper.properties', - updatedDeps: [], - newPackageFileContent: `distributionSha256Sum=336b6898b491f6334502d8074a6b8c2d73ed83b92123106bd4bf837f04111043\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-6.3-bin.zip`, - config, - }); + const result = await updateArtifacts({ + packageFileName: 'gradle/wrapper/gradle-wrapper.properties', + updatedDeps: [], + newPackageFileContent: `distributionSha256Sum=336b6898b491f6334502d8074a6b8c2d73ed83b92123106bd4bf837f04111043\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-6.3-bin.zip`, + config, + }); - expect(result).toEqual([ - { - file: { - contents: 'test', - path: 'gradle/wrapper/gradle-wrapper.properties', - type: 'addition', + expect(result).toEqual([ + { + file: { + contents: 'test', + path: 'gradle/wrapper/gradle-wrapper.properties', + type: 'addition', + }, }, - }, - ]); - expect(execSnapshots).toMatchObject([ - { cmd: 'docker pull renovate/sidecar' }, - { cmd: 'docker ps --filter name=renovate_sidecar -aq' }, - { - cmd: - 'docker run --rm --name=renovate_sidecar --label=renovate_child ' + - '-v "/tmp/github/some/repo":"/tmp/github/some/repo" ' + - '-v "/tmp/cache":"/tmp/cache" ' + - '-e GRADLE_OPTS ' + - '-e BUILDPACK_CACHE_DIR ' + - '-w "/tmp/github/some/repo" ' + - 'renovate/sidecar' + - ' bash -l -c "' + - 'install-tool java 11.0.1' + - ' && ' + - './gradlew wrapper --gradle-distribution-url https://services.gradle.org/distributions/gradle-6.3-bin.zip --gradle-distribution-sha256-sum 038794feef1f4745c6347107b6726279d1c824f3fc634b60f86ace1e9fbd1768' + - '"', - options: { cwd: '/tmp/github/some/repo' }, - }, - ]); - }); + ]); + expect(execSnapshots).toMatchObject([ + { cmd: 'docker pull renovate/sidecar' }, + { cmd: 'docker ps --filter name=renovate_sidecar -aq' }, + { + cmd: + 'docker run --rm --name=renovate_sidecar --label=renovate_child ' + + '-v "/tmp/github/some/repo":"/tmp/github/some/repo" ' + + '-v "/tmp/cache":"/tmp/cache" ' + + '-e GRADLE_OPTS ' + + '-e BUILDPACK_CACHE_DIR ' + + '-w "/tmp/github/some/repo" ' + + 'renovate/sidecar' + + ' bash -l -c "' + + 'install-tool java 11.0.1' + + ' && ' + + './gradlew wrapper --gradle-distribution-url https://services.gradle.org/distributions/gradle-6.3-bin.zip --gradle-distribution-sha256-sum 038794feef1f4745c6347107b6726279d1c824f3fc634b60f86ace1e9fbd1768' + + '"', + options: { cwd: '/tmp/github/some/repo' }, + }, + ]); + }); - it('updates distributionSha256Sum (install)', async () => { - const execSnapshots = mockExecAll(); - httpMock - .scope('https://services.gradle.org') - .get('/distributions/gradle-6.3-bin.zip.sha256') - .reply( - 200, - '038794feef1f4745c6347107b6726279d1c824f3fc634b60f86ace1e9fbd1768' + it('updates distributionSha256Sum (install)', async () => { + const execSnapshots = mockExecAll(); + httpMock + .scope('https://services.gradle.org') + .get('/distributions/gradle-6.3-bin.zip.sha256') + .reply( + 200, + '038794feef1f4745c6347107b6726279d1c824f3fc634b60f86ace1e9fbd1768' + ); + git.getRepoStatus.mockResolvedValueOnce( + partial<StatusResult>({ + modified: ['gradle/wrapper/gradle-wrapper.properties'], + }) ); - git.getRepoStatus.mockResolvedValueOnce( - partial<StatusResult>({ - modified: ['gradle/wrapper/gradle-wrapper.properties'], - }) - ); - GlobalConfig.set({ ...adminConfig, binarySource: 'install' }); + GlobalConfig.set({ ...adminConfig, binarySource: 'install' }); - const result = await updateArtifacts({ - packageFileName: 'gradle/wrapper/gradle-wrapper.properties', - updatedDeps: [], - newPackageFileContent: `distributionSha256Sum=336b6898b491f6334502d8074a6b8c2d73ed83b92123106bd4bf837f04111043\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-6.3-bin.zip`, - config, - }); + const result = await updateArtifacts({ + packageFileName: 'gradle/wrapper/gradle-wrapper.properties', + updatedDeps: [], + newPackageFileContent: `distributionSha256Sum=336b6898b491f6334502d8074a6b8c2d73ed83b92123106bd4bf837f04111043\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-6.3-bin.zip`, + config, + }); - expect(result).toEqual([ - { - file: { - contents: 'test', - path: 'gradle/wrapper/gradle-wrapper.properties', - type: 'addition', + expect(result).toEqual([ + { + file: { + contents: 'test', + path: 'gradle/wrapper/gradle-wrapper.properties', + type: 'addition', + }, }, - }, - ]); - expect(execSnapshots).toMatchObject([ - { cmd: 'install-tool java 11.0.1' }, - { - cmd: './gradlew wrapper --gradle-distribution-url https://services.gradle.org/distributions/gradle-6.3-bin.zip --gradle-distribution-sha256-sum 038794feef1f4745c6347107b6726279d1c824f3fc634b60f86ace1e9fbd1768', - options: { cwd: '/tmp/github/some/repo' }, - }, - ]); - }); - - it('distributionSha256Sum 404', async () => { - const execSnapshots = mockExecAll(); - httpMock - .scope('https://services.gradle.org') - .get('/distributions/gradle-6.3-bin.zip.sha256') - .reply(404); - - const result = await updateArtifacts({ - packageFileName: 'gradle/wrapper/gradle-wrapper.properties', - updatedDeps: [], - newPackageFileContent: `distributionSha256Sum=336b6898b491f6334502d8074a6b8c2d73ed83b92123106bd4bf837f04111043\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-6.3-bin.zip`, - config, + ]); + expect(execSnapshots).toMatchObject([ + { cmd: 'install-tool java 11.0.1' }, + { + cmd: './gradlew wrapper --gradle-distribution-url https://services.gradle.org/distributions/gradle-6.3-bin.zip --gradle-distribution-sha256-sum 038794feef1f4745c6347107b6726279d1c824f3fc634b60f86ace1e9fbd1768', + options: { cwd: '/tmp/github/some/repo' }, + }, + ]); }); - expect(result).toEqual([ - { - artifactError: { - lockFile: 'gradle/wrapper/gradle-wrapper.properties', - stderr: 'Response code 404 (Not Found)', + it('distributionSha256Sum 404', async () => { + const execSnapshots = mockExecAll(); + httpMock + .scope('https://services.gradle.org') + .get('/distributions/gradle-6.3-bin.zip.sha256') + .reply(404); + + const result = await updateArtifacts({ + packageFileName: 'gradle/wrapper/gradle-wrapper.properties', + updatedDeps: [], + newPackageFileContent: `distributionSha256Sum=336b6898b491f6334502d8074a6b8c2d73ed83b92123106bd4bf837f04111043\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-6.3-bin.zip`, + config, + }); + + expect(result).toEqual([ + { + artifactError: { + lockFile: 'gradle/wrapper/gradle-wrapper.properties', + stderr: 'Response code 404 (Not Found)', + }, }, - }, - ]); - expect(execSnapshots).toBeEmptyArray(); - }); + ]); + expect(execSnapshots).toBeEmptyArray(); + }); + + it('handles gradle-wrapper in subdirectory', async () => { + const execSnapshots = mockExecAll(); + git.getRepoStatus.mockResolvedValue( + partial<StatusResult>({ + modified: [ + 'sub/gradle/wrapper/gradle-wrapper.properties', + 'sub/gradlew', + 'sub/gradlew.bat', + ], + }) + ); - it('handles gradle-wrapper in subdirectory', async () => { - const execSnapshots = mockExecAll(); - git.getRepoStatus.mockResolvedValue( - partial<StatusResult>({ - modified: [ + 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', + }, + }, + }, + ]); + }); + }); - 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' }, + describe('updateBuildFile()', () => { + it('updates wrapper configuration in gradle build file', async () => { + fs.readLocalFile.mockResolvedValueOnce(` + tasks.named("wrapper", Wrapper::class) { + gradleVersion = '5.6.2' + distributionSha256Sum="027fdd265d277bae65a0d349b6b8da02135b0b8e14ba891e26281fa877fe37a2" + distributionUrl = "https://services.gradle.org/distributions/gradle-5.6.2-bin.zip" + }`); + + fs.writeLocalFile.mockImplementationOnce( + (fileName: string, fileContent: string | Buffer): Promise<void> => { + expect(fileContent).toBe(` + tasks.named("wrapper", Wrapper::class) { + gradleVersion = '6.3' + distributionSha256Sum="038794feef1f4745c6347107b6726279d1c824f3fc634b60f86ace1e9fbd1768" + distributionUrl = "https://services.gradle.org/distributions/gradle-6.3-bin.zip" + }`); + return Promise.resolve(); + } + ); + + const res = await updateBuildFile('', { + gradleVersion: '6.3', + distributionSha256Sum: + '038794feef1f4745c6347107b6726279d1c824f3fc634b60f86ace1e9fbd1768', + distributionUrl: + 'https://services.gradle.org/distributions/gradle-6.3-bin.zip', + }); + expect(res).toBe('build.gradle.kts'); }); - 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', - }, - }, - }, - ]); + it('gradle build file update skips missing distributionSha256Sum property', async () => { + fs.localPathExists.mockResolvedValueOnce(true); + fs.readLocalFile.mockResolvedValueOnce(` + wrapper { + gradleVersion = '5.6.2' + distributionUrl = "https://services.gradle.org/distributions/gradle-$gradleVersion-all.zip" + }`); + + fs.writeLocalFile.mockImplementationOnce( + (fileName: string, fileContent: string | Buffer): Promise<void> => { + expect(fileContent).toBe(` + wrapper { + gradleVersion = '6.3' + distributionUrl = "https://services.gradle.org/distributions/gradle-$gradleVersion-all.zip" + }`); + return Promise.resolve(); + } + ); + + const res = await updateBuildFile('', { + gradleVersion: '6.3', + distributionSha256Sum: null, + distributionUrl: + 'https://services.gradle.org/distributions/gradle-6.3-bin.zip', + }); + expect(res).toBe('build.gradle'); + }); + + it('gradle build file update returns early if file not found', async () => { + fs.readLocalFile.mockResolvedValueOnce(null); + + const res = await updateBuildFile('', { + gradleVersion: '6.3', + distributionSha256Sum: + '038794feef1f4745c6347107b6726279d1c824f3fc634b60f86ace1e9fbd1768', + distributionUrl: + 'https://services.gradle.org/distributions/gradle-6.3-bin.zip', + }); + expect(logger.logger.debug).toHaveBeenCalledWith( + 'build.gradle or build.gradle.kts not found' + ); + expect(res).toBe('build.gradle.kts'); + }); }); }); diff --git a/lib/modules/manager/gradle-wrapper/artifacts.ts b/lib/modules/manager/gradle-wrapper/artifacts.ts index 442531e996c093ee344b5f6a43d5846e0ad37274..ccac69ae2da9b12babcfbd0aaa21cdcd94e00466 100644 --- a/lib/modules/manager/gradle-wrapper/artifacts.ts +++ b/lib/modules/manager/gradle-wrapper/artifacts.ts @@ -1,15 +1,21 @@ import is from '@sindresorhus/is'; +import { lang, query as q } from 'good-enough-parser'; 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'; import type { ExecOptions } from '../../../util/exec/types'; -import { readLocalFile, writeLocalFile } from '../../../util/fs'; +import { + localPathExists, + readLocalFile, + writeLocalFile, +} from '../../../util/fs'; import { getRepoStatus } from '../../../util/git'; import type { StatusResult } from '../../../util/git/types'; import { Http } from '../../../util/http'; import { newlineRegex } from '../../../util/regex'; +import { replaceAt } from '../../../util/string'; import type { UpdateArtifact, UpdateArtifactsResult } from '../types'; import { extraEnv, @@ -19,6 +25,9 @@ import { } from './utils'; const http = new Http('gradle-wrapper'); +const groovy = lang.createLang('groovy'); + +type Ctx = string[]; async function addIfUpdated( status: StatusResult, @@ -53,6 +62,51 @@ async function getDistributionChecksum(url: string): Promise<string> { return body; } +export async function updateBuildFile( + localGradleDir: string, + wrapperProperties: Record<string, string | undefined | null> +): Promise<string> { + let buildFileName = join(localGradleDir, 'build.gradle'); + if (!(await localPathExists(buildFileName))) { + buildFileName = join(localGradleDir, 'build.gradle.kts'); + } + + const buildFileContent = await readLocalFile(buildFileName, 'utf8'); + if (!buildFileContent) { + logger.debug('build.gradle or build.gradle.kts not found'); + return buildFileName; + } + + let buildFileUpdated = buildFileContent; + for (const [propertyName, newValue] of Object.entries(wrapperProperties)) { + if (!newValue) { + continue; + } + + const query = q.tree({ + type: 'wrapped-tree', + maxDepth: 1, + search: q + .sym<Ctx>(propertyName) + .op('=') + .str((ctx, { value, offset }) => { + buildFileUpdated = replaceAt( + buildFileUpdated, + offset, + value, + newValue + ); + return ctx; + }), + }); + groovy.query(buildFileUpdated, query, []); + } + + await writeLocalFile(buildFileName, buildFileUpdated); + + return buildFileName; +} + export async function updateArtifacts({ packageFileName, newPackageFileContent, @@ -70,12 +124,14 @@ export async function updateArtifacts({ return null; } cmd += ' wrapper'; + + let checksum: string | null = null; const distributionUrl = getDistributionUrl(newPackageFileContent); if (distributionUrl) { cmd += ` --gradle-distribution-url ${distributionUrl}`; if (newPackageFileContent.includes('distributionSha256Sum=')) { //update checksum in case of distributionSha256Sum in properties then run wrapper - const checksum = await getDistributionChecksum(distributionUrl); + checksum = await getDistributionChecksum(distributionUrl); await writeLocalFile( packageFileName, newPackageFileContent.replace( @@ -115,18 +171,21 @@ export async function updateArtifacts({ 'Error executing gradle wrapper update command. It can be not a critical one though.' ); } + + const buildFileName = await updateBuildFile(localGradleDir, { + gradleVersion: config.newValue, + distributionSha256Sum: checksum, + distributionUrl, + }); + const status = await getRepoStatus(); const artifactFileNames = [ - 'gradle/wrapper/gradle-wrapper.properties', - 'gradle/wrapper/gradle-wrapper.jar', - 'gradlew', - 'gradlew.bat', - ].map( - (filename) => - packageFileName - .replace('gradle/wrapper/', '') - .replace('gradle-wrapper.properties', '') + filename - ); + packageFileName, + buildFileName, + ...['gradle/wrapper/gradle-wrapper.jar', 'gradlew', 'gradlew.bat'].map( + (filename) => join(localGradleDir, filename) + ), + ]; const updateArtifactsResult = ( await Promise.all( artifactFileNames.map((fileProjectPath) =>