forked from mantidproject/jenkins-scripts
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcheck_pullrequest_mergeable.sh
More file actions
executable file
·157 lines (138 loc) · 4.6 KB
/
check_pullrequest_mergeable.sh
File metadata and controls
executable file
·157 lines (138 loc) · 4.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#!/bin/bash
# Check if a given pull request is in a mergeable state
# See https://docs.github.com/en/rest/guides/getting-started-with-the-git-database-api#checking-mergeability-of-pull-requests
# for the background to the steps followed here.
# It is assumend an environment variable GITHUB_OAUTH_TOKEN is defined
# An exit status of:
# - 0: pull request can be merged
# - 1: pull request has conflicts
# - 2: other error
EXIT_STATUS_MERGEABLE=0
EXIT_STATUS_ERRORS=1
EXIT_STATUS_CONFLICTS=2
function usage {
echo 'Check if a given pull request is in a mergeable state'
echo "Usage: $0 owner/repo pull_request_number"
exit $EXIT_STATUS_ERRORS
}
if [[ $# -ne 2 ]]; then
usage
fi
BASE_REPO=$1
PULL_NUMBER=$2
GH_TOKEN=${GITHUB_OAUTH_TOKEN:?Missing GITHUB_OAUTH_TOKEN environment variable}
# Use curl or wget?
HAVE_CURL=false
HAVE_WGET=false
if [ $(command -v curl) ]; then
HAVE_CURL=true
elif [ $(command -v wget) ]; then
HAVE_WGET=true
else
echo "Unable to find curl or wget. Cannot continue"
exit $EXIT_STATUS_ERRORS
fi
# GET json data using either curl or wget depending on what is available
function _get_json() {
local endpoint=$1
local json_encoding_header="Content-Type: application/json; charset=utf-8"
if [[ ${HAVE_CURL} == true ]]; then
curl \
--silent \
--header "$json_encoding_header" \
--request GET \
$endpoint
else
# assume script exits if wget/curl not available
wget \
--quiet \
--output-document=- \
--header "$json_encoding_header" \
"$endpoint"
fi
}
# POST json data using either curl or wget depending on what is available
function _post_json() {
local endpoint="$1"
local data="$2"
local json_encoding_header="Content-Type: application/json; charset=utf-8"
local authorization_header="Authorization: bearer ${GH_TOKEN}"
if [[ ${HAVE_CURL} == true ]]; then
curl \
--silent \
--header "$authorization_header" \
--header "$json_encoding_header" \
--request POST \
"$endpoint" \
--data "$data"
else
wget \
--quiet \
--output-document=- \
--header "$authorization_header" \
--header "$json_encoding_header" \
--post-data="$data" \
"$endpoint"
fi
}
# Query a single pull request
function pull_request_info() {
local repo=$1
local pr_number=$2
_get_json https://api.github.com/repos/${repo}/pulls/${pr_number}
}
function pull_request_mergeable() {
local orgrepo=$1
local pr_number=$2
# Form graphql query on the mergeable status
# as it allows for an unknown state while it is being calculated
local owner=$(echo $orgrepo | cut -d'/' -f 1)
local name=$(echo $orgrepo | cut -d'/' -f 2)
local query=$(cat <<EOF
query {
repository(owner:\"${owner}\", name: \"${name}\") {
pullRequest(number: ${pr_number}) { mergeable }
}
}
EOF
)
# At time of writing newlines are not allowed in the query
query="$(echo $query)"
# Make request
response=$(_post_json https://api.github.com/graphql "{\"query\": \"$query\"}")
# Parse JSON response and extract mergable status.
# Uses Python as jq is not available
echo $(python3 -c "import json;print(json.loads('$response')['data']['repository']['pullRequest']['mergeable'])")
}
# Trigger an asynchronous calculation of whether the pull request is mergeable
# Deliberately ignoring output as it might be out of date
echo "Triggering calculation of mergability for pull request #${PULL_NUMBER}"
pull_request_info ${BASE_REPO} ${PULL_NUMBER} > /dev/null
# Check value of mergeable flag. See https://docs.github.com/en/graphql/reference/enums#mergeablestate
# for allowed states
counter=0
max_tries=5
while [ "$counter" -lt $max_tries ]; do
mergeable="$(pull_request_mergeable ${BASE_REPO} ${PULL_NUMBER})"
if [ "$mergeable" == "MERGEABLE" ]; then
echo "Pull request can be merged."
exit $EXIT_STATUS_MERGEABLE
elif [ "$mergeable" == "CONFLICTING" ]; then
echo
echo "Pull request ${PULL_NUMBER} cannot be merged as there are conflicts. Please fix them by rebasing against the base branch."
echo
exit $EXIT_STATUS_CONFLICTS
elif [ "$mergeable" == "UNKNOWN" ]; then
echo "Mergeable status is still being computed."
counter=$(( counter + 1 ))
sleep 1
else
echo "Unknown state returned from pull request mergability check. Found '${mergable}', expected one of (MERGABLE|CONFLICTING|UNKNOWN)"
echo "Perhaps the pull request has been closed?"
exit $EXIT_STATUS_ERRORS
fi
done
if [ "$counter" -eq $max_tries ]; then
echo "Unable to determine mergability of pull request #${PULL_NUMBER}. Perhaps contact GitHub?"
exit $EXIT_STATUS_ERRORS
fi