Skip to content

Commit

Permalink
Merge pull request #40 from azohra/release/0.6.0
Browse files Browse the repository at this point in the history
Releasing Shell Linter v0.6.0
  • Loading branch information
Azbagheri authored Nov 11, 2021
2 parents ad87939 + 7d4299c commit 6bbeaa8
Show file tree
Hide file tree
Showing 15 changed files with 146 additions and 54 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v1
- name: Update Shellcheck
run: ./src/download_shellcheck.sh
- name: Install Shellcheck
run: ./src/install_shellcheck.sh
- name: Run tests
run: ./tests/test_runner
shell: bash
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ jobs:
token: ${{ secrets.GITHUB_TOKEN }}
tag: ${{ steps.app-version.outputs.VERSION }}
commit: master
name: Shell Linter v0.5.0
bodyFile: ./docs/release_notes/v0.5.0.md
name: Shell Linter ${{ steps.app-version.outputs.VERSION }}
bodyFile: ./docs/release_notes/v0.6.0.md

- name: Update latest tag
run: ./src/tagging.sh ${{ secrets.GITHUB_TOKEN }}
Expand Down
9 changes: 5 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
FROM alpine:3.10.3
FROM alpine:3.13.6

RUN echo "http://dl-cdn.alpinelinux.org/alpine/v3.11/community" >> /etc/apk/repositories; \
apk update && apk add --no-cache bash shellcheck=0.7.0-r1
RUN apk update && apk add --no-cache bash
RUN bash --version

RUN bash --version && shellcheck --version
COPY ./src/install_shellcheck.sh ./install_shellcheck.sh
RUN ./install_shellcheck.sh

COPY entrypoint.sh /entrypoint.sh

