diff --git a/.automation/test/golang/README.md b/.automation/test/golang/README.md new file mode 100644 index 00000000..a8e7db24 --- /dev/null +++ b/.automation/test/golang/README.md @@ -0,0 +1,13 @@ +# Golang Test Cases +This folder holds the test cases for **Golang**. + +## Additional Docs +No Additional information is needed for this test case. + +## Good Test Cases +The test cases denoted: `LANGUAGE_good_FILE.EXTENSION` are all valid, and should pass successfully when linted. +- **Note:** They are linted utilizing the default linter rules. + +## Bad Test Cases +The test cases denoted: `LANGUAGE_bad_FILE.EXTENSION` are **NOT** valid, and should trigger errors when linted. +- **Note:** They are linted utilizing the default linter rules. diff --git a/.automation/test/golang/golang_bad_01.go b/.automation/test/golang/golang_bad_01.go new file mode 100644 index 00000000..370c8c5f --- /dev/null +++ b/.automation/test/golang/golang_bad_01.go @@ -0,0 +1,3 @@ +if len(in) == 0 { + return "", fmt.Errorf("Input is empty") +} diff --git a/.automation/test/golang/golang_good_01.go b/.automation/test/golang/golang_good_01.go new file mode 100644 index 00000000..c0481191 --- /dev/null +++ b/.automation/test/golang/golang_good_01.go @@ -0,0 +1,7 @@ +package main + +import "fmt" + +func main() { + fmt.Println("hello world") +} diff --git a/.github/linters/.golangci.yml b/.github/linters/.golangci.yml new file mode 100644 index 00000000..c3e3c91a --- /dev/null +++ b/.github/linters/.golangci.yml @@ -0,0 +1,40 @@ +--- +######################### +######################### +## Golang Linter rules ## +######################### +######################### + +# configure golangci-lint +# see https://github.com/golangci/golangci-lint/blob/master/.golangci.example.yml +issues: + exclude-rules: + - path: _test\.go + linters: + - dupl + - gosec + - goconst +linters: + enable: + - golint + - gosec + - unconvert + - gocyclo + - goconst + - goimports + - maligned + - gocritic +linters-settings: + errcheck: + # report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`; + # default is false: such cases aren't reported by default. + check-blank: true + govet: + # report about shadowed variables + check-shadowing: true + gocyclo: + # minimal code complexity to report, 30 by default + min-complexity: 15 + maligned: + # print struct with more effective memory layout or not, false by default + suggest-new: true diff --git a/.github/run-linter-locally.md b/.github/run-linter-locally.md index 13f2c7d6..952c152e 100644 --- a/.github/run-linter-locally.md +++ b/.github/run-linter-locally.md @@ -70,6 +70,10 @@ Once the container has been downloaded to your local environment, you can then b - `-e VALIDATE_DOCKER=` - Default: `true` - Flag to enable or disable the linting process of the language + - **VALIDATE_GO** + - `-e VALIDATE_GO=` + - Default: `true` + - Flag to enable or disable the linting process of the language - **ANSIBLE_DIRECTORY** - `-e ANSIBLE_DIRECTORY=` - Default: `/ansible` diff --git a/Dockerfile b/Dockerfile index 40e79a19..83d70bc7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,8 +25,9 @@ RUN apk add --no-cache \ bash git musl-dev curl gcc jq \ npm nodejs \ libxml2-utils perl \ - ruby ruby-dev ruby-bundler ruby-rdoc make\ - py3-setuptools ansible-lint + ruby ruby-dev ruby-bundler ruby-rdoc make \ + py3-setuptools ansible-lint \ + go ##################### # Run Pip3 Installs # @@ -62,11 +63,11 @@ RUN npm -g --no-cache install \ #################################### # Install dockerfilelint from repo # #################################### - RUN git clone https://github.com/replicatedhq/dockerfilelint.git && cd /dockerfilelint && npm install # I think we could fix this with path but not sure the language... # https://github.com/nodejs/docker-node/blob/master/docs/BestPractices.md + #################### # Run GEM installs # #################### @@ -78,6 +79,12 @@ RUN gem install rubocop:0.74 rubocop-rails rubocop-github:0.13 RUN wget -qO- "https://storage.googleapis.com/shellcheck/shellcheck-stable.linux.x86_64.tar.xz" | tar -xJv \ && cp "shellcheck-stable/shellcheck" /usr/bin/ +##################### +# Install Go Linter # +##################### +ARG GO_VERSION='v1.23.7' +RUN wget -O- -nv https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s "$GO_VERSION" + ########################################### # Load GitHub Env Vars for Github Actions # ########################################### @@ -97,6 +104,7 @@ ENV GITHUB_SHA=${GITHUB_SHA} \ VALIDATE_ANSIBLE=${VALIDATE_ANSIBLE} \ VALIDATE_DOCKER=${VALIDATE_DOCKER} \ VALIDATE_JAVASCRIPT=${VALIDATE_JAVASCRIPT} \ + VALIDATE_GO=${VALIDATE_GO} \ ANSIBLE_DIRECTORY=${ANSIBLE_DIRECTORY} \ RUN_LOCAL=${RUN_LOCAL} \ TEST_CASE_RUN=${TEST_CASE_RUN} diff --git a/README.md b/README.md index a545fc87..ac644bab 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ Developers on **GitHub** can call this Action to lint their code base with the f - **XML** (LibXML) - **Coffeescript** (coffeelint) - **Javascript** (eslint)(standard) +- **Golang** (golangci-lint) - **Dockerfile** (dockerfilelint) ## How to use @@ -121,7 +122,10 @@ The super-linter allows you to pass the following `ENV` variables to be able to - Flag to set the root directory for Ansible file location(s) - **VALIDATE_DOCKER** - Default: `true` - - Flag to enable or disable the linting process of the language + - Flag to enable or disable the linting process of the language +- **VALIDATE_GO** + - Default: `true` + - Flag to enable or disable the linting process of the language - **VERBOSE_OUTPUT** - Default: `false` - Flag to enable additional information about the linter, versions, and additional output diff --git a/TEMPLATES/.golangci.yml b/TEMPLATES/.golangci.yml new file mode 100644 index 00000000..c3e3c91a --- /dev/null +++ b/TEMPLATES/.golangci.yml @@ -0,0 +1,40 @@ +--- +######################### +######################### +## Golang Linter rules ## +######################### +######################### + +# configure golangci-lint +# see https://github.com/golangci/golangci-lint/blob/master/.golangci.example.yml +issues: + exclude-rules: + - path: _test\.go + linters: + - dupl + - gosec + - goconst +linters: + enable: + - golint + - gosec + - unconvert + - gocyclo + - goconst + - goimports + - maligned + - gocritic +linters-settings: + errcheck: + # report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`; + # default is false: such cases aren't reported by default. + check-blank: true + govet: + # report about shadowed variables + check-shadowing: true + gocyclo: + # minimal code complexity to report, 30 by default + min-complexity: 15 + maligned: + # print struct with more effective memory layout or not, false by default + suggest-new: true diff --git a/lib/linter.sh b/lib/linter.sh index 352b7700..02798c7e 100755 --- a/lib/linter.sh +++ b/lib/linter.sh @@ -36,13 +36,16 @@ ANSIBLE_LINTER_RULES="$DEFAULT_RULES_LOCATION/$ANSIBLE_FILE_NAME" # Path to th # Docker Vars DOCKER_FILE_NAME='.dockerfilelintrc' # Name of the file DOCKER_LINTER_RULES="$DEFAULT_RULES_LOCATION/$DOCKER_FILE_NAME" # Path to the Docker lint rules +# Golang Vars +GO_FILE_NAME='.golangci.yml' # Name of the file +GO_LINTER_RULES="$DEFAULT_RULES_LOCATION/$GO_FILE_NAME" # Path to the Docker lint rules ####################################### # Linter array for information prints # ####################################### LINTER_ARRAY=("jsonlint" "yamllint" "xmllint" "markdownlint" "shellcheck" "pylint" "perl" "rubocop" "coffeelint" "eslint" "standard" - "ansible-lint" "/dockerfilelint/bin/dockerfilelint") + "ansible-lint" "/dockerfilelint/bin/dockerfilelint" "golangci-lint") ################### # GitHub ENV Vars # @@ -64,6 +67,7 @@ VALIDATE_COFFEE="${VALIDATE_COFFEE}" # Boolean to validate language VALIDATE_ANSIBLE="${VALIDATE_ANSIBLE}" # Boolean to validate language VALIDATE_JAVASCRIPT="${VALIDATE_JAVASCRIPT}" # Boolean to validate language VALIDATE_DOCKER="${VALIDATE_DOCKER}" # Boolean to validate language +VALIDATE_GO="${VALIDATE_GO}" # Boolean to validate language TEST_CASE_RUN="${TEST_CASE_RUN}" # Boolean to validate only test cases ############## @@ -102,6 +106,7 @@ FILE_ARRAY_COFFEESCRIPT=() # Array of files to check FILE_ARRAY_ESLINT=() # Array of files to check FILE_ARRAY_STANDARD=() # Array of files to check FILE_ARRAY_DOCKER=() # Array of files to check +FILE_ARRAY_GO=() # Array of files to check ############ # Counters # @@ -119,6 +124,7 @@ ERRORS_FOUND_ANSIBLE=0 # Count of errors found ERRORS_FOUND_STANDARD=0 # Count of errors found ERRORS_FOUND_ESLINT=0 # Count of errors found ERRORS_FOUND_DOCKER=0 # Count of errors found +ERRORS_FOUND_GO=0 # Count of errors found ################################################################################ ########################## FUNCTIONS BELOW ##################################### @@ -806,6 +812,21 @@ GetGitHubVars() echo "- Excluding [DOCKER] files in code base..." fi + ############################### + # Convert string to lowercase # + ############################### + VALIDATE_GO=$(echo "$VALIDATE_GO" | awk '{print tolower($0)}') + ###################################### + # Validate we should check all files # + ###################################### + if [[ "$VALIDATE_GO" != "false" ]]; then + # Set to true + VALIDATE_GO="$DEFAULT_VALIDATE_LANGUAGE" + echo "- Validating [GOLANG] files in code base..." + else + # Its false + echo "- Excluding [GOLANG] files in code base..." + fi ############################## # Validate Ansible Directory # @@ -1056,6 +1077,18 @@ BuildFileList() # Set the READ_ONLY_CHANGE_FLAG since this could be exec # ########################################################## READ_ONLY_CHANGE_FLAG=1 + ######################## + # Get the Golang files # + ######################## + elif [ "$FILE_TYPE" == "go" ]; then + ################################ + # Append the file to the array # + ################################ + FILE_ARRAY_GO+=("$FILE") + ########################################################## + # Set the READ_ONLY_CHANGE_FLAG since this could be exec # + ########################################################## + READ_ONLY_CHANGE_FLAG=1 elif [ "$FILE" == "Dockerfile" ]; then ################################ # Append the file to the array # @@ -1452,6 +1485,7 @@ Footer() echo "ERRORS FOUND in JAVASCRIPT(eslint):[$ERRORS_FOUND_ESLINT]" echo "ERRORS FOUND in JAVASCRIPT(Standard):[$ERRORS_FOUND_STANDARD]" echo "ERRORS FOUND in DOCKER:[$ERRORS_FOUND_DOCKER]" + echo "ERRORS FOUND in GO:[$ERRORS_FOUND_GO]" echo "----------------------------------------------" echo "" @@ -1470,6 +1504,7 @@ Footer() [ $ERRORS_FOUND_ESLINT -ne 0 ] || \ [ $ERRORS_FOUND_STANDARD -ne 0 ] || \ [ $ERRORS_FOUND_DOCKER -ne 0 ] || \ + [ $ERRORS_FOUND_GO -ne 0 ] || \ [ $ERRORS_FOUND_RUBY -ne 0 ]; then # Failed exit echo "Exiting with errors found!" @@ -1511,6 +1546,7 @@ RunTestCases() TestCodebase "PYTHON" "pylint" "pylint --rcfile $PYTHON_LINTER_RULES -E" ".*\.\(py\)\$" TestCodebase "PERL" "perl" "perl -Mstrict -cw" ".*\.\(pl\)\$" TestCodebase "RUBY" "rubocop" "rubocop -c $RUBY_LINTER_RULES" ".*\.\(rb\)\$" + TestCodebase "GO" "golangci-lint" "golangci-lint run -c $GO_LINTER_RULES" ".*\.\(go\)\$" TestCodebase "COFFEESCRIPT" "coffeelint" "coffeelint -f $COFFEESCRIPT_LINTER_RULES" ".*\.\(coffee\)\$" TestCodebase "ESLINT" "eslint" "eslint --no-eslintrc -c $JAVASCRIPT_LINTER_RULES" ".*\.\(js\)\$" TestCodebase "STANDARD" "standard" "standard $STANDARD_LINTER_RULES" ".*\.\(js\)\$" @@ -1557,6 +1593,8 @@ GetLinterRules "$COFFEE_FILE_NAME" "$COFFEESCRIPT_LINTER_RULES" GetLinterRules "$ANSIBLE_FILE_NAME" "$ANSIBLE_LINTER_RULES" # Get javascript rules GetLinterRules "$JAVASCRIPT_FILE_NAME" "$JAVASCRIPT_LINTER_RULES" +# Get Golang rules +GetLinterRules "$GO_FILE_NAME" "$GO_LINTER_RULES" # Get docker rules GetLinterRules "$DOCKER_FILE_NAME" "$DOCKER_LINTER_RULES" @@ -1690,6 +1728,17 @@ if [ "$VALIDATE_COFFEE" == "true" ]; then LintCodebase "COFFEESCRIPT" "coffeelint" "coffeelint -f $COFFEESCRIPT_LINTER_RULES" ".*\.\(coffee\)\$" "${FILE_ARRAY_COFFEESCRIPT[@]}" fi +################## +# GOLANG LINTING # +################## +if [ "$VALIDATE_GO" == "true" ]; then + ######################### + # Lint the golang files # + ######################### + # LintCodebase "FILE_TYPE" "LINTER_NAME" "LINTER_CMD" "FILE_TYPES_REGEX" "FILE_ARRAY" + LintCodebase "GO" "golangci-lint" "golangci-lint run -c $GO_LINTER_RULES" ".*\.\(go\)\$" "${FILE_ARRAY_GO[@]}" +fi + ################### # ANSIBLE LINTING # ###################