Skip to content

Commit 307ffbf

Browse files
Add a validation workflow (#4)
* Add a validation workflow * Fix shellcheck * Remove redundant var for generate_random_password * Fix lint * Remove format check * Make scripts executable
1 parent 9cc90cd commit 307ffbf

5 files changed

Lines changed: 166 additions & 6 deletions

File tree

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
name: Shell Script Validation
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
8+
jobs:
9+
validate-shell-scripts:
10+
runs-on: ubuntu-latest
11+
name: Validate Shell Scripts
12+
13+
steps:
14+
- name: Checkout repository
15+
uses: actions/checkout@v4
16+
17+
- name: Install shellcheck
18+
run: |
19+
sudo apt-get update
20+
sudo apt-get install -y shellcheck
21+
22+
- name: Install shfmt
23+
run: |
24+
curl -L -o shfmt https://github.com/mvdan/sh/releases/latest/download/shfmt_v3.7.0_linux_amd64
25+
chmod +x shfmt
26+
sudo mv shfmt /usr/local/bin/
27+
28+
- name: Find shell scripts
29+
id: find-scripts
30+
run: |
31+
echo "Found shell scripts:"
32+
find scripts/ -type f -executable -o -name "*.sh" | tee scripts-list.txt
33+
# Also check files with shell shebangs
34+
find scripts/ -type f -exec grep -l '^#!/bin/sh\|^#!/bin/bash\|^#!/usr/bin/env sh\|^#!/usr/bin/env bash' {} \; | tee -a scripts-list.txt
35+
sort -u scripts-list.txt > unique-scripts.txt
36+
mv unique-scripts.txt scripts-list.txt
37+
cat scripts-list.txt
38+
39+
- name: POSIX Compliance Check (shellcheck)
40+
run: |
41+
echo "Running shellcheck for POSIX compliance..."
42+
exit_code=0
43+
while IFS= read -r script; do
44+
if [ -f "$script" ]; then
45+
echo "Checking $script..."
46+
if ! shellcheck -s sh -e SC1091 -e SC2039 "$script"; then
47+
echo "❌ $script failed POSIX compliance check"
48+
exit_code=1
49+
else
50+
echo "✅ $script passed POSIX compliance check"
51+
fi
52+
echo "---"
53+
fi
54+
done < scripts-list.txt
55+
exit $exit_code
56+
57+
- name: Shell Script Linting (shellcheck extended)
58+
run: |
59+
echo "Running extended shellcheck analysis..."
60+
exit_code=0
61+
while IFS= read -r script; do
62+
if [ -f "$script" ]; then
63+
echo "Linting $script..."
64+
if ! shellcheck -f gcc "$script"; then
65+
echo "❌ $script failed extended linting"
66+
exit_code=1
67+
else
68+
echo "✅ $script passed extended linting"
69+
fi
70+
echo "---"
71+
fi
72+
done < scripts-list.txt
73+
exit $exit_code
74+
75+
- name: Executable Permissions Check
76+
run: |
77+
echo "Checking executable permissions..."
78+
exit_code=0
79+
while IFS= read -r script; do
80+
if [ -f "$script" ]; then
81+
if [ ! -x "$script" ]; then
82+
echo "⚠️ $script is not executable"
83+
exit_code=1
84+
else
85+
echo "✅ $script has correct executable permissions"
86+
fi
87+
fi
88+
done < scripts-list.txt
89+
exit $exit_code
90+
91+
- name: Shebang Validation
92+
run: |
93+
echo "Validating shebangs..."
94+
exit_code=0
95+
while IFS= read -r script; do
96+
if [ -f "$script" ]; then
97+
first_line=$(head -n1 "$script")
98+
case "$first_line" in
99+
"#!/bin/sh"|"#!/usr/bin/env sh")
100+
echo "✅ $script has valid POSIX shebang: $first_line"
101+
;;
102+
"#!/bin/bash"|"#!/usr/bin/env bash")
103+
echo "⚠️ $script uses bash shebang (not POSIX): $first_line"
104+
;;
105+
"#!"*)
106+
echo "❌ $script has non-standard shebang: $first_line"
107+
exit_code=1
108+
;;
109+
*)
110+
echo "❌ $script missing shebang"
111+
exit_code=1
112+
;;
113+
esac
114+
fi
115+
done < scripts-list.txt
116+
exit $exit_code
117+
118+
- name: Security Scan (basic)
119+
run: |
120+
echo "Running basic security checks..."
121+
exit_code=0
122+
while IFS= read -r script; do
123+
if [ -f "$script" ]; then
124+
echo "Security scanning $script..."
125+
126+
# Check for potentially dangerous patterns
127+
if grep -n "eval\|exec\|system\|curl.*|.*sh\|wget.*|.*sh" "$script" | grep -v "^#"; then
128+
echo "⚠️ $script contains potentially dangerous patterns"
129+
fi
130+
131+
# Check for hardcoded credentials patterns
132+
if grep -ni "password\|secret\|token\|key" "$script" | grep -v "^#" | grep "="; then
133+
echo "⚠️ $script may contain hardcoded credentials"
134+
fi
135+
136+
# Check for unquoted variables
137+
if grep -n '\$[A-Za-z_][A-Za-z0-9_]*[^A-Za-z0-9_"]' "$script" | grep -v "^#"; then
138+
echo "⚠️ $script has potentially unquoted variables"
139+
fi
140+
141+
echo "✅ Basic security scan completed for $script"
142+
echo "---"
143+
fi
144+
done < scripts-list.txt
145+
exit $exit_code
146+
147+
- name: Summary Report
148+
if: always()
149+
run: |
150+
echo "=== Shell Script Validation Summary ==="
151+
echo "Scripts validated:"
152+
cat scripts-list.txt | wc -l
153+
echo ""
154+
echo "Validation completed. Check individual step results above for details."

