ci/github-script: split getting commit details for PR into its own file

This commit is contained in:
Michael Daniels
2026-03-12 18:04:32 -04:00
parent 541eb1682b
commit 743ab29528
3 changed files with 102 additions and 81 deletions
+93
View File
@@ -0,0 +1,93 @@
// @ts-check
const { promisify } = require('node:util')
const execFile = promisify(require('node:child_process').execFile)
/**
* @param {{
* args: string[]
* core: import('@actions/core'),
* quiet?: boolean,
* repoPath?: string,
* }} RunGitProps
*/
async function runGit({ args, repoPath, core, quiet }) {
if (repoPath) {
args = ['-C', repoPath, ...args]
}
if (!quiet) {
core.info(`About to run \`git ${args.map((s) => `'${s}'`).join(' ')}\``)
}
return await execFile('git', args)
}
/**
* GitHub's API will return a maximum of 250 commits.
* We will use it if we can, but fall back to using git locally.
*
* @param {{
* context: import('@actions/github/lib/context').Context,
* core: import('@actions/core'),
* github: InstanceType<import('@actions/github/lib/utils').GitHub>,
* pr: Awaited<ReturnType<InstanceType<import('@actions/github/lib/utils').GitHub>["rest"]["pulls"]["get"]>>["data"]
* repoPath?: string,
* }} GetCommitMessagesForPRProps
*
* @returns {Promise<{
* message: string,
* sha: string,
* }[]>}
*/
async function getCommitDetailsForPR({ context, core, github, pr, repoPath }) {
if (pr.commits < 250) {
return (
await github.paginate(github.rest.pulls.listCommits, {
...context.repo,
pull_number: pr.number,
})
).map((commit) => ({ message: commit.commit.message, sha: commit.sha }))
} else {
await runGit({
args: ['fetch', `--depth=1`, 'origin', pr.base.sha],
repoPath,
core,
})
await runGit({
args: ['fetch', `--depth=${pr.commits + 1}`, 'origin', pr.head.sha],
repoPath,
core,
})
const shas = (
await runGit({
args: [
'rev-list',
`--max-count=${pr.commits}`,
`${pr.base.sha}..${pr.head.sha}`,
],
repoPath,
core,
})
).stdout
.split('\n')
.map((s) => s.trim())
.filter(Boolean)
return Promise.all(
shas.map(async (sha) => ({
sha,
message: (
await runGit({
args: ['log', '--format=%s', '-1', sha],
repoPath,
core,
quiet: true,
})
).stdout,
})),
)
}
}
module.exports = { getCommitDetailsForPR }
+8 -81
View File
@@ -1,27 +1,6 @@
// @ts-check
const { classify } = require('../supportedBranches.js')
const { promisify } = require('node:util')
const execFile = promisify(require('node:child_process').execFile)
/**
* @param {{
* args: string[]
* core: import('@actions/core'),
* quiet?: boolean,
* repoPath?: string,
* }} RunGitProps
*/
async function runGit({ args, repoPath, core, quiet }) {
if (repoPath) {
args = ['-C', repoPath, ...args]
}
if (!quiet) {
core.info(`About to run \`git ${args.map((s) => `'${s}'`).join(' ')}\``)
}
return await execFile('git', args)
}
const { getCommitDetailsForPR } = require('./get-pr-commit-details.js')
/**
* @param {{
@@ -67,65 +46,13 @@ async function checkCommitMessages({ github, context, core, repoPath }) {
return
}
/**
* GitHub's API will return a maximum of 250 commits.
* We will use it if we can, but fall back to using git locally.
* This type is used to abstract over the differences between the two.
* @type {{
* message: string,
* sha: string,
* }[]}
*/
let commits
if (pr.commits < 250) {
commits = (
await github.paginate(github.rest.pulls.listCommits, {
...context.repo,
pull_number,
})
).map((commit) => ({ message: commit.commit.message, sha: commit.sha }))
} else {
await runGit({
args: ['fetch', `--depth=1`, 'origin', pr.base.sha],
repoPath,
core,
})
await runGit({
args: ['fetch', `--depth=${pr.commits + 1}`, 'origin', pr.head.sha],
repoPath,
core,
})
const shas = (
await runGit({
args: [
'rev-list',
`--max-count=${pr.commits}`,
`${pr.base.sha}..${pr.head.sha}`,
],
repoPath,
core,
})
).stdout
.split('\n')
.map((s) => s.trim())
.filter(Boolean)
commits = await Promise.all(
shas.map(async (sha) => ({
sha,
message: (
await runGit({
args: ['log', '--format=%s', '-1', sha],
repoPath,
core,
quiet: true,
})
).stdout,
})),
)
}
const commits = await getCommitDetailsForPR({
context,
core,
github,
pr,
repoPath,
})
const failures = new Set()