# This script depends (at least) on git (>= 2.7) and jq. # It should be used like this: dev/tools/merge-pr.sh /PR number/
# Set SLOW_CONF to have the confirmation output wait for a newline # E.g. call $ SLOW_CONF= dev/tools/merge-pr.sh /PR number/ # emacs doesn't send characters until the RET so we can't quick_conf if [ -z ${SLOW_CONF+x} ] || [ -n "$INSIDE_EMACS" ]; then
QUICK_CONF="-n 1" else
QUICK_CONF="" fi
check_util() { if ! command -v "$1" > /dev/null 2>&1; then
error "this script requires the $1 command line utility"
exit 1 fi
}
ask_confirmation() {
read -p "Continue anyway? [y/N] " $QUICK_CONF -r echo if [[ ! $REPLY =~ ^[Yy]$ ]] then
exit 1 fi
}
curl_paginate_array() { # as per https://developer.github.com/v3/guides/traversing-with-pagination/#changing-the-number-of-items-received, GitHub will never give us more than 100
url="$1?per_page=100" # we keep fetching pages until the response is below the per-page limit (possibly 0 elements)
page=1 while true; do
response="$(curl -s "${url}&page=${page}")" echo"${response}" if [ "$(jq 'length' <<< "$response")" -lt 100 ]; then# done
break fi
page=$(($page + 1)) done | jq '[.[]]'# we concatenate the arrays
}
CURRENT_LOCAL_BRANCH=$(git rev-parse --abbrev-ref HEAD)
info "you are merging in $CURRENT_LOCAL_BRANCH"
REMOTE=$(git config --get "branch.$CURRENT_LOCAL_BRANCH.remote" || true) if [ -z "$REMOTE" ]; then
error "branch $CURRENT_LOCAL_BRANCH has not associated remote"
error "don't know where to fetch the PR from"
error "please run: git branch --set-upstream-to=THE_REMOTE/$CURRENT_LOCAL_BRANCH"
exit 1 fi
REMOTE_URL=$(git remote get-url "$REMOTE" --all) if [ "$REMOTE_URL" != "${OFFICIAL_REMOTE_GIT_URL}" ] && \
[ "$REMOTE_URL" != "${OFFICIAL_REMOTE_GIT_URL}.git" ] && \
[ "$REMOTE_URL" != "https://${OFFICIAL_REMOTE_HTTPS_URL}" ] && \
[ "$REMOTE_URL" != "https://${OFFICIAL_REMOTE_HTTPS_URL}.git" ] && \
[[ "$REMOTE_URL" != "https://"*"@${OFFICIAL_REMOTE_HTTPS_URL}" ]] && \
[[ "$REMOTE_URL" != "https://"*"@${OFFICIAL_REMOTE_HTTPS_URL}.git" ]] ; then
error "remote $REMOTE does not point to the official Rocq repo"
error "that is $OFFICIAL_REMOTE_GIT_URL"
error "it points to $REMOTE_URL instead"
ask_confirmation fi
info "remote for $CURRENT_LOCAL_BRANCH is $REMOTE"
info "fetching from $REMOTE the PR"
git remote update "$REMOTE" if ! git ls-remote "$REMOTE" | grep pull >/dev/null; then
error "remote $REMOTE is not configured to fetch pull requests"
error "run: git config remote.$REMOTE.fetch +refs/pull/*/head:refs/remotes/$REMOTE/pr/*"
exit 1 fi
git fetch "$REMOTE""refs/pull/$PR/head"
COMMIT=$(git rev-parse FETCH_HEAD)
info "commit for PR $PR is $COMMIT"
# Sanity check: merge to a different branch
if [ "$BASE_BRANCH" != "$CURRENT_LOCAL_BRANCH" ]; then
error "PR requests merge in $BASE_BRANCH but you are merging in $CURRENT_LOCAL_BRANCH"
ask_confirmation fi;
# Sanity check: the local branch is up-to-date with upstream
LOCAL_BRANCH_COMMIT=$(git rev-parse HEAD)
UPSTREAM_COMMIT=$(git rev-parse @{u}) if [ "$LOCAL_BRANCH_COMMIT" != "$UPSTREAM_COMMIT" ]; then
# Is it just that the upstream branch is behind? # It could just be that we merged other PRs and we didn't push yet
if [ "$BASE_BRANCH" = master ] \
&& git merge-base --is-ancestor -- "$UPSTREAM_COMMIT""$LOCAL_BRANCH_COMMIT"; then
warning "Your branch is ahead of ${REMOTE}."
warning "On master, GitHub's branch protection rule prevents merging several PRs at once."
warning "You should run [git push ${REMOTE}] between each call to the merge script."
ask_confirmation else
error "Local branch is not up-to-date with ${REMOTE}."
error "Pull before merging." # This check should never be bypassed.
exit 1 fi fi
if ! git diff --quiet "$BASE_COMMIT""$LOCAL_BRANCH_COMMIT" -- "${CI_FILES[@]}" then
warning "This PR didn't run with the latest version of CI."
warning "It is probably a good idea to ask for a rebase."
read -p "Do you want to see the diff? [Y/n] " $QUICK_CONF -r echo if [[ ! $REPLY =~ ^[Nn]$ ]] then
git diff "$BASE_COMMIT""$LOCAL_BRANCH_COMMIT" -- "${CI_FILES[@]}" fi
ask_confirmation fi
# Sanity check: CI failed
STATUS=$(curl -s "$API/commits/$COMMIT/status")
if [ "$(echo "$STATUS" | jq -r '.state')" != "success" ]; then
error "CI unsuccessful on $(echo "$STATUS" |
jq -r -c '.statuses|map(select(.state != "success"))|map(.context)')"
ask_confirmation fi;
# Sanity check: has labels named "needs:"
NEEDS_LABELS=$(echo"$PRDATA" | jq -rc '.labels | map(select(.name | match("needs:"))) | map(.name)') if [ "$NEEDS_LABELS" != "[]" ]; then
error "needs:something labels still present: $NEEDS_LABELS"
ask_confirmation fi
# Sanity check: has milestone
MILESTONE=$(echo"$PRDATA" | jq -rc '.milestone.title') if [ "$MILESTONE" = "null" ]; then
error "no milestone set, please set one"
ask_confirmation fi
# Sanity check: has kind
KIND=$(echo"$PRDATA" | jq -rc '.labels | map(select(.name | match("kind:"))) | map(.name)') if [ "$KIND" = "[]" ]; then
error "no kind:something label set, please set one"
ask_confirmation fi
# Sanity check: user.signingkey if [ -z "$(git config user.signingkey)" ]; then
warning "git config user.signingkey is empty"
warning "gpg will guess a key out of your git config user.* data" fi
# Generate commit message
info "Fetching review data"
reviews=$(curl_paginate_array "$API/pulls/$PR/reviews")
msg="Merge PR #$PR: $TITLE"
# TODO: improve this check if ! git diff --quiet --diff-filter=A "$REMOTE/$CURRENT_LOCAL_BRANCH" -- dev/ci/user-overlays; then
warning "this PR has overlays, please check the following:"
warning "- each overlay has a corresponding open PR on the upstream repo"
warning "- after merging please notify the upstream they can merge the PR" fi
¤ Dauer der Verarbeitung: 0.29 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.