-
Notifications
You must be signed in to change notification settings - Fork 1
/
entrypoint
executable file
·189 lines (166 loc) · 6.48 KB
/
entrypoint
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#!/bin/sh
REPOSITORY_OWNER="$INPUT_REPOSITORY_OWNER"
REPOSITORY_NAME="$INPUT_REPOSITORY_NAME"
PULL_REQUEST="$INPUT_PULL_REQUEST"
ADD_LINKS_BY_CONTENT="$INPUT_ADD_LINKS_BY_CONTENT"
_RETRY_OPTS="--connect-timeout 15 --max-time 60 --retry 10 --retry-delay 1 --retry-max-time 600"
prepareInputs() {
if [ -z "$REPOSITORY_OWNER" ]; then
REPOSITORY_OWNER=$(< "$GITHUB_EVENT_PATH" jq -r ".repository.owner.login")
fi
if [ -z "$REPOSITORY_NAME" ]; then
REPOSITORY_NAME=$(< "$GITHUB_EVENT_PATH" jq -r ".repository.name")
fi
if [ -z "$PULL_REQUEST" ]; then
PULL_REQUEST=$(< "$GITHUB_EVENT_PATH" jq ".number")
if [ "$PULL_REQUEST" = "null" ]; then
printf "PR number can't be retrieved from event data.\n" >&2
printf "You must define a pull request number using 'pr_number' input or" >&2
printf " run the action against a pull request event.\n" >&2
exit 1
fi
fi
}
get_issues() {
# create a temporal directory to store unique pull request numbers
linked_issues_tmpdir="/tmp/pr-linked-issues"
rm -rf "$linked_issues_tmpdir"
mkdir -p "$linked_issues_tmpdir"
# get linked issued from GraphQL API
script="query{repository(name:\\\"$REPOSITORY_NAME\\\",owner:\\\"$REPOSITORY_OWNER\\\"){pullRequest(number:$PULL_REQUEST){closingIssuesReferences(first:100){nodes{number}}}}}"
linked_issues_response="$(
curl -s -H 'Content-Type: application/json' \
-H "authorization: Bearer $GITHUB_TOKEN" \
-X POST -d "{ \"query\": \"$script\"}" https://api.github.com/graphql \
$_RETRY_OPTS
)"
# iterate over PRs and create files for each one of them
echo $linked_issues_response \
| jq ".data.repository.pullRequest.closingIssuesReferences.nodes[].number?" \
| while read linked_issue_number; do
touch "$linked_issues_tmpdir/$linked_issue_number"
done;
# add links to other issues by content
if [ -n "$ADD_LINKS_BY_CONTENT" ]; then
if [ -z "$REPOSITORY_OWNER" ] || [ -z "$REPOSITORY_NAME" ] || [ -z "$PULL_REQUEST" ]; then
# get body from event pull request
pull_request_body="$(< "$GITHUB_EVENT_PATH" jq ".pull_request.body")"
else
# get body from Github API
pull_request_body="$(
curl -s \
-H "Accept: application/vnd.github.v3+json" \
-H "authorization: Bearer $GITHUB_TOKEN" \
https://api.github.com/repos/$REPOSITORY_OWNER/$REPOSITORY_NAME/pulls/$PULL_REQUEST \
$_RETRY_OPTS \
| jq .body
)"
fi;
# iterate over placeholder expressions
echo "$ADD_LINKS_BY_CONTENT" | while read placeholder_line; do
# ignore empty input lines and comments
if [ -z "$placeholder_line" ] || [ "$(echo "$placeholder_line" | cut -c -1)" = "#" ]; then
continue
fi;
# check that every line of 'add_links_by_content' input contains the '{issue_number}' placeholder
if ! echo "$placeholder_line" | grep "{issue_number}" > /dev/null; then
printf "The line '%s' of the input 'add_links_by_content'" "$placeholder_line" >&2
printf " does not contains the '{issue_number}' placeholder.\n" >&2
exit 1
fi;
# build regex replacing '{issue_number}' with digit matcher using Posix ERE and
# escaping regex characters
#
# Current limitations:
# - '{{issue_number}}' placeholder does not work in Alpine (in Ubuntu is OK)
#
# Hexadecimal characters used in the following regexes
# \x2b -> '+'
# \x28 -> '('
# \x29 -> ')'
# \x7b -> '{'
# \x7c -> '|'
# \x7d -> '}'
regex="$(
echo "$placeholder_line" \
| sed -e "s/\*/\\\\*/g" \
-e "s/\x2b/\\\\+/g" \
-e "s/\./\\\\./g" \
-e "s/\[/\\\\[/g" \
-e "s/\]/\\\\]/g" \
-e "s/\\^/\\\\^/g" \
-e "s/\\$/\\\\$/g" \
-e "s/\x7c/\\\\\x7c/g" \
-e "s/\x28/\\\\\x28/g" \
-e "s/\x29/\\\\\x29/g" \
-e "s/\x7b(?!?issue_number)/\\\x7b/g" \
-e "s/\x7d(?<!?issue_number)/\\\x7d/g" \
-e "s/{issue_number}/([[:digit:]]+)/"
)"
# if grep doesn't found any matchs, it exists with code 1,
# which in combination with 'set -e' makes the program terminate
# unexpectedly without printing any errors, so the part
# '|| test $? = 1' makes it to only terminate if the grep exitcode
# is different to 1
more_linked_issues_by_content="$(
echo "$pull_request_body" \
| { grep -Eo "$regex" || test $? = 1; } \
| { grep -Eo "[[:digit:]]+" || test $? = 1; }
)"
echo "$more_linked_issues_by_content" | while read linked_issue_by_content; do
if [ -n "$linked_issue_by_content" ]; then
linked_issue_filepath="$linked_issues_tmpdir/$linked_issue_by_content"
if [ ! -f "$linked_issue_filepath" ]; then
touch "$linked_issue_filepath"
fi;
fi;
done;
done;
fi;
# output issue numbers numerically ordered (-v)
ls -v -1 "$linked_issues_tmpdir" | tr '\n' ',' | sed 's/,$//'
rm -rf "$linked_issues_tmpdir"
}
main() {
set -e
prepareInputs
issues="$(get_issues)"
echo "issues=$issues" >> "$GITHUB_OUTPUT"
# if we need don't need to get the issue owners, exit now
if [ -z "$INPUT_OWNERS" ]; then
return 0
fi;
PULL_REQUEST_OPENER="$(
curl -s "https://api.github.com/repos/$REPOSITORY_OWNER/$REPOSITORY_NAME/pulls/$PULL_REQUEST" \
-H "authorization: Bearer $GITHUB_TOKEN" \
$_RETRY_OPTS \
| jq -r .user.login
)"
touch /tmp/opener.txt /tmp/others.txt /tmp/null.txt
# iterate through linked issues
echo "$issues\n" | tr ',' '\n' | while read issue; do
owner="$(
curl -s "https://api.github.com/repos/$REPOSITORY_OWNER/$REPOSITORY_NAME/issues/$issue" \
-H "authorization: Bearer $GITHUB_TOKEN" \
$_RETRY_OPTS \
| jq -r .user.login
)"
if [ "$owner" = "$PULL_REQUEST_OPENER" ]; then
printf "$issue," >> /tmp/opener.txt
elif [ "$owner" = "null" ] && [ -n "$ADD_LINKS_BY_CONTENT" ]; then
# non existent issue
printf "$issue," >> /tmp/null.txt
else
printf "$issue," >> /tmp/others.txt
fi
done
echo "opener=$(< /tmp/opener.txt sed 's/[n,]\{1,\}$//')" >> "$GITHUB_OUTPUT"
echo "others=$(< /tmp/others.txt sed 's/[n,]\{1,\}$//')" >> "$GITHUB_OUTPUT"
rm -f /tmp/opener.txt /tmp/others.txt
if [ -n "$ADD_LINKS_BY_CONTENT" ]; then
# add null output
echo "null=$(< /tmp/null.txt sed 's/[n,]\{1,\}$//')" >> "$GITHUB_OUTPUT"
rm -rf /tmp/null.txt
fi;
}
main