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 354ab13
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 113 deletions.
16 changes: 11 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,16 @@ jobs:
runs-on: ubuntu-latest

steps:
# Check out a copy of this repository so that we can compute a diff to
# evaluate and load the Action's configuration.
# Check out a copy of this repository so that we can retrieve a diff to
# evaluate and load the `sizeup` configuration file.
#
# This step must fetch the pull request's base branch using the `ref`
# and `filter` arguments as shown below.
- name: Checkout this repository
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.base.ref }}
filter: tree:0

# Run the estimation tool
- name: Run sizeup
Expand All @@ -49,13 +55,13 @@ jobs:
# This input is required.
token: "${{ secrets.GITHUB_TOKEN }}"

# Optional arguments that will be forwarded to `git diff` when
# computing the diff to evaluate with this Action.
# Options that will be forwarded to `git diff` when computing the
# diff to evaluate with this Action.
#
# Defaults to "--ignore-space-change", which ignores lines of the
# diff in which the only change is to the amount of whitespace on the
# line.
git-diff-args: ""
git-diff-options: ""

# Path to a YAML configuration file for this Action that is stored in
# this repository.
Expand Down
4 changes: 2 additions & 2 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ inputs:
token:
description: 'GitHub API token with read permissions for pull requests in this repository.'
required: true
git-diff-args:
git-diff-options:
description: |
Optional custom arguments to forward to `git diff` when retrieving the diff of the pull request that triggered this workflow.
Custom options 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=tree:0`,
'--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-options').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 354ab13

Please sign in to comment.