github-merge-pr: handle user using master as pushing repo
[maintainer-tools.git] / github-merge-pr.sh
1 #!/bin/bash
2
3 # Github repository, just the name/repo part, no .git suffix, no base url!
4 REPO="openwrt/openwrt"
5
6 # Your repository token, generate this token at your profile page:
7 # - Navigate to https://github.com/settings/tokens
8 # - Click on "Generate new token"
9 # - Enter a description, e.g. "pr.sh" and pick the "repo" scope
10 # - Hit "Generate token"
11 #TOKEN="d41d8cd98f00b204e9800998ecf8427e"
12
13 PRID="$1"
14 BRANCH="${2:-master}"
15 DRY_RUN="$3"
16 GIT=git
17
18 if ! command -v jq &> /dev/null; then
19 echo "jq could not be found! This script require jq!"
20 exit 1
21 fi
22
23 if [ -z "$PRID" -o -n "${PRID//[0-9]*/}" ]; then
24 echo "Usage: $0 <PR-ID> [rebase-branch] [dry-run]" >&2
25 exit 1
26 fi
27
28 if [ -n "$DRY_RUN" ]; then
29 GIT="echo git"
30 fi
31
32 if [ -z "$(git branch --list "$BRANCH")" ]; then
33 echo "Given rebase branch '$BRANCH' does not exist!" >&2
34 exit 2
35 fi
36
37 if ! PR_INFO="$(curl -f -s "https://api.github.com/repos/$REPO/pulls/$PRID")"; then
38 echo "Failed fetch PR #$PRID info" >&2
39 exit 3
40 fi
41
42 if [ "$(echo "$PR_INFO" | jq -r ".maintainer_can_modify")" == "false" ]; then
43 echo "PR #$PRID can't be force pushed by maintainers. Can't merge this PR!" >&2
44 exit 4
45 fi
46
47 if [ "$(echo "$PR_INFO" | jq -r ".mergeable")" == "false" ]; then
48 echo "PR #$PRID is not mergeable for Github.com. Check the PR!" >&2
49 exit 5
50 fi
51
52 echo "Pulling current $BRANCH from origin"
53 $GIT checkout $BRANCH
54 $GIT fetch origin
55
56 if ! $GIT rebase origin/$BRANCH; then
57 echo "Failed to rebase $BRANCH with origin/$BRANCH" >&2
58 exit 7
59 fi
60
61 PR_USER="$(echo "$PR_INFO" | jq -r ".head.user.login")"
62 PR_BRANCH="$(echo "$PR_INFO" | jq -r ".head.ref")"
63 LOCAL_PR_BRANCH="$PR_BRANCH"-"$PR_USER"
64 PR_REPO="$(echo "$PR_INFO" | jq -r ".head.repo.html_url")"
65
66 if ! $GIT remote get-url $PR_USER &> /dev/null || [ -n "$DRY_RUN" ]; then
67 echo "Adding $PR_USER with repo $PR_REPO to remote"
68 $GIT remote add $PR_USER $PR_REPO
69 fi
70
71 echo "Fetching remote $PR_USER"
72 $GIT fetch $PR_USER
73
74 echo "Creating branch $LOCAL_PR_BRANCH for $PR_BRANCH"
75 if ! $GIT checkout -b $LOCAL_PR_BRANCH $PR_USER/$PR_BRANCH; then
76 echo "Failed to checkout new branch $PR_BRANCH from $PR_USER/$PR_BRANCH" >&2
77 exit 8
78 fi
79
80 echo "Rebasing $LOCAL_PR_BRANCH on top of $BRANCH"
81 if ! $GIT rebase origin/$BRANCH; then
82 echo "Failed to rebase $PR_BRANCH with origin/$BRANCH" >&2
83 exit 9
84 fi
85
86 echo "Force pushing $LOCAL_PR_BRANCH to HEAD:$PR_BRANCH for $PR_USER"
87 if ! $GIT push $PR_USER HEAD:$PR_BRANCH --force; then
88 echo "Failed to force push HEAD to $PR_USER" >&2
89 exit 10
90 fi
91
92 echo "Returning to $BRANCH"
93 $GIT checkout $BRANCH
94
95 echo "Actually merging the PR #$PRID from branch $PR_USER/$PR_BRANCH"
96 if ! $GIT merge --ff-only $PR_USER/$PR_BRANCH; then
97 echo "Failed to merge $PR_USER/$PR_BRANCH on $BRANCH" >&2
98 exit 11
99 fi
100
101 echo "Pushing to openwrt git server"
102 if ! $GIT push; then
103 echo "Failed to push to $BRANCH but left branch as is." >&2
104 exit 12
105 fi
106
107 echo "Deleting branch $LOCAL_PR_BRANCH"
108 $GIT branch -D $LOCAL_PR_BRANCH
109
110 # Default close comment
111 COMMENT="Thanks! Rebased on top of $BRANCH and merged!"
112
113 if [ -n "$TOKEN" ] && [ -z "$DRY_RUN" ]; then
114 echo ""
115 echo "Enter a comment and hit <enter> to close the PR at Github automatically now."
116 echo "Hit <ctrl>-<c> to exit."
117 echo ""
118 echo "If you do not provide a comment, the default will be: "
119 echo "[$COMMENT]"
120
121 echo -n "Comment > "
122 read usercomment
123
124 echo "Sending message to PR..."
125
126 comment="${usercomment:-$COMMENT}"
127 comment="${comment//\\/\\\\}"
128 comment="${comment//\"/\\\"}"
129 comment="$(printf '{"body":"%s"}' "$comment")"
130
131 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" || \
132 ! 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"
133 then
134 echo "" >&2
135 echo "Something failed while sending comment to the PR via ">&2
136 echo "the Github API, please review the state manually at " >&2
137 echo "https://github.com/$REPO/pull/$PRID" >&2
138 exit 6
139 fi
140 fi
141
142 echo ""
143 echo "The PR has been merged!"
144
145 exit 0