diff --git a/docs/development/local-development.md b/docs/development/local-development.md index faba5746bc2341..4d848f83163f63 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 `>=2.22.0` +- Git `>=2.33.0` - Node.js `>=14.15.4` - Yarn `^1.22.5` - C++ compiler diff --git a/docs/usage/getting-started/running.md b/docs/usage/getting-started/running.md index 9831beb5f65b98..9b33176075447c 100644 --- a/docs/usage/getting-started/running.md +++ b/docs/usage/getting-started/running.md @@ -27,6 +27,8 @@ Therefore if you need Renovate to support any non-npm lock files like Bundler th The `renovate` npm package is compatible with all of Renovate's supported platforms. +Renovate requires Node.js >=14.15.0 as well as Git >=2.33.0. + #### Docker image The `renovate` npm package is also distributed via pre-built Node.js images on Docker Hub (`renovate/renovate`). diff --git a/lib/util/git/index.spec.ts b/lib/util/git/index.spec.ts index 36a3136e7453b0..d7412b37208283 100644 --- a/lib/util/git/index.spec.ts +++ b/lib/util/git/index.spec.ts @@ -75,7 +75,7 @@ describe('util/git/index', () => { await git.initRepo({ url: origin.path, }); - await git.setUserRepoConfig({ branchPrefix: 'renovate/' }); + git.setUserRepoConfig({ branchPrefix: 'renovate/' }); git.setGitAuthor('Jest '); setNoVerify([]); await git.syncGit(); @@ -159,7 +159,7 @@ describe('util/git/index', () => { expect(await git.isBranchModified('renovate/future_branch')).toBe(false); }); it('should return false when author is ignored', async () => { - await git.setUserRepoConfig({ + git.setUserRepoConfig({ gitIgnoredAuthors: ['custom@example.com'], }); expect(await git.isBranchModified('renovate/custom_author')).toBe(false); @@ -494,7 +494,7 @@ describe('util/git/index', () => { url: base.path, }); - await git.setUserRepoConfig({ branchPrefix: 'renovate/' }); + git.setUserRepoConfig({ branchPrefix: 'renovate/' }); expect(git.branchExists('renovate/test')).toBe(true); await git.initRepo({ @@ -504,7 +504,7 @@ describe('util/git/index', () => { await repo.checkout('renovate/test'); await repo.commit('past message3', ['--amend']); - await git.setUserRepoConfig({ branchPrefix: 'renovate/' }); + git.setUserRepoConfig({ branchPrefix: 'renovate/' }); expect(git.branchExists('renovate/test')).toBe(true); }); diff --git a/lib/util/git/index.ts b/lib/util/git/index.ts index 7a674036c68c5e..a0faf92734787a 100644 --- a/lib/util/git/index.ts +++ b/lib/util/git/index.ts @@ -53,7 +53,6 @@ interface LocalConfig extends StorageConfig { currentBranchSha: string; branchCommits: Record; branchIsModified: Record; - branchPrefix: string; ignoredAuthors: string[]; gitAuthorName?: string; gitAuthorEmail?: string; @@ -215,25 +214,6 @@ async function cleanLocalBranches(): Promise { } } -/* - * When we initially clone, we clone only the default branch so how no knowledge of other branches existing. - * By calling this function once the repo's branchPrefix is known, we can fetch all of Renovate's branches in one command. - */ -async function setBranchPrefix(branchPrefix: string): Promise { - config.branchPrefix = branchPrefix; - // If the repo is already cloned then set branchPrefix now, otherwise it will be called again during syncGit() - if (gitInitialized) { - logger.debug('Setting branchPrefix: ' + branchPrefix); - const ref = `refs/heads/${branchPrefix}*:refs/remotes/origin/${branchPrefix}*`; - try { - await git.fetch(['origin', ref, '--depth=5', '--force']); - } catch (err) /* istanbul ignore next */ { - checkForPlatformFailure(err); - throw err; - } - } -} - export function setGitAuthor(gitAuthor: string): void { const gitAuthorParsed = parseGitAuthor( gitAuthor || 'Renovate Bot ' @@ -270,12 +250,10 @@ export async function writeGitAuthor(): Promise { } } -export async function setUserRepoConfig({ - branchPrefix, +export function setUserRepoConfig({ gitIgnoredAuthors, gitAuthor, -}: RenovateConfig): Promise { - await setBranchPrefix(branchPrefix); +}: RenovateConfig): void { config.ignoredAuthors = gitIgnoredAuthors ?? []; setGitAuthor(gitAuthor); } @@ -316,7 +294,7 @@ export async function syncGit(): Promise { await resetToBranch(await getDefaultBranch(git)); const fetchStart = Date.now(); await git.pull(); - await git.fetch(['--depth=10']); + await git.fetch(); config.currentBranch = config.currentBranch || (await getDefaultBranch(git)); await resetToBranch(config.currentBranch); @@ -336,8 +314,8 @@ export async function syncGit(): Promise { await fs.emptyDir(localDir); const cloneStart = Date.now(); try { - // clone only the default branch - const opts = ['--depth=10']; + // blobless clone + const opts = ['--filter=blob:none']; if (config.extraCloneOpts) { Object.entries(config.extraCloneOpts).forEach((e) => opts.push(e[0], `${e[1]}`) @@ -383,9 +361,6 @@ export async function syncGit(): Promise { logger.warn({ err }, 'Cannot retrieve latest commit'); } config.currentBranch = config.currentBranch || (await getDefaultBranch(git)); - if (config.branchPrefix) { - await setBranchPrefix(config.branchPrefix); - } } // istanbul ignore next @@ -394,24 +369,6 @@ export async function getRepoStatus(): Promise { return git.status(); } -async function syncBranch(branchName: string): Promise { - await syncGit(); - if (branchName.startsWith(config.branchPrefix)) { - return; - } - if (config.additionalBranches.includes(branchName)) { - return; - } - config.additionalBranches.push(branchName); - // fetch the branch only if it's not part of the existing branchPrefix - try { - await git.raw(['remote', 'set-branches', '--add', 'origin', branchName]); - await git.fetch(['origin', branchName, '--depth=5']); - } catch (err) /* istanbul ignore next */ { - checkForPlatformFailure(err); - } -} - export function branchExists(branchName: string): boolean { return !!config.branchCommits[branchName]; } @@ -447,7 +404,7 @@ export async function getCommitMessages(): Promise { export async function checkoutBranch(branchName: string): Promise { logger.debug(`Setting current branch to ${branchName}`); - await syncBranch(branchName); + await syncGit(); try { config.currentBranch = branchName; config.currentBranchSha = ( @@ -506,7 +463,7 @@ export function getBranchList(): string[] { } export async function isBranchStale(branchName: string): Promise { - await syncBranch(branchName); + await syncGit(); try { const { currentBranchSha, currentBranch } = config; const branches = await git.branch([ @@ -528,7 +485,7 @@ export async function isBranchStale(branchName: string): Promise { } export async function isBranchModified(branchName: string): Promise { - await syncBranch(branchName); + await syncGit(); // First check cache if (config.branchIsModified[branchName] !== undefined) { return config.branchIsModified[branchName]; @@ -580,7 +537,7 @@ export async function isBranchModified(branchName: string): Promise { } export async function deleteBranch(branchName: string): Promise { - await syncBranch(branchName); + await syncGit(); try { await git.raw(['push', '--delete', 'origin', branchName]); logger.debug({ branchName }, 'Deleted remote branch'); @@ -602,7 +559,7 @@ export async function deleteBranch(branchName: string): Promise { export async function mergeBranch(branchName: string): Promise { let status; try { - await syncBranch(branchName); + await syncGit(); await git.reset(ResetMode.HARD); await git.checkout(['-B', branchName, 'origin/' + branchName]); await git.checkout([ @@ -633,7 +590,7 @@ export async function mergeBranch(branchName: string): Promise { export async function getBranchLastCommitTime( branchName: string ): Promise { - await syncBranch(branchName); + await syncGit(); try { const time = await git.show(['-s', '--format=%ai', 'origin/' + branchName]); return new Date(Date.parse(time)); @@ -644,7 +601,7 @@ export async function getBranchLastCommitTime( } export async function getBranchFiles(branchName: string): Promise { - await syncBranch(branchName); + await syncGit(); try { const diff = await git.diffSummary([ `origin/${branchName}`, @@ -675,7 +632,7 @@ export async function getFile( } export async function hasDiff(branchName: string): Promise { - await syncBranch(branchName); + await syncGit(); try { return (await git.diff(['HEAD', branchName])) !== ''; } catch (err) { @@ -816,7 +773,7 @@ export async function commitFiles({ logger.debug({ result: pushRes }, 'git push'); // Fetch it after create const ref = `refs/heads/${branchName}:refs/remotes/origin/${branchName}`; - await git.fetch(['origin', ref, '--depth=5', '--force']); + await git.fetch(['origin', ref, '--force']); config.branchCommits[branchName] = ( await git.revparse([branchName]) ).trim(); diff --git a/lib/workers/repository/init/index.ts b/lib/workers/repository/init/index.ts index b3584ee83b916a..62c292ad1f2884 100644 --- a/lib/workers/repository/init/index.ts +++ b/lib/workers/repository/init/index.ts @@ -32,7 +32,7 @@ export async function initRepo( checkIfConfigured(config); warnOnUnsupportedOptions(config); config = applySecretsToConfig(config); - await setUserRepoConfig(config); + setUserRepoConfig(config); config = await detectVulnerabilityAlerts(config); // istanbul ignore if if (config.printConfig) {