@@ -16,25 +16,36 @@ name: 'Shell Script Syntax Check'
1616description : ' check shell script syntax'
1717inputs :
1818 included_file_patterns :
19- description : " included file pattern "
19+ description : " Comma-separated list of file patterns to include (e.g., '*.sh,*.bash') "
2020 required : true
2121 type : string
2222 excluded_file_patterns :
23- description : " excluded file pattern "
23+ description : " Comma-separated list of file patterns to exclude (e.g., 'src/**') "
2424 required : false
2525 type : string
26+ default : " "
2627
2728runs :
2829 using : " composite"
2930 steps :
3031 - name : Install shellcheck
3132 shell : bash
3233 run : |
33- sudo apt-get update && sudo apt-get install -y shellcheck
34+ sudo apt-get update
35+ sudo apt-get install -y shellcheck
36+ env :
37+ DEBIAN_FRONTEND : noninteractive
38+
3439 - name : Check shell scripts
3540 shell : bash
3641 run : |
37- set -e
42+ # Initialize variables
43+ error_log="shell_errors.log"
44+ error_count=0
45+ failed_files=()
46+
47+ # Clean up any previous error log
48+ rm -f "$error_log
3849
3950 # Format file patterns
4051 IFS="," read -r -a INCLUDE_PATTERNS <<< "$(echo "${{ inputs.included_file_patterns }}" | tr -d ' ' | tr -d '\n')"
@@ -51,25 +62,82 @@ runs:
5162 FILES=($FILES $RENAME_FILES)
5263 echo "Files to be detected: ${FILES[@]}"
5364
54- # Check license header
55- NO_LICENSE_FILES=""
65+ # Check shell syntax
5666 for FILE in "${FILES[@]}"; do
57- INCLUDE=false
58- for INCLUDE_PATTERN in "${INCLUDE_PATTERNS[@]}"; do
59- if [[ $FILE == $INCLUDE_PATTERN ]]; then
60- INCLUDE=true
67+ # Skip directories
68+ [ -d "$FILE" ] && continue
69+ # Check if file matches include patterns
70+ included=false
71+ for pattern in "${INCLUDE_PATTERNS[@]}"; do
72+ if [[ $FILE == $pattern ]]; then
73+ included=true
6174 break
6275 fi
6376 done
64- EXCLUDE =false
65- for EXCLUDE_PATTERN in "${EXCLUDE_PATTERNS[@]}"; do
66- if [[ $FILE == $EXCLUDE_PATTERN ]]; then
67- EXCLUDE =true
77+ excluded =false
78+ for pattern in "${EXCLUDE_PATTERNS[@]}"; do
79+ if [[ $FILE == $pattern ]]; then
80+ excluded =true
6881 break
6982 fi
7083 done
71- if [[ $INCLUDE == true && $EXCLUDE == false ]]; then
72- echo "Checking $FILE"
73- bash -n $FILE && shellcheck $FILE
84+
85+ if $included && ! $excluded; then
86+ echo "🔍 Checking: $FILE"
87+
88+ # Create a temporary file for this file's errors
89+ tmp_error=$(mktemp)
90+
91+ # Check if file exists
92+ # Run bash -n syntax check
93+ if ! bash -n "$FILE" 2>&1 | tee -a "$tmp_error"; then
94+ echo "❌ bash -n failed for $FILE" | tee -a "$tmp_error"
95+ ((error_count++))
96+ fi
97+
98+ # Run shellcheck
99+ if ! shellcheck --format=tty --color=always "$FILE" 2>&1 | tee -a "$tmp_error"; then
100+ echo "❌ shellcheck failed for $FILE" | tee -a "$tmp_error"
101+ ((error_count++))
102+ fi
103+
104+ # If errors were found, add to main log
105+ if [ -s "$tmp_error" ]; then
106+ failed_files+=("$FILE")
107+ echo -e "\n=== Errors in $FILE ===" >> "$error_log"
108+ cat "$tmp_error" >> "$error_log"
109+ echo -e "\n" >> "$error_log"
110+ fi
111+
112+ rm -f "$tmp_error"
74113 fi
75- done
114+ done
115+
116+ # Final report
117+ if [ -s "$error_log" ]; then
118+ echo -e "\n❌ Found $error_count errors in ${#failed_files[@]} files:"
119+ printf ' - %s\n' "${failed_files[@]}"
120+
121+ echo "::group::Detailed Error Report"
122+ cat "$error_log"
123+ echo "::endgroup::"
124+
125+ # Create GitHub annotations for each error
126+ while IFS= read -r line; do
127+ if [[ "$line" == *:*:*:* ]]; then
128+ # Extract filename, line number, and message
129+ file_path=$(echo "$line" | cut -d: -f1)
130+ line_num=$(echo "$line" | cut -d: -f2)
131+ message=$(echo "$line" | cut -d: -f4- | sed 's/^ *//')
132+
133+ echo "::error file=$file_path,line=$line_num::$message"
134+ fi
135+ done < "$error_log"
136+
137+ echo "::error::Found $error_count shell script errors"
138+ exit 1
139+ else
140+ echo "✅ No shell script errors found"
141+ fi
142+ env :
143+ SHELLCHECK_OPTS : " -e SC1090 -e SC1091" # Ignore source not found errors
0 commit comments