github-merge-pr: doc: Install extra git-filter-repo
[maintainer-tools.git] / github-merge-pr.sh
index 6d0dbe558aeb9178124b01b2e1c97756df4f01e8..1bd3e2f0b072146f66a42fb7142817edcc9e078d 100755 (executable)
@@ -1,22 +1,49 @@
 #!/bin/bash
 
-# Github repository, just the name/repo part, no .git suffix, no base url!
-REPO="openwrt/openwrt"
+# How to setup the repository to make this correctly work
+# 1. Clone repo and make sure you can correctly push to that
+#    (example with openwrt main repo you need to use ssh remote url)
+# 2. Make sure you can correctly push and force push to the github
+#    repository
+#
+# Make sure to install the extra git-filter-repo package.
+#
+# Usage: github-merge-pr.sh PR_NUMBER BRANCH REPO_NAME
+#
+# BRANCH is optional and defaults to main.
+# REPO_NAME is optional and defaults to openwrt. It does
+# describe the repository name to use to pull PR info from.
+
+# Script .config variables
+# Github repository owner or organization name.
+# By default set to openwrt, set this line in .config to overwrite
+# the default value.
+GITHUB_REPO_OWNER="openwrt"
 
 # Your repository token, generate this token at your profile page:
 # - Navigate to https://github.com/settings/tokens
 # - Click on "Generate new token"
 # - Enter a description, e.g. "pr.sh" and pick the "repo" scope
 # - Hit "Generate token"
-#TOKEN="d41d8cd98f00b204e9800998ecf8427e"
+# Set this line in .config to provide a GITHUB_TOKEN and add comments
+#GITHUB_TOKEN="d41d8cd98f00b204e9800998ecf8427e"
 #
-# Uncomment this line to use SSH key to rebase PR branch
-# USE_SSH=1
+# Set this line in .config to use SSH key to rebase PR branch
+# GITHUB_USE_SSH=1
+
+SCRIPT_DIR="$(dirname $0)"
+[ -h $0 ] && SCRIPT_DIR="$(dirname $(readlink $0))"
+
+# Everything in .config will overwrite the default values set up
+[ -f "$SCRIPT_DIR/.config" ] && source "$SCRIPT_DIR"/.config
 
 PRID="$1"
 BRANCH="${2:-main}"
-DRY_RUN="$3"
+GITHUB_REPO_NAME="${3:-openwrt}"
+DRY_RUN="$4"
+
 GIT=git
