diff --git a/.automation/cleanup-docker.sh b/.automation/cleanup-docker.sh index e6a81770..838119c4 100755 --- a/.automation/cleanup-docker.sh +++ b/.automation/cleanup-docker.sh @@ -8,7 +8,7 @@ # Its based on being built from a GitHub Action, but could be easily updated # To be ran in a different medium. # -# PRE-Reqs: +# PRE-Requirements: # - Dockerfile # - System with Docker installed # - Global variables met diff --git a/.automation/test/ansible/ghe-initialize/templates/ghe-config-apply.sh b/.automation/test/ansible/ghe-initialize/templates/ghe-config-apply.sh index 6ddf4d71..5a0f32dd 100644 --- a/.automation/test/ansible/ghe-initialize/templates/ghe-config-apply.sh +++ b/.automation/test/ansible/ghe-initialize/templates/ghe-config-apply.sh @@ -35,7 +35,7 @@ CheckGHEPid() ################################################ if [ ! -f "$GHE_CONFIG_PID" ]; then # File not found - echo "Were good to move forward, no .pid file found at:[$GHE_CONFIG_PID]" + echo "We're good to move forward, no .pid file found at:[$GHE_CONFIG_PID]" else # Found the pid running, need to sleep echo "Current PID found, sleeping $SLEEP_SECONDS seconds before next check..." @@ -189,10 +189,10 @@ CheckGHEProcess #################### RunConfigApply -########################################## -# Were going to run it again after a nap # -# to make sure there is no crazy actions # -########################################## +########################################### +# We're going to run it again after a nap # +# to make sure there is no crazy actions # +########################################### sleep 300s ###################### diff --git a/.automation/test/clojure/README.md b/.automation/test/clojure/README.md new file mode 100644 index 00000000..6606ef5b --- /dev/null +++ b/.automation/test/clojure/README.md @@ -0,0 +1,13 @@ +# Clojure Test Cases +This folder holds the test cases for **Clojure**. + +## 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/clojure/clojure_bad_1.clj b/.automation/test/clojure/clojure_bad_1.clj new file mode 100644 index 00000000..c8366066 --- /dev/null +++ b/.automation/test/clojure/clojure_bad_1.clj @@ -0,0 +1,64 @@ +(ns foo + (:require + [clojure.string :as str] + ;; We're never using this namespace. Also, the namespaces aren't sorted. + [clojure.set :as set])) + +;; Here we made a typo, so the symbol is unresolved: +(but-last [1 2 3]) + +;; Clj-kondo knows about arities of clojure namespaces, but you can also teach +;; it about your libraries or own namespaces +(str/join) + +;; foo has an arity of 2, but we're not actually using y +(defn foo-fn [x y] + ;; this do is redundant: + (do + ;; this is handy for debugging, but please remove it before pushing your code: + (def tmp_x x) + (let [y (fn [] (inc x))] + ;; the next let can be squashed together with the previous: + (let [z y] + ;; whoopsy, calling a local function with an incorrect number of args: + (y x) + ;; also wrong: + (recur))))) + +(letfn + [(f [] (h 1)) + (h [] (f 1))]) + +(defn- private-fn []) +;; redefining it... +(defn- private-fn []) + +(defn foo [] :foo) +;; Type error, because foo doesn't return a number! +(inc (foo)) + +;; I'm tired now, let's sleep... +;; Oops, not happening because of wrong amount of args: +(Thread/sleep 1000 1 2) + +;; Here we switch to another namespace and require the previous: +(ns bar (:require [foo :as f])) + +;; Wrong arity when calling a function from the previous namespace: +(f/foo-fn) + +;; private: +(f/private-fn) + +;; this won't pass the reader: +{:a 1 :a 2} +;; and neither will this: +#{1 1} +;; nor this: +{:a 1 :b} + +(ns bar-test (:require [clojure.test :as t])) + +(t/deftest my-tests + ;; you're not actually testing something here: + (odd? (inc 1))) \ No newline at end of file diff --git a/.automation/test/clojure/clojure_good_1.clj b/.automation/test/clojure/clojure_good_1.clj new file mode 100644 index 00000000..391f4688 --- /dev/null +++ b/.automation/test/clojure/clojure_good_1.clj @@ -0,0 +1,34 @@ +(ns foo + (:require + [clojure.string :as str])) + +(butlast [1 2 3]) + +(str/join "" "") + +(defn foo-fn [x] + (let [y (fn [] (inc x))] + (y))) + +(letfn + [(f [g] (h g)) + (h [i] (f i))]) + +(defn foo [] 1) +(inc (foo)) + +(Thread/sleep 1000 1) + +;; Here we switch to another namespace and require the previous: +(ns bar (:require [foo :as f])) + +(f/foo-fn 1) + +{:a 1 :b 2} +#{1 2} +{:a 1 :b 2} + +(ns bar-test (:require [clojure.test :as t])) + +(t/deftest my-tests + (t/is (odd? (inc 1)))) \ No newline at end of file diff --git a/.automation/test/coffeescript/coffeescript_bad_1.coffee b/.automation/test/coffeescript/coffeescript_bad_1.coffee index 5efeeacb..e388e7cc 100644 --- a/.automation/test/coffeescript/coffeescript_bad_1.coffee +++ b/.automation/test/coffeescript/coffeescript_bad_1.coffee @@ -6,7 +6,7 @@ # `mona echo *` - repeats what you say # # Author: -# admiralAwkbar@github.com +# admiralawkbar@github.com ############################### # Drop Hammer array of images # diff --git a/.automation/test/coffeescript/coffeescript_good_1.coffee b/.automation/test/coffeescript/coffeescript_good_1.coffee index 62f2a4fe..064f850e 100644 --- a/.automation/test/coffeescript/coffeescript_good_1.coffee +++ b/.automation/test/coffeescript/coffeescript_good_1.coffee @@ -6,7 +6,7 @@ # `mona echo *` - repeats what you say # # Author: -# admiralAwkbar@github.com +# admiralawkbar@github.com ############################### # Drop Hammer array of images # diff --git a/.automation/test/css/css_bad_01.css b/.automation/test/css/css_bad_01.css index 3c600b36..6ae90d7e 100644 --- a/.automation/test/css/css_bad_01.css +++ b/.automation/test/css/css_bad_01.css @@ -1,5 +1,5 @@ /* Bad */ -/* Multiline */ +/* Multi-line */ /* Comment */ .selector-3[type="text"] { background: linear-gradient(#FFFFFF, rgba(0, 0, 0, 0.8)); diff --git a/.automation/test/markdown/markdown_bad_1.md b/.automation/test/markdown/markdown_bad_1.md index 47aa18af..6599ac74 100644 --- a/.automation/test/markdown/markdown_bad_1.md +++ b/.automation/test/markdown/markdown_bad_1.md @@ -16,5 +16,5 @@ ls -la # Walk away -Were all done **here**. +We're all done **here**. - [Link Action]https://github.com diff --git a/.automation/test/markdown/markdown_good_1.md b/.automation/test/markdown/markdown_good_1.md index 5634a455..7a0aef45 100644 --- a/.automation/test/markdown/markdown_good_1.md +++ b/.automation/test/markdown/markdown_good_1.md @@ -16,5 +16,5 @@ ls -la ### Walk away -Were all done **here**. +We're all done **here**. - [Link Action](https://github.com) diff --git a/.automation/test/openapi/README.md b/.automation/test/openapi/README.md new file mode 100644 index 00000000..6f5d2c24 --- /dev/null +++ b/.automation/test/openapi/README.md @@ -0,0 +1,14 @@ +# OpenAPI Test Cases +This folder holds the test cases for **OpenAPI**. + +## Additional Docs +The `_bad_` tests are valid `.yml`/`.json` but invalid OpenAPI specs. +The test extensions used are `.ymlopenapi`/`.jsonopenapi` instead of `.yml`/`.json`. This is to prevent the [YAML] and [JSON] tests from picking them up. + +## 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/openapi/openapi_bad_1.ymlopenapi b/.automation/test/openapi/openapi_bad_1.ymlopenapi new file mode 100644 index 00000000..6c86b1b4 --- /dev/null +++ b/.automation/test/openapi/openapi_bad_1.ymlopenapi @@ -0,0 +1 @@ +openapi: '3.0.0' diff --git a/.automation/test/openapi/openapi_bad_2.jsonopenapi b/.automation/test/openapi/openapi_bad_2.jsonopenapi new file mode 100644 index 00000000..b0b97ddb --- /dev/null +++ b/.automation/test/openapi/openapi_bad_2.jsonopenapi @@ -0,0 +1,3 @@ +{ + "openapi": "3.0.0" +} diff --git a/.automation/test/openapi/openapi_good_1.ymlopenapi b/.automation/test/openapi/openapi_good_1.ymlopenapi new file mode 100644 index 00000000..eb4924a1 --- /dev/null +++ b/.automation/test/openapi/openapi_good_1.ymlopenapi @@ -0,0 +1,13 @@ +openapi: 3.0.0 +info: + title: Example + version: '1.0' + contact: + name: Justin Kalland + email: justin@kalland.com + description: Test for super-linter +servers: + - url: 'http://localhost:3000' +paths: {} +tags: + - name: example diff --git a/.automation/test/openapi/openapi_good_2.jsonopenapi b/.automation/test/openapi/openapi_good_2.jsonopenapi new file mode 100644 index 00000000..93f59635 --- /dev/null +++ b/.automation/test/openapi/openapi_good_2.jsonopenapi @@ -0,0 +1,23 @@ +{ + "openapi": "3.0.0", + "info": { + "title": "Example", + "version": "1.0", + "contact": { + "name": "Justin Kalland", + "email": "justin@kalland.com" + }, + "description": "Test for super-linter" + }, + "servers": [ + { + "url": "http://localhost:3000" + } + ], + "paths": {}, + "tags": [ + { + "name": "example" + } + ] +} diff --git a/.automation/test/perl/perl_bad_1.pl b/.automation/test/perl/perl_bad_1.pl index e3626f88..7b127b99 100644 --- a/.automation/test/perl/perl_bad_1.pl +++ b/.automation/test/perl/perl_bad_1.pl @@ -1,7 +1,7 @@ #!/usr/bin/perl ################################################################################ ################################################################################ -######### Script action @admiralAwkbar ######################################### +######### Script action @admiralawkbar ######################################### ################################################################################ ############# diff --git a/.automation/test/perl/perl_good_1.pl b/.automation/test/perl/perl_good_1.pl index f35c1409..caca0994 100644 --- a/.automation/test/perl/perl_good_1.pl +++ b/.automation/test/perl/perl_good_1.pl @@ -1,7 +1,7 @@ #!/usr/bin/perl ################################################################################ ################################################################################ -######### Script action @admiralAwkbar ######################################### +######### Script action @admiralawkbar ######################################### ################################################################################ ############# diff --git a/.automation/upload-docker.sh b/.automation/upload-docker.sh index 4902edfb..12c15635 100755 --- a/.automation/upload-docker.sh +++ b/.automation/upload-docker.sh @@ -9,7 +9,7 @@ # Its based on being built from a GitHub Action, but could be easily updated # To be ran in a different medium. # -# PRE-Reqs: +# PRE-Requirements: # - Dockerfile # - System with Docker installed # - Global variables met diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 253b1933..86d05b97 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -33,9 +33,10 @@ Draft pull requests are also welcome to get feedback early on, or if there is so If you are the current maintainer of this action: 1. Update `README.md` and the wiki to reflect new version number in the example workflow file sections 2. Draft [Release](https://help.github.com/en/github/administering-a-repository/managing-releases-in-a-repository) with a summarized changelog -3. A GitHub Action will Publish the Docker image to GitHub Package Registry once a Release is created -4. A GitHub Action will Publish the Docker image to Docker Hub once a Release is created -5. Look for approval from [CODEOWNERS](https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners) +3. Ensure you check the box for [publishing to the marketplace](https://help.github.com/en/actions/creating-actions/publishing-actions-in-github-marketplace#publishing-an-action) +4. A GitHub Action will Publish the Docker image to GitHub Package Registry once a Release is created +5. A GitHub Action will Publish the Docker image to Docker Hub once a Release is created +6. Look for approval from [CODEOWNERS](https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners) ## Resources - [How to Contribute to Open Source](https://opensource.guide/how-to-contribute/) diff --git a/.github/linters/.clj-kondo/config.edn b/.github/linters/.clj-kondo/config.edn new file mode 100644 index 00000000..30cae4c6 --- /dev/null +++ b/.github/linters/.clj-kondo/config.edn @@ -0,0 +1,2 @@ +{:linters {:unresolved-symbol {:exclude [(compojure.api.sweet/defroutes)]} + :refer-all {:exclude [clj-time.jdbc]}}} diff --git a/.github/linters/.openapirc.yml b/.github/linters/.openapirc.yml new file mode 100644 index 00000000..fdf641e1 --- /dev/null +++ b/.github/linters/.openapirc.yml @@ -0,0 +1,9 @@ +--- + +########################## +########################## +## OpenAPI Linter rules ## +########################## +########################## + +extends: spectral:oas diff --git a/.github/linters/.python-lint b/.github/linters/.python-lint index 8e9cc00e..e3d9f5b5 100644 --- a/.github/linters/.python-lint +++ b/.github/linters/.python-lint @@ -1,4 +1,5 @@ [MASTER] +errors-only= # A comma-separated list of package or module names from where C extensions may # be loaded. Extensions are loading into the active Python interpreter and may @@ -157,7 +158,7 @@ output-format=text reports=no # Activate the evaluation score. -score=yes +score=no [REFACTORING] diff --git a/.gitignore b/.gitignore index ad46b308..e529ffb7 100644 --- a/.gitignore +++ b/.gitignore @@ -29,7 +29,7 @@ bower_components # node-waf configuration .lock-wscript -# Compiled binary addons (https://nodejs.org/api/addons.html) +# Compiled binary add-ons (https://nodejs.org/api/addons.html) build/Release # Dependency directories @@ -59,3 +59,6 @@ typings/ # next.js build output .next + +# clj-kondo cache +.cache \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 49a5dbb1..d0c3a70b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -27,7 +27,7 @@ RUN apk add --no-cache \ libxml2-utils perl \ ruby ruby-dev ruby-bundler ruby-rdoc make \ py3-setuptools ansible-lint \ - go \ + go \ openjdk8-jre \ php7 \ ca-certificates less ncurses-terminfo-base \ @@ -72,6 +72,7 @@ RUN npm config set package-lock false \ eslint-plugin-jest \ stylelint \ stylelint-config-standard \ + @stoplight/spectral \ && npm --no-cache install \ markdownlint-cli \ jsonlint prettyjson \ @@ -131,6 +132,15 @@ RUN curl -Ls "$(curl -Ls https://api.github.com/repos/terraform-linters/tflint/r RUN wget "https://github.com/dotenv-linter/dotenv-linter/releases/latest/download/dotenv-linter-alpine-x86_64.tar.gz" -O - -q | tar -xzf - \ && mv "dotenv-linter" /usr/bin +##################### +# Install clj-kondo # +##################### +ARG CLJ_KONDO_VERSION='2020.06.12' +RUN curl -sLO https://github.com/borkdude/clj-kondo/releases/download/v${CLJ_KONDO_VERSION}/clj-kondo-${CLJ_KONDO_VERSION}-linux-static-amd64.zip \ + && unzip clj-kondo-${CLJ_KONDO_VERSION}-linux-static-amd64.zip \ + && rm clj-kondo-${CLJ_KONDO_VERSION}-linux-static-amd64.zip \ + && mv clj-kondo /usr/bin/ + ################## # Install ktlint # ################## @@ -166,8 +176,10 @@ ENV GITHUB_SHA=${GITHUB_SHA} \ VALIDATE_TERRAFORM=${VALIDATE_TERRAFORM} \ VALIDATE_CSS=${VALIDATE_CSS} \ VALIDATE_ENV=${VALIDATE_ENV} \ + VALIDATE_CLOJURE=${VALIDATE_CLOJURE} \ VALIDATE_KOTLIN=${VALIDATE_KOTLIN} \ VALIDATE_POWERSHELL=${VALIDATE_POWERSHELL} \ + VALIDATE_OPENAPI=${VALIDATE_OPENAPI} \ ANSIBLE_DIRECTORY=${ANSIBLE_DIRECTORY} \ RUN_LOCAL=${RUN_LOCAL} \ TEST_CASE_RUN=${TEST_CASE_RUN} \ diff --git a/README.md b/README.md index fe4627be..747ae791 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,20 @@ The end goal of this tool: - Build guidelines for code layout and format - Automate the process to help streamline code reviews + +## Table of Contents + +- [How it works](#how-it-works) +- [Supported linters](#supported-linters) +- [Usage](#how-to-use) +- [Environment variables](#environment-variables) +- [Disable rules](#disabling-rules) +- [Docker Hub](#docker-hub) +- [Run Super-Linter locally](#running-super-linter-locally-troubleshootingdebuggingenhancements) + - [CI / CT/ CD](#cictcd) +- [Limitations](#limitations) +- [Contributing](#how-to-contribute) + ## How it Works The super-linter finds issues and reports them to the console output. Fixes are suggested in the console output but not automatically fixed, and a status check will show up as failed on the pull request. @@ -22,6 +36,7 @@ Developers on **GitHub** can call the **GitHub Action** to lint their code base | --- | --- | | **Ansible** | [ansible-lint](https://github.com/ansible/ansible-lint) | | **CSS** | [stylelint](https://stylelint.io/) | +| **Clojure** | [clj-kondo](https://github.com/borkdude/clj-kondo) | | **CoffeeScript** | [coffeelint](https://coffeelint.github.io/) | | **Dockerfile** | [dockerfilelint](https://github.com/replicatedhq/dockerfilelint.git) | | **Golang** | [golangci-lint](https://github.com/golangci/golangci-lint) | @@ -40,6 +55,7 @@ Developers on **GitHub** can call the **GitHub Action** to lint their code base | **PowerShell** | [PSScriptAnalyzer](https://github.com/PowerShell/Psscriptanalyzer) | | **ENV** | [dotenv-linter](https://github.com/dotenv-linter/dotenv-linter) | | **Kotlin** | [ktlint](https://github.com/pinterest/ktlint) | +| **OpenAPI** | [spectral](https://github.com/stoplightio/spectral) | ## How to use To use this **GitHub** Action you will need to complete the following: @@ -133,11 +149,14 @@ and won't run anything unexpected. | **VALIDATE_PHP** | `true` | Flag to enable or disable the linting process of the language. | | **VALIDATE_PYTHON** | `true` | Flag to enable or disable the linting process of the language. | | **VALIDATE_RUBY** | `true` | Flag to enable or disable the linting process of the language. | +| **RUBY_CONFIG_FILE** | `.ruby-lint.yml` | Filename for [rubocop configuration](https://docs.rubocop.org/rubocop/configuration.html) (ex: `.ruby-lint.yml`, `.rubocop.yml`)| | **VALIDATE_COFFEE** | `true` | Flag to enable or disable the linting process of the language . | | **VALIDATE_ANSIBLE** | `true` | Flag to enable or disable the linting process of the language. | | **VALIDATE_JAVASCRIPT_ES** | `true` | Flag to enable or disable the linting process of the language. (Utilizing: eslint) | +| **JAVASCRIPT_ES_CONFIG_FILE** | `.eslintrc.yml` | Filename for [eslint configuration](https://eslint.org/docs/user-guide/configuring#configuration-file-formats) (ex: `.eslintrc.yml`, `.eslintrc.json`)| | **VALIDATE_JAVASCRIPT_STANDARD** | `true` | Flag to enable or disable the linting process of the language. (Utilizing: standard) | | **VALIDATE_TYPESCRIPT_ES** | `true` | Flag to enable or disable the linting process of the language. (Utilizing: eslint) | +| **TYPESCRIPT_ES_CONFIG_FILE** | `.eslintrc.yml` | Filename for [eslint configuration](https://eslint.org/docs/user-guide/configuring#configuration-file-formats) (ex: `.eslintrc.yml`, `.eslintrc.json`)| | **VALIDATE_TYPESCRIPT_STANDARD** | `true` | Flag to enable or disable the linting process of the language. (Utilizing: standard) | | **VALIDATE_DOCKER** | `true` | Flag to enable or disable the linting process of the language. | | **VALIDATE_GO** | `true` | Flag to enable or disable the linting process of the language. | @@ -145,7 +164,9 @@ and won't run anything unexpected. | **VALIDATE_TERRAFORM** | `true` | Flag to enable or disable the linting process of the language. | | **VALIDATE_CSS** | `true` | Flag to enable or disable the linting process of the language. | | **VALIDATE_ENV** | `true` | Flag to enable or disable the linting process of the language. | +| **VALIDATE_CLOJURE** | `true` | Flag to enable or disable the linting process of the language. | | **VALIDATE_KOTLIN** | `true` | Flag to enable or disable the linting process of the language. | +| **VALIDATE_OPENAPI** | `true` | Flag to enable or disable the linting process of the language. | | **ANSIBLE_DIRECTORY** | `/ansible` | Flag to set the root directory for Ansible file location(s). | | **ACTIONS_RUNNER_DEBUG** | `false` | Flag to enable additional information about the linter, versions, and additional output. | | **DISABLE_ERRORS** | `false` | Flag to have the linter complete with exit code 0 even if errors were detected. | diff --git a/TEMPLATES/.clj-kondo/config.edn b/TEMPLATES/.clj-kondo/config.edn new file mode 100644 index 00000000..30cae4c6 --- /dev/null +++ b/TEMPLATES/.clj-kondo/config.edn @@ -0,0 +1,2 @@ +{:linters {:unresolved-symbol {:exclude [(compojure.api.sweet/defroutes)]} + :refer-all {:exclude [clj-time.jdbc]}}} diff --git a/TEMPLATES/.openapirc.yml b/TEMPLATES/.openapirc.yml new file mode 100644 index 00000000..fdf641e1 --- /dev/null +++ b/TEMPLATES/.openapirc.yml @@ -0,0 +1,9 @@ +--- + +########################## +########################## +## OpenAPI Linter rules ## +########################## +########################## + +extends: spectral:oas diff --git a/TEMPLATES/.python-lint b/TEMPLATES/.python-lint index 8e9cc00e..e3d9f5b5 100644 --- a/TEMPLATES/.python-lint +++ b/TEMPLATES/.python-lint @@ -1,4 +1,5 @@ [MASTER] +errors-only= # A comma-separated list of package or module names from where C extensions may # be loaded. Extensions are loading into the active Python interpreter and may @@ -157,7 +158,7 @@ output-format=text reports=no # Activate the evaluation score. -score=yes +score=no [REFACTORING] diff --git a/docs/disabling-linters.md b/docs/disabling-linters.md index c738bdbd..408eba19 100644 --- a/docs/disabling-linters.md +++ b/docs/disabling-linters.md @@ -24,6 +24,7 @@ Below are examples and documentation for each language and the various methods t - [CSS](#stylelint) - [ENV](#dotenv-linter) - [Kotlin](#kotlin) +- [OpenAPI](#openapi) @@ -156,9 +157,9 @@ This line is waaaaaaaaaay too long # yamllint disable-line ### Yamllint disable code block ```yml # yamllint disable rule:colons -- Lorem : ipsum - dolor : sit amet, - consectetur : adipiscing elit +- Key : value + dolor : sit, + foo : bar # yamllint enable ``` @@ -222,9 +223,9 @@ class Foo(object): def meth3(self): """test one line disabling""" # no error - print(self.bla) # pylint: disable=no-member + print(self.baz) # pylint: disable=no-member # error - print(self.blop) + print(self.baz) ``` ### Pylint disable entire file @@ -607,3 +608,44 @@ import package.b.* ### ktlint disable entire file - There is currently **No** way to disable rules inline of the file(s) + +-------------------------------------------------------------------------------- + +## OpenAPI +- [spectral](https://github.com/stoplightio/spectral) + +### OpenAPI Config file +- `.github/linters/.openapirc.yml` +- You can add, extend, and disable rules +- Documentation at [Spectral Custom Rulesets](https://stoplight.io/p/docs/gh/stoplightio/spectral/docs/guides/4-custom-rulesets.md) +- File should be located at: `.github/linters/.openapirc.yml` + +### OpenAPI disable single line +- There is currently **No** way to disable rules inline of the file(s) + +### OpenAPI disable code block +- There is currently **No** way to disable rules inline of the file(s) + +### OpenAPI disable entire file +- There is currently **No** way to disable rules inline of the file(s) +- However, you can make [rule exceptions](https://stoplight.io/p/docs/gh/stoplightio/spectral/docs/guides/6-exceptions.md?srn=gh/stoplightio/spectral/docs/guides/6-exceptions.md) in the config for individual file(s). + +-------------------------------------------------------------------------------- + +## Clojure +- [clj-kondo](https://github.com/borkdude/clj-kondo) +- Since clj-kondo approaches static analysis in a very Clojure way, it is advised to read the [configuration docs](https://github.com/borkdude/clj-kondo/blob/master/doc/config.md) + +### clj-kondo standard Config file +- `.github/linters/.clj-kondo/config.edn` + +### clj-kondo disable single line +- There is currently **No** way to disable rules in a single line + +### clj-kondo disable code block +- There is currently **No** way to disable rules in a code block + +### clj-kondo disable entire file +```clojure +{:output {:exclude-files ["path/to/file"]}} +``` diff --git a/lib/linter.sh b/lib/linter.sh index 1b25ead7..1a5e9ab0 100755 --- a/lib/linter.sh +++ b/lib/linter.sh @@ -3,7 +3,7 @@ ################################################################################ ################################################################################ -########### Super-Linter (Lint all the code) @AdmiralAwkbar #################### +########### Super-Linter (Lint all the code) @admiralawkbar #################### ################################################################################ ################################################################################ @@ -23,17 +23,17 @@ MD_LINTER_RULES="$DEFAULT_RULES_LOCATION/$MD_FILE_NAME" # Path to th PYTHON_FILE_NAME='.python-lint' # Name of the file PYTHON_LINTER_RULES="$DEFAULT_RULES_LOCATION/$PYTHON_FILE_NAME" # Path to the python lint rules # Ruby Vars -RUBY_FILE_NAME='.ruby-lint.yml' # Name of the file +RUBY_FILE_NAME="${RUBY_CONFIG_FILE:-.ruby-lint.yml}" # Name of the file RUBY_LINTER_RULES="$DEFAULT_RULES_LOCATION/$RUBY_FILE_NAME" # Path to the ruby lint rules # Coffee Vars COFFEE_FILE_NAME='.coffee-lint.json' # Name of the file -COFFEESCRIPT_LINTER_RULES="$DEFAULT_RULES_LOCATION/$COFFEE_FILE_NAME" # Path to the coffescript lint rules +COFFEESCRIPT_LINTER_RULES="$DEFAULT_RULES_LOCATION/$COFFEE_FILE_NAME" # Path to the coffeescript lint rules # Javascript Vars -JAVASCRIPT_FILE_NAME='.eslintrc.yml' # Name of the file +JAVASCRIPT_FILE_NAME="${JAVASCRIPT_ES_CONFIG_FILE:-.eslintrc.yml}" # Name of the file JAVASCRIPT_LINTER_RULES="$DEFAULT_RULES_LOCATION/$JAVASCRIPT_FILE_NAME" # Path to the Javascript lint rules JAVASCRIPT_STANDARD_LINTER_RULES='' # ENV string to pass when running js standard # Typescript Vars -TYPESCRIPT_FILE_NAME='.eslintrc.yml' # Name of the file +TYPESCRIPT_FILE_NAME="${TYPESCRIPT_ES_CONFIG_FILE:-.eslintrc.yml}" # Name of the file TYPESCRIPT_LINTER_RULES="$DEFAULT_RULES_LOCATION/$TYPESCRIPT_FILE_NAME" # Path to the Typescript lint rules TYPESCRIPT_STANDARD_LINTER_RULES='' # ENV string to pass when running js standard # Ansible Vars @@ -54,6 +54,12 @@ POWERSHELL_LINTER_RULES="$DEFAULT_RULES_LOCATION/$POWERSHELL_FILE_NAME" # Pat # CSS Vars CSS_FILE_NAME='.stylelintrc.json' # Name of the file CSS_LINTER_RULES="$DEFAULT_RULES_LOCATION/$CSS_FILE_NAME" # Path to the CSS lint rules +# OpenAPI Vars +OPENAPI_FILE_NAME='.openapirc.yml' # Name of the file +OPENAPI_LINTER_RULES="$DEFAULT_RULES_LOCATION/$OPENAPI_FILE_NAME" # Path to the OpenAPI lint rules +# Clojure Vars +CLOJURE_FILE_NAME='.clj-kondo/config.edn' +CLOJURE_LINTER_RULES="$DEFAULT_RULES_LOCATION/$CLOJURE_FILE_NAME" ####################################### # Linter array for information prints # @@ -61,7 +67,7 @@ CSS_LINTER_RULES="$DEFAULT_RULES_LOCATION/$CSS_FILE_NAME" # Path to th LINTER_ARRAY=("jsonlint" "yamllint" "xmllint" "markdownlint" "shellcheck" "pylint" "perl" "rubocop" "coffeelint" "eslint" "standard" "ansible-lint" "/dockerfilelint/bin/dockerfilelint" "golangci-lint" "tflint" - "stylelint" "dotenv-linter" "powershell" "ktlint") + "stylelint" "dotenv-linter" "powershell" "ktlint" "clj-kondo" "spectral") ############################# # Language array for prints # @@ -69,7 +75,7 @@ LINTER_ARRAY=("jsonlint" "yamllint" "xmllint" "markdownlint" "shellcheck" LANGUAGE_ARRAY=('YML' 'JSON' 'XML' 'MARKDOWN' 'BASH' 'PERL' 'PHP' 'RUBY' 'PYTHON' 'COFFEESCRIPT' 'ANSIBLE' 'JAVASCRIPT_STANDARD' 'JAVASCRIPT_ES' 'TYPESCRIPT_STANDARD' 'TYPESCRIPT_ES' 'DOCKER' 'GO' 'TERRAFORM' - 'ENV' 'POWERSHELL' 'KOTLIN') + 'CSS' 'ENV' 'POWERSHELL' 'KOTLIN' 'CLOJURE' 'OPENAPI') ################### # GitHub ENV Vars # @@ -99,9 +105,11 @@ VALIDATE_DOCKER="${VALIDATE_DOCKER}" # Boolean to validate lang VALIDATE_GO="${VALIDATE_GO}" # Boolean to validate language VALIDATE_CSS="${VALIDATE_CSS}" # Boolean to validate language VALIDATE_ENV="${VALIDATE_ENV}" # Boolean to validate language +VALIDATE_CLOJURE="${VALIDATE_CLOJURE}" # Boolean to validate language VALIDATE_TERRAFORM="${VALIDATE_TERRAFORM}" # Boolean to validate language VALIDATE_POWERSHELL="${VALIDATE_POWERSHELL}" # Boolean to validate language VALIDATE_KOTLIN="${VALIDATE_KOTLIN}" # Boolean to validate language +VALIDATE_OPENAPI="${VALIDATE_OPENAPI}" # Boolean to validate language TEST_CASE_RUN="${TEST_CASE_RUN}" # Boolean to validate only test cases DISABLE_ERRORS="${DISABLE_ERRORS}" # Boolean to enable warning-only output without throwing errors @@ -124,6 +132,7 @@ RAW_FILE_ARRAY=() # Array of all files that were changed READ_ONLY_CHANGE_FLAG=0 # Flag set to 1 if files changed are not txt or md TEST_CASE_FOLDER='.automation/test' # Folder for test cases we should always ignore DEFAULT_DISABLE_ERRORS='false' # Default to enabling errors +DEFAULT_IFS="$IFS" # Get the Default IFS for updating ########################## # Array of changed files # @@ -148,7 +157,9 @@ FILE_ARRAY_TERRAFORM=() # Array of files to check FILE_ARRAY_POWERSHELL=() # Array of files to check FILE_ARRAY_CSS=() # Array of files to check FILE_ARRAY_ENV=() # Array of files to check +FILE_ARRAY_CLOJURE=() # Array of files to check FILE_ARRAY_KOTLIN=() # Array of files to check +FILE_ARRAY_OPENAPI=() # Array of files to check ############ # Counters # @@ -174,7 +185,9 @@ ERRORS_FOUND_TERRAFORM=0 # Count of errors found ERRORS_FOUND_POWERSHELL=0 # Count of errors found ERRORS_FOUND_CSS=0 # Count of errors found ERRORS_FOUND_ENV=0 # Count of errors found +ERRORS_FOUND_CLOJURE=0 # Count of errors found ERRORS_FOUND_KOTLIN=0 # Count of errors found +ERRORS_FOUND_OPENAPI=0 # Count of errors found ################################################################################ ########################## FUNCTIONS BELOW ##################################### @@ -556,6 +569,42 @@ LintAnsibleFiles() fi fi } + +################################################################################ +#### Function DetectOpenAPIFile ################################################ +DetectOpenAPIFile() +{ + ################ + # Pull in vars # + ################ + FILE="$1" + + ############################### + # Check the file for keywords # + ############################### + grep -E '"openapi":|"swagger":|^openapi:|^swagger:' "$GITHUB_WORKSPACE/$FILE" > /dev/null + + ####################### + # Load the error code # + ####################### + ERROR_CODE=$? + + ############################## + # Check the shell for errors # + ############################## + if [ $ERROR_CODE -eq 0 ]; then + ######################## + # Found string in file # + ######################## + return 0 + else + ################### + # No string match # + ################### + return 1 + fi +} + ################################################################################ #### Function GetGitHubVars #################################################### GetGitHubVars() @@ -759,7 +808,9 @@ GetValidationInfo() VALIDATE_POWERSHELL=$(echo "$VALIDATE_POWERSHELL" | awk '{print tolower($0)}') VALIDATE_CSS=$(echo "$VALIDATE_CSS" | awk '{print tolower($0)}') VALIDATE_ENV=$(echo "$VALIDATE_ENV" | awk '{print tolower($0)}') + VALIDATE_CLOJURE=$(echo "$VALIDATE_CLOJURE" | awk '{print tolower($0)') VALIDATE_KOTLIN=$(echo "$VALIDATE_KOTLIN" | awk '{print tolower($0)}') + VALIDATE_OPENAPI=$(echo "$VALIDATE_OPENAPI" | awk '{print tolower($0)}') ################################################ # Determine if any linters were explicitly set # @@ -786,6 +837,8 @@ GetValidationInfo() -n "$VALIDATE_POWERSHELL" || \ -n "$VALIDATE_CSS" || \ -n "$VALIDATE_ENV" || \ + -n "$VALIDATE_CLOJURE" || \ + -n "$VALIDATE_OPENAPI" || \ -n "$VALIDATE_KOTLIN" ]]; then ANY_SET="true" fi @@ -1098,6 +1151,33 @@ GetValidationInfo() VALIDATE_KOTLIN="true" fi + ####################################### + # Validate if we should check OPENAPI # + ####################################### + if [[ "$ANY_SET" == "true" ]]; then + # Some linter flags were set - only run those set to true + if [[ -z "$VALIDATE_OPENAPI" ]]; then + # OPENAPI flag was not set - default to false + VALIDATE_OPENAPI="false" + fi + else + # No linter flags were set - default all to true + VALIDATE_OPENAPI="true" + fi + + ####################################### + # Validate if we should check Clojure # + ####################################### + if [[ "$ANY_SET" == "true" ]]; then + # Some linter flags were set - only run those set to true + if [[ -z "$VALIDATE_CLOJURE" ]]; then + # Clojure flag was not set - default to false + VALIDATE_CLOJURE="false" + fi + else + # No linter flags were set - default all to true + VALIDATE_CLOJURE="true" + fi ####################################### # Print which linters we are enabling # @@ -1202,6 +1282,11 @@ GetValidationInfo() else PRINT_ARRAY+=("- Excluding [CSS] files in code base...") fi + if [[ "$VALIDATE_CLOJURE" == "true" ]]; then + PRINT_ARRAY+=("- Validating [CLOJURE] files in code base...") + else + PRINT_ARRAY+=("- Excluding [CLOJURE] files in code base...") + fi if [[ "$VALIDATE_ENV" == "true" ]]; then PRINT_ARRAY+=("- Validating [ENV] files in code base...") else @@ -1212,6 +1297,11 @@ GetValidationInfo() else PRINT_ARRAY+=("- Excluding [KOTLIN] files in code base...") fi + if [[ "$VALIDATE_OPENAPI" == "true" ]]; then + PRINT_ARRAY+=("- Validating [OPENAPI] files in code base...") + else + PRINT_ARRAY+=("- Excluding [OPENAPI] files in code base...") + fi ############################## # Validate Ansible Directory # @@ -1395,6 +1485,12 @@ BuildFileList() # Append the file to the array # ################################ FILE_ARRAY_YML+=("$FILE") + ############################ + # Check if file is OpenAPI # + ############################ + if DetectOpenAPIFile "$FILE"; then + FILE_ARRAY_OPENAPI+=("$FILE") + fi ########################################################## # Set the READ_ONLY_CHANGE_FLAG since this could be exec # ########################################################## @@ -1407,6 +1503,12 @@ BuildFileList() # Append the file to the array # ################################ FILE_ARRAY_JSON+=("$FILE") + ############################ + # Check if file is OpenAPI # + ############################ + if DetectOpenAPIFile "$FILE"; then + FILE_ARRAY_OPENAPI+=("$FILE") + fi ########################################################## # Set the READ_ONLY_CHANGE_FLAG since this could be exec # ########################################################## @@ -1597,6 +1699,15 @@ BuildFileList() # Set the READ_ONLY_CHANGE_FLAG since this could be exec # ########################################################## READ_ONLY_CHANGE_FLAG=1 + elif [ "$FILE_TYPE" == "clj" ] || [ "$FILE_TYPE" == "cljs" ] || [ "$FILE_TYPE" == "cljc" ] || [ "$FILE_TYPE" == "edn" ]; then + ################################ + # Append the file to the array # + ################################ + FILE_ARRAY_CLOJURE+=("$FILE") + ########################################################## + # Set the READ_ONLY_CHANGE_FLAG since this could be exec # + ########################################################## + READ_ONLY_CHANGE_FLAG=1 else ############################################## # Use file to see if we can parse what it is # @@ -1750,12 +1861,22 @@ LintCodebase() # We have files added to array of files to check LIST_FILES=("${FILE_ARRAY[@]}") # Copy the array into list else + ############################################################################### + # Set the file seperator to newline to allow for grabbing objects with spaces # + ############################################################################### + IFS=$'\n' + ################################# # Get list of all files to lint # ################################# # shellcheck disable=SC2207,SC2086 LIST_FILES=($(cd "$GITHUB_WORKSPACE" || exit; find . -type f -regex "$FILE_EXTENSIONS" 2>&1)) + ########################### + # Set IFS back to default # + ########################### + IFS="$DEFAULT_IFS" + ############################################################ # Set it back to empty if loaded with blanks from scanning # ############################################################ @@ -1922,11 +2043,21 @@ TestCodebase() # shellcheck disable=SC2207,SC2086,SC2010 LIST_FILES=($(cd "$GITHUB_WORKSPACE/$TEST_CASE_FOLDER" || exit; ls ansible/ | grep ".yml" 2>&1)) else + ############################################################################### + # Set the file seperator to newline to allow for grabbing objects with spaces # + ############################################################################### + IFS=$'\n' + ################################# # Get list of all files to lint # ################################# # shellcheck disable=SC2207,SC2086 LIST_FILES=($(cd "$GITHUB_WORKSPACE/$TEST_CASE_FOLDER" || exit; find . -type f -regex "$FILE_EXTENSIONS" ! -path "*./ansible*" 2>&1)) + + ########################### + # Set IFS back to default # + ########################### + IFS="$DEFAULT_IFS" fi ################## @@ -2126,6 +2257,8 @@ Footer() [ "$ERRORS_FOUND_RUBY" -ne 0 ] || \ [ "$ERRORS_FOUND_CSS" -ne 0 ] || \ [ "$ERRORS_FOUND_ENV" -ne 0 ] || \ + [ "$ERRORS_FOUND_OPENAPI" -ne 0 ] || \ + [ "$ERRORS_FOUND_CLOJURE" -ne 0 ] || \ [ "$ERRORS_FOUND_KOTLIN" -ne 0 ]; then # Failed exit echo "Exiting with errors found!" @@ -2171,7 +2304,7 @@ RunTestCases() TestCodebase "XML" "xmllint" "xmllint" ".*\.\(xml\)\$" TestCodebase "MARKDOWN" "markdownlint" "markdownlint -c $MD_LINTER_RULES" ".*\.\(md\)\$" TestCodebase "BASH" "shellcheck" "shellcheck" ".*\.\(sh\)\$" - TestCodebase "PYTHON" "pylint" "pylint --rcfile $PYTHON_LINTER_RULES -E" ".*\.\(py\)\$" + TestCodebase "PYTHON" "pylint" "pylint --rcfile $PYTHON_LINTER_RULES" ".*\.\(py\)\$" TestCodebase "PERL" "perl" "perl -Mstrict -cw" ".*\.\(pl\)\$" TestCodebase "PHP" "php" "php -l" ".*\.\(php\)\$" TestCodebase "RUBY" "rubocop" "rubocop -c $RUBY_LINTER_RULES" ".*\.\(rb\)\$" @@ -2181,13 +2314,15 @@ RunTestCases() TestCodebase "JAVASCRIPT_STANDARD" "standard" "standard $JAVASCRIPT_STANDARD_LINTER_RULES" ".*\.\(js\)\$" TestCodebase "TYPESCRIPT_ES" "eslint" "eslint --no-eslintrc -c $TYPESCRIPT_LINTER_RULES" ".*\.\(ts\)\$" TestCodebase "TYPESCRIPT_STANDARD" "standard" "standard --parser @typescript-eslint/parser --plugin @typescript-eslint/eslint-plugin $TYPESCRIPT_STANDARD_LINTER_RULES" ".*\.\(ts\)\$" - TestCodebase "DOCKER" "/dockerfilelint/bin/dockerfilelint" "/dockerfilelint/bin/dockerfilelint" ".*\(Dockerfile\)\$" + TestCodebase "DOCKER" "/dockerfilelint/bin/dockerfilelint" "/dockerfilelint/bin/dockerfilelint -c $DOCKER_LINTER_RULES" ".*\(Dockerfile\)\$" TestCodebase "ANSIBLE" "ansible-lint" "ansible-lint -v -c $ANSIBLE_LINTER_RULES" "ansible-lint" TestCodebase "TERRAFORM" "tflint" "tflint -c $TERRAFORM_LINTER_RULES" ".*\.\(tf\)\$" TestCodebase "POWERSHELL" "pwsh" "pwsh -c Invoke-ScriptAnalyzer -EnableExit -Settings $POWERSHELL_LINTER_RULES -Path" ".*\.\(ps1\|psm1\|psd1\|ps1xml\|pssc\|psrc\|cdxml\)\$" TestCodebase "CSS" "stylelint" "stylelint --config $CSS_LINTER_RULES" ".*\.\(css\)\$" TestCodebase "ENV" "dotenv-linter" "dotenv-linter" ".*\.\(env\)\$" + TestCodebase "CLOJURE" "clj-kondo" "clj-kondo --config $CLOJURE_LINTER_RULES --lint" ".*\.\(clj\|cljs\|cljc\|edn\)\$" TestCodebase "KOTLIN" "ktlint" "ktlint" ".*\.\(kt\|kts\)\$" + TestCodebase "OPENAPI" "spectral" "spectral lint -r $OPENAPI_LINTER_RULES" ".*\.\(ymlopenapi\|jsonopenapi\)\$" ################# # Footer prints # @@ -2341,7 +2476,7 @@ if [ "$VALIDATE_PYTHON" == "true" ]; then # Lint the python files # ######################### # LintCodebase "FILE_TYPE" "LINTER_NAME" "LINTER_CMD" "FILE_TYPES_REGEX" "FILE_ARRAY" - LintCodebase "PYTHON" "pylint" "pylint --rcfile $PYTHON_LINTER_RULES -E" ".*\.\(py\)\$" "${FILE_ARRAY_PYTHON[@]}" + LintCodebase "PYTHON" "pylint" "pylint --rcfile $PYTHON_LINTER_RULES" ".*\.\(py\)\$" "${FILE_ARRAY_PYTHON[@]}" fi ################ @@ -2516,7 +2651,21 @@ if [ "$VALIDATE_DOCKER" == "true" ]; then # Lint the docker files # ######################### # LintCodebase "FILE_TYPE" "LINTER_NAME" "LINTER_CMD" "FILE_TYPES_REGEX" "FILE_ARRAY" - LintCodebase "DOCKER" "/dockerfilelint/bin/dockerfilelint" "/dockerfilelint/bin/dockerfilelint" ".*\(Dockerfile\)\$" "${FILE_ARRAY_DOCKER[@]}" + LintCodebase "DOCKER" "/dockerfilelint/bin/dockerfilelint" "/dockerfilelint/bin/dockerfilelint -c $DOCKER_LINTER_RULES" ".*\(Dockerfile\)\$" "${FILE_ARRAY_DOCKER[@]}" +fi + +################### +# CLOJURE LINTING # +################### +if [ "$VALIDATE_CLOJURE" == "true" ]; then + ################################# + # Get Clojure standard rules # + ################################# + GetStandardRules "clj-kondo" + ######################### + # Lint the Clojure files # + ######################### + LintCodebase "CLOJURE" "clj-kondo" "clj-kondo --config $CLOJURE_LINTER_RULES --lint" ".*\.\(clj\|cljs\|cljc\|edn\)\$" "${FILE_ARRAY_CLOJURE[@]}" fi ###################### @@ -2530,6 +2679,39 @@ if [ "$VALIDATE_POWERSHELL" == "true" ]; then LintCodebase "POWERSHELL" "pwsh" "pwsh -c Invoke-ScriptAnalyzer -EnableExit -Settings $POWERSHELL_LINTER_RULES -Path" ".*\.\(ps1\|psm1\|psd1\|ps1xml\|pssc\|psrc\|cdxml\)\$" "${FILE_ARRAY_POWERSHELL[@]}" fi +################### +# OPENAPI LINTING # +################### +if [ "$VALIDATE_OPENAPI" == "true" ]; then + # If we are validating all codebase we need to build file list because not every yml/json file is an OpenAPI file + if [ "$VALIDATE_ALL_CODEBASE" == "true" ]; then + ############################################################################### + # Set the file seperator to newline to allow for grabbing objects with spaces # + ############################################################################### + IFS=$'\n' + + # shellcheck disable=SC2207 + LIST_FILES=($(cd "$GITHUB_WORKSPACE" || exit; find . -type f -regex ".*\.\(yml\|yaml\|json\)\$" 2>&1)) + for FILE in "${LIST_FILES[@]}" + do + if DetectOpenAPIFile "$FILE"; then + FILE_ARRAY_OPENAPI+=("$FILE") + fi + done + + ########################### + # Set IFS back to default # + ########################### + IFS="$DEFAULT_IFS" + fi + + ########################## + # Lint the OpenAPI files # + ########################## + # LintCodebase "FILE_TYPE" "LINTER_NAME" "LINTER_CMD" "FILE_TYPES_REGEX" "FILE_ARRAY" + LintCodebase "OPENAPI" "spectral" "spectral lint -r $OPENAPI_LINTER_RULES" "disabledfileext" "${FILE_ARRAY_OPENAPI[@]}" +fi + ########## # Footer # ##########