diff --git a/lib/modules/manager/maven-wrapper/artifacts.spec.ts b/lib/modules/manager/maven-wrapper/artifacts.spec.ts index cb340197f27b1fb20ea8f92b701f75f677562180..672b14172801c78243dbbca3bd67ea8556c0461b 100644 --- a/lib/modules/manager/maven-wrapper/artifacts.spec.ts +++ b/lib/modules/manager/maven-wrapper/artifacts.spec.ts @@ -308,4 +308,121 @@ describe('modules/manager/maven-wrapper/artifacts', () => { }, ]); }); + + it('should run wrapper:wrapper with MVNW_REPOURL if it is a custom artifactory', async () => { + const execSnapshots = mockExecAll({ stdout: '', stderr: '' }); + mockMavenFileChangedInGit(); + await updateArtifacts({ + packageFileName: 'maven-wrapper', + newPackageFileContent: '', + updatedDeps: [ + { + depName: 'maven-wrapper', + replaceString: + 'https://internal.local/maven-public/org/apache/maven/wrapper/maven-wrapper/3.0.0/maven-wrapper-3.0.0.jar', + }, + ], + config: { currentValue: '3.0.0', newValue: '3.3.1' }, + }); + + expect(execSnapshots).toMatchObject([ + { + cmd: './mvnw wrapper:wrapper', + options: { + cwd: '/tmp/github', + encoding: 'utf-8', + env: { + HOME: '/home/user', + HTTPS_PROXY: 'https://example.com', + HTTP_PROXY: 'http://example.com', + LANG: 'en_US.UTF-8', + LC_ALL: 'en_US', + NO_PROXY: 'localhost', + PATH: '/tmp/path', + MVNW_REPOURL: 'https://internal.local/maven-public', + }, + maxBuffer: 10485760, + timeout: 900000, + }, + }, + ]); + }); + + it('should run not include MVNW_REPOURL when run with default maven repo url', async () => { + const execSnapshots = mockExecAll({ stdout: '', stderr: '' }); + mockMavenFileChangedInGit(); + await updateArtifacts({ + packageFileName: 'maven-wrapper', + newPackageFileContent: '', + updatedDeps: [ + { + depName: 'maven-wrapper', + replaceString: + 'https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar', + }, + ], + config: { currentValue: '3.0.0', newValue: '3.3.1' }, + }); + + expect(execSnapshots).toMatchObject([ + { + cmd: './mvnw wrapper:wrapper', + options: { + cwd: '/tmp/github', + encoding: 'utf-8', + env: { + HOME: '/home/user', + HTTPS_PROXY: 'https://example.com', + HTTP_PROXY: 'http://example.com', + LANG: 'en_US.UTF-8', + LC_ALL: 'en_US', + NO_PROXY: 'localhost', + PATH: '/tmp/path', + }, + maxBuffer: 10485760, + timeout: 900000, + }, + }, + ]); + expect(execSnapshots[0]!.options!.env).not.toHaveProperty('MVNW_REPOURL'); + }); + + it('should run not include MVNW_REPOURL when run with a malformed replaceString', async () => { + const execSnapshots = mockExecAll({ stdout: '', stderr: '' }); + mockMavenFileChangedInGit(); + await updateArtifacts({ + packageFileName: 'maven-wrapper', + newPackageFileContent: '', + updatedDeps: [ + { + depName: 'maven-wrapper', + replaceString: 'not a good url', + }, + ], + config: { currentValue: '3.0.0', newValue: '3.3.1' }, + }); + + expect(execSnapshots).toMatchObject([ + { + cmd: './mvnw wrapper:wrapper', + options: { + cwd: '/tmp/github', + encoding: 'utf-8', + env: { + HOME: '/home/user', + HTTPS_PROXY: 'https://example.com', + HTTP_PROXY: 'http://example.com', + LANG: 'en_US.UTF-8', + LC_ALL: 'en_US', + NO_PROXY: 'localhost', + PATH: '/tmp/path', + }, + maxBuffer: 10485760, + timeout: 900000, + }, + }, + ]); + + expect(execSnapshots[0]!.options!.env).not.toHaveProperty('MVNW_REPOURL'); + }); }); diff --git a/lib/modules/manager/maven-wrapper/artifacts.ts b/lib/modules/manager/maven-wrapper/artifacts.ts index 38c319a7353222e042929faa635d2eec12c312bd..61a2adc969106779a9cef5f4c12d7f96cc95a10e 100644 --- a/lib/modules/manager/maven-wrapper/artifacts.ts +++ b/lib/modules/manager/maven-wrapper/artifacts.ts @@ -5,17 +5,20 @@ import { dirname, join } from 'upath'; import { GlobalConfig } from '../../../config/global'; import { logger } from '../../../logger'; import { exec } from '../../../util/exec'; -import type { ExecOptions } from '../../../util/exec/types'; +import type { ExecOptions, ExtraEnv } from '../../../util/exec/types'; import { chmodLocalFile, readLocalFile, statLocalFile } from '../../../util/fs'; import { getRepoStatus } from '../../../util/git'; import type { StatusResult } from '../../../util/git/types'; +import { regEx } from '../../../util/regex'; import mavenVersioning from '../../versioning/maven'; import type { + PackageDependency, UpdateArtifact, UpdateArtifactsConfig, UpdateArtifactsResult, } from '../types'; +const DEFAULT_MAVEN_REPO_URL = 'https://repo.maven.apache.org/maven2'; interface MavenWrapperPaths { wrapperExecutableFileName: string; localProjectDir: string; @@ -60,7 +63,9 @@ export async function updateArtifacts({ logger.info('No mvnw found - skipping Artifacts update'); return null; } - await executeWrapperCommand(cmd, config, packageFileName); + + const extraEnv = getExtraEnvOptions(updatedDeps); + await executeWrapperCommand(cmd, config, packageFileName, extraEnv); const status = await getRepoStatus(); const artifactFileNames = [ @@ -133,13 +138,16 @@ export function getJavaConstraint( async function executeWrapperCommand( cmd: string, config: UpdateArtifactsConfig, - packageFileName: string + packageFileName: string, + extraEnv: ExtraEnv ): Promise<void> { logger.debug(`Updating maven wrapper: "${cmd}"`); const { wrapperFullyQualifiedPath } = getMavenPaths(packageFileName); + const execOptions: ExecOptions = { cwdFile: wrapperFullyQualifiedPath, docker: {}, + extraEnv, toolConstraints: [ { toolName: 'java', @@ -157,6 +165,36 @@ async function executeWrapperCommand( } } +function getExtraEnvOptions(deps: PackageDependency[]): ExtraEnv { + const customMavenWrapperUrl = getCustomMavenWrapperRepoUrl(deps); + if (customMavenWrapperUrl) { + return { MVNW_REPOURL: customMavenWrapperUrl }; + } + return {}; +} + +function getCustomMavenWrapperRepoUrl( + deps: PackageDependency[] +): string | null { + const replaceString = deps.find( + (dep) => dep.depName === 'maven-wrapper' + )?.replaceString; + + if (!replaceString) { + return null; + } + + const match = regEx(/^(.*?)\/org\/apache\/maven\/wrapper\//).exec( + replaceString + ); + + if (!match) { + return null; + } + + return match[1] === DEFAULT_MAVEN_REPO_URL ? null : match[1]; +} + async function createWrapperCommand( packageFileName: string ): Promise<string | null> {