diff --git a/.github/actions/get-merge-commit/action.yml b/.github/actions/get-merge-commit/action.yml index f54010d077a0..1d37ef6abd43 100644 --- a/.github/actions/get-merge-commit/action.yml +++ b/.github/actions/get-merge-commit/action.yml @@ -35,50 +35,11 @@ runs: uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 with: script: | - for (const retryInterval of [5, 10, 20, 40, 80]) { - console.log("Checking whether the pull request can be merged...") - const prInfo = (await github.rest.pulls.get({ - owner: context.repo.owner, - repo: context.repo.repo, - pull_number: context.payload.pull_request.number - })).data - - if (prInfo.state != 'open') throw new Error ("PR is not open anymore.") - - if (prInfo.mergeable == null) { - console.log(`GitHub is still computing whether this PR can be merged, waiting ${retryInterval} seconds before trying again...`) - await new Promise(resolve => setTimeout(resolve, retryInterval * 1000)) - continue - } - - let mergedSha, targetSha - - if (prInfo.mergeable) { - console.log("The PR can be merged.") - - mergedSha = prInfo.merge_commit_sha - targetSha = (await github.rest.repos.getCommit({ - owner: context.repo.owner, - repo: context.repo.repo, - ref: prInfo.merge_commit_sha - })).data.parents[0].sha - } else { - console.log("The PR has a merge conflict.") - - mergedSha = prInfo.head.sha - targetSha = (await github.rest.repos.compareCommitsWithBasehead({ - owner: context.repo.owner, - repo: context.repo.repo, - basehead: `${prInfo.base.sha}...${prInfo.head.sha}` - })).data.merge_base_commit.sha - } - - console.log(`Checking the commits:\nmerged:${mergedSha}\ntarget:${targetSha}`) - core.setOutput('mergedSha', mergedSha) - core.setOutput('targetSha', targetSha) - return - } - throw new Error("Not retrying anymore. It's likely that GitHub is having internal issues: check https://www.githubstatus.com.") + require('./ci/github-script/prepare.js')({ + github, + context, + core, + }) - if: inputs.merged-as-untrusted && (inputs.mergedSha || steps.commits.outputs.mergedSha) # Would be great to do the checkouts in git worktrees of the existing spare checkout instead, diff --git a/.github/workflows/codeowners-v2.yml b/.github/workflows/codeowners-v2.yml index 94cb82a68e73..b8efcd549aea 100644 --- a/.github/workflows/codeowners-v2.yml +++ b/.github/workflows/codeowners-v2.yml @@ -53,7 +53,9 @@ jobs: steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: - sparse-checkout: .github/actions + sparse-checkout: | + .github/actions + ci/github-script - name: Check if the PR can be merged and checkout the merge and target commits uses: ./.github/actions/get-merge-commit with: diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index c5a9b7ccf7c9..6c7e37b9db22 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -34,6 +34,7 @@ jobs: with: sparse-checkout: | .github/actions + ci/github-script ci/supportedBranches.js ci/supportedSystems.json - name: Check if the PR can be merged and get the test merge commit diff --git a/ci/github-script/prepare.js b/ci/github-script/prepare.js new file mode 100644 index 000000000000..967934bc2d7e --- /dev/null +++ b/ci/github-script/prepare.js @@ -0,0 +1,46 @@ +module.exports = async function ({ github, context, core }) { + for (const retryInterval of [5, 10, 20, 40, 80]) { + console.log("Checking whether the pull request can be merged...") + const prInfo = (await github.rest.pulls.get({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: context.payload.pull_request.number + })).data + + if (prInfo.state != 'open') throw new Error ("PR is not open anymore.") + + if (prInfo.mergeable == null) { + console.log(`GitHub is still computing whether this PR can be merged, waiting ${retryInterval} seconds before trying again...`) + await new Promise(resolve => setTimeout(resolve, retryInterval * 1000)) + continue + } + + let mergedSha, targetSha + + if (prInfo.mergeable) { + console.log("The PR can be merged.") + + mergedSha = prInfo.merge_commit_sha + targetSha = (await github.rest.repos.getCommit({ + owner: context.repo.owner, + repo: context.repo.repo, + ref: prInfo.merge_commit_sha + })).data.parents[0].sha + } else { + console.log("The PR has a merge conflict.") + + mergedSha = prInfo.head.sha + targetSha = (await github.rest.repos.compareCommitsWithBasehead({ + owner: context.repo.owner, + repo: context.repo.repo, + basehead: `${prInfo.base.sha}...${prInfo.head.sha}` + })).data.merge_base_commit.sha + } + + console.log(`Checking the commits:\nmerged:${mergedSha}\ntarget:${targetSha}`) + core.setOutput('mergedSha', mergedSha) + core.setOutput('targetSha', targetSha) + return + } + throw new Error("Not retrying anymore. It's likely that GitHub is having internal issues: check https://www.githubstatus.com.") +} diff --git a/ci/github-script/run b/ci/github-script/run index 3fe6e189eb96..ae107df73b51 100755 --- a/ci/github-script/run +++ b/ci/github-script/run @@ -39,6 +39,17 @@ async function run(action, owner, repo, pull_number, dry = true) { }) } +program + .command('prepare') + .description('Prepare relevant information of a pull request.') + .argument('', 'Owner of the GitHub repository to check (Example: NixOS)') + .argument('', 'Name of the GitHub repository to check (Example: nixpkgs)') + .argument('', 'Number of the Pull Request to check') + .action(async (owner, repo, pr) => { + const prepare = (await import('./prepare.js')).default + run(prepare, owner, repo, pr) + }) + program .command('commits') .description('Check commit structure of a pull request.')