diff --git a/lib/util/git/index.spec.ts b/lib/util/git/index.spec.ts index 23dfe76acf5a0f3ed2938c9658510a5c2b55e221..1b4e1282193ee7060cd701387816c5746aaaf58f 100644 --- a/lib/util/git/index.spec.ts +++ b/lib/util/git/index.spec.ts @@ -94,6 +94,13 @@ describe('util/git/index', () => { await base.cleanup(); }); + describe('validateGitVersion()', () => { + it('has a git version greater or equal to the minimum required', async () => { + const res = await git.validateGitVersion(); + expect(res).toBeTrue(); + }); + }); + describe('checkoutBranch(branchName)', () => { it('sets the base branch as master', async () => { await expect(git.checkoutBranch(defaultBranch)).resolves.not.toThrow(); diff --git a/lib/util/git/index.ts b/lib/util/git/index.ts index 58f5450373eef1e28815e19b8dd63e564bd6aa3c..c9130d17189973dc4e4167340665bb966b14fda9 100644 --- a/lib/util/git/index.ts +++ b/lib/util/git/index.ts @@ -16,6 +16,7 @@ import { import { logger } from '../../logger'; import { ExternalHostError } from '../../types/errors/external-host-error'; import type { GitProtocol } from '../../types/git'; +import { api as semverCoerced } from '../../versioning/semver-coerced'; import { Limit, incLimitedValue } from '../../workers/global/limits'; import { regEx } from '../regex'; import { parseGitAuthor } from './author'; @@ -143,6 +144,41 @@ let gitInitialized: boolean; let privateKeySet = false; +export const GIT_MINIMUM_VERSION = '2.33.0'; // git show-current + +export async function validateGitVersion(): Promise<boolean> { + let version: string; + const globalGit = Git(); + try { + const raw = await globalGit.raw(['--version']); + for (const section of raw.split(/\s+/)) { + if (semverCoerced.isVersion(section)) { + version = section; + break; + } + } + } catch (err) /* istanbul ignore next */ { + logger.error({ err }, 'Error fetching git version'); + return false; + } + // istanbul ignore if + if ( + !( + version && + (version === GIT_MINIMUM_VERSION || + semverCoerced.isGreaterThan(version, GIT_MINIMUM_VERSION)) + ) + ) { + logger.error( + { detectedVersion: version, minimumVersion: GIT_MINIMUM_VERSION }, + 'Git version needs upgrading' + ); + return false; + } + logger.debug(`Found valid git version: ${version}`); + return true; +} + async function fetchBranchCommits(): Promise<void> { config.branchCommits = {}; const opts = ['ls-remote', '--heads', config.url]; diff --git a/lib/workers/global/initialize.spec.ts b/lib/workers/global/initialize.spec.ts new file mode 100644 index 0000000000000000000000000000000000000000..27df1dca77973add94657f50e0f97ae191e5627c --- /dev/null +++ b/lib/workers/global/initialize.spec.ts @@ -0,0 +1,21 @@ +import { git } from '../../../test/util'; +import type { RenovateConfig } from '../../config/types'; +import { globalInitialize } from './initialize'; + +jest.mock('../../util/git'); + +describe('workers/global/initialize', () => { + describe('checkVersions()', () => { + it('throws if invalid version', async () => { + const config: RenovateConfig = {}; + git.validateGitVersion.mockResolvedValueOnce(false); + await expect(globalInitialize(config)).rejects.toThrow(); + }); + + it('returns if valid git version', async () => { + const config: RenovateConfig = {}; + git.validateGitVersion.mockResolvedValueOnce(true); + await expect(globalInitialize(config)).toResolve(); + }); + }); +}); diff --git a/lib/workers/global/initialize.ts b/lib/workers/global/initialize.ts index c82fc237bbd24c6c03dd94b95d1e3aa5689d4fa0..fa374d1a5ac0bfa3a58fe464ccfbb5864110f62c 100644 --- a/lib/workers/global/initialize.ts +++ b/lib/workers/global/initialize.ts @@ -6,6 +6,7 @@ import { logger } from '../../logger'; import { initPlatform } from '../../platform'; import * as packageCache from '../../util/cache/package'; import { setEmojiConfig } from '../../util/emoji'; +import { validateGitVersion } from '../../util/git'; import { Limit, setMaxLimit } from './limits'; async function setDirectories(input: AllConfig): Promise<AllConfig> { @@ -34,10 +35,18 @@ function limitCommitsPerRun(config: RenovateConfig): void { setMaxLimit(Limit.Commits, limit); } +async function checkVersions(): Promise<void> { + const validGitVersion = await validateGitVersion(); + if (!validGitVersion) { + throw new Error('Init: git version needs upgrading'); + } +} + export async function globalInitialize( config_: RenovateConfig ): Promise<RenovateConfig> { let config = config_; + await checkVersions(); config = await initPlatform(config); config = await setDirectories(config); packageCache.init(config);