1
+ #! /bin/bash
2
+ # 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
3
+ # for GitHub review comment API. Also checks if a commment already exists before posting.
4
+ # To test locally, create a Github personal access token and export a $GITHUB_AUTH_TOKEN environmental variable to use the token
5
+
6
+ # Check if jq is installed
7
+ hash jq 2> /dev/null || { echo >&2 " Error: jq is not installed" ; exit 1; }
8
+
9
+ # Set $PULL_NUMBER and $COMMIT_ID for local testing. Otherwise use variables passed by Prow
10
+ if [ $# -eq 0 ]; then
11
+ COMMIT_ID=$( git log -n 1 --pretty=format:" %H" )
12
+ PULL_NUMBER=$( curl -s " https://api.github.com/search/issues?q=$COMMIT_ID " | jq ' .items[0].number' )
13
+ else
14
+ PULL_NUMBER=$1
15
+ COMMIT_ID=$2
16
+ fi
17
+
18
+ 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' )
19
+
20
+ function post_review_comment {
21
+
22
+ LINE_NUMBER=$3
23
+ BODY=$1
24
+ FILENAME=$2
25
+ echo " Sending review comment curl request..."
26
+ 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"}'
27
+
28
+ }
29
+
30
+ function get_vale_errors {
31
+ echo " Getting the Vale errors and PR comments and filtering out existing comments..."
32
+ local vale_json=" $1 "
33
+ local pull_comments_json=" $2 "
34
+
35
+ # jq map and filter to retain only Vale alerts that don't already have a corresponding review comment on the PR
36
+ 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)
37
+
38
+ export updated_vale_json
39
+
40
+ }
41
+
42
+ # Run vale with the custom template on updated files and determine if a review comment should be posted
43
+ for FILE in ${FILES} ;
44
+ do
45
+ # Check if Vale should use the modules config or the root config. Ensures correct rule enabling/disabling
46
+ if [[ $FILE == modules/* ]]; then
47
+ INI=" modules/.vale.ini"
48
+ else
49
+ INI=" .vale.ini"
50
+ fi
51
+
52
+ # Update conditional markup in place
53
+ sed -i ' s/ifdef::.*/ifdef::temp-ifdef[]/; s/ifeval::.*/ifeval::["{temp-ifeval}" == "temp"]/; s/ifndef::.*/ifndef::temp-ifndef[]/; s/endif::.*/endif::[]/;' " $FILE "
54
+
55
+ # Parse for vale errors
56
+ vale_json=$( vale --minAlertLevel=error --output=.vale/templates/bot-comment-output.tmpl --config=" $INI " " $FILE " | jq)
57
+
58
+ # Check if there are Vale errors before processing the file further.
59
+ if [[ " $vale_json " != " []" ]]; then
60
+ echo " Vale errors found in the file..."
61
+
62
+ # Check if Vale review comments already exist in the PR
63
+ 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)
64
+
65
+ # If there are existing comments in the response, compare with Vale errors, otherwise proceed with existing Vale errors
66
+ if [[ " $pull_comments_json " != " []" ]]; then
67
+ get_vale_errors " $vale_json " " $pull_comments_json "
68
+ else
69
+ echo " No existing comments found..."
70
+ updated_vale_json=" $vale_json "
71
+ fi
72
+ else
73
+ echo " No Vale errors found in the file, moving to next file..."
74
+ continue # move to next file
75
+ fi
76
+
77
+ # 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.
78
+ # We only want to check new/modified content, plus the GitHub API only accepts comments within the diff for the review comments endpoint.
79
+ if [[ " $updated_vale_json " == " []" ]]; then
80
+ echo " All Vale alerts already have existing comments, moving to next file..."
81
+ continue # move to next file
82
+ else
83
+ echo " Checking if Vale alerts without existing comments are part of added or modified content..."
84
+ fi
85
+
86
+ # Iterate through $updated_vale_json and post a comment if required
87
+ jq -c ' .[]' <<< " $updated_vale_json" | while IFS= read -r object; do
88
+ BODY=$( echo " $object " | jq -r ' .body' )
89
+ FILENAME=$( echo " $object " | jq -r ' .path' )
90
+ LINE_NUMBER=$( echo " $object " | jq -r ' .line' )
91
+
92
+ # Check the unified file diff for the alert and file
93
+ file_diff=$( git diff --unified=0 --stat --diff-filter=AM HEAD~1 HEAD " ${FILENAME} " ' :(exclude)_unused_topics/*' )
94
+
95
+ # Iterate through each line to find the line diff info and check if the alert is in the diff
96
+ while read -r line; do
97
+ # Check if the line contains the hunk beginning with @@
98
+ if [[ $line =~ @@ ]]; then
99
+
100
+ # Valid:
101
+ # @@ -35 +31 @@
102
+ # @@ -35 +31,5 @@
103
+
104
+ # Check if there is a comma in the number pairing before @@
105
+ if [[ $line =~ \+ .* \, .* \ @@ ]]; then
106
+ # 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.
107
+ added_lines=$( echo " $line " | grep -oP ' \d+\s+@@' | grep -oP ' \d+' )
108
+ diff_start_line=$( echo " $line " | awk -F' +' ' {print $2}' | awk -F' ,' ' {print $1}' )
109
+ else
110
+ # 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
111
+ added_lines=0
112
+ diff_start_line=$( echo " $line " | grep -oP ' \+\d+\s+@@' | grep -oP ' \d+' )
113
+ fi
114
+
115
+ # If the last_number is 0, disregard the hunk and move to the next hunk as zero lines were modified (deletions only)
116
+ if [ " $diff_start_line " -eq 0 ]; then
117
+ continue
118
+ fi
119
+
120
+ # Check if the LINE_NUMBER falls within the range (diff_start_line) to (diff_start_line + added_lines)
121
+ if (( LINE_NUMBER >= diff_start_line && LINE_NUMBER <= diff_start_line + added_lines )) ; then
122
+
123
+ post_review_comment " $BODY " " $FILENAME " " $LINE_NUMBER "
124
+
125
+ break # Exit the loop since the alert is within the diff, move on to the next JSON object
126
+ else
127
+ echo " Vale error alert not part of the file's added/modified content..."
128
+ fi
129
+ fi
130
+
131
+ done <<< " $file_diff"
132
+
133
+ done
134
+
135
+ done
0 commit comments