diff --git a/CHANGELOG.md b/CHANGELOG.md index 1177360b..9113e26e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ * Use [@actions/toolkit](https://github.com/actions/toolkit) and [@probot/probot](https://github.com/probot/probot) instead of currently used `bash` and `Docker`. * Improve usability - human readable and accessible output in form of comments, suggestions, etc. -* More customization - whitelisting and blacklisting of error codes and scripts +* More customization - allowlisting and denylisting of error codes and scripts * And more... ## v2.3.1 ... v2.3.3 diff --git a/README.md b/README.md index d65854ad..c45b5f93 100644 --- a/README.md +++ b/README.md @@ -22,22 +22,22 @@ -This repository hosts code for running differential ShellCheck in GitHub actions. Idea of having something like differential ShellCheck was first introduced in [@fedora-sysv/initscripts](https://github.com/fedora-sysv/initscripts). Initscripts needed some way to verify incoming PR's without getting warnings and errors about already merged and for years working code. Therefore, differential ShellCheck was born. +This repository hosts code for running differential ShellCheck in GitHub actions. Idea of having something like a differential ShellCheck was first introduced in [@fedora-sysv/initscripts](https://github.com/fedora-sysv/initscripts). Initscripts needed some way to verify incoming PRs without getting warnings and errors about already merged and for years working code. Therefore, differential ShellCheck was born. ## How does it work -First Differential ShellCheck gets a list of changed shell scripts based on file extensions, shebangs and script list, if provided. Then it calls [@koalaman/shellcheck](https://github.com/koalaman/shellcheck) on those scripts where it stores ShellCheck output for later use. Then it switches from `HEAD` to provided `BASE` and runs ShellCheck on the same files as before and stores output to separate file. +First Differential ShellCheck gets a list of changed shell scripts based on file extensions, shebangs and script list, if provided. Then it calls [@koalaman/shellcheck](https://github.com/koalaman/shellcheck) on those scripts where it stores ShellCheck output for later use. Then it switches from `HEAD` to provided `BASE` and runs ShellCheck on the same files as before and stores output to a separate file. -To evaluate results Differential ShellCheck uses utilities `csdiff` and `csgrep` from [@csutils/csdiff](https://github.com/csutils/csdiff). First is used `csdiff` to get a list/number of fixed and added errors. And then is used `csgrep` to output results in a nice colorized way to console and optionally into GitHub GUI as security alert. +To evaluate results, Differential ShellCheck uses utilities `csdiff` and `csgrep` from [@csutils/csdiff](https://github.com/csutils/csdiff). First `csdiff` is used to get a list/number of fixed and added errors. And then `csgrep` is used to output the results in a nice colorized way to console and optionally into GitHub GUI as a security alert. ## Features * Shell scripts auto-detection based on shebangs (`!#/bin/sh` or `!#/bin/bash`) and file extensions (`.sh`, `.bash`) -* Ability to white list specific error codes +* Ability to allowlist specific error codes * Statistics about fixed and added errors * Colored console output with emojis -* [SARIF support](https://docs.github.com/en/code-security/code-scanning/integrating-with-code-scanning/sarif-support-for-code-scanning) - warnings are visible in `Changed files` tab of Pull-Request -* Ability to run in verbose mode when run with [debug option](https://github.blog/changelog/2022-05-24-github-actions-re-run-jobs-with-debug-logging/) +* [SARIF support](https://docs.github.com/en/code-security/code-scanning/integrating-with-code-scanning/sarif-support-for-code-scanning) - warnings are visible in the `Changed files` tab of the Pull-Request +* Ability to run in a verbose mode when run with [debug option](https://github.blog/changelog/2022-05-24-github-actions-re-run-jobs-with-debug-logging/) * Results displayed as [job summaries](https://github.blog/2022-05-09-supercharging-github-actions-with-job-summaries/) ## Usage @@ -103,7 +103,7 @@ jobs: ## Configuration options -Action currently accept following options: +Action currently accepts following options: ```yml # ... @@ -122,7 +122,7 @@ Action currently accept following options: ### base -`SHA` of commit which will be used as base when performing differential ShellCheck. +`SHA` of commit which will be used as the base when performing differential ShellCheck. * default value: `github.event.pull_request.base.sha` * requirements: `optional` @@ -136,7 +136,7 @@ Action currently accept following options: ### ignored-codes -Path to text file which holds a list of ShellCheck codes which should be excluded from validation. +Path to a text file which holds a list of ShellCheck codes which should be excluded from validation. * default value: `undefined` * requirements: `optional` @@ -144,26 +144,26 @@ Path to text file which holds a list of ShellCheck codes which should be exclude ### shell-scripts -Path to text file which holds a list of shell scripts in this repository which would not for some reason picked up by shell script auto-detection routine. +Path to a text file which holds a list of shell scripts which would not, otherwise, be automatically picked by the shell script auto-detection routine. * default value: `undefined` * requirements: `optional` * example: [.diff-shellcheck-scripts.txt](.github/.diff-shellcheck-scripts.txt) -> **Note**: _Every path should be absolute and placed on separate lines. Avoid spaces in list since they are counted as comment._ +> **Note**: _Every path should be absolute and placed on a separate line. Avoid spaces in the list since they are interpreted as comments._ ### token -Token used to upload findings in SARIF format to GitHub +Token used to upload findings in SARIF format to GitHub. * default value: `undefined` * requirements: `optional` -Token needs to have following [characteristics](https://docs.github.com/en/rest/code-scanning#upload-an-analysis-as-sarif-data): +Token needs to have the following [characteristics](https://docs.github.com/en/rest/code-scanning#upload-an-analysis-as-sarif-data): * Token with the `security_events` scope to use this endpoint for private repositories. * Token with the `public_repo` scope for **public repositories only**. ## Limitations -* Currently `differential-shellcheck` action could be run only on Pull-Requests +* Currently `differential-shellcheck` action can be run only on Pull-Requests. diff --git a/src/functions.sh b/src/functions.sh index 9f8deee9..25f97fd8 100644 --- a/src/functions.sh +++ b/src/functions.sh @@ -1,8 +1,9 @@ # shellcheck shell=bash -# Function to check whether input param is on list of shell scripts -# $1 - absolute path to file + +# Function to check whether the input param is on the list of shell scripts +# $1 - absolute path to a file # $@ - list of strings to compare with -# $? - return value - 0 when succes +# $? - return value - 0 on success is_script_listed () { [ $# -le 1 ] && return 1 local file="$1" @@ -12,10 +13,10 @@ is_script_listed () { [[ " ${scripts[*]} " =~ " ${file} " ]] && return 0 || return 2 } -# Function to check if given file has .sh extension +# Function to check whether the given file has the .{,ba}sh extension # https://stackoverflow.com/a/6926061 -# $1 - absolute path to file -# $? - return value - 0 when succes +# $1 - absolute path to a file +# $? - return value - 0 on success is_shell_extension () { [ $# -le 0 ] && return 1 local file="$1" @@ -27,10 +28,10 @@ is_shell_extension () { esac } -# Function to check if given file contain shell shebang (bash or sh) +# Function to check whether the given file contains a shell shebang (bash or sh) # https://unix.stackexchange.com/a/406939 -# $1 - absolute path to file -# $? - return value - 0 when succes +# $1 - absolute path to a file +# $? - return value - 0 on success has_shebang () { [ $# -le 0 ] && return 1 local file="$1" @@ -46,10 +47,11 @@ has_shebang () { return 3 } -# Function to prepare string from array of strings where first argument specify one character separator +# Function to concatenate an array of strings where the first argument +# specifies the separator # https://stackoverflow.com/a/17841619 -# $1 - Character used to join elements of array -# $@ - list of strings +# $1 - character used to join the elements of the array +# $@ - list of strings # return value - string join_by () { local IFS="$1" @@ -59,25 +61,25 @@ join_by () { # Function to get rid of comments represented by '#' # $1 - file path -# $2 - name of variable where will be stored result array -# $3 - value 1|0 - does file content inline comments? -# $? - return value - 0 when succes +# $2 - name of a variable where the result array will be stored +# $3 - value 1|0 - does the file contain inline comments? +# $? - return value - 0 on success file_to_array () { [ $# -le 2 ] && return 1 local output=() - [ "$3" -eq 0 ] && readarray output < <(grep -v "^#.*" "$1") # fetch array with lines from file while excluding '#' comments - [ "$3" -eq 1 ] && readarray output < <(cut -d ' ' -f 1 < <(grep -v "^#.*" "$1")) # fetch array with lines from file while excluding '#' comments + [ "$3" -eq 0 ] && readarray output < <(grep -v "^#.*" "$1") # fetch the array with lines from the file while excluding '#' comments + [ "$3" -eq 1 ] && readarray output < <(cut -d ' ' -f 1 < <(grep -v "^#.*" "$1")) # fetch the array with lines from the file while excluding '#' comments clean_array "$2" "${output[@]}" && return 0 } -# Function to get rid of spaces and new lines from array elements +# Function to trim spaces and new lines from array elements # https://stackoverflow.com/a/9715377 # https://stackoverflow.com/a/19347380 # https://unix.stackexchange.com/a/225517 -# $1 - name of variable where will be stored result array +# $1 - name of a variable where the result array will be stored # $@ - source array -# $? - return value - 0 when succes +# $? - return value - 0 on success clean_array () { [ $# -le 1 ] && return 1 local output="$1" @@ -89,12 +91,12 @@ clean_array () { done } -# Function to check if action is run in Debug mode +# Function to check if the action is run in a Debug mode is_debug () { [[ "${RUNNER_DEBUG}" -eq 1 ]] && return 0 || return 1 } -# Function to upload SARIF report to GitHub +# Function to upload the SARIF report to GitHub # Source: https://github.com/github/codeql-action/blob/dbe6f211e66b3aa5e9a5c4731145ed310ed54e28/lib/upload-lib.js#L104-L106 # Parameters: https://github.com/github/codeql-action/blob/69e09909dc219ed3374913e41c167490fc57202a/lib/upload-lib.js#L211-L224 # Values: https://github.com/github/codeql-action/blob/main/lib/upload-lib.test.js#L72 @@ -114,7 +116,7 @@ uploadSARIF () { echo -e "✅ ${GREEN}SARIF report was successfully uploaded to GitHub${NOCOLOR}" is_debug && cat curl_std else - echo -e "❌ ${RED}Fail to upload SARIF to GitHub${NOCOLOR}" + echo -e "❌ ${RED}Failed to upload the SARIF report to GitHub${NOCOLOR}" cat curl_std fi } @@ -144,7 +146,7 @@ Changed scripts: \`${#list_of_changed_scripts[@]}\` - [ShellCheck Documentation](https://github.com/koalaman/shellcheck#readme) --- -_ℹ️ When you have an issue with GitHub action please try to run it in [debug mode](https://github.blog/changelog/2022-05-24-github-actions-re-run-jobs-with-debug-logging/) and submit an [issue](https://github.com/redhat-plumbers-in-action/differential-shellcheck/issues/new)._" +_ℹ️ If you have an issue with this GitHub action, please try to run it in the [debug mode](https://github.blog/changelog/2022-05-24-github-actions-re-run-jobs-with-debug-logging/) and submit an [issue](https://github.com/redhat-plumbers-in-action/differential-shellcheck/issues/new)._" } # Logging aliases, use echo -e to use them diff --git a/src/index.sh b/src/index.sh index b5d7cb94..60d470a1 100755 --- a/src/index.sh +++ b/src/index.sh @@ -12,7 +12,7 @@ SCRIPT_DIR="$(dirname "$(readlink -f "$0")")" git config --global --add safe.directory /github/workspace # https://github.com/actions/runner/issues/342 -# get names of files from PR (excluding deleted files) +# Get the names of files from the PR (excluding deleted files) git diff --name-only --diff-filter=db "$INPUT_BASE".."$INPUT_HEAD" > ../pr-changes.txt # Find modified shell scripts @@ -21,7 +21,7 @@ file_to_array "../pr-changes.txt" "list_of_changes" 0 list_of_scripts=() [ -f "$INPUT_SHELL_SCRIPTS" ] && file_to_array "$INPUT_SHELL_SCRIPTS" "list_of_scripts" 1 -# Create list of scripts for testing +# Create a list of scripts for testing list_of_changed_scripts=() for file in "${list_of_changes[@]}"; do is_script_listed "$file" "${list_of_scripts[@]}" && list_of_changed_scripts+=("./${file}") && continue @@ -29,10 +29,10 @@ for file in "${list_of_changes[@]}"; do has_shebang "$file" && list_of_changed_scripts+=("./${file}") done -# Expose list_of_changed_scripts[*] for use inside GA workflow +# Expose list_of_changed_scripts[*] for use within the GA workflow echo "LIST_OF_SCRIPTS=${list_of_changed_scripts[*]}" >> "$GITHUB_ENV" -# Get list of exceptions +# Get a list of exceptions list_of_exceptions=() [ -f "$INPUT_IGNORED_CODES" ] && file_to_array "$INPUT_IGNORED_CODES" "list_of_exceptions" 1 string_of_exceptions=$(join_by , "${list_of_exceptions[@]}") @@ -43,7 +43,7 @@ if is_debug ; then echo -e "📜 ${WHITE}Changed shell scripts${NOCOLOR}" echo "${list_of_changed_scripts[@]}" echo - echo -e "👌 ${WHITE}List of shellcheck exceptions${NOCOLOR}" + echo -e "👌 ${WHITE}List of ShellCheck exceptions${NOCOLOR}" echo "${string_of_exceptions}" echo fi @@ -52,10 +52,11 @@ fi # SHELLCHECK # # ------------ # -# sed part is to edit shellcheck output so csdiff/csgrep knows it is shellcheck output (--format=gcc) +# The sed part ensures that cstools will recognize the output as being produced +# by ShellCheck and not GCC. shellcheck --format=gcc --exclude="${string_of_exceptions}" "${list_of_changed_scripts[@]}" 2> /dev/null | sed -e 's|$| <--[shellcheck]|' > ../pr-br-shellcheck.err -# make destination branch +# Check the destination branch # shellcheck disable=SC2086 git checkout -q -b ci_br_dest $INPUT_BASE @@ -83,18 +84,18 @@ echo csdiff --fixed "../pr-br-shellcheck.err" "../dest-br-shellcheck.err" > ../bugs.log if [ -s ../bugs.log ]; then - echo -e "✋ ${YELLOW}Added bugs, NEED INSPECTION${NOCOLOR}" + echo -e "✋ ${YELLOW}Added bugs, NEEDS INSPECTION${NOCOLOR}" csgrep ../bugs.log exit_status=1 else - echo -e "🥳 ${GREEN}No bugs added Yay!${NOCOLOR}" + echo -e "🥳 ${GREEN}No bugs added. Yay!${NOCOLOR}" exit_status=0 fi # SARIF upload if [ -n "$INPUT_TOKEN" ]; then echo - # GitHub support absolute path, so let's remove './' from file path + # GitHub requires an absolute path, so let's remove the './' prefix from it. csgrep --strip-path-prefix './' --mode=sarif ../bugs.log >> output.sarif && uploadSARIF fi