From 516762ab693041918d221f6ebc3118fec2fdbc4c Mon Sep 17 00:00:00 2001 From: Markus Schulz Date: Tue, 29 Nov 2022 16:20:17 +0100 Subject: [PATCH] refactor: Move all Git commands behind a PlatformScm interface #19065 this is a proof of concept only... --- lib/modules/platform/gerrit/index.ts | 95 ++++++++++++++++--- lib/modules/platform/gerrit/scm.ts | 19 ++++ lib/modules/platform/gerrit/types.ts | 3 +- lib/modules/platform/index.ts | 2 + lib/modules/platform/scm.ts | 33 +++++++ lib/modules/platform/types.ts | 9 ++ lib/util/git/index.ts | 12 +-- lib/workers/repository/cache.ts | 14 +-- .../config-migration/branch/rebase.ts | 9 +- lib/workers/repository/finalise/prune.ts | 13 +-- .../repository/onboarding/branch/rebase.ts | 14 +-- lib/workers/repository/onboarding/pr/index.ts | 12 +-- lib/workers/repository/update/branch/index.ts | 7 +- lib/workers/repository/update/branch/reuse.ts | 16 ++-- lib/workers/repository/update/pr/automerge.ts | 12 +-- 15 files changed, 191 insertions(+), 79 deletions(-) create mode 100644 lib/modules/platform/gerrit/scm.ts create mode 100644 lib/modules/platform/scm.ts diff --git a/lib/modules/platform/gerrit/index.ts b/lib/modules/platform/gerrit/index.ts index e92a0f21fddb943..1d223f21b68bda4 100644 --- a/lib/modules/platform/gerrit/index.ts +++ b/lib/modules/platform/gerrit/index.ts @@ -160,14 +160,14 @@ export async function initRepo({ continue; } const currentGerritPatchset = change.revisions![change.current_revision!]; - const remoteRefSpec = `${currentGerritPatchset.ref}`; - const localRefSpec = `refs/heads/${branchName}`; - await git.fetchRevSpec(`${remoteRefSpec}:${localRefSpec}`); - //TODO/HACK: we fetch the current changeset with the name "origin/" as prefix too. then most util/git/* cmds should work as expected (like isBranchConflicted, isBranchModified)... - await git.fetchRevSpec(`${remoteRefSpec}:refs/heads/origin/${branchName}`); + //const remoteRefSpec = `${currentGerritPatchset.ref}`; + //const localRefSpec = `refs/heads/${branchName}`; + //await git.fetchRevSpec(`${remoteRefSpec}:${localRefSpec}`); + //TODO: for git.branchExists and git.getBranchCommit await git.registerBranch( branchName, - currentGerritPatchset.uploader.username !== gerritUsername + currentGerritPatchset.uploader.username !== gerritUsername, + change.current_revision ); } @@ -179,6 +179,79 @@ export async function initRepo({ return repoConfig; } +export async function isBranchModified(branchName: string): Promise { + const change = await findOwnPr({ branchName, state: 'open' }, true).then( + (res) => res.pop() + ); + if (change) { + const currentGerritPatchset = change.revisions![change.current_revision!]; + return currentGerritPatchset.uploader.username !== gerritUsername; + } + return false; +} + +export async function isBranchBehindBase( + branchName: string, + baseBranch: string +): Promise { + const change = await findOwnPr({ branchName, state: 'open' }, true).then( + (res) => res.pop() + ); + if (change) { + const currentGerritPatchset = change.revisions![change.current_revision!]; + return currentGerritPatchset.actions?.['rebase'].enabled === true; + } + return true; +} + +export async function isBranchConflicted( + baseBranch: string, + branch: string +): Promise { + //TODO: Gerrit can/would do this for us (seen in UI), but where in the REST-Response we found this information? + //if (!git.branchExists(`origin/${branch}`)) { without registering fake-branches this is always false + const change = await findOwnPr({ + branchName: branch, + targetBranch: baseBranch, + state: 'open', + }).then((res) => res.pop()); + if (change) { + if (change.mergeable) { + //is this the right property? + return change.mergeable; + } + //the long way...see #change.mergeabilityComputationBehavior documentation + const currentGerritPatchset = change.revisions![change.current_revision!]; + const remoteRefSpec = `${currentGerritPatchset.ref}`; + await git.fetchRevSpec(`${remoteRefSpec}:refs/heads/origin/${branch}`); + } else { + throw new Error( + `There is no change with branch=${branch} and baseBranch=${baseBranch}` + ); + } + //} + return git.isBranchConflicted(baseBranch, branch); +} + +export async function branchExists(branchName: string): Promise { + const change = await findOwnPr({ branchName, state: 'open' }).then((res) => + res.pop() + ); + return !!change; +} + +export async function getBranchCommit( + branchName: string +): Promise { + const change = await findOwnPr({ branchName, state: 'open' }).then((res) => + res.pop() + ); + if (change) { + return change.current_revision!; + } + return null; +} + /** * in Gerrit: "Searching Changes" * /changes/?q=$QUERY @@ -206,12 +279,12 @@ async function findOwnPr( reviewLabel, ]; const requestDetails = [ - 'SUBMITTABLE', - 'CHECK', + 'SUBMITTABLE', //include the submittable field in ChangeInfo, which can be used to tell if the change is reviewed and ready for submit. + 'CHECK', // include potential problems with the change. 'MESSAGES', 'DETAILED_ACCOUNTS', 'LABELS', - 'CURRENT_ACTIONS', + 'CURRENT_ACTIONS', //to check if current_revision can be "rebase" 'CURRENT_REVISION', //get RevisionInfo::ref to fetch ]; const changes = await gerritHttp.getJson( @@ -500,7 +573,7 @@ export async function getJsonFile( } export function getRepoForceRebase(): Promise { - return Promise.resolve(true); + return Promise.resolve(false); } export async function addReviewers( @@ -597,8 +670,6 @@ export async function commitFiles( files: commit.files, }); if (pushResult) { - //TODO: check why this was done by original commitAndPush method.. - await git.registerBranch(commit.branchName, false, commitSha); if (change && config.approveAvailable && wasApprovedByMe(change)) { //change was the old change before commit/push. we need to approve again only if it was previously approved from renovate only await approveChange(change._number); diff --git a/lib/modules/platform/gerrit/scm.ts b/lib/modules/platform/gerrit/scm.ts new file mode 100644 index 000000000000000..232faa8255ba203 --- /dev/null +++ b/lib/modules/platform/gerrit/scm.ts @@ -0,0 +1,19 @@ +import type { PlatformScm } from '../types'; +import { + isBranchBehindBase, + isBranchConflicted, + isBranchModified, +} from './index'; + +const gerritScm: Partial = { + isBranchModified, + isBranchBehindBase, + isBranchConflicted, + + //branchExists: ...TODO: Problem the call needs to be async + //getBranchCommit: ...TODO: Problem the call needs to be async + + deleteBranch: (branchName: string) => Promise.resolve(), //no-op for gerrit, there exists no remote-branches for PRs +}; + +export default gerritScm; diff --git a/lib/modules/platform/gerrit/types.ts b/lib/modules/platform/gerrit/types.ts index 1257e68db575ecd..b58e370217f9ff1 100644 --- a/lib/modules/platform/gerrit/types.ts +++ b/lib/modules/platform/gerrit/types.ts @@ -61,7 +61,7 @@ export interface GerritChange { unresolved_comment_count?: number; _number: number; owner: GerritAccountInfo; - actions?: GerritActionInfo[]; + actions?: { [key: string]: GerritActionInfo }; submit_records: any[]; // SubmitRecordInfo[] requirements?: any[]; //List of the requirements submit_requirements?: any[]; //List of the SubmitRequirementResultInfo @@ -95,6 +95,7 @@ export interface GerritRevisionInfo { created: Date; //TODO: map uploader: GerritAccountInfo; ref: string; //The Git reference for the patch set. + actions?: { [key: string]: GerritActionInfo }; //... many more...still not necessary } diff --git a/lib/modules/platform/index.ts b/lib/modules/platform/index.ts index be1315a76b88360..30b6041ac392c77 100644 --- a/lib/modules/platform/index.ts +++ b/lib/modules/platform/index.ts @@ -6,6 +6,7 @@ import type { HostRule } from '../../types'; import { setGitAuthor, setNoVerify, setPrivateKey } from '../../util/git'; import * as hostRules from '../../util/host-rules'; import platforms from './api'; +import { setPlatformScmApi } from './scm'; import type { Platform } from './types'; export * from './types'; @@ -35,6 +36,7 @@ export function setPlatformApi(name: string): void { ); } _platform = platforms.get(name); + setPlatformScmApi(name); } export async function initPlatform(config: AllConfig): Promise { diff --git a/lib/modules/platform/scm.ts b/lib/modules/platform/scm.ts new file mode 100644 index 000000000000000..9dbbda0126ea530 --- /dev/null +++ b/lib/modules/platform/scm.ts @@ -0,0 +1,33 @@ +import * as _git from '../../util/git'; +import gerritScm from './gerrit/scm'; +import type { PlatformScm } from './types'; + +export const platformScmImpls = new Map>(); +platformScmImpls.set('gerrit', gerritScm); + +export const defaultGitScm: PlatformScm = { + isBranchBehindBase: _git.isBranchBehindBase, + isBranchModified: _git.isBranchModified, + isBranchConflicted: _git.isBranchConflicted, + branchExists: _git.branchExists, + getBranchCommit: _git.getBranchCommit, + deleteBranch: _git.deleteBranch, +}; + +const scmProxy: ProxyHandler = { + get(_target: PlatformScm, prop: keyof PlatformScm, receiver: any) { + if (typeof _scm[prop] !== 'undefined') { + return _scm[prop]; + } + return Reflect.get(_target, prop, receiver); + }, +}; + +export const scm = new Proxy(defaultGitScm, scmProxy); +let _scm: Partial = defaultGitScm; + +export function setPlatformScmApi(name: string): void { + _scm = platformScmImpls.has(name) + ? platformScmImpls.get(name)! + : defaultGitScm; +} diff --git a/lib/modules/platform/types.ts b/lib/modules/platform/types.ts index 70aaf991ad01066..1c740ff91b250ff 100644 --- a/lib/modules/platform/types.ts +++ b/lib/modules/platform/types.ts @@ -212,3 +212,12 @@ export interface Platform { filterUnavailableUsers?(users: string[]): Promise; commitFiles?(config: CommitFilesConfig): Promise; } + +export interface PlatformScm { + isBranchBehindBase(branchName: string, baseBranch: string): Promise; + isBranchModified(branchName: string): Promise; + isBranchConflicted(baseBranch: string, branch: string): Promise; + branchExists(branchName: string): boolean; + getBranchCommit(branchName: string): CommitSha | null; + deleteBranch(branchName: string): Promise; +} diff --git a/lib/util/git/index.ts b/lib/util/git/index.ts index e3f854c7e9f995b..fe41896b0ec685e 100644 --- a/lib/util/git/index.ts +++ b/lib/util/git/index.ts @@ -107,6 +107,10 @@ export async function gitRetry(gitFunc: () => Promise): Promise { throw lastError; } +function localName(branchName: string): string { + return branchName.replace(regEx(/^origin\//), ''); +} + async function isDirectory(dir: string): Promise { try { return (await fs.stat(dir)).isDirectory(); @@ -580,7 +584,6 @@ export function getBranchList(): string[] { return Object.keys(config.branchCommits); } -//TODO: move to Platform-Interface export async function isBranchBehindBase( branchName: string, baseBranch: string @@ -602,13 +605,12 @@ export async function isBranchBehindBase( try { const { currentBranchSha, currentBranch } = config; const branches = await git.branch([ - '--all', //for gerrit we check by name, there are no real remote branches. origin/$branchname was faked + '--remotes', '--verbose', '--contains', config.currentBranchSha, ]); - isBehind = !branches.all.filter((b) => b.match(`origin/${branchName}$`)) - .length; + isBehind = !branches.all.map(localName).includes(branchName); logger.debug( { currentBranch, currentBranchSha }, `branch.isBehindBase(): ${isBehind}` @@ -623,7 +625,6 @@ export async function isBranchBehindBase( } } -//TODO: move to Platform-Interface export async function isBranchModified(branchName: string): Promise { if (!branchExists(branchName)) { logger.debug('branch.isModified(): no cache'); @@ -689,7 +690,6 @@ export async function isBranchModified(branchName: string): Promise { return true; } -//TODO: move to Platform-Interface export async function isBranchConflicted( baseBranch: string, branch: string diff --git a/lib/workers/repository/cache.ts b/lib/workers/repository/cache.ts index 0733c8d5ae6b0f4..683f76f9f291632 100644 --- a/lib/workers/repository/cache.ts +++ b/lib/workers/repository/cache.ts @@ -2,17 +2,13 @@ import { logger } from '../../logger'; import { platform } from '../../modules/platform'; +import { scm } from '../../modules/platform/scm'; import { getCache } from '../../util/cache/repository'; import type { BranchCache, BranchUpgradeCache, } from '../../util/cache/repository/types'; -import { - getBranchCommit, - isBranchBehindBase, - isBranchConflicted, - isBranchModified, -} from '../../util/git'; +import { getBranchCommit } from '../../util/git'; import { getCachedPristineResult } from '../../util/git/pristine'; import type { BranchConfig, BranchUpgradeConfig } from '../types'; @@ -63,9 +59,9 @@ async function generateBranchCache( if (branchPr) { prNo = branchPr.number; } - isModified = await isBranchModified(branchName); - isBehindBase = await isBranchBehindBase(branchName, baseBranch); - isConflicted = await isBranchConflicted(baseBranch, branchName); + isModified = await scm.isBranchModified(branchName); + isBehindBase = await scm.isBranchBehindBase(branchName, baseBranch); + isConflicted = await scm.isBranchConflicted(baseBranch, branchName); } const automerge = !!branch.automerge; const upgrades: BranchUpgradeCache[] = branch.upgrades diff --git a/lib/workers/repository/config-migration/branch/rebase.ts b/lib/workers/repository/config-migration/branch/rebase.ts index ebf03f00cf2845f..9806c172cabca99 100644 --- a/lib/workers/repository/config-migration/branch/rebase.ts +++ b/lib/workers/repository/config-migration/branch/rebase.ts @@ -2,11 +2,8 @@ import { GlobalConfig } from '../../../../config/global'; import type { RenovateConfig } from '../../../../config/types'; import { logger } from '../../../../logger'; import { commitAndPush } from '../../../../modules/platform/commit'; -import { - checkoutBranch, - getFile, - isBranchModified, -} from '../../../../util/git'; +import { scm } from '../../../../modules/platform/scm'; +import { checkoutBranch, getFile } from '../../../../util/git'; import { quickStringify } from '../../../../util/stringify'; import { getMigrationBranchName } from '../common'; import { ConfigMigrationCommitMessageFactory } from './commit-message'; @@ -19,7 +16,7 @@ export async function rebaseMigrationBranch( ): Promise { logger.debug('Checking if migration branch needs rebasing'); const branchName = getMigrationBranchName(config); - if (await isBranchModified(branchName)) { + if (await scm.isBranchModified(branchName)) { logger.debug('Migration branch has been edited and cannot be rebased'); return null; } diff --git a/lib/workers/repository/finalise/prune.ts b/lib/workers/repository/finalise/prune.ts index 566a02141e02dd6..3546ec41b746da6 100644 --- a/lib/workers/repository/finalise/prune.ts +++ b/lib/workers/repository/finalise/prune.ts @@ -4,11 +4,8 @@ import { REPOSITORY_CHANGED } from '../../../constants/error-messages'; import { logger } from '../../../logger'; import { platform } from '../../../modules/platform'; import { ensureComment } from '../../../modules/platform/comment'; -import { - deleteBranch, - getBranchList, - isBranchModified, -} from '../../../util/git'; +import { scm } from '../../../modules/platform/scm'; +import { getBranchList } from '../../../util/git'; async function cleanUpBranches( { pruneStaleBranches: enabled }: RenovateConfig, @@ -24,7 +21,7 @@ async function cleanUpBranches( branchName, state: 'open', }); - const branchIsModified = await isBranchModified(branchName); + const branchIsModified = await scm.isBranchModified(branchName); if (pr) { if (branchIsModified) { logger.debug( @@ -69,7 +66,7 @@ async function cleanUpBranches( prTitle: newPrTitle, state: 'closed', }); - await deleteBranch(branchName); + await scm.deleteBranch(branchName); } } else if (branchIsModified) { logger.debug('Orphan Branch is modified - skipping branch deletion'); @@ -77,7 +74,7 @@ async function cleanUpBranches( logger.info(`DRY-RUN: Would delete orphan branch ${branchName}`); } else { logger.info({ branch: branchName }, `Deleting orphan branch`); - await deleteBranch(branchName); + await scm.deleteBranch(branchName); } } catch (err) /* istanbul ignore next */ { if (err.message === 'config-validation') { diff --git a/lib/workers/repository/onboarding/branch/rebase.ts b/lib/workers/repository/onboarding/branch/rebase.ts index 2c714dca54f24a9..61185932e33ed0f 100644 --- a/lib/workers/repository/onboarding/branch/rebase.ts +++ b/lib/workers/repository/onboarding/branch/rebase.ts @@ -3,11 +3,8 @@ import { GlobalConfig } from '../../../../config/global'; import type { RenovateConfig } from '../../../../config/types'; import { logger } from '../../../../logger'; import { commitAndPush } from '../../../../modules/platform/commit'; -import { - getFile, - isBranchBehindBase, - isBranchModified, -} from '../../../../util/git'; +import { scm } from '../../../../modules/platform/scm'; +import { getFile } from '../../../../util/git'; import { OnboardingCommitMessageFactory } from './commit-message'; import { getOnboardingConfigContents } from './config'; @@ -22,7 +19,7 @@ export async function rebaseOnboardingBranch( ): Promise { logger.debug('Checking if onboarding branch needs rebasing'); // TODO #7154 - if (await isBranchModified(config.onboardingBranch!)) { + if (await scm.isBranchModified(config.onboardingBranch!)) { logger.debug('Onboarding branch has been edited and cannot be rebased'); return null; } @@ -32,7 +29,10 @@ export async function rebaseOnboardingBranch( // TODO: fix types (#7154) if ( contents === existingContents && - !(await isBranchBehindBase(config.onboardingBranch!, config.defaultBranch!)) + !(await scm.isBranchBehindBase( + config.onboardingBranch!, + config.defaultBranch! + )) ) { logger.debug('Onboarding branch is up to date'); return null; diff --git a/lib/workers/repository/onboarding/pr/index.ts b/lib/workers/repository/onboarding/pr/index.ts index 1c1c41f35e2ee51..1206dd676eb91e5 100644 --- a/lib/workers/repository/onboarding/pr/index.ts +++ b/lib/workers/repository/onboarding/pr/index.ts @@ -5,12 +5,8 @@ import { logger } from '../../../../logger'; import type { PackageFile } from '../../../../modules/manager/types'; import { platform } from '../../../../modules/platform'; import { hashBody } from '../../../../modules/platform/pr-body'; +import { scm } from '../../../../modules/platform/scm'; import { emojify } from '../../../../util/emoji'; -import { - deleteBranch, - isBranchConflicted, - isBranchModified, -} from '../../../../util/git'; import * as template from '../../../../util/template'; import type { BranchConfig } from '../../../types'; import { @@ -92,13 +88,13 @@ If you need any further assistance then you can also [request help here](${ if (GlobalConfig.get('dryRun')) { // TODO: types (#7154) logger.info(`DRY-RUN: Would check branch ${config.onboardingBranch!}`); - } else if (await isBranchModified(config.onboardingBranch!)) { + } else if (await scm.isBranchModified(config.onboardingBranch!)) { configDesc = emojify( `### Configuration\n\n:abcd: Renovate has detected a custom config for this PR. Feel free to ask for [help](${ config.productLinks!.help }) if you have any doubts and would like it reviewed.\n\n` ); - const isConflicted = await isBranchConflicted( + const isConflicted = await scm.isBranchConflicted( config.baseBranch!, config.onboardingBranch! ); @@ -180,7 +176,7 @@ If you need any further assistance then you can also [request help here](${ logger.warn( 'Onboarding PR already exists but cannot find it. It was probably created by a different user.' ); - await deleteBranch(config.onboardingBranch!); + await scm.deleteBranch(config.onboardingBranch!); return; } throw err; diff --git a/lib/workers/repository/update/branch/index.ts b/lib/workers/repository/update/branch/index.ts index 88ad96ef8741b47..2bcb764dc4feadd 100644 --- a/lib/workers/repository/update/branch/index.ts +++ b/lib/workers/repository/update/branch/index.ts @@ -22,6 +22,7 @@ import { ensureCommentRemoval, } from '../../../../modules/platform/comment'; import { hashBody } from '../../../../modules/platform/pr-body'; +import { scm } from '../../../../modules/platform/scm'; import { ExternalHostError } from '../../../../types/errors/external-host-error'; import { getElapsedDays } from '../../../../util/date'; import { emojify } from '../../../../util/emoji'; @@ -30,8 +31,6 @@ import { deleteBranch, getBranchCommit, branchExists as gitBranchExists, - isBranchConflicted, - isBranchModified, } from '../../../../util/git'; import { getMergeConfidenceLevel, @@ -197,7 +196,7 @@ export async function processBranch( } logger.debug('Checking if PR has been edited'); - const branchIsModified = await isBranchModified(config.branchName); + const branchIsModified = await scm.isBranchModified(config.branchName); if (branchPr) { logger.debug('Found existing branch PR'); if (branchPr.state !== 'open') { @@ -503,7 +502,7 @@ export async function processBranch( config.isConflicted ??= branchExists && - (await isBranchConflicted(config.baseBranch, config.branchName)); + (await scm.isBranchConflicted(config.baseBranch, config.branchName)); config.forceCommit = forcedManually || config.isConflicted; // compile commit message with body, which maybe needs changelogs diff --git a/lib/workers/repository/update/branch/reuse.ts b/lib/workers/repository/update/branch/reuse.ts index 767e21225617082..371f3c768ac12f8 100644 --- a/lib/workers/repository/update/branch/reuse.ts +++ b/lib/workers/repository/update/branch/reuse.ts @@ -1,13 +1,9 @@ import { GlobalConfig } from '../../../../config/global'; import { logger } from '../../../../logger'; import { platform } from '../../../../modules/platform'; +import { scm } from '../../../../modules/platform/scm'; import type { RangeStrategy } from '../../../../types'; -import { - branchExists, - isBranchBehindBase, - isBranchConflicted, - isBranchModified, -} from '../../../../util/git'; +import { branchExists } from '../../../../util/git'; import type { BranchConfig } from '../../../types'; type ParentBranch = { @@ -61,10 +57,10 @@ export async function shouldReuseExistingBranch( (config.rebaseWhen === 'auto' && (config.automerge || (await platform.getRepoForceRebase()))) ) { - if (await isBranchBehindBase(branchName, baseBranch)) { + if (await scm.isBranchBehindBase(branchName, baseBranch)) { logger.debug(`Branch is behind base branch and needs rebasing`); // We can rebase the branch only if no PR or PR can be rebased - if (await isBranchModified(branchName)) { + if (await scm.isBranchModified(branchName)) { logger.debug('Cannot rebase branch as it has been modified'); result.reuseExistingBranch = true; result.isModified = true; @@ -81,11 +77,11 @@ export async function shouldReuseExistingBranch( } // Now check if PR is unmergeable. If so then we also rebase - result.isConflicted = await isBranchConflicted(baseBranch, branchName); + result.isConflicted = await scm.isBranchConflicted(baseBranch, branchName); if (result.isConflicted) { logger.debug('Branch is conflicted'); - if ((await isBranchModified(branchName)) === false) { + if ((await scm.isBranchModified(branchName)) === false) { logger.debug(`Branch is not mergeable and needs rebasing`); if (config.rebaseWhen === 'never') { logger.debug('Rebasing disabled by config'); diff --git a/lib/workers/repository/update/pr/automerge.ts b/lib/workers/repository/update/pr/automerge.ts index b2c66e68641eb36..486867a6308c207 100644 --- a/lib/workers/repository/update/pr/automerge.ts +++ b/lib/workers/repository/update/pr/automerge.ts @@ -6,11 +6,7 @@ import { ensureComment, ensureCommentRemoval, } from '../../../../modules/platform/comment'; -import { - deleteBranch, - isBranchConflicted, - isBranchModified, -} from '../../../../util/git'; +import { scm } from '../../../../modules/platform/scm'; import type { BranchConfig } from '../../../types'; import { isScheduledNow } from '../branch/schedule'; import { resolveBranchStatus } from '../branch/status-checks'; @@ -54,7 +50,7 @@ export async function checkAutoMerge( } const isConflicted = config.isConflicted ?? - (await isBranchConflicted(config.baseBranch, config.branchName)); + (await scm.isBranchConflicted(config.baseBranch, config.branchName)); if (isConflicted) { logger.debug('PR is conflicted'); return { @@ -85,7 +81,7 @@ export async function checkAutoMerge( }; } // Check if it's been touched - if (await isBranchModified(branchName)) { + if (await scm.isBranchModified(branchName)) { logger.debug('PR is ready for automerge but has been modified'); return { automerged: false, @@ -148,7 +144,7 @@ export async function checkAutoMerge( } let branchRemoved = false; try { - await deleteBranch(branchName); + await scm.deleteBranch(branchName); branchRemoved = true; } catch (err) /* istanbul ignore next */ { logger.warn({ branchName, err }, 'Branch auto-remove failed');