-
Notifications
You must be signed in to change notification settings - Fork 1.8k
/
Copy pathprow-vale-review.sh
executable file
·135 lines (106 loc) · 6.91 KB
/
prow-vale-review.sh
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
#!/bin/bash
# This runs Vale on updated files in last commit, checks if the Vale alerts are on new/modified lines, and if so, builds curl request
# for GitHub review comment API. Also checks if a commment already exists before posting.
# To test locally, create a Github personal access token and export a $GITHUB_AUTH_TOKEN environmental variable to use the token
# Check if jq is installed
hash jq 2>/dev/null || { echo >&2 "Error: jq is not installed"; exit 1; }
# Set $PULL_NUMBER and $COMMIT_ID for local testing. Otherwise use variables passed by Prow
if [ $# -eq 0 ]; then
COMMIT_ID=$(git log -n 1 --pretty=format:"%H")
PULL_NUMBER=$(curl -s "https://api.github.com/search/issues?q=$COMMIT_ID" | jq '.items[0].number')
else
PULL_NUMBER=$1
COMMIT_ID=$2
fi
FILES=$(git diff --name-only HEAD~1 HEAD --diff-filter=d "*.adoc" ':(exclude)_unused_topics/*' ':(exclude)rest_api/*' ':(exclude)microshift_rest_api/*' ':(exclude)modules/virt-runbook-*' ':(exclude)modules/oc-by-example-content.adoc' ':(exclude)modules/oc-adm-by-example-content.adoc' ':(exclude)monitoring/config-map-reference-for-the-cluster-monitoring-operator.adoc' ':(exclude)modules/microshift-oc-adm-by-example-content.adoc' ':(exclude)modules/microshift-oc-by-example-content.adoc')
function post_review_comment {
LINE_NUMBER=$3
BODY=$1
FILENAME=$2
echo "Sending review comment curl request..."
curl -L -X POST -H "Accept: application/vnd.github+json" -H "Authorization: Bearer $GITHUB_AUTH_TOKEN" -H "X-GitHub-Api-Version: 2022-11-28" https://api.github.com/repos/openshift/openshift-docs/pulls/$PULL_NUMBER/comments -d '{"body":"'"$BODY"'","commit_id":"'"$COMMIT_ID"'","path":"'"$FILENAME"'","line":'"$LINE_NUMBER"',"side":"RIGHT"}'
}
function get_vale_errors {
echo "Getting the Vale errors and PR comments and filtering out existing comments..."
local vale_json="$1"
local pull_comments_json="$2"
# jq map and filter to retain only Vale alerts that don't already have a corresponding review comment on the PR
updated_vale_json=$(jq -n --argjson vale "$vale_json" --argjson comments "$pull_comments_json" '$vale | map(select(. as $v | $comments | any(.path == $v.path and .line == $v.line and .body == $v.body) | not))' | jq)
export updated_vale_json
}
# Run vale with the custom template on updated files and determine if a review comment should be posted
for FILE in ${FILES};
do
# Check if Vale should use the modules config or the root config. Ensures correct rule enabling/disabling
if [[ $FILE == modules/* ]]; then
INI="modules/.vale.ini"
else
INI=".vale.ini"
fi
# Update conditional markup in place
sed -i 's/ifdef::.*/ifdef::temp-ifdef[]/; s/ifeval::.*/ifeval::["{temp-ifeval}" == "temp"]/; s/ifndef::.*/ifndef::temp-ifndef[]/; s/endif::.*/endif::[]/;' "$FILE"
# Parse for vale errors
vale_json=$(vale --minAlertLevel=error --output=.vale/templates/bot-comment-output.tmpl --config="$INI" "$FILE" | jq)
# Check if there are Vale errors before processing the file further.
if [[ "$vale_json" != "[]" ]]; then
echo "Vale errors found in the file..."
#Check if Vale review comments already exist in the PR
pull_comments_json=$(curl -L -H "Accept: application/vnd.github+json" -H "Authorization: Bearer $GITHUB_AUTH_TOKEN" -H "X-GitHub-Api-Version: 2022-11-28" https://api.github.com/repos/openshift/openshift-docs/pulls/$PULL_NUMBER/comments | jq)
# If there are existing comments in the response, compare with Vale errors, otherwise proceed with existing Vale errors
if [[ "$pull_comments_json" != "[]" ]]; then
get_vale_errors "$vale_json" "$pull_comments_json"
else
echo "No existing comments found..."
updated_vale_json="$vale_json"
fi
else
echo "No Vale errors found in the file, moving to next file..."
continue # move to next file
fi
# Following logic checks if the line number is a part of the git diff. If it's not part of the diff it will be discarded.
# We only want to check new/modified content, plus the GitHub API only accepts comments within the diff for the review comments endpoint.
if [[ "$updated_vale_json" == "[]" ]]; then
echo "All Vale alerts already have existing comments, moving to next file..."
continue # move to next file
else
echo "Checking if Vale alerts without existing comments are part of added or modified content..."
fi
# Iterate through $updated_vale_json and post a comment if required
jq -c '.[]' <<< "$updated_vale_json" | while IFS= read -r object; do
BODY=$(echo "$object" | jq -r '.body')
FILENAME=$(echo "$object" | jq -r '.path')
LINE_NUMBER=$(echo "$object" | jq -r '.line')
# Check the unified file diff for the alert and file
file_diff=$(git diff --unified=0 --stat --diff-filter=AM HEAD~1 HEAD "${FILENAME}" ':(exclude)_unused_topics/*')
# Iterate through each line to find the line diff info and check if the alert is in the diff
while read -r line; do
# Check if the line contains the hunk beginning with @@
if [[ $line =~ @@ ]]; then
# Valid:
# @@ -35 +31 @@
# @@ -35 +31,5 @@
# Check if there is a comma in the number pairing before @@
if [[ $line =~ \+.*\,.*\ @@ ]]; then
# There are comma separated numbers before closing @@. Grab the number before the comma as the diff_start_line, after the comma is the added_lines.
added_lines=$(echo "$line" | grep -oP '\d+\s+@@' | grep -oP '\d+')
diff_start_line=$(echo "$line" | awk -F'+' '{print $2}' | awk -F',' '{print $1}')
else
# There are no comma seperated numbers. Consider the number after the plus as diff_start_line with no added lines - this means there's a modification on a single line
added_lines=0
diff_start_line=$(echo "$line" | grep -oP '\+\d+\s+@@' | grep -oP '\d+')
fi
# If the last_number is 0, disregard the hunk and move to the next hunk as zero lines were modified (deletions only)
if [ "$diff_start_line" -eq 0 ]; then
continue
fi
# Check if the LINE_NUMBER falls within the range (diff_start_line) to (diff_start_line + added_lines)
if (( LINE_NUMBER >= diff_start_line && LINE_NUMBER <= diff_start_line + added_lines )); then
post_review_comment "$BODY" "$FILENAME" "$LINE_NUMBER"
break # Exit the loop since the alert is within the diff, move on to the next JSON object
else
echo "Vale error alert not part of the file's added/modified content..."
fi
fi
done <<< "$file_diff"
done
done