scripts/help

100644100755
File mode changed.

scripts/install

100644100755
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ headline() {
8080
check_for_user_confirmation() {
8181
if [ "$INTERACTIVE" = "true" ]; then
8282
echo "Press Enter to continue, or Ctrl+C to cancel..."
83+
# shellcheck disable=SC2034
8384
read -r answer </dev/tty
8485
fi
8586
}
@@ -97,7 +98,7 @@ get_latest_release_version() {
9798
}
9899

99100
generate_random_password() {
100-
dd if=/dev/urandom bs=1 count=512 2>/dev/null | LC_ALL=C tr -dc '[:alnum:]' | cut -c -"${1:-16}"
101+
dd if=/dev/urandom bs=1 count=512 2>/dev/null | LC_ALL=C tr -dc '[:alnum:]' | cut -c -16
101102
}
102103

103104
generate_random_hex() {
@@ -174,8 +175,10 @@ install_docker_debian() {
174175
echo "Installing Docker on Debian-like..."
175176
sudo apt-get update -y
176177
sudo apt-get install -y apt-transport-https ca-certificates curl gnupg lsb-release
178+
# shellcheck disable=SC2046,SC1091
177179
curl -fsSL https://download.docker.com/linux/$(. /etc/os-release; echo "$ID")/gpg \
178180
| sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
181+
# shellcheck disable=SC1091
179182
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] \
180183
https://download.docker.com/linux/$(. /etc/os-release; echo "$ID") \
181184
$(lsb_release -cs) stable" \

scripts/share-logs

100644100755
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ if [ -f docker-compose.yml ]; then
1818
echo "Found docker-compose.yml"
1919
else
2020
echo "Could not find docker-compose.yml, trying $INSTALL_DIR"
21-
cd $INSTALL_DIR || exit 1
21+
cd "$INSTALL_DIR" || exit 1
2222
if [ -f docker-compose.yml ]; then
2323
echo "Found docker-compose.yml"
2424
else
@@ -28,10 +28,11 @@ else
2828
fi
2929

3030
echo "Writing logs to a file..."
31+
# shellcheck disable=SC2024
3132
sudo docker compose logs --timestamps --no-color > logs.txt
3233
echo "Uploading logs to S3..."
3334
LOGS_FILE=$(date +%Y%m%d_%H%M%S).log
34-
curl -fLX PUT --upload-file logs.txt https://openops-client-logs.s3.amazonaws.com/$LOGS_FILE
35+
curl -fLX PUT --upload-file logs.txt "https://openops-client-logs.s3.amazonaws.com/$LOGS_FILE"
3536
echo "Done. File uploaded to https://openops-client-logs.s3.amazonaws.com/$LOGS_FILE"
3637
echo "Please share the following file name with OpenOps: $LOGS_FILE"
3738

scripts/tls

100644100755
Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ headline() {
7070
check_for_user_confirmation() {
7171
if [ "$INTERACTIVE" = "true" ]; then
7272
echo "Press Enter to continue, or Ctrl+C to cancel..."
73+
# shellcheck disable=SC2034
7374
read -r answer </dev/tty
7475
fi
7576
}
@@ -170,6 +171,7 @@ retry() {
170171
}
171172

172173
create_certificates() {
174+
cd "$INSTALL_DIR"
173175
sudo mkdir -p tls/etc tls/var tls/acme
174176
dockercmd run --rm --name certbot \
175177
-v ./tls/etc:/etc/letsencrypt \
@@ -178,11 +180,11 @@ create_certificates() {
178180
certbot/certbot certonly \
179181
--webroot -w /var/www/acme \
180182
-m "$EMAIL" \
181-
-d $DOMAIN \
183+
-d "$DOMAIN" \
182184
--non-interactive --agree-tos
183185

184-
sudo cp -v tls/etc/live/$DOMAIN/fullchain.pem tls/cert.pem
185-
sudo cp -v tls/etc/live/$DOMAIN/privkey.pem tls/key.pem
186+
sudo cp -v "tls/etc/live/$DOMAIN/fullchain.pem" tls/cert.pem
187+
sudo cp -v "tls/etc/live/$DOMAIN/privkey.pem" tls/key.pem
186188
}
187189

188190
main

0 commit comments

Comments
 (0)