Skip to content

Commit 704af4c

Browse files
authored
test: add shellcheck to CI tests (#469)
* test: add linter for shell files Also: * fix shellcheck errors in new tools/gcs2bq/run.sh * update contributing guide with local formatter / linter instructions * fix: lint errors with shell scripts * revert shellcheck image in cloudbuild.yaml * fix: format files in examples/ and tools/ subdirectories * fix: exclude node_modules from shellcheck * reduce width of check_format script
1 parent e559027 commit 704af4c

15 files changed

Lines changed: 256 additions & 179 deletions

File tree

CONTRIBUTING.md

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,41 @@ To get started contributing:
1313

1414
```
1515
gcloud config set project YOUR-PROJECT
16-
cd cloudbuild
17-
terraform init
18-
terraform apply -var="project_id=$(gcloud config get-value project)" -var='github_owner=GITHUB-USER-ID'
16+
export GITHUB_USER=YOUR_GITHUB_USERNAME
17+
18+
pushd cloudbuild
19+
teraform init
20+
terraform apply -var="project_id=$(gcloud config get-value project)" -var="github_owner=${GITHUB_USER}"
21+
popd
1922
```
2023

2124
Builds require a `make` container image in the same project. Build with
22-
the following command:
25+
the following commands:
2326

2427
```
28+
pushd cloudbuild
2529
gcloud builds submit --tag gcr.io/$(gcloud config get-value project)/make .
30+
popd
31+
```
32+
33+
1. Run the formatter locally.
34+
35+
From the root of the repository, run the Docker command:
36+
```
37+
docker run \
38+
--mount type=bind,source="$( pwd )",target=/workspace \
39+
--workdir=/workspace \
40+
gcr.io/$(gcloud config get-value project)/make fmt
41+
```
42+
43+
1. Run the linter locally.
44+
45+
From the root of the repository, run the Docker command:
46+
```
47+
docker run \
48+
--mount type=bind,source="$( pwd )",target=/workspace \
49+
--workdir=/workspace \
50+
gcr.io/$(gcloud config get-value project)/make test
2651
```
2752

2853
1. Develop using the following guidelines to help expedite your review:

cloudbuild.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
steps:
22
- name: 'gcr.io/$PROJECT_ID/make'
3-
args: ['test']
3+
args: ['test']
4+
waitFor: ['-']

cloudbuild/Dockerfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,7 @@ RUN npm install gts
3131
RUN apt-get install -y default-jdk
3232
RUN wget https://github.com/google/google-java-format/releases/download/google-java-format-1.7/google-java-format-1.7-all-deps.jar --directory-prefix=/usr/share/java/
3333

34+
# install bash linter
35+
RUN apt-get install -y shellcheck
3436

3537
ENTRYPOINT ["make"]

examples/bigtable-change-key/scripts/copy_schema_to_new_table.sh

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,12 @@ fi
3636
INPUT_TABLE=$1
3737
OUTPUT_TABLE=$2
3838

39-
echo Creating table $OUTPUT_TABLE
40-
cbt createtable $OUTPUT_TABLE
39+
echo Creating table "$OUTPUT_TABLE"
40+
cbt createtable "$OUTPUT_TABLE"
4141

42-
cbt ls $INPUT_TABLE | tail -n+3 | while read line
42+
cbt ls "$INPUT_TABLE" | tail -n+3 | while read -r line
4343
do
44-
FAMILY=`echo $line | cut -d " " -f 1`
45-
echo Adding column family $FAMILY
46-
cbt createfamily $OUTPUT_TABLE $FAMILY
44+
FAMILY=$( echo "$line" | cut -d " " -f 1 )
45+
echo Adding column family "$FAMILY"
46+
cbt createfamily "$OUTPUT_TABLE" "$FAMILY"
4747
done

examples/bigtable-change-key/scripts/create_sandbox_table.sh

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,19 +37,19 @@ fi
3737
# Create table
3838
TABLE_NAME=$1
3939

40-
cbt createtable $TABLE_NAME
41-
cbt createfamily $TABLE_NAME id
42-
cbt createfamily $TABLE_NAME loc
40+
cbt createtable "$TABLE_NAME"
41+
cbt createfamily "$TABLE_NAME" id
42+
cbt createfamily "$TABLE_NAME" loc
4343

4444
# Populate table with dummy data (3 records)
45-
cbt set $TABLE_NAME e57c5e6a-609f-4371-86db-158304c2c1de#189 id:ride_id=e57c5e6a-609f-4371-86db-158304c2c1de
46-
cbt set $TABLE_NAME e57c5e6a-609f-4371-86db-158304c2c1de#189 id:point_idx=189
47-
cbt set $TABLE_NAME e57c5e6a-609f-4371-86db-158304c2c1de#189 loc:latitude=40.7854
45+
cbt set "$TABLE_NAME" e57c5e6a-609f-4371-86db-158304c2c1de#189 id:ride_id=e57c5e6a-609f-4371-86db-158304c2c1de
46+
cbt set "$TABLE_NAME" e57c5e6a-609f-4371-86db-158304c2c1de#189 id:point_idx=189
47+
cbt set "$TABLE_NAME" e57c5e6a-609f-4371-86db-158304c2c1de#189 loc:latitude=40.7854
4848

49-
cbt set $TABLE_NAME 33cb2a42-d9f5-4b64-9e8a-b5aa1d6e142f#132 id:ride_id=33cb2a42-d9f5-4b64-9e8a-b5aa1d6e142f
50-
cbt set $TABLE_NAME 33cb2a42-d9f5-4b64-9e8a-b5aa1d6e142f#132 id:point_idx=132
51-
cbt set $TABLE_NAME 33cb2a42-d9f5-4b64-9e8a-b5aa1d6e142f#132 loc:latitude=41.7854
49+
cbt set "$TABLE_NAME" 33cb2a42-d9f5-4b64-9e8a-b5aa1d6e142f#132 id:ride_id=33cb2a42-d9f5-4b64-9e8a-b5aa1d6e142f
50+
cbt set "$TABLE_NAME" 33cb2a42-d9f5-4b64-9e8a-b5aa1d6e142f#132 id:point_idx=132
51+
cbt set "$TABLE_NAME" 33cb2a42-d9f5-4b64-9e8a-b5aa1d6e142f#132 loc:latitude=41.7854
5252

53-
cbt set $TABLE_NAME 8fa1905e-422c-49f6-8ea3-23c579504d83#1003 id:ride_id=8fa1905e-422c-49f6-8ea3-23c579504d83
54-
cbt set $TABLE_NAME 8fa1905e-422c-49f6-8ea3-23c579504d83#1003 id:point_idx=1003
55-
cbt set $TABLE_NAME 8fa1905e-422c-49f6-8ea3-23c579504d83#1003 loc:latitude=11.7854
53+
cbt set "$TABLE_NAME" 8fa1905e-422c-49f6-8ea3-23c579504d83#1003 id:ride_id=8fa1905e-422c-49f6-8ea3-23c579504d83
54+
cbt set "$TABLE_NAME" 8fa1905e-422c-49f6-8ea3-23c579504d83#1003 id:point_idx=1003
55+
cbt set "$TABLE_NAME" 8fa1905e-422c-49f6-8ea3-23c579504d83#1003 loc:latitude=11.7854

examples/dataproc-gcs-connector/build_gcs_connector.sh

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,11 @@ fi
5656
cd ..
5757

5858
echo "Running Terraform to build Dataproc cluster"
59-
cd terraform || exit
60-
terraform init
61-
terraform apply -auto-approve
62-
63-
cd ..
59+
(
60+
cd terraform || exit
61+
terraform init
62+
terraform apply -auto-approve
63+
)
6464

6565
echo "Running test script on Dataproc cluster"
6666
chmod u+x test_gcs_connector.sh

examples/dataproc-gcs-connector/connectors.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ is_worker() {
5050
}
5151

5252
min_version() {
53-
echo -e "$1\n$2" | sort -r -t'.' -n -k1,1 -k2,2 -k3,3 | tail -n1
53+
echo -e "$1"'\n'"$2" | sort -r -t'.' -n -k1,1 -k2,2 -k3,3 | tail -n1
5454
}
5555

5656
get_connector_url() {

helpers/check_format.sh

Lines changed: 93 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#!/bin/bash
1+
#!/usr/bin/env bash
22

33
# Copyright 2019 Google LLC
44
#
@@ -27,28 +27,57 @@
2727
# Exit with error code 1 - always
2828
need_formatting() {
2929
FOLDER=$1
30-
FILES_TO_LINT=${@:2}
30+
FILES_TO_LINT=${*:2}
3131
echo "Some files need to be formatted in $FOLDER - FAIL"
3232
echo "$FILES_TO_LINT"
3333
exit 1
3434
}
3535

36+
# validate_bash - takes a folder path as input and shell checks files
37+
validate_bash() {
38+
FOLDER=$1
39+
echo "Validating $FOLDER - Checking bash files"
40+
41+
FILES_TO_CHECK=$(find "$FOLDER" -not \( -name node_modules -prune \) -type f -name "*.sh")
42+
43+
# Initialize FILES_TO_LINT to empty string
44+
FILES_TO_LINT=""
45+
46+
if [[ ! -z "$FILES_TO_CHECK" ]]
47+
then
48+
for FILE_TO_CHECK in $FILES_TO_CHECK
49+
do
50+
if ! shellcheck "$FILE_TO_CHECK";
51+
then
52+
FILES_TO_LINT+="$FILE_TO_CHECK "
53+
fi
54+
done
55+
56+
if [[ ! -z "$FILES_TO_LINT" ]]
57+
then
58+
need_formatting "$FOLDER" "$FILES_TO_LINT"
59+
fi
60+
else
61+
echo "No bash files found for $FOLDER - SKIP"
62+
fi
63+
}
64+
3665
# validate_python - takes a folder path as input and validate python files
3766
# using yapf (supports both python2 and python3)
3867
# errors out if yapf --diff -r --style google returns a non-0 status
3968
validate_python() {
4069
FOLDER=$1
4170
echo "Validating $FOLDER - Checking python files"
4271

43-
FILES_TO_CHECK=$(find $FOLDER -type f -name "*.py")
72+
FILES_TO_CHECK=$(find "$FOLDER" -type f -name "*.py")
4473

4574
# Initialize FILES_TO_LINT to empty string
4675
FILES_TO_LINT=""
4776

48-
(cd $FOLDER && flake8 --exclude=.git,__pycache__,.venv,venv --select=E9,F,C)
49-
if [ $? -ne 0 ]
77+
78+
if ! (cd "$FOLDER" && flake8 --exclude=.git,__pycache__,.venv,venv --select=E9,F,C)
5079
then
51-
need_formatting $FOLDER
80+
need_formatting "$FOLDER"
5281
fi
5382

5483
if [[ ! -z "$FILES_TO_CHECK" ]]
@@ -58,27 +87,31 @@ validate_python() {
5887
echo "Testing formatting for python2 files in $FOLDER"
5988

6089
# Getting the list of files to lint
61-
YAPF_PYTHON2_OUTPUT=$(python2 -m yapf --diff -r --style google $FILES_TO_CHECK 2>&1)
62-
YAPF_PYTHON2_STATUS=$(echo $?)
63-
FILES_TO_LINT+=$( echo $YAPF_PYTHON2_OUTPUT | egrep '^---.*\(original\)$' | awk '{print $2}')
90+
YAPF_PYTHON2_OUTPUT=$(python2 -m yapf --diff -r --style google "$FILES_TO_CHECK" 2>&1)
91+
YAPF_PYTHON2_STATUS=$?
92+
FILES_TO_LINT+=$( echo "$YAPF_PYTHON2_OUTPUT" | grep -E '^---.*\(original\)$' | awk '{print $2}')
6493

6594
if [[ ! -z "$FILES_TO_LINT" ]]
6695
then
6796
# Error out with details
68-
need_formatting $FOLDER $FILES_TO_LINT
97+
need_formatting "$FOLDER" "$FILES_TO_LINT"
6998
fi
7099

71100
# Checking python files if python2 failed (i.e not python2 compatible code)
72101
if [[ "$YAPF_PYTHON2_STATUS" -ne 0 ]]
73102
then
74103
# python 3 yapf
75104
echo "Testing formatting for python3 files in $FOLDER"
76-
FILES_TO_LINT+=$(python3 -m yapf --diff -r --style google $FILES_TO_CHECK | egrep '^---.*\(original\)$' | awk '{print $2}')
105+
FILES_TO_LINT+=$(
106+
python3 -m yapf --diff -r --style google "$FILES_TO_CHECK" |
107+
grep -E '^---.*\(original\)$' |
108+
awk '{print $2}'
109+
)
77110

78111
if [[ ! -z "$FILES_TO_LINT" ]]
79112
then
80113
# Error out with details
81-
need_formatting $FOLDER $FILES_TO_LINT
114+
need_formatting "$FOLDER" "$FILES_TO_LINT"
82115
fi
83116

84117
if [[ -z "$FILES_TO_LINT" ]]
@@ -98,12 +131,12 @@ validate_go() {
98131
FOLDER=$1
99132
echo "Validating $FOLDER - Checking GO files"
100133

101-
FILES_TO_LINT=$(gofmt -l $FOLDER)
134+
FILES_TO_LINT=$(gofmt -l "$FOLDER")
102135

103136
if [[ ! -z "$FILES_TO_LINT" ]]
104137
then
105138
# Error out with details
106-
need_formatting $FOLDER $FILES_TO_LINT
139+
need_formatting "$FOLDER" "$FILES_TO_LINT"
107140
else
108141
echo "No go files need formatting for $FOLDER - SKIP"
109142
fi
@@ -114,61 +147,62 @@ validate_go() {
114147
# errors out if gts init or npm audit returns a non-0 status
115148
validate_typescript(){
116149
FOLDER=$1
117-
if [[ -f "$FOLDER/tsconfig.json" ]]
150+
151+
FILES_TO_CHECK=$(find "$FOLDER" -type f -name "tsconfig.json")
152+
153+
if [[ ! -z "$FILES_TO_CHECK" ]]
118154
then
119-
echo "Validating $FOLDER - Checking typescript files"
120-
cd $FOLDER
121-
npx gts -y init > /dev/null
155+
for tsconfig_path in $FILES_TO_CHECK
156+
do
157+
tsconfig_dir=$(dirname "$tsconfig_path")
158+
echo "Validating $tsconfig_dir - Checking typescript files"
159+
cd "$tsconfig_dir" || exit 1
122160

123-
if [[ "$?" -eq 0 ]]
124-
then
125-
echo "Running npm audit..."
126-
npm audit
127-
cd -
128-
if [[ "$?" -ne 0 ]]
161+
if ! npx gts -y init > /dev/null ;
129162
then
130-
echo "$FOLDER npm audit needs fixing - FAIL"
131-
exit 1
163+
echo "Running npm audit..."
164+
if npm audit ;
165+
then
166+
echo "$tsconfig_dir npm audit needs fixing - FAIL"
167+
exit 1
168+
else
169+
echo "$tsconfig_dir npm audit is clean - PASS"
170+
fi
132171
else
133-
echo "$FOLDER npm audit is clean - PASS"
172+
echo "gts init returned an error - FAIL"
173+
exit 1
134174
fi
135-
else
136-
cd -
137-
echo "gts init returned an error - FAIL"
138-
exit 1
139-
fi
175+
cd - || exit 1
176+
done
140177
fi
141-
142178
}
143179

144-
# validate_go - takes a folder path as input and validate folder
180+
# validate_java - takes a folder path as input and validate folder
145181
# using gts
146182
# errors out if gts init or npm audit returns a non-0 status
147183
validate_java(){
148184
FOLDER=$1
149185
echo "Validating $FOLDER - Checking java files"
150186

151-
FILES_TO_CHECK=$(find $FOLDER -type f -name "*.java")
187+
FILES_TO_CHECK=$(find "$FOLDER" -type f -name "*.java")
152188

153189
# Initialize FILES_TO_LINT to empty string
154190
FILES_TO_LINT=""
155191

156192
if [[ ! -z "$FILES_TO_CHECK" ]]
157193
then
158194
echo "Testing formatting for java files in $FOLDER"
159-
for FILE_TO_CHECK in $FILES_TO_CHECK
160-
do
161-
java -jar /usr/share/java/google-java-format-1.7-all-deps.jar --set-exit-if-changed $FILE_TO_CHECK > /dev/null
162195

163-
if [[ "$?" -ne 0 ]]
164-
then
165-
FILES_TO_LINT+="$FILE_TO_CHECK "
166-
fi
167-
done
196+
# shellcheck disable=SC2086
197+
FILES_TO_LINT=$(
198+
java -jar "/usr/share/java/google-java-format-1.7-all-deps.jar" \
199+
--set-exit-if-changed \
200+
-n $FILES_TO_CHECK
201+
)
168202

169203
if [[ ! -z "$FILES_TO_LINT" ]]
170204
then
171-
need_formatting $FOLDER $FILES_TO_LINT
205+
need_formatting "$FOLDER" "$FILES_TO_LINT"
172206
fi
173207

174208
if [[ -z "$FILES_TO_LINT" ]]
@@ -182,16 +216,23 @@ validate_java(){
182216

183217
# temporary list of folders to exclude
184218
EXCLUDE_FOLDERS=$(cat helpers/exclusion_list.txt)
185-
186-
for FOLDER in $(find tools examples -maxdepth 1 -mindepth 1 -type d);
219+
while IFS= read -r -d '' FOLDER
187220
do
188-
if [[ ! ${EXCLUDE_FOLDERS[@]} =~ "$FOLDER" ]]
221+
if [[ ! ${EXCLUDE_FOLDERS[*]} =~ $FOLDER ]]
189222
then
190-
validate_python $FOLDER
191-
validate_go $FOLDER
192-
validate_typescript $FOLDER
193-
validate_java $FOLDER
223+
validate_bash "$FOLDER"
224+
validate_go "$FOLDER"
225+
validate_java "$FOLDER"
226+
validate_python "$FOLDER"
227+
validate_typescript "$FOLDER"
194228
else
195229
echo "$FOLDER in exclusion list - SKIP "
196230
fi
197-
done
231+
# Search all directories and sub-directories except sub-directories of .git
232+
# https://stackoverflow.com/a/16595367/101923
233+
done < <(
234+
find . -maxdepth 2 -mindepth 1 -type d \
235+
-not \( -path ./.git -prune \) \
236+
-print0
237+
)
238+
echo "finished checking format"

0 commit comments

Comments
 (0)