From 1304bc930e63640037f6df946d207e6bae0caddd Mon Sep 17 00:00:00 2001 From: Rhys Arkins <rhys@arkins.net> Date: Fri, 21 May 2021 21:51:03 +0200 Subject: [PATCH] feat: validate git version (#9979) --- docs/development/local-development.md | 2 +- lib/util/git/index.spec.ts | 6 +++++ lib/util/git/index.ts | 36 +++++++++++++++++++++++++++ lib/workers/global/initialize.spec.ts | 20 +++++++++++++++ lib/workers/global/initialize.ts | 9 +++++++ 5 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 lib/workers/global/initialize.spec.ts diff --git a/docs/development/local-development.md b/docs/development/local-development.md index 75c10b72ea..a35a7f5fa6 100644 --- a/docs/development/local-development.md +++ b/docs/development/local-development.md @@ -10,7 +10,7 @@ For example, if you think anything is unclear, or you think something needs to b You need the following dependencies for local development: -- Git +- Git `>= 1.22.0` - Node.js `>=14.15.4` - Yarn `^1.22.5` - C++ compiler diff --git a/lib/util/git/index.spec.ts b/lib/util/git/index.spec.ts index 4c7a231b94..d12876c280 100644 --- a/lib/util/git/index.spec.ts +++ b/lib/util/git/index.spec.ts @@ -95,6 +95,12 @@ describe(getName(), () => { 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 0acf7e4fe7..e1b0acb506 100644 --- a/lib/util/git/index.ts +++ b/lib/util/git/index.ts @@ -23,6 +23,7 @@ import { import { logger } from '../../logger'; import { ExternalHostError } from '../../types/errors/external-host-error'; import { GitOptions, GitProtocol } from '../../types/git'; +import { api as semver } from '../../versioning/semver'; import { Limit, incLimitedValue } from '../../workers/global/limits'; import { GitNoVerifyOption, getNoVerify } from './config'; import { configSigningKey, writePrivateKey } from './private-key'; @@ -145,6 +146,41 @@ let gitInitialized: boolean; let privateKeySet = false; +export const GIT_MINIMUM_VERSION = '2.22.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 (semver.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 || + semver.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 0000000000..bfbcc3ee7c --- /dev/null +++ b/lib/workers/global/initialize.spec.ts @@ -0,0 +1,20 @@ +import { getName, mocked } from '../../../test/util'; +import * as _git from '../../util/git'; +import { checkVersions } from './initialize'; + +jest.mock('../../util/git'); + +const git = mocked(_git); + +describe(getName(), () => { + describe('checkVersions()', () => { + it('throws if invalid version', async () => { + git.validateGitVersion.mockResolvedValueOnce(false); + await expect(checkVersions()).rejects.toThrow(); + }); + it('returns if valid git version', async () => { + git.validateGitVersion.mockResolvedValueOnce(true); + await expect(checkVersions()).toResolve(); + }); + }); +}); diff --git a/lib/workers/global/initialize.ts b/lib/workers/global/initialize.ts index 4f1e3286ce..c80dc0ea7f 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: GlobalConfig): Promise<GlobalConfig> { @@ -34,10 +35,18 @@ function limitCommitsPerRun(config: RenovateConfig): void { setMaxLimit(Limit.Commits, limit); } +export 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); -- GitLab