Skip to content

Commit

Permalink
Find merge base by progressively deepening history
Browse files Browse the repository at this point in the history
  • Loading branch information
lerebear committed Dec 31, 2023
1 parent 7037589 commit bcf310b
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 107 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,15 @@ jobs:
steps:
# Check out a copy of this repository so that we can compute a diff to
# evaluate and load the Action's configuration.
#
# This step must fetch the pull request's base branch using the `ref`
# argument as shown below. The `filter` argument is optional but
# recommended for efficiency, particularly in large repositories.
- name: Checkout this repository
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.base.ref }}
filter: blob:none

# Run the estimation tool
- name: Run sizeup
Expand Down
7 changes: 6 additions & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion badges/coverage.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
92 changes: 43 additions & 49 deletions dist/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

106 changes: 52 additions & 54 deletions src/initializer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,60 +26,6 @@ export function loadConfiguration(): Configuration {
return YAML.parse(fs.readFileSync(configFile, 'utf8')) as Configuration
}

/**
* Retrieves the diff of the pull request that triggered this workflow which we
* will use for evaluation.
*
* @param pull The pull request that triggered this workflow.
* @returns The diff of the given pull request.
*/
export async function fetchDiff(pull: PullRequest): Promise<string> {
const git = 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}`)
await git.fetch([
'origin',
`+${pull.head.ref}:${pull.head.ref}`,
`--depth=${pull.commits + 1}`,
'--no-tags',
'--prune',
'--no-recurse-submodules'
])

core.debug(`Switching to branch ${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.
return git.diff(diffArgs)
}

export function workflowTriggeredForUnsupportedEvent(): boolean {
if (github.context.eventName !== 'pull_request') {
core.setFailed(
Expand Down Expand Up @@ -113,3 +59,55 @@ export function pullRequestAuthorHasNotOptedIn(

return false
}

/**
* Retrieves the diff of the pull request that triggered this workflow which we
* will use for evaluation.
*
* @param pull The pull request that triggered this workflow.
* @returns The diff of the given pull request or `undefined` if we failed to retrieve it.
*/
export async function fetchDiff(
pull: PullRequest
): Promise<string | undefined> {
const git = simpleGit('.', { trimmed: true })

let baseRefExists = false
try {
baseRefExists = !!(await git.raw('rev-parse', '--verify', pull.base.ref))
} catch (e) {
core.error(
`Error from 'git rev-parse --verfy ${pull.base.ref}': ${
(e as Error).message
}`
)
}

if (!baseRefExists) {
core.setFailed(
`Could not find pull request base branch ${pull.base.ref}. ` +
`Please make sure actions/checkout was used beforehand to fetch ${pull.base.ref}.`
)
return
}

core.debug(`Fetching head ref "${pull.head.ref}"`)

await git.fetch([
'origin',
`+${pull.head.ref}:${pull.head.ref}`,
'--filter=blob:none',
'--no-tags',
'--prune',
'--no-recurse-submodules'
])

core.debug(`Switching to head ref "${pull.head.ref}"`)
await git.raw('switch', pull.head.ref)

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)
}
7 changes: 5 additions & 2 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ export async function run(): Promise<void> {

if (pullRequestAuthorHasNotOptedIn(config, pullRequest)) return

const score = await evaluatePullRequest(pullRequest, config)
const diff = await fetchDiff(pullRequest)
if (!diff) return

const score = await evaluatePullRequest(pullRequest, diff, config)

await applyCategoryLabel(pullRequest, score, config)
await addScoreThresholdExceededComment(pullRequest, score, config)
Expand All @@ -58,6 +61,7 @@ export async function run(): Promise<void> {
*/
async function evaluatePullRequest(
pull: PullRequest,
diff: string,
config: Configuration
): Promise<Score> {
const pullRequestNickname = `${pull.base.repo.owner.login}/${pull.base.repo.name}#${pull.number}`
Expand All @@ -70,7 +74,6 @@ async function evaluatePullRequest(
fs.writeFileSync(sizeupConfigFile, YAML.stringify(config.sizeup))
}

const diff = await fetchDiff(pull)
const score = SizeUp.evaluate(diff, sizeupConfigFile)

if (sizeupConfigFile) {
Expand Down

0 comments on commit bcf310b

Please sign in to comment.