diff --git a/.github/actions/get-merge-commit/action.yml b/.github/actions/get-merge-commit/action.yml index 041817bbb3c8..1d37ef6abd43 100644 --- a/.github/actions/get-merge-commit/action.yml +++ b/.github/actions/get-merge-commit/action.yml @@ -35,52 +35,11 @@ runs: uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 with: script: | - if (context.eventName == 'push') return core.setOutput('mergedSha', context.sha) - - 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/eval.yml b/.github/workflows/eval.yml index 53ad022a559f..a89f2e4d5f9b 100644 --- a/.github/workflows/eval.yml +++ b/.github/workflows/eval.yml @@ -378,6 +378,7 @@ jobs: - name: Check if the PR can be merged and checkout the merge commit uses: ./.github/actions/get-merge-commit with: + mergedSha: ${{ inputs.mergedSha }} merged-as-untrusted: true - name: Install Nix 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..60225db0635e --- /dev/null +++ b/ci/github-script/prepare.js @@ -0,0 +1,57 @@ +module.exports = async function ({ github, context, core }) { + const pull_number = context.payload.pull_request.number + + for (const retryInterval of [5, 10, 20, 40, 80]) { + core.info('Checking whether the pull request can be merged...') + const prInfo = ( + await github.rest.pulls.get({ + ...context.repo, + pull_number, + }) + ).data + + if (prInfo.state !== 'open') throw new Error('PR is not open anymore.') + + if (prInfo.mergeable == null) { + core.info( + `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) { + core.info('The PR can be merged.') + + mergedSha = prInfo.merge_commit_sha + targetSha = ( + await github.rest.repos.getCommit({ + ...context.repo, + ref: prInfo.merge_commit_sha, + }) + ).data.parents[0].sha + } else { + core.warning('The PR has a merge conflict.') + + mergedSha = prInfo.head.sha + targetSha = ( + await github.rest.repos.compareCommitsWithBasehead({ + ...context.repo, + basehead: `${prInfo.base.sha}...${prInfo.head.sha}`, + }) + ).data.merge_base_commit.sha + } + + core.info( + `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.')