555cd8a8f9
GitOrigin-RevId: 5633bcff0c6162b9e4b5f1264264611e950c8ec7
87 lines
2.6 KiB
Bash
Executable file
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(" ")
|
|
}'
|