Skip to content

Commit 78344c3

Browse files
committed
linting: add shelcheck for shell script lint
Add linting for shell scripts in the scipts directory as well as any *.sh file accross the project using shellcheck. Signed-off-by: Andreas Hatziiliou <andreas.hatziiliou@savoirfairelinux.com>
1 parent 1915e47 commit 78344c3

File tree

2 files changed

+70
-11
lines changed

2 files changed

+70
-11
lines changed

nix/util.nix

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ rec {
8888

8989
inherit (pkgs)
9090
nixpkgs-fmt
91-
shfmt;
91+
shfmt
92+
shellcheck;
9293

9394
inherit (pkgs.python3Packages)
9495
mpmath sympy black pyparsing pyyaml;

scripts/lint

Lines changed: 68 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@ fi
2020
# Standard color definitions
2121
GREEN="\033[32m"
2222
RED="\033[31m"
23-
BLUE="\033[94m"
24-
BOLD="\033[1m"
2523
NORMAL="\033[0m"
2624

2725
info()
@@ -106,6 +104,62 @@ gh_error_simple()
106104
fi
107105
}
108106

107+
# Identify shell scripts that should be linted with shellcheck.
108+
shellcheck-targets()
109+
{
110+
local file
111+
112+
# Emit every tracked file that explicitly ends with .sh.
113+
while IFS= read -r -d '' file; do
114+
printf '%s\0' "$file"
115+
done < <(git ls-files -z -- '*.sh')
116+
117+
# Add extensionless shell scripts that live under scripts/.
118+
while IFS= read -r -d '' file; do
119+
if [[ -L $file || ! -f $file ]]; then
120+
continue
121+
fi
122+
123+
if head -n1 "$file" | grep -qE '^#!.*/(env )?(ba|da|k|mk|z|)sh'; then
124+
printf '%s\0' "$file"
125+
fi
126+
done < <(git ls-files -z -- 'scripts/*' 'scripts/**/*')
127+
}
128+
129+
run-shellcheck()
130+
{
131+
if ! command -v shellcheck >/dev/null; then
132+
gh_error_simple "Shellcheck missing" "shellcheck is not installed"
133+
error "Lint shellcheck"
134+
SUCCESS=false
135+
gh_summary_failure "Lint shellcheck"
136+
return 0
137+
fi
138+
139+
local file
140+
local -a files=()
141+
while IFS= read -r -d '' file; do
142+
files+=("$file")
143+
done < <(shellcheck-targets)
144+
145+
if [[ ${#files[@]} == 0 ]]; then
146+
info "Lint shellcheck (no scripts)"
147+
gh_summary_success "Lint shellcheck"
148+
return 0
149+
fi
150+
151+
local shellcheck_out
152+
if ! shellcheck_out=$(shellcheck --severity=warning "${files[@]}" 2>&1); then
153+
gh_error_simple "Shellcheck error" "$shellcheck_out"
154+
error "Lint shellcheck"
155+
SUCCESS=false
156+
gh_summary_failure "Lint shellcheck"
157+
else
158+
info "Lint shellcheck"
159+
gh_summary_success "Lint shellcheck"
160+
fi
161+
}
162+
109163
# Formatting
110164
SUCCESS=true
111165

@@ -114,7 +168,11 @@ checkerr "Lint nix" "$(nixpkgs-fmt --check "$ROOT")"
114168
gh_group_end
115169

116170
gh_group_start "Linting shell scripts with shfmt"
117-
checkerr "Lint shell" "$(shfmt -s -l -i 2 -ci -fn $(shfmt -f $(git grep -l '' :/)))"
171+
checkerr "Lint shell" "$(shfmt -s -l -i 2 -ci -fn "$(shfmt -f "$(git grep -l '' :/)")")"
172+
gh_group_end
173+
174+
gh_group_start "Linting shell scripts with shellcheck"
175+
run-shellcheck
118176
gh_group_end
119177

120178
gh_group_start "Linting python scripts with black"
@@ -130,7 +188,7 @@ fi
130188
gh_group_end
131189

132190
gh_group_start "Linting c files with clang-format"
133-
checkerr "Lint C" "$(clang-format $(git ls-files ":/*.c" ":/*.h") --Werror --dry-run 2>&1 | grep "error:" | cut -d ':' -f 1,2 | tr ':' ' ')"
191+
checkerr "Lint C" "$(clang-format "$(git ls-files ":/*.c" ":/*.h")" --Werror --dry-run 2>&1 | grep "error:" | cut -d ':' -f 1,2 | tr ':' ' ')"
134192
gh_group_end
135193

136194
check-eol-dry-run()
@@ -152,22 +210,22 @@ check-spdx()
152210
local success=true
153211
for file in $(git ls-files -- ":/" ":/!:*.json" ":/!:*.png" ":/!:*LICENSE*" ":/!:.git*" ":/!:flake.lock"); do
154212
# Ignore symlinks
155-
if [[ ! -L $file && $(grep "SPDX-License-Identifier:" $file | wc -l) == 0 ]]; then
213+
if [[ ! -L $file && $(grep "SPDX-License-Identifier:" "$file" | wc -l) == 0 ]]; then
156214
gh_error "$file" "${line:-1}" "Missing license header error" "$file is missing SPDX License header"
157215
success=false
158216
fi
159217
done
160218
for file in $(git ls-files -- "*.[chsS]" "*.py" "*.mk" "*.yml" "**/Makefile*" ":/!proofs/cbmc/*.py" ":/!examples/bring_your_own_fips202/custom_fips202/tiny_sha3/*"); do
161219
# Ignore symlinks
162-
if [[ ! -L $file && $(grep "Copyright (c) The mldsa-native project authors" $file | wc -l) == 0 ]]; then
220+
if [[ ! -L $file && $(grep "Copyright (c) The mldsa-native project authors" "$file" | wc -l) == 0 ]]; then
163221
gh_error "$file" "${line:-1}" "Missing copyright header error" "$file is missing copyright header"
164222
success=false
165223
fi
166224
done
167225
# For source files in dev/* and mldsa/*, we enforce `Apache-2.0 OR ISC OR MIT`
168226
for file in $(git ls-files -- "*.[chsSi]" | grep "^dev/\|^mldsa/"); do
169227
# Ignore symlinks
170-
if [[ ! -L $file && $(grep "SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT" $file | wc -l) == 0 ]]; then
228+
if [[ ! -L $file && $(grep "SPDX-License-Identifier: Apache-2.0 OR ISC OR MIT" "$file" | wc -l) == 0 ]]; then
171229
gh_error "$file" "${line:-1}" "Missing license header error" "$file is not licensed under 'Apache-2.0 OR ISC OR MIT'"
172230
success=false
173231
fi
@@ -188,7 +246,7 @@ gh_group_end
188246

189247
check-autogenerated-files()
190248
{
191-
if python3 $ROOT/scripts/autogen --dry-run; then
249+
if python3 "$ROOT"/scripts/autogen --dry-run; then
192250
info "Check native auto-generated files"
193251
gh_summary_success "Check native auto-generated files"
194252
else
@@ -204,7 +262,7 @@ gh_group_end
204262

205263
check-magic()
206264
{
207-
if python3 $ROOT/scripts/check-magic >/dev/null; then
265+
if python3 "$ROOT"/scripts/check-magic >/dev/null; then
208266
info "Check magic constants"
209267
gh_summary_success "Check magic constants"
210268
else
@@ -224,7 +282,7 @@ fi
224282

225283
check-contracts()
226284
{
227-
if python3 $ROOT/scripts/check-contracts >/dev/null; then
285+
if python3 "$ROOT"/scripts/check-contracts >/dev/null; then
228286
info "Check contracts"
229287
gh_summary_success "Check contracts"
230288
else

0 commit comments

Comments
 (0)