Expand Down
32 changes: 21 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ A GitHub Action that performs static analysis for shell scripts using [ShellChec

# Usage

Shell Linter can perform static analysis in various ways. You can use it to lint all the shell scripts in your project or lint a specific file or folder using the `path` parameter. Specific use cases are shown below:
Shell Linter can perform static analysis in various ways. By default it scans all the Shellcheck-supported shell scripts (sh/bash/dash/ksh) in your project. However, you can use the `path` parameter to scan a specific file or folder or use the `exclude-paths` parameter to exclude files or folders from the scan. With Shell Linter, you can also specify the minimum severity of errors to consider using the `severity` parameter. Specific use cases along with examples are shown below:

Run static analysis for all shell scripts in your repository:
#### Run static analysis for all the supported shell scripts in your repository:
```yml
jobs:
lint:
Expand All @@ -27,48 +27,57 @@ jobs:
uses: azohra/shell-linter@latest
```
Run static analysis for a single shell script:
#### Run static analysis for a single shell script:
```yml
- name: Run Shellcheck
uses: azohra/shell-linter@latest
with:
path: "setup.sh"
```
Run static analysis for multiple shell scripts **with or without** extension:
#### Run static analysis for multiple shell scripts **with or without** extension:
```yml
- name: Run Shellcheck
uses: azohra/shell-linter@latest
with:
path: "setup,deploy.sh"
```
Run static analysis for all the shell scripts in a folder:
#### Run static analysis for all the shell scripts in a folder:
```yml
- name: Run Shellcheck
uses: azohra/shell-linter@latest
with:
path: "src"
```
Run static analysis using a **wildcard** path:
#### Run static analysis using a **wildcard** path:
```yml
- name: Run Shellcheck
uses: azohra/shell-linter@latest
with:
path: "src/*.sh"
```
#### Exclude files and folders from the static analysis:
```yml
- name: Run Shellcheck
uses: azohra/shell-linter@latest
with:
exclude-paths: "src/setup.sh,tests/unit_tests"
```
Note that `exclude-paths` only accepts paths relative to your project's root directory. However, **do not** include `./` at the beginning of the paths.

Run static analysis for all the shell scripts and only report issue with error severity:
To exclude a folder and it's content recursively just provide the path of the folder **without** a `/` at the end. In the example above, the entire folder at the path `tests/unit_tests` will be excluded from linting.

#### Run static analysis for all the shell scripts and only report issue with error severity:
```yml
- name: Run Shellcheck
uses: azohra/shell-linter@latest
with:
path: "src/*.sh"
severity: "error"
```
Run analysis by using a specific version of Shell Linter:
#### Run analysis by using a specific version of Shell Linter:
```yml
- name: Run Shellcheck
uses: azohra/shell-linter@v0.5.0
Expand All @@ -77,11 +86,12 @@ Run analysis by using a specific version of Shell Linter:
# Input

### `path`

Optional. Execute lint check on a specific file or folder. Default: `.`

### `severity`
### `exclude-paths`
Optional. Exclude files and folders from Shellcheck scan.

### `severity`
Optional. Specify minimum severity of errors to consider [style, info, warning, error]. Default: `style`

# License
Expand Down
6 changes: 6 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,18 @@ inputs:
description: 'Specify minimum severity of errors to consider.'
required: false
default: 'style'
exclude-paths:
description: 'Specify files or folders to exclude during scan.'
required: false
default: ''

runs:
using: 'docker'
image: 'Dockerfile'
args:
- ${{ inputs.path }}
- ${{ inputs.severity }}
- ${{ inputs.exclude-paths}}
branding:
icon: 'check-circle'
color: 'green'
Expand Down
2 changes: 1 addition & 1 deletion docs/release_notes/v0.4.0.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
- Added support for ShellCheck severity mode
- The default behavior is set to `style` which considers errors with all severity levels
- Improved tagging
- The latest stable version can be fetched by using `@latest`
- The latest stable version can be fetched by using `@latest`
3 changes: 3 additions & 0 deletions docs/release_notes/v0.6.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- Added support for excluding files and folders from Shellcheck scan
- Upgraded the Shellcheck version used in the Shell-linter action to v0.7.2 to support the updated error/warning codes
- Improved performance by adding `-x` to shellcheck to follow sourced files that are not specified as input
2 changes: 1 addition & 1 deletion docs/version
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#! /bin/bash

VERSION="v0.5.0"
VERSION="v0.6.0"
echo $VERSION
33 changes: 23 additions & 10 deletions entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
# shellcheck disable=SC2155

input_paths="$1"
severity_mode="${2}"
execution_mode="$3"
severity_mode="$2"
exclude_paths="$3"
execution_mode="$4"
my_dir=$(pwd)
status_code="0"
find_path_clauses=(! -path "${my_dir}/.git/*")
invalid_files=()
scan_regex="#!.*[/ ](sh|bash|dash|ksh)$"

Expand All @@ -19,18 +21,28 @@ process_input(){
severity_mode="style"
fi

if [ "$input_paths" != "." ]; then
if [ -n "$exclude_paths" ]; then
for path in $(echo "$exclude_paths" | tr "," "\n"); do
if [ -d "${my_dir}/$path" ]; then
find_path_clauses+=( ! -path "${my_dir}/$path/*")
else
find_path_clauses+=( ! -path "${my_dir}/$path" )
fi
done
fi

if [[ -n "$input_paths" && "$input_paths" != "." ]]; then
for path in $(echo "$input_paths" | tr "," "\n"); do
if [ -d "$path" ]; then
scan_all "$path"
scan_dir "$path"
else
scan_file "$path"
fi
done
[[ ${#invalid_files[@]} -gt 0 ]] && log_invalid_files
[ -z "$execution_mode" ] && exit $status_code
else
scan_all "$my_dir"
scan_dir "$my_dir"
[[ ${#invalid_files[@]} -gt 0 ]] && log_invalid_files
[ -z "$execution_mode" ] && exit $status_code
fi
Expand All @@ -46,7 +58,7 @@ scan_file(){
echo "###############################################"
echo " Scanning $file"
echo "###############################################"
shellcheck "$file_path" --severity="$severity_mode"
shellcheck -x "$file_path" --severity="$severity_mode"
local exit_code=$?
if [ $exit_code -eq 0 ] ; then
printf "%b" "Successfully scanned ${file_path} 🙌\n"
Expand All @@ -59,7 +71,7 @@ scan_file(){
fi
}

scan_all(){
scan_dir(){
echo "Scanning all the shell scripts at $1 🔎"
while IFS= read -r script
do
Expand All @@ -69,7 +81,7 @@ scan_all(){
else
invalid_files+=( $script )
fi
done < <(find "$1" -iname '*.sh' -o -iname '*.bash' -o -iname '*.ksh' -o ! -iname '*.*' -type f ! -path "$1/.git/*")
done < <(find "$1" -type f \( -iname '*.sh' -o -iname '*.bash' -o -iname '*.ksh' -o ! -iname '*.*' \) "${find_path_clauses[@]}")
}

# Logging files with no extension that are not amongst the supported scripts or scripts that are supported but don't have a shebang.
Expand All @@ -78,8 +90,9 @@ log_invalid_files(){
for file in ${invalid_files[@]}; do
printf "\n\t\e[33m %s \e[0m\n" "$file"
done
printf "\n\e[33m ShellCheck only supports sh/bash/dash/ksh scripts. For supported scripts to be scanned, make sure to add a proper shebang on the first line of the script.\e[0m\n"
printf "\n\e[33m ShellCheck only supports sh/bash/dash/ksh scripts. For supported scripts to be scanned, make sure to add a proper shebang on the first line of the script.\n\n To fix the warning for the unsupported scripts or to ignore specific files, use the 'exclude-paths' input. For more information check:
https://github.com/azohra/shell-linter#input\e[0m\n"
}

# To avoid execution when sourcing this script for testing
[ "$0" = "${BASH_SOURCE[0]}" ] && process_input "$@"
[ "$0" = "${BASH_SOURCE[0]}" ] && process_input
8 changes: 4 additions & 4 deletions src/download_shellcheck.sh → src/install_shellcheck.sh
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#! /bin/bash
#!/bin/bash

# Update shellcheck to the locked v0.7.0 version through the binary distribution
scversion='v0.7.0'
scversion='v0.7.2'

wget -qO- "https://github.com/koalaman/shellcheck/releases/download/${scversion?}/shellcheck-${scversion?}.linux.x86_64.tar.xz" | tar -xJv
sudo cp "shellcheck-${scversion}/shellcheck" /usr/bin/
cp "shellcheck-${scversion}/shellcheck" /usr/local/bin
rm -rf "shellcheck-${scversion}"
shellcheck --version
5 changes: 5 additions & 0 deletions test_data/test_dir/external_sources.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/bash

if [[ -f ./src/tagging.sh ]]; then
. /src/tagging.sh
fi
47 changes: 47 additions & 0 deletions tests/integration_tests/ignored_path_tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#! /bin/bash
# shellcheck disable=SC2155

source ./entrypoint.sh "" "" "" "--test"

test_ignore_directories(){
local exclude_paths="test_dir,severity_mode"
local actual_message=$(process_input)
local message1="Scanning example_script.sh"
local message2="Scanning test_script_info.sh"
local expected1="Scanning test_script_wsh.sh"

assertNotContains "Actual message:$actual_message contains the message.\n" "$actual_message" "$message1"
assertNotContains "Actual message:$actual_message contains the message.\n" "$actual_message" "$message2"
assertContains "Actual messages:$actual_message Did not contain the expected message.\n" "$actual_message" "$expected1"
}

test_ignore_files(){
local input_paths="./test_data/script_type"
local exclude_paths="script_type/test.zsh,script_type/test_script.js,script_type/test_zsh_wsh,script_type/test_python,script_type/test_script_wosh.sh"
local actual_message=$(process_input)
local expected1="Scanning sample.bash"
local expected2="Scanning test_script_wsh.sh"
local notExpected="ShellCheck only supports sh/bash/dash/ksh scripts. For supported scripts to be scanned, make sure to add a proper shebang on the first line of the script."

assertContains "Actual messages:$actual_message Did not contain the expected message.\n" "$actual_message" "$expected1"
assertContains "Actual messages:$actual_message Did not contain the expected message.\n" "$actual_message" "$expected2"
assertNotContains "Actual message:$actual_message contains the message.\n" "$actual_message" "$notExpected"
}

test_ignore_file_and_directory(){
local exclude_paths="script_type,severity_mode,test_dir/invalid_script"
local actual_message=$(process_input)
local expected1="Scanning example_script.sh"
local expected2="Scanning executable_script"
local notExpected="ShellCheck only supports sh/bash/dash/ksh scripts. For supported scripts to be scanned, make sure to add a proper shebang on the first line of the script."

assertContains "Actual messages:$actual_message Did not contain the expected message.\n" "$actual_message" "$expected1"
assertContains "Actual messages:$actual_message Did not contain the expected message.\n" "$actual_message" "$expected2"
assertNotContains "Actual message:$actual_message contains the message.\n" "$actual_message" "$notExpected"
}

tearDown(){
input_paths=""
invalid_files=()
}
source ./tests/shunit2
8 changes: 2 additions & 6 deletions tests/integration_tests/input_path_tests.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#! /bin/bash
# shellcheck disable=SC2155

source ./entrypoint.sh "" "" "--test"
source ./entrypoint.sh "" "" "" "--test"

test_execution_mode(){
local expected_path=./test_data
Expand All @@ -19,7 +19,6 @@ test_invalid_script_with_extension(){

assertContains "Actual messages:$actual Did not contain the expected message.\n" "$actual" "$expected1"
assertContains "Actual messages:$actual Did not contain the expected message.\n" "$actual" "$expected2"

}

test_invalid_script_without_extension(){
Expand All @@ -30,7 +29,6 @@ test_invalid_script_without_extension(){

assertContains "Actual messages:$actual Did not contain the expected message.\n" "$actual" "$expected1"
assertContains "Actual messages:$actual Did not contain the expected message.\n" "$actual" "$expected2"

}

test_unsupported_script_without_extension(){
Expand Down Expand Up @@ -61,7 +59,6 @@ test_valid_file_without_shebang(){

assertContains "Actual messages:$actual Did not contain the expected message.\n" "$actual" "$expected1"
assertContains "Actual messages:$actual Did not contain the expected message.\n" "$actual" "$expected2"

}

test_valid_file_input(){
Expand Down Expand Up @@ -114,9 +111,8 @@ test_input_files_with_wildcard() {
assertContains "Actual messages:$actual Did not contain the expected message.\n" "$actual" "$expected2"
}



tearDown(){
input_paths=""
invalid_files=()
}
source ./tests/shunit2
2 changes: 1 addition & 1 deletion tests/integration_tests/severity_mode_tests.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#! /bin/bash

source ./entrypoint.sh "" "" "--test"
source ./entrypoint.sh "" "" "" "--test"

test_severity_mode_invalid(){
input_paths="./test_data/severity_mode/test_script_warning.sh"
Expand Down
Loading

0 comments on commit 6bbeaa8

Please sign in to comment.