depot/third_party/nixpkgs/ci/request-reviews/get-reviewers.sh
Default email 555cd8a8f9 Project import generated by Copybara.
GitOrigin-RevId: 5633bcff0c6162b9e4b5f1264264611e950c8ec7
2024-10-09 18:51:18 +02:00

87 lines
2.6 KiB
Bash
Executable file

#!/usr/bin/env bash
# Get the code owners of the files changed by a PR,
# suitable to be consumed by the API endpoint to request reviews:
# https://docs.github.com/en/rest/pulls/review-requests?apiVersion=2022-11-28#request-reviewers-for-a-pull-request
set -euo pipefail
log() {
echo "$@" >&2
}
if (( "$#" < 5 )); then
log "Usage: $0 GIT_REPO BASE_REF HEAD_REF OWNERS_FILE PR_AUTHOR"
exit 1
fi
gitRepo=$1
baseRef=$2
headRef=$3
ownersFile=$4
prAuthor=$5
tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' exit
git -C "$gitRepo" diff --name-only --merge-base "$baseRef" "$headRef" > "$tmp/touched-files"
readarray -t touchedFiles < "$tmp/touched-files"
log "This PR touches ${#touchedFiles[@]} files"
# Get the owners file from the base, because we don't want to allow PRs to
# remove code owners to avoid pinging them
git -C "$gitRepo" show "$baseRef":"$ownersFile" > "$tmp"/codeowners
# Associative arrays with the team/user as the key for easy deduplication
declare -A teams users
for file in "${touchedFiles[@]}"; do
result=$(codeowners --file "$tmp"/codeowners "$file")
read -r file owners <<< "$result"
if [[ "$owners" == "(unowned)" ]]; then
log "File $file is unowned"
continue
fi
log "File $file is owned by $owners"
# Split up multiple owners, separated by arbitrary amounts of spaces
IFS=" " read -r -a entries <<< "$owners"
for entry in "${entries[@]}"; do
# GitHub technically also supports Emails as code owners,
# but we can't easily support that, so let's not
if [[ ! "$entry" =~ @(.*) ]]; then
warn -e "\e[33mCodeowner \"$entry\" for file $file is not valid: Must start with \"@\"\e[0m" >&2
# Don't fail, because the PR for which this script runs can't fix it,
# it has to be fixed in the base branch
continue
fi
# The first regex match is everything after the @
entry=${BASH_REMATCH[1]}
if [[ "$entry" =~ .*/(.*) ]]; then
# Teams look like $org/$team, where we only need $team for the API
# call to request reviews from teams
teams[${BASH_REMATCH[1]}]=
else
# Everything else is a user
users[$entry]=
fi
done
done
# Cannot request a review from the author
if [[ -v users[$prAuthor] ]]; then
log "One or more files are owned by the PR author, ignoring"
unset 'users[$prAuthor]'
fi
# Turn it into a JSON for the GitHub API call to request PR reviewers
jq -n \
--arg users "${!users[*]}" \
--arg teams "${!teams[*]}" \
'{
reviewers: $users | split(" "),
team_reviewers: $teams | split(" ")
}'