+REPO="$GITHUB_REPO_OWNER"/"$GITHUB_REPO_NAME"
 
 yesno() {
        local prompt="$1"
@@ -52,7 +79,13 @@ if [ -z "$(git branch --list "$BRANCH")" ]; then
        exit 2
 fi
 
-if ! PR_INFO="$(curl -f -s "https://api.github.com/repos/$REPO/pulls/$PRID")"; then
+if [ -n "$GITHUB_TOKEN" ]; then
+       CURL_CMD=" --user \"$GITHUB_TOKEN:x-oauth-basic\" "
+else
+       CURL_CMD=" "
+fi
+
+if ! PR_INFO="$(curl $CURL_CMD -f -s "https://api.github.com/repos/$REPO/pulls/$PRID")"; then
        echo "Failed fetch PR #$PRID info" >&2
        exit 3
 fi
@@ -78,7 +111,7 @@ fi
 PR_USER="$(echo "$PR_INFO" | jq -r ".head.user.login")"
 PR_BRANCH="$(echo "$PR_INFO" | jq -r ".head.ref")"
 LOCAL_PR_BRANCH="$PR_BRANCH"-"$PR_USER"
-if [ "$USE_SSH" = "1" ]; then
+if [ "$GITHUB_USE_SSH" = "1" ]; then
        PR_REPO="$(echo "$PR_INFO" | jq -r ".head.repo.ssh_url")"
 else
        PR_REPO="$(echo "$PR_INFO" | jq -r ".head.repo.html_url")"
@@ -92,7 +125,7 @@ fi
 echo "Fetching remote $PR_USER"
 $GIT fetch $PR_USER $PR_BRANCH
 
-if [ "$(echo "$PR_INFO" | jq -r ".maintainer_can_modify")" == "true" ]; then
+if [ "$(echo "$PR_INFO" | jq -r ".maintainer_can_modify")" == "true" ] || [ "$IGNORE_MERGEABLE" = "1" ]; then
        echo "Creating branch $LOCAL_PR_BRANCH for $PR_BRANCH"
        if ! $GIT checkout -b $LOCAL_PR_BRANCH $PR_USER/$PR_BRANCH; then
                echo "Failed to checkout new branch $PR_BRANCH from $PR_USER/$PR_BRANCH" >&2
@@ -105,6 +138,43 @@ if [ "$(echo "$PR_INFO" | jq -r ".maintainer_can_modify")" == "true" ]; then
                exit 9
        fi
 
+       # Add to each commit Link: https://github.com/$REPO/pull/$PRID
+       if ! $GIT filter-repo --message-callback "
+               return message + b\"Link: https://github.com/$REPO/pull/$PRID\"
+       " --refs $BRANCH..$LOCAL_PR_BRANCH --force; then
+               echo "Failed to add Link: Pull Request tag" >&2
+               exit 9
+       fi
+
+       # Remove any previous SoB tag if the Pull Request Author and Committer match
+       if ! $GIT filter-repo --message-callback "
+               return message.replace(b\"Signed-off-by: $(git config user.name) <$(git config user.email)>\n\",b\"\")
+       " --refs $BRANCH..$LOCAL_PR_BRANCH --force; then
+               echo "Failed to remove previous Committer SoB tag" >&2
+               exit 9
+       fi
+
+       # Add Committer SoB to better reference who merged the thing last
+       if ! $GIT rebase origin/$BRANCH $LOCAL_PR_BRANCH --exec "git commit -s --amend -C HEAD"; then
+               echo "Failed to add Committer SoB tag" >&2
+               exit 9
+       fi
+
+       if [ "$GITHUB_NO_PUSH" = "1" ]; then
+               echo "next commands:"
+               if [ "$(echo "$PR_INFO" | jq -r ".maintainer_can_modify")" == "true" ]; then
+                       echo "$GIT push $PR_USER HEAD:$PR_BRANCH --force"
+                       echo "$GIT checkout $BRANCH"
+                       echo "$GIT merge --ff-only $PR_USER/$PR_BRANCH"
+               else
+                       echo "$GIT checkout $BRANCH"
+                       echo "$GIT merge --ff-only $LOCAL_PR_BRANCH"
+               fi
+               echo "$GIT push"
+               echo "$GIT branch -D $LOCAL_PR_BRANCH"
+               exit 20
+       fi
+
        echo "Force pushing $LOCAL_PR_BRANCH to HEAD:$PR_BRANCH for $PR_USER"
        if ! $GIT push $PR_USER HEAD:$PR_BRANCH --force; then
                echo "Failed to force push HEAD to $PR_USER" >&2
@@ -134,7 +204,7 @@ else
                # Default close comment
                COMMENT="Thanks! Rebased on top of $BRANCH and merged!"
 
-               if [ -n "$TOKEN" ] && [ -z "$DRY_RUN" ]; then
+               if [ -n "$GITHUB_TOKEN" ] && [ -z "$DRY_RUN" ]; then
                        echo ""
                        echo "Enter a comment and hit <enter> to close the PR at Github automatically now."
                        echo "Hit <ctrl>-<c> to exit."
@@ -152,8 +222,8 @@ else
                        comment="${comment//\"/\\\"}"
                        comment="$(printf '{"body":"%s"}' "$comment")"
 
-                       if ! curl -s -o /dev/null -w "%{http_code} %{url_effective}\\n" --user "$TOKEN:x-oauth-basic" --request POST --data "$comment" "https://api.github.com/repos/$REPO/issues/$PRID/comments" || \
-                       ! curl -s -o /dev/null -w "%{http_code} %{url_effective}\\n" --user "$TOKEN:x-oauth-basic" --request PATCH --data '{"state":"closed"}' "https://api.github.com/repos/$REPO/pulls/$PRID"
+                       if ! curl -s -o /dev/null -w "%{http_code} %{url_effective}\\n" --user "$GITHUB_TOKEN:x-oauth-basic" --request POST --data "$comment" "https://api.github.com/repos/$REPO/issues/$PRID/comments" || \
+                       ! curl -s -o /dev/null -w "%{http_code} %{url_effective}\\n" --user "$GITHUB_TOKEN:x-oauth-basic" --request PATCH --data '{"state":"closed"}' "https://api.github.com/repos/$REPO/pulls/$PRID"
                        then
                                echo ""                                                     >&2
                                echo "Something failed while sending comment to the PR via ">&2