diff --git a/.github/actions/get-merge-commit.yml b/.github/actions/get-merge-commit.yml new file mode 100644 index 000000000..8c67fdfc9 --- /dev/null +++ b/.github/actions/get-merge-commit.yml @@ -0,0 +1,103 @@ +# This file incorporates work covered by the following copyright and +# permission notice +# +# Copyright (c) 2003-2025 Eelco Dolstra and the Nixpkgs/NixOS contributors +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +name: Get merge commit +description: Get a merge commit of a given pull request + +inputs: + repository: + description: Repository containing the pull request + required: false + pull-request-id: + description: ID of a pull request + required: true + +outputs: + merge-commit-sha: + description: Git SHA of a merge commit + value: ${{ steps.query.outputs.merge-commit-sha }} + +runs: + using: composite + + steps: + - name: Wait for GitHub to report merge commit + id: query + shell: bash + env: + GITHUB_REPO: ${{ inputs.repository || github.repository }} + PR_ID: ${{ inputs.pull-request-id }} + # https://github.com/NixOS/nixpkgs/blob/8f77f3600f1ee775b85dc2c72fd842768e486ec9/ci/get-merge-commit.sh + run: | + set -euo pipefail + + log() { + echo "$@" >&2 + } + + # Retry the API query this many times + retryCount=5 + # Start with 5 seconds, but double every retry + retryInterval=5 + + while true; do + log "Checking whether the pull request can be merged" + prInfo=$(gh api \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + "/repos/$GITHUB_REPO/pulls/$PR_ID") + + # Non-open PRs won't have their mergeability computed no matter what + state=$(jq -r .state <<<"$prInfo") + if [[ "$state" != open ]]; then + log "PR is not open anymore" + exit 1 + fi + + mergeable=$(jq -r .mergeable <<<"$prInfo") + if [[ "$mergeable" == "null" ]]; then + if ((retryCount == 0)); then + log "Not retrying anymore. It's likely that GitHub is having internal issues: check https://www.githubstatus.com/" + exit 3 + else + ((retryCount -= 1)) || true + + # null indicates that GitHub is still computing whether it's mergeable + # Wait a couple seconds before trying again + log "GitHub is still computing whether this PR can be merged, waiting $retryInterval seconds before trying again ($retryCount retries left)" + sleep "$retryInterval" + + ((retryInterval *= 2)) || true + fi + else + break + fi + done + + if [[ "$mergeable" == "true" ]]; then + echo "merge-commit-sha=$(jq -r .merge_commit_sha <<<"$prInfo")" >> "$GITHUB_OUTPUT" + else + echo "# 🚨 The PR has a merge conflict!" >>> "$GITHUB_STEP_SUMMARY" + exit 2 + fi