mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-06-11 12:15:34 +03:00
workflows/get-merge-commit: inline get-merge-commit.sh script as github-script
The reason this was a separate shell script was, that this would be included in multiple workflows separately. But a while ago this had been changed to a re-usable workflow, so we can just as well inline the script. This also allows us to use actions/github-script, which makes for a much more readable script than the bash script before.
This commit is contained in:
parent
f66ede7fd3
commit
277f7b998c
3 changed files with 41 additions and 128 deletions
61
.github/workflows/get-merge-commit.yml
vendored
61
.github/workflows/get-merge-commit.yml
vendored
|
@ -22,8 +22,8 @@ jobs:
|
||||||
resolve-merge-commit:
|
resolve-merge-commit:
|
||||||
runs-on: ubuntu-24.04-arm
|
runs-on: ubuntu-24.04-arm
|
||||||
outputs:
|
outputs:
|
||||||
mergedSha: ${{ steps.merged.outputs.mergedSha }}
|
mergedSha: ${{ fromJSON(steps.merged.outputs.result).mergedSha }}
|
||||||
targetSha: ${{ steps.merged.outputs.targetSha }}
|
targetSha: ${{ fromJSON(steps.merged.outputs.result).targetSha }}
|
||||||
systems: ${{ steps.systems.outputs.systems }}
|
systems: ${{ steps.systems.outputs.systems }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
@ -33,24 +33,45 @@ jobs:
|
||||||
|
|
||||||
- name: Check if the PR can be merged and get the test merge commit
|
- name: Check if the PR can be merged and get the test merge commit
|
||||||
id: merged
|
id: merged
|
||||||
env:
|
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||||
GH_TOKEN: ${{ github.token }}
|
with:
|
||||||
GH_EVENT: ${{ github.event_name }}
|
script: |
|
||||||
run: |
|
if (context.eventName == 'push') return { mergedSha: context.sha }
|
||||||
case "$GH_EVENT" in
|
|
||||||
push)
|
for (const retryInterval of [5, 10, 20, 40, 80]) {
|
||||||
echo "mergedSha=${{ github.sha }}" >> "$GITHUB_OUTPUT"
|
console.log("Checking whether the pull request can be merged...")
|
||||||
;;
|
const prInfo = (await github.rest.pulls.get({
|
||||||
pull_request*)
|
owner: context.repo.owner,
|
||||||
if commits=$(base/ci/get-merge-commit.sh ${{ github.repository }} ${{ github.event.number }}); then
|
repo: context.repo.repo,
|
||||||
echo -e "Checking the commits:\n$commits"
|
pull_number: context.payload.pull_request.number
|
||||||
echo "$commits" >> "$GITHUB_OUTPUT"
|
})).data
|
||||||
else
|
|
||||||
# Skipping so that no notifications are sent
|
if (prInfo.state != 'open') throw new Error ("PR is not open anymore.")
|
||||||
echo "Skipping the rest..."
|
|
||||||
fi
|
if (prInfo.mergeable == null) {
|
||||||
;;
|
console.log(`GitHub is still computing whether this PR can be merged, waiting ${retryInterval} seconds before trying again...`)
|
||||||
esac
|
await new Promise(resolve => setTimeout(resolve, retryInterval * 1000))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prInfo.mergeable) {
|
||||||
|
console.log("The PR can be merged.")
|
||||||
|
|
||||||
|
const mergedSha = prInfo.merge_commit_sha
|
||||||
|
const targetSha = (await github.rest.repos.getCommit({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
ref: prInfo.merge_commit_sha
|
||||||
|
})).data.parents[0].sha
|
||||||
|
|
||||||
|
console.log(`Checking the commits:\nmerged:${mergedSha}\ntarget:${targetSha}`)
|
||||||
|
|
||||||
|
return { mergedSha, targetSha }
|
||||||
|
} else {
|
||||||
|
throw new Error("The PR has a merge conflict. Skipping the rest...")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Error("Not retrying anymore. It's likely that GitHub is having internal issues: check https://www.githubstatus.com.")
|
||||||
|
|
||||||
- name: Load supported systems
|
- name: Load supported systems
|
||||||
id: systems
|
id: systems
|
||||||
|
|
43
ci/README.md
43
ci/README.md
|
@ -40,46 +40,3 @@ Why not just build the tooling right from the PRs Nixpkgs version?
|
||||||
- Because it makes the CI check very fast, since no Nix builds need to be done, even for mass rebuilds.
|
- Because it makes the CI check very fast, since no Nix builds need to be done, even for mass rebuilds.
|
||||||
- Because it improves security, since we don't have to build potentially untrusted code from PRs.
|
- 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).
|
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) and its parent.
|
|
||||||
|
|
||||||
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 hashes of the test merge commit and the target commit are 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 is implemented as a reusable GitHub Actions workflow, and can be used 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:
|
|
||||||
get-merge-commit:
|
|
||||||
# use the relative path of the get-merge-commit workflow yaml here
|
|
||||||
uses: ./.github/workflows/get-merge-commit.yml
|
|
||||||
|
|
||||||
build:
|
|
||||||
name: Build
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
needs: get-merge-commit
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@<VERSION>
|
|
||||||
# Add this to _all_ subsequent steps to skip them
|
|
||||||
if: needs.get-merge-commit.outputs.mergedSha
|
|
||||||
with:
|
|
||||||
ref: ${{ needs.get-merge-commit.outputs.mergedSha }}
|
|
||||||
- ...
|
|
||||||
```
|
|
||||||
|
|
|
@ -1,65 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
# See ./README.md for docs
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
log() {
|
|
||||||
echo "$@" >&2
|
|
||||||
}
|
|
||||||
|
|
||||||
if (( $# < 2 )); then
|
|
||||||
log "Usage: $0 GITHUB_REPO PR_NUMBER"
|
|
||||||
exit 99
|
|
||||||
fi
|
|
||||||
repo=$1
|
|
||||||
prNumber=$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/$repo/pulls/$prNumber")
|
|
||||||
|
|
||||||
# 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
|
|
||||||
log "The PR can be merged"
|
|
||||||
mergedSha="$(jq -r .merge_commit_sha <<< "$prInfo")"
|
|
||||||
echo "mergedSha=$mergedSha"
|
|
||||||
targetSha="$(gh api "/repos/$repo/commits/$mergedSha" --jq '.parents[0].sha')"
|
|
||||||
echo "targetSha=$targetSha"
|
|
||||||
else
|
|
||||||
log "The PR has a merge conflict"
|
|
||||||
exit 2
|
|
||||||
fi
|
|
Loading…
Add table
Add a link
Reference in a new issue