@@ -31,48 +31,69 @@ jobs:
3131 with :
3232 python-version : " 3.11"
3333
34- - name : Install Bash Linters
35- run : |
36- pip install beautysh
37- sudo apt-get update
38- sudo apt-get install -y shellcheck
34+ - name : Set up uv
35+ uses : astral-sh/setup-uv@v6
36+ with :
37+ enable-cache : true
3938
4039 - name : Run Beautysh
4140 run : |
4241 shopt -s globstar nullglob
4342 if compgen -G "**/*.sh" > /dev/null; then
44- beautysh **/*.sh --indent-size 2 --check
43+ uv tool run --from beautysh beautysh **/*.sh --indent-size 2 --check
4544 fi
4645 shopt -u globstar nullglob
4746
48- - name : Check Bash Script Shebang
47+ - name : Check Bash Scripts for bash shebang
4948 run : |
50- while IFS= read -r -d '' file; do
51- if head -n 1 "$file" | grep -Eq '^#!/usr/bin/env bash$|^#!/bin/bash$'; then
49+ while read -r file
50+ do
51+ shebang="$(head -n 1 "$file")"
52+ if [[ "$shebang" = "#!/bin/bash" || "$shebang" = "#!/usr/bin/env bash" ]]
53+ then
5254 echo "[bash shebang -> Present] $file"
5355 else
54- echo "[bash shebang -> NOT FOUND] $file"
55- exit 1
56+ echo "[bash shebang -> NOT FOUND] $file" && exit 1
5657 fi
57- done < <(find . -name '*.sh' -print0 )
58+ done < <(find . -name '*.sh')
5859
59- - name : Check Bash Scripts for Pipefail
60+ - name : Check Bash Scripts for strict mode opt-in
6061 run : |
61- while IFS= read -r -d '' file; do
62+ while read -r file
63+ do
6264 if grep -q \
6365 -e "^[[:space:]]*set -euo pipefail$" \
6466 -e "^[[:space:]]*set -Eeuo pipefail$" \
65- -e "^[[:space:]]*# @paradedb-skip-check-pipefail$" \
66- "$file"; then
67- echo "[pipefail -> Present] $file"
67+ -e "^# @paradedb-skip-check-pipefail$" \
68+ "$file"
69+ then
70+ echo "[strict mode -> Present] $file"
6871 else
69- echo "[pipefail -> NOT FOUND] $file"
70- exit 1
72+ echo "[strict mode -> NOT FOUND] $file" && exit 1
7173 fi
72- done < <(find . -name '*.sh' -print0 )
74+ done < <(find . -name '*.sh')
7375
7476 - name : Run ShellCheck
7577 run : |
76- while IFS= read -r -d '' file; do
77- shellcheck -x "$file"
78- done < <(find . -name '*.sh' -print0)
78+ uv run --no-sync python - <<'PY'
79+ import glob
80+ import subprocess
81+ import sys
82+
83+ sh_files = sorted(set(glob.glob("**/*.sh", recursive=True)))
84+ if not sh_files:
85+ print("[Shellcheck skipped] No shell scripts found.")
86+ sys.exit(0)
87+ for file in sh_files:
88+ p = subprocess.run(
89+ f"shellcheck -x -P scripts {file}",
90+ shell=True,
91+ capture_output=True,
92+ check=False,
93+ )
94+ print(p.stdout.decode())
95+ if p.returncode != 0:
96+ print(f"[Shellcheck did not pass] {file}")
97+ sys.exit(1)
98+ print(f"[Shellcheck passed] {len(sh_files)} script(s)")
99+ PY
0 commit comments