diff --git a/action.yml b/action.yml index d81583f..893c4b2 100644 --- a/action.yml +++ b/action.yml @@ -6,9 +6,14 @@ inputs: token: description: 'GitHub API token with read permissions for pull requests in this repository.' required: true + fetch-depth: + description: | + Number of commits to fetch each time we need to deepen git history in order to find the + merge base between the head ref and the base ref of the pull request + default: 10 git-diff-args: description: | - Optional custom arguments to forward to `git diff` when retrieving the diff of the pull request that triggered this workflow. + Custom arguments to forward to `git diff` when retrieving the diff of the pull request that triggered this workflow. The result of that `git diff` command will be used for evaluation with sizeup. default: '--ignore-space-change' configuration-file-path: diff --git a/badges/coverage.svg b/badges/coverage.svg index f7c1988..bef488a 100644 --- a/badges/coverage.svg +++ b/badges/coverage.svg @@ -1 +1 @@ -Coverage: 61.59%Coverage61.59% \ No newline at end of file +Coverage: 56.29%Coverage56.29% \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index 9ad1763..fa63db5 100644 --- a/dist/index.js +++ b/dist/index.js @@ -16382,39 +16382,51 @@ exports.loadConfiguration = loadConfiguration; */ async function fetchDiff(pull) { const git = (0, simple_git_1.simpleGit)('.', { trimmed: true }); - const diffArgs = ['--merge-base', `origin/${pull.base.ref}`].concat(core.getInput('git-diff-args').split(/\s+/)); - core.info(`Retrieving diff with \`git diff ${diffArgs.join(' ')}\``); - // Fetch all commits for the head branch back to where it diverged from the base. - core.debug(`Fetching ${pull.commits + 1} commits for ${pull.head.ref}`); + const fetchDepth = parseInt(core.getInput('fetch-depth')); + core.debug(`Fetching base ref "${pull.base.ref}" and head ref "${pull.head.ref}" with depth ${fetchDepth}`); await git.fetch([ 'origin', + `+${pull.base.ref}:${pull.base.ref}`, `+${pull.head.ref}:${pull.head.ref}`, - `--depth=${pull.commits + 1}`, + `--depth=${fetchDepth}`, '--no-tags', '--prune', '--no-recurse-submodules' ]); - core.debug(`Switching to branch ${pull.head.ref}`); + core.debug(`Switching to head ref "${pull.head.ref}"`); await git.raw('switch', pull.head.ref); - // Fetch commits for the base branch that were made since the head diverged from it. - const divergedFrom = await git.raw('rev-list', '--max-parents=0', 'HEAD'); - const divergedAt = await git.show([ - '--quiet', - '--date=unix', - '--format=%cd', - divergedFrom - ]); - core.debug(`Retrieving history for origin/${pull.base.ref} since ${divergedFrom} which was committed at ${divergedAt}`); - await git.fetch([ - 'origin', - `+${pull.base.ref}:${pull.base.ref}`, - `--shallow-since=${divergedAt}`, - '--no-tags', - '--prune', - '--no-recurse-submodules' - ]); - // Now we have all relevant history from both base and head branches, so we - // can compute an accurate diff relative to the base branch. + core.info(`Searching for merge base between "${pull.base.ref}" and "${pull.head.ref}"`); + let mergeBase = ''; + let fetches = 0; + while (mergeBase) { + try { + mergeBase = await git.raw('merge-base', pull.base.ref, pull.head.ref); + core.info(`Found merge base: ${mergeBase}`); + } + catch (e) { + if (fetches === 0) { + core.debug(`git merge-base error: ${e.message}`); + core.info('Deepening git history in search of merge base'); + } + else if (fetches % 10 === 0) { + core.debug(`git merge-base error: ${e.message}`); + core.info(`Still searching for merge base after ${fetches} fetches`); + } + fetches++; + await git.fetch([ + 'origin', + pull.base.ref, + pull.head.ref, + `--deepen=${fetchDepth}`, + '--no-tags', + '--prune', + '--no-recurse-modules' + ]); + } + } + core.debug(`Performed ${fetches} fetch${fetches === 1 ? '' : 'es'} to find the merge base`); + const diffArgs = ['--merge-base', pull.base.ref].concat(core.getInput('git-diff-args').split(/\s+/)); + core.info(`Retrieving diff with \`git diff ${diffArgs.join(' ')}\``); return git.diff(diffArgs); } exports.fetchDiff = fetchDiff; diff --git a/src/initializer.ts b/src/initializer.ts index 34e1992..9968bb2 100644 --- a/src/initializer.ts +++ b/src/initializer.ts @@ -35,48 +35,65 @@ export function loadConfiguration(): Configuration { */ export async function fetchDiff(pull: PullRequest): Promise { const git = simpleGit('.', { trimmed: true }) - const diffArgs = ['--merge-base', `origin/${pull.base.ref}`].concat( - core.getInput('git-diff-args').split(/\s+/) - ) + const fetchDepth = parseInt(core.getInput('fetch-depth')) - core.info(`Retrieving diff with \`git diff ${diffArgs.join(' ')}\``) + core.debug( + `Fetching base ref "${pull.base.ref}" and head ref "${pull.head.ref}" with depth ${fetchDepth}` + ) - // Fetch all commits for the head branch back to where it diverged from the base. - core.debug(`Fetching ${pull.commits + 1} commits for ${pull.head.ref}`) await git.fetch([ 'origin', + `+${pull.base.ref}:${pull.base.ref}`, `+${pull.head.ref}:${pull.head.ref}`, - `--depth=${pull.commits + 1}`, + `--depth=${fetchDepth}`, '--no-tags', '--prune', '--no-recurse-submodules' ]) - core.debug(`Switching to branch ${pull.head.ref}`) + core.debug(`Switching to head ref "${pull.head.ref}"`) await git.raw('switch', pull.head.ref) - // Fetch commits for the base branch that were made since the head diverged from it. - const divergedFrom = await git.raw('rev-list', '--max-parents=0', 'HEAD') - const divergedAt = await git.show([ - '--quiet', - '--date=unix', - '--format=%cd', - divergedFrom - ]) + core.info( + `Searching for merge base between "${pull.base.ref}" and "${pull.head.ref}"` + ) + let mergeBase = '' + let fetches = 0 + while (mergeBase) { + try { + mergeBase = await git.raw('merge-base', pull.base.ref, pull.head.ref) + core.info(`Found merge base: ${mergeBase}`) + } catch (e) { + if (fetches === 0) { + core.debug(`git merge-base error: ${(e as Error).message}`) + core.info('Deepening git history in search of merge base') + } else if (fetches % 10 === 0) { + core.debug(`git merge-base error: ${(e as Error).message}`) + core.info(`Still searching for merge base after ${fetches} fetches`) + } + fetches++ + await git.fetch([ + 'origin', + pull.base.ref, + pull.head.ref, + `--deepen=${fetchDepth}`, + '--no-tags', + '--prune', + '--no-recurse-modules' + ]) + } + } + core.debug( - `Retrieving history for origin/${pull.base.ref} since ${divergedFrom} which was committed at ${divergedAt}` + `Performed ${fetches} fetch${ + fetches === 1 ? '' : 'es' + } to find the merge base` ) - await git.fetch([ - 'origin', - `+${pull.base.ref}:${pull.base.ref}`, - `--shallow-since=${divergedAt}`, - '--no-tags', - '--prune', - '--no-recurse-submodules' - ]) - // Now we have all relevant history from both base and head branches, so we - // can compute an accurate diff relative to the base branch. + const diffArgs = ['--merge-base', pull.base.ref].concat( + core.getInput('git-diff-args').split(/\s+/) + ) + core.info(`Retrieving diff with \`git diff ${diffArgs.join(' ')}\``) return git.diff(diffArgs) }