1
- #! /bin/bash
1
+ #! /usr/ bin/env bash
2
2
3
- cd " $GITHUB_WORKSPACE " || exit 1
3
+ cd " $GITHUB_WORKSPACE " || {
4
+ printf ' Directory not found: "%s"\n' " $GITHUB_WORKSPACE "
5
+ exit 1
6
+ }
4
7
5
8
SHELLCHECK_DISABLE=0
6
9
SHFMT_DISABLE=0
7
10
SH_CHECKER_COMMENT=0
8
11
CHECKBASHISMS_ENABLE=0
9
12
10
- if [ " ${INPUT_SH_CHECKER_SHELLCHECK_DISABLE} " == " 1" ] || [ " ${INPUT_SH_CHECKER_SHELLCHECK_DISABLE} " == " true" ]; then
11
- SHELLCHECK_DISABLE=1
13
+ shopt -s nocasematch
14
+
15
+ if [[ " ${INPUT_SH_CHECKER_SHELLCHECK_DISABLE} " =~ ^(1| true| on| yes)$ ]]; then
16
+ SHELLCHECK_DISABLE=1
12
17
fi
13
18
14
- if [ " ${INPUT_SH_CHECKER_SHFMT_DISABLE} " == " 1 " ] || [ " ${INPUT_SH_CHECKER_SHFMT_DISABLE} " == " true " ]; then
15
- SHFMT_DISABLE=1
19
+ if [[ " ${INPUT_SH_CHECKER_SHFMT_DISABLE} " =~ ^(1 | true | on | yes)$ ] ]; then
20
+ SHFMT_DISABLE=1
16
21
fi
17
22
18
- if [ " ${INPUT_SH_CHECKER_COMMENT} " == " 1 " ] || [ " ${INPUT_SH_CHECKER_COMMENT} " == " true " ]; then
19
- SH_CHECKER_COMMENT=1
23
+ if [[ " ${INPUT_SH_CHECKER_COMMENT} " =~ ^(1 | true | on | yes)$ ] ]; then
24
+ SH_CHECKER_COMMENT=1
20
25
fi
21
26
22
- if [ " $SHELLCHECK_DISABLE " == " 1 " ] && [ " $SHFMT_DISABLE " == " 1 " ]; then
23
- echo " All checks are disabled, it's mean that \` sh_checker_shellcheck_disable \` and \` sh_checker_shfmt_disable \` are true "
27
+ if [[ " ${INPUT_SH_CHECKER_CHECKBASHISMS_ENABLE} " =~ ^(1 | true | on | yes)$ ] ]; then
28
+ CHECKBASHISMS_ENABLE=1
24
29
fi
25
30
26
- if [ " ${INPUT_SH_CHECKER_CHECKBASHISMS_ENABLE} " == " 1 " ] || [ " ${INPUT_SH_CHECKER_CHECKBASHISMS_ENABLE} " == " true " ] ; then
27
- CHECKBASHISMS_ENABLE=1
31
+ if (( SHELLCHECK_DISABLE == 1 && SHFMT_DISABLE == 1 && CHECKBASHISMS_ENABLE != 1 )) ; then
32
+ echo " All checks are disabled: \` sh_checker_shellcheck_disable \` and \` sh_checker_shfmt_disable \` are both set to 1/true. "
28
33
fi
29
34
30
35
# Internal functions
31
36
_show_sh_files () {
32
- local sh_files
33
- sh_files=" $( shfmt -f .) "
34
-
35
- if [ -n " $INPUT_SH_CHECKER_EXCLUDE " ]; then
36
- for i in $INPUT_SH_CHECKER_EXCLUDE ; do
37
- sh_files=" $( echo " $sh_files " | grep -Ev " $i " ) "
38
- done
39
- fi
40
-
41
- echo " $sh_files "
37
+ # using a global, as returning arrays in bash is ugly
38
+ # setting IFS to \n allows for spaces in file names:
39
+ IFS=$' \n ' mapfile -t sh_files < <( shfmt -f .)
40
+
41
+ if [ -z " $INPUT_SH_CHECKER_EXCLUDE " ]; then
42
+ return 0
43
+ fi
44
+
45
+ OLDIFS=" $IFS "
46
+ IFS=$' \t\n ' read -d ' ' -ra excludes <<< " $INPUT_SH_CHECKER_EXCLUDE"
47
+ IFS=$' \n '
48
+ sh_all=(" ${sh_files[@]} " )
49
+ sh_files=()
50
+ excluded=()
51
+ local sh exclude
52
+ for sh in " ${sh_all[@]} " ; do
53
+ for exclude in " ${excludes[@]} " ; do
54
+ grep -q -E " $exclude " <<< " $sh" || continue
55
+ excluded+=(" $sh " )
56
+ continue 2
57
+ done
58
+ sh_files+=(" $sh " )
59
+ done
60
+ if (( "${# excluded[@]} " != 0 )) ; then
61
+ printf ' The following %d shell script(s) will not be checked:\n' " ${# excluded[@]} "
62
+ printf ' "%s"\n' " ${excluded[@]} "
63
+ fi
64
+ IFS=" $OLDIFS "
42
65
}
43
66
44
67
_comment_on_github () {
45
- local -r content="
68
+ local content
69
+ IFS= read -r -d ' ' content << EOF
46
70
#### \` sh-checker report\`
47
71
48
72
To get the full details, please check in the [job]("https://github.com/$GITHUB_REPOSITORY /actions/runs/$GITHUB_RUN_ID ") output.
@@ -51,104 +75,136 @@ To get the full details, please check in the [job]("https://github.com/$GITHUB_R
51
75
<summary>shellcheck errors</summary>
52
76
53
77
\`\`\`
54
- ${1 :- No errors or shellcheck is disabled}
78
+ $1
55
79
\`\`\`
56
80
</details>
57
81
58
82
<details>
59
- <summary>shfmt erros </summary>
83
+ <summary>shfmt errors </summary>
60
84
61
85
\`\`\`
62
- ${2 :- No errors or shfmt is disabled}
86
+ $2
63
87
\`\`\`
64
88
</details>
65
89
66
- "
67
- local -r payload=$( echo " $content " | jq -R --slurp ' {body: .}' )
68
- local -r comment_url=$( jq -r .pull_request.comments_url < " $GITHUB_EVENT_PATH " )
90
+ EOF
91
+ local -r payload=$( jq -R --slurp ' {body: .}' <<< " $content " )
92
+ local -r comment_url=$( jq -r .pull_request.comments_url < " $GITHUB_EVENT_PATH " )
69
93
70
- echo " Commenting on the pull request"
71
- echo " $payload " | curl -s -S -H " Authorization: token $GITHUB_TOKEN " --header " Content-Type: application/json" --data @- " $comment_url " > /dev/null
94
+ echo " Commenting on the pull request"
95
+ curl -s -S -H " Authorization: token $GITHUB_TOKEN " --header " Content-Type: application/json" --data @- " $comment_url " <<< " $payload " > /dev/null
72
96
}
73
97
74
- sh_files=" $( _show_sh_files) "
75
-
76
- test " $sh_files " || {
77
- if (( ONLY_DIFF == 1 )) ; then
78
- echo " No shell scripts were changed."
79
- else
80
- echo " No shell scripts found in this repository. Make a sure that you did a checkout :)"
81
- fi
82
- exit 0
98
+ _show_sh_files
99
+
100
+ (( ${# sh_files[@]} == 0 )) && {
101
+ if (( ONLY_DIFF == 1 )) ; then
102
+ echo " No shell scripts were changed."
103
+ exit 0
104
+ fi
105
+ if [ -n " $INPUT_SH_CHECKER_EXCLUDE " ]; then
106
+ if (( ${# excluded[@]} == ${# sh_all[@]} )) ; then
107
+ printf ' All %d shell script(s) have been excluded per your sh_checker_exclude setting:\n' " ${# sh_all[@]} "
108
+ IFS=$' \t\n ' printf ' "%s"\n' " ${excludes[@]} "
109
+ exit 0
110
+ fi
111
+ fi
112
+ echo " No shell scripts were found in this repository. Please check your settings."
113
+ exit 0
83
114
}
84
115
85
116
# Validate sh files
86
117
shellcheck_code=0
87
118
checkbashisms_code=0
88
119
shfmt_code=0
89
120
exit_code=0
90
-
91
- if [ " $SHELLCHECK_DISABLE " != " 1" ]; then
92
- echo -e " Validating shell scripts files using shellcheck\n"
93
- # shellcheck disable=SC2086
94
- shellcheck_error=$( (shellcheck $sh_files ) | while read -r x; do echo " $x " ; done)
95
- test -n " $shellcheck_error " && {
96
- shellcheck_code=" 1"
97
- }
121
+ shellcheck_error=' shellcheck checking is disabled.'
122
+ shfmt_error=' shfmt checking is disabled.'
123
+
124
+ if (( SHELLCHECK_DISABLE != 1 )) ; then
125
+ printf " Validating %d shell script(s) using 'shellcheck %s':\\ n" " ${# sh_files[@]} " " $SHELLCHECK_OPTS "
126
+ IFS=$' \t\n ' read -d ' ' -ra args <<< " $SHELLCHECK_OPTS"
127
+ shellcheck_output=" $( shellcheck " ${args[@]} " " ${sh_files[@]} " 2>&1 ) "
128
+ shellcheck_code=$?
129
+ if (( shellcheck_code == 0 )) ; then
130
+ printf -v shellcheck_error " 'shellcheck %s' found no issues.\\ n" " $SHELLCHECK_OPTS "
131
+ else
132
+ # .shellcheck returns 0-4: https://github.com/koalaman/shellcheck/blob/dff8f9492a153b4ad8ac7d085136ce532e8ea081/shellcheck.hs#L191
133
+ exit_code=$shellcheck_code
134
+ IFS= read -r -d ' ' shellcheck_error << EOF
135
+
136
+ 'shellcheck $SHELLCHECK_OPTS ' returned error $shellcheck_code finding the following syntactical issues:
137
+
138
+ ----------
139
+ $shellcheck_output
140
+ ----------
141
+
142
+ You can address the above issues in on of three ways:
143
+ 1. Manually correct the issue in the offending shell script;
144
+ 2. Disable specific issues by adding the comment:
145
+ # shellcheck disable=NNNN
146
+ above the line that contains the issue, where NNNN is the error code;
147
+ 3. Add '-e NNNN' to the SHELLCHECK_OPTS setting in your .yml action file.
148
+
149
+
150
+ EOF
151
+ fi
152
+ printf ' %s' " $shellcheck_error "
98
153
fi
99
154
100
- if [ " $SHFMT_DISABLE " != " 1" ]; then
101
- echo -e " Validating shell scripts files using shfmt\n"
102
- # shellcheck disable=SC2086
103
- shfmt_error=" $( eval shfmt $SHFMT_OPTS -d $sh_files ) "
104
- shfmt_code=" $? "
105
- fi
155
+ if (( SHFMT_DISABLE != 1 )) ; then
156
+ printf " Validating %d shell script(s) using 'shfmt %s':\\ n" " ${# sh_files[@]} " " $SHFMT_OPTS "
157
+ IFS=$' \t\n ' read -d ' ' -ra args <<< " $SHFMT_OPTS"
158
+ shfmt_output=" $( shfmt " ${args[@]} " " ${sh_files[@]} " 2>&1 ) "
159
+ shfmt_code=$?
160
+ if (( shfmt_code == 0 )) ; then
161
+ printf -v shfmt_error " 'shfmt %s' found no issues.\\ n" " $SHFMT_OPTS "
162
+ else
163
+ # shfmt returns 0 or 1: https://github.com/mvdan/sh/blob/dbbad59b44d586c0f3d044a3820c18c41b495e2a/cmd/shfmt/main.go#L72
164
+ (( exit_code |= 8 ))
165
+ IFS= read -r -d ' ' shfmt_error << EOF
106
166
107
- if [ " $CHECKBASHISMS_ENABLE " == " 1" ]; then
108
- echo -e " Validating 'bashisms' for shell scripts files using checkbashisms\n"
109
- # shellcheck disable=SC2086
110
- checkbashisms_error=" $( checkbashisms $sh_files ) "
111
- checkbashisms_code=" $? "
112
- fi
167
+ 'shfmt $SHFMT_OPTS ' returned error $shfmt_code finding the following formatting issues:
113
168
114
- # Outputs
115
- if [ " $SHELLCHECK_DISABLE " != 1 ]; then
116
- test " $shellcheck_code " ! = " 0" && {
117
- echo -e " $shellcheck_error "
118
- echo -e " \nThe files above have some shellcheck issues\n"
119
- exit_code=1
120
- }
121
- fi
169
+ ----------
170
+ $shfmt_output
171
+ ----------
172
+
173
+ You can reformat the above files to meet shfmt's requirements by typing:
174
+
175
+ shfmt $SHFMT_OPTS -w filename
122
176
123
- if [ " $SHFMT_DISABLE " != 1 ]; then
124
- test " $shfmt_code " ! = " 0" && {
125
- echo -e " $shfmt_error "
126
- echo -e " \nThe files above have some formatting problems, you can use \` shfmt -w\` to fix them\n"
127
- exit_code=1
128
- }
177
+ EOF
178
+ fi
179
+ printf ' %s' " $shfmt_error "
129
180
fi
130
181
131
- if [ " $CHECKBASHISMS_ENABLE " == " 1" ]; then
132
- test " $checkbashisms_code " ! = " 0" && {
133
- echo -e " $checkbashisms_error "
134
- echo -e " \nThe files above have some checkbashisms issues\n"
135
- if (( checkbashisms_code != 4 )) ; then
136
- exit_code=1
137
- else
138
- # see https://github.com/duggan/shlint/blob/0fcd979319e3f37c2cd53ccea0b51e16fda710a1/lib/checkbashisms#L489
139
- echo -e " Ignoring 'could not find any possible bashisms in bash script' issues"
140
- fi
141
- }
182
+ if (( CHECKBASHISMS_ENABLE == 1 )) ; then
183
+ printf ' \n\nValidating %d shell script(s) files using checkbashisms:\n' " ${# sh_files[@]} "
184
+ checkbashisms " ${sh_files[@]} "
185
+ checkbashisms_code=$?
186
+ if (( checkbashisms_code == 0 )) ; then
187
+ printf ' \ncheckbashisms found no issues.\n'
188
+ else
189
+ printf ' \ncheckbashisms returned error %d finding the bashisms listed above.\n' " $checkbashisms_code "
190
+ if (( checkbashisms_code == 4 )) ; then
191
+ # see https://github.com/duggan/shlint/blob/0fcd979319e3f37c2cd53ccea0b51e16fda710a1/lib/checkbashisms#L489
192
+ printf " \\ nIgnoring 'could not find any possible bashisms in bash script' issues\\ n"
193
+ else
194
+ # checkbashisms returns 0-3: https://linux.die.net/man/1/checkbashisms
195
+ (( exit_code |= (checkbashisms_code << 4 )) )
196
+ fi
197
+ fi
142
198
fi
143
199
144
- if [ " $ shellcheck_code" != " 0 " ] || [ " $ shfmt_code" != " 0 " ] ; then
145
- if [ " $GITHUB_EVENT_NAME " == " pull_request" ] && [ " $ SH_CHECKER_COMMENT" == " 1 " ] ; then
146
- _comment_on_github " $shellcheck_error " " $shfmt_error "
147
- fi
200
+ if (( shellcheck_code != 0 || shfmt_code != 0 )) ; then
201
+ if [ " $GITHUB_EVENT_NAME " == " pull_request" ] && (( SH_CHECKER_COMMENT == 1 )) ; then
202
+ _comment_on_github " $shellcheck_error " " $shfmt_error "
203
+ fi
148
204
fi
149
205
150
- if [ " $shellcheck_code " == " 0 " ] && [ " $shfmt_code " == " 0 " ] ; then
151
- echo -e " All sh files found looks fine :)\n"
206
+ if (( exit_code == 0 )) ; then
207
+ printf ' \nNo issues found in the %d shell script(s) scanned :)\n' " ${ # sh_files[@]} "
152
208
fi
153
209
154
- exit " $exit_code "
210
+ exit $exit_code
0 commit comments