diff --git a/ci/README.md b/ci/README.md index 40c3d0ed344b..11b53c6095e6 100644 --- a/ci/README.md +++ b/ci/README.md @@ -41,3 +41,58 @@ Why not just build the tooling right from the PRs Nixpkgs version? - Because it improves security, since we don't have to build potentially untrusted code from PRs. The tool only needs a very minimal Nix evaluation at runtime, which can work with [readonly-mode](https://nixos.org/manual/nix/stable/command-ref/opt-common.html#opt-readonly-mode) and [restrict-eval](https://nixos.org/manual/nix/stable/command-ref/conf-file.html#conf-restrict-eval). +## `get-merge-commit.sh GITHUB_REPO PR_NUMBER` + +Check whether a PR is mergeable and return the test merge commit as +[computed by GitHub](https://docs.github.com/en/rest/guides/using-the-rest-api-to-interact-with-your-git-database?apiVersion=2022-11-28#checking-mergeability-of-pull-requests). + +Arguments: +- `GITHUB_REPO`: The repository of the PR, e.g. `NixOS/nixpkgs` +- `PR_NUMBER`: The PR number, e.g. `1234` + +Exit codes: +- 0: The PR can be merged, the test merge commit hash is returned on stdout +- 1: The PR cannot be merged because it's not open anymore +- 2: The PR cannot be merged because it has a merge conflict +- 3: The merge commit isn't being computed, GitHub is likely having internal issues, unknown if the PR is mergeable + +### Usage + +This script can be used in GitHub Actions workflows as follows: + +```yaml +on: pull_request_target + +# We need a token to query the API, but it doesn't need any special permissions +permissions: {} + +jobs: + build: + name: Build + runs-on: ubuntu-latest + steps: + # Important: Because of `pull_request_target`, this doesn't check out the PR, + # but rather the base branch of the PR, which is needed so we don't run untrusted code + - uses: actions/checkout@ + with: + path: base + sparse-checkout: ci + - name: Resolving the merge commit + env: + GH_TOKEN: ${{ github.token }} + run: | + if mergedSha=$(base/ci/get-merge-commit.sh ${{ github.repository }} ${{ github.event.number }}); then + echo "Checking the merge commit $mergedSha" + echo "mergedSha=$mergedSha" >> "$GITHUB_ENV" + else + # Skipping so that no notifications are sent + echo "Skipping the rest..." + fi + rm -rf base + - uses: actions/checkout@ + # Add this to _all_ subsequent steps to skip them + if: env.mergedSha + with: + ref: ${{ env.mergedSha }} + - ... +``` diff --git a/ci/get-merge-commit.sh b/ci/get-merge-commit.sh index 75fc7fcbe60f..c62bb56dd993 100755 --- a/ci/get-merge-commit.sh +++ b/ci/get-merge-commit.sh @@ -1,6 +1,5 @@ #!/usr/bin/env bash -# This checks for mergeability of a pull request as recommended in -# https://docs.github.com/en/rest/guides/using-the-rest-api-to-interact-with-your-git-database?apiVersion=2022-11-28#checking-mergeability-of-pull-requests +# See ./README.md for docs set -euo pipefail @@ -31,14 +30,14 @@ while true; do state=$(jq -r .state <<< "$prInfo") if [[ "$state" != open ]]; then log "PR is not open anymore" - exit 2 + 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 1 + exit 3 else (( retryCount -= 1 )) || true @@ -59,5 +58,5 @@ if [[ "$mergeable" == "true" ]]; then jq -r .merge_commit_sha <<< "$prInfo" else log "The PR has a merge conflict" - exit 1 + exit 2 fi