diff --git a/.automation/test/csharp/README.md b/.automation/test/csharp/README.md new file mode 100644 index 00000000..eadae5be --- /dev/null +++ b/.automation/test/csharp/README.md @@ -0,0 +1,19 @@ +# CSharp Test Cases + +This folder holds the test cases for **CSharp**. + +## 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/csharp/csharp_bad_01.cs b/.automation/test/csharp/csharp_bad_01.cs new file mode 100644 index 00000000..132f5d24 --- /dev/null +++ b/.automation/test/csharp/csharp_bad_01.cs @@ -0,0 +1,9 @@ +using System; + +namespace HelloWorld { + class Program { + static void Main(string[] args) { + Console.WriteLine("Hello World"); + } + } +} diff --git a/.automation/test/csharp/csharp_good_01.cs b/.automation/test/csharp/csharp_good_01.cs new file mode 100644 index 00000000..a68542dc --- /dev/null +++ b/.automation/test/csharp/csharp_good_01.cs @@ -0,0 +1,12 @@ +using System; + +namespace HelloWorld +{ + class Program + { + static void Main(string[] args) + { + Console.WriteLine("Hello World!"); + } + } +} diff --git a/.automation/test/csharp/reports/expected-CSHARP.tap.ignored b/.automation/test/csharp/reports/expected-CSHARP.tap.ignored new file mode 100644 index 00000000..98d94702 --- /dev/null +++ b/.automation/test/csharp/reports/expected-CSHARP.tap.ignored @@ -0,0 +1,7 @@ +TAP version 13 +1..2 +not ok 1 - css_bad_01.css + --- + message: \ncss/css_bad_01.css\n 2 1 ✖ Expected empty line before comment comment-empty-line-before\n 3 1 ✖ Expected empty line before comment comment-empty-line-before\n 5 5 ✖ Expected indentation of 2 spaces indentation \n 5 33 ✖ Expected "#FFFFFF" to be "#ffffff" color-hex-case \n 5 33 ✖ Expected "#FFFFFF" to be "#FFF" color-hex-length \n 6 5 ✖ Expected indentation of 2 spaces indentation \n 7 5 ✖ Expected indentation of 2 spaces indentation \n 8 5 ✖ Expected indentation of 2 spaces indentation \n 8 12 ✖ Expected "#AAAAAA" to be "#aaaaaa" color-hex-case \n 8 12 ✖ Expected "#AAAAAA" to be "#AAA" color-hex-length\n + ... +ok 2 - css_good_01.css diff --git a/Dockerfile b/Dockerfile index 32e81ef5..6dee160a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -65,7 +65,9 @@ RUN apk add --update --no-cache \ gnupg \ icu-libs \ jq \ - libc-dev libxml2-dev libxml2-utils \ + krb5-libs \ + libc-dev libxml2-dev libxml2-utils libgcc \ + libcurl libintl libssl1.1 libstdc++ \ make \ musl-dev \ npm nodejs-current \ @@ -106,6 +108,16 @@ ENV PATH="/node_modules/.bin:${PATH}" ############################## RUN bundle install +################################### +# Install DotNet and Dependancies # +################################### +RUN wget --tries=5 -O dotnet-install.sh https://dot.net/v1/dotnet-install.sh \ + && chmod +x dotnet-install.sh \ + && ./dotnet-install.sh --install-dir /usr/share/dotnet -channel Current -version latest \ + && /usr/share/dotnet/dotnet tool install -g dotnet-format + +ENV PATH="${PATH}:/root/.dotnet/tools:/usr/share/dotnet" + ############################## # Installs Perl dependencies # ############################## @@ -222,9 +234,9 @@ RUN wget --tries=5 https://storage.googleapis.com/dart-archive/channels/stable/r RUN printf '#!/bin/bash \n\nif [[ -x "$1" ]]; then exit 0; else echo "Error: File:[$1] is not executable"; exit 1; fi' > /usr/bin/bash-exec \ && chmod +x /usr/bin/bash-exec -################ -# Install Raku # -################ +################################################# +# Install Raku and additional Edge dependencies # +################################################# # Basic setup, programs and init RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing/" >> /etc/apk/repositories \ && apk add --update --no-cache rakudo zef @@ -232,7 +244,6 @@ RUN echo "http://dl-cdn.alpinelinux.org/alpine/edge/testing/" >> /etc/apk/reposi ###################### # Install CheckStyle # ###################### - RUN CHECKSTYLE_LATEST=$(curl -s https://api.github.com/repos/checkstyle/checkstyle/releases/latest \ | grep browser_download_url \ | grep ".jar" \ @@ -301,6 +312,7 @@ ENV ACTIONS_RUNNER_DEBUG=${ACTIONS_RUNNER_DEBUG} \ VALIDATE_CLOJURE=${VALIDATE_CLOJURE} \ VALIDATE_CLOUDFORMATION=${VALIDATE_CLOUDFORMATION} \ VALIDATE_COFFEE=${VALIDATE_COFFEE} \ + VALIDATE_CSHARP=${VALIDATE_CSHARP} \ VALIDATE_CSS=${VALIDATE_CSS} \ VALIDATE_DART=${VALIDATE_DART} \ VALIDATE_DOCKERFILE=${VALIDATE_DOCKERFILE} \ diff --git a/README.md b/README.md index f2e0b516..6a4a9bba 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,7 @@ Developers on **GitHub** can call the **GitHub Action** to lint their code base | **Ansible** | [ansible-lint](https://github.com/ansible/ansible-lint) | | **Azure Resource Manager (ARM)** | [arm-ttk](https://github.com/azure/arm-ttk) | | **AWS CloudFormation templates** | [cfn-lint](https://github.com/aws-cloudformation/cfn-python-lint/) | +| **C#** | [dotnet-format](https://github.com/dotnet/format) | | **CSS** | [stylelint](https://stylelint.io/) | | **Clojure** | [clj-kondo](https://github.com/borkdude/clj-kondo) | | **CoffeeScript** | [coffeelint](https://coffeelint.github.io/) | @@ -200,6 +201,7 @@ But if you wish to select or exclude specific linters, we give you full control | **VALIDATE_CLOJURE** | `true` | Flag to enable or disable the linting process of the Clojure language. | | **VALIDATE_CLOUDFORMATION** | `true` | Flag to enable or disable the linting process of the AWS Cloud Formation language. | | **VALIDATE_COFFEE** | `true` | Flag to enable or disable the linting process of the Coffeescript language . | +| **VALIDATE_CSHARP** | `true` | Flag to enable or disable the linting process of the C# language. | | **VALIDATE_CSS** | `true` | Flag to enable or disable the linting process of the CSS language. | | **VALIDATE_DART** | `true` | Flag to enable or disable the linting process of the Dart language. | | **VALIDATE_DOCKERFILE** | `true` | Flag to enable or disable the linting process of the Docker language. | @@ -245,7 +247,6 @@ But if you wish to select or exclude specific linters, we give you full control | **VALIDATE_YAML** | `true` | Flag to enable or disable the linting process of the YAML language. | | **YAML_CONFIG_FILE** | `.yaml-lint.yml` | Filename for [Yamllint configuration](https://yamllint.readthedocs.io/en/stable/configuration.html) (ex: `.yaml-lint.yml`, `.yamllint.yml`) | - ### Template rules files You can use the **GitHub** **Super-Linter** _with_ or _without_ your own personal rules sets. This allows for greater flexibility for each individual code base. The Template rules all try to follow the standards we believe should be enabled at the basic level. diff --git a/lib/buildFileList.sh b/lib/buildFileList.sh index 17f9d271..1f9d1159 100755 --- a/lib/buildFileList.sh +++ b/lib/buildFileList.sh @@ -405,6 +405,19 @@ function BuildFileList() { # Append the file to the array # ################################ FILE_ARRAY_POWERSHELL+=("${FILE}") + ########################################################## + # Set the READ_ONLY_CHANGE_FLAG since this could be exec # + ########################################################## + READ_ONLY_CHANGE_FLAG=1 + elif [ "${FILE_TYPE}" == "cs" ]; then + ################################ + # Append the file to the array # + ################################ + FILE_ARRAY_CSHARP+=("${FILE}") + ########################################################## + # Set the READ_ONLY_CHANGE_FLAG since this could be exec # + ########################################################## + READ_ONLY_CHANGE_FLAG=1 elif [ "${FILE_TYPE}" == "css" ] || [ "${FILE_TYPE}" == "scss" ] || [ "${FILE_TYPE}" == "sass" ]; then ################################ diff --git a/lib/linter.sh b/lib/linter.sh index 1d526005..f27b3da7 100755 --- a/lib/linter.sh +++ b/lib/linter.sh @@ -133,8 +133,8 @@ YAML_LINTER_RULES="${DEFAULT_RULES_LOCATION}/${YAML_FILE_NAME}" # Path to the ya ####################################### # Linter array for information prints # ####################################### -LINTER_ARRAY=('ansible-lint' 'arm-ttk' 'asl-validator' 'black' 'bash-exec' 'cfn-lint' 'checkstyle' 'chktex' 'clj-kondo' 'coffeelint' - 'dart' 'dockerfilelint' 'dotenv-linter' 'editorconfig-checker' 'eslint' 'flake8' 'golangci-lint' +LINTER_ARRAY=('ansible-lint' 'arm-ttk' 'asl-validator' 'bash-exec' 'black' 'cfn-lint' 'checkstyle' 'chktex' 'clj-kondo' 'coffeelint' + 'dotnet-format' 'dart' 'dockerfilelint' 'dotenv-linter' 'editorconfig-checker' 'eslint' 'flake8' 'golangci-lint' 'hadolint' 'htmlhint' 'jsonlint' 'ktlint' 'lintr' 'lua' 'markdownlint' 'npm-groovy-lint' 'perl' 'protolint' 'pwsh' 'pylint' 'raku' 'rubocop' 'shellcheck' 'spectral' 'standard' 'stylelint' 'sql-lint' 'terrascan' 'tflint' 'xmllint' 'yamllint') @@ -142,7 +142,7 @@ LINTER_ARRAY=('ansible-lint' 'arm-ttk' 'asl-validator' 'black' 'bash-exec' 'cfn- ############################# # Language array for prints # ############################# -LANGUAGE_ARRAY=('ANSIBLE' 'ARM' 'BASH' 'BASH_EXEC' 'CLOUDFORMATION' 'CLOJURE' 'COFFEESCRIPT' 'CSS' +LANGUAGE_ARRAY=('ANSIBLE' 'ARM' 'BASH' 'BASH_EXEC' 'CLOUDFORMATION' 'CLOJURE' 'COFFEESCRIPT' 'CSHARP' 'CSS' 'DART' 'DOCKERFILE' 'DOCKERFILE_HADOLINT' 'EDITORCONFIG' 'ENV' 'GO' 'GROOVY' 'HTML' 'JAVA' 'JAVASCRIPT_ES' 'JAVASCRIPT_STANDARD' 'JSON' 'JSX' 'KOTLIN' 'LATEX' 'LUA' 'MARKDOWN' 'OPENAPI' 'PERL' 'PHP_BUILTIN' 'PHP_PHPCS' 'PHP_PHPSTAN' 'PHP_PSALM' 'POWERSHELL' @@ -178,6 +178,7 @@ VALIDATE_BASH_EXEC="${VALIDATE_BASH_EXEC}" # Boolean t VALIDATE_CLOUDFORMATION="${VALIDATE_CLOUDFORMATION}" # Boolean to validate language VALIDATE_CLOJURE="${VALIDATE_CLOJURE}" # Boolean to validate language VALIDATE_COFFEE="${VALIDATE_COFFEE}" # Boolean to validate language +VALIDATE_CSHARP="${VALIDATE_CSHARP}" # Boolean to validate language VALIDATE_CSS="${VALIDATE_CSS}" # Boolean to validate language VALIDATE_DART="${VALIDATE_DART}" # Boolean to validate language VALIDATE_DOCKERFILE="${VALIDATE_DOCKERFILE}" # Boolean to validate language @@ -280,6 +281,7 @@ FILE_ARRAY_BASH=() # Array of files to check FILE_ARRAY_CLOUDFORMATION=() # Array of files to check FILE_ARRAY_CLOJURE=() # Array of files to check FILE_ARRAY_COFFEESCRIPT=() # Array of files to check +FILE_ARRAY_CSHARP=() # Array of files to check FILE_ARRAY_CSS=() # Array of files to check FILE_ARRAY_DART=() # Array of files to check FILE_ARRAY_DOCKERFILE=() # Array of files to check @@ -334,6 +336,8 @@ ERRORS_FOUND_CLOUDFORMATION=0 # Count of errors found export ERRORS_FOUND_CLOUDFORMATION # Workaround SC2034 ERRORS_FOUND_CLOJURE=0 # Count of errors found export ERRORS_FOUND_CLOJURE # Workaround SC2034 +ERRORS_FOUND_CSHARP=0 # Count of errors found +export ERRORS_FOUND_CSHARP # Workaround SC2034 ERRORS_FOUND_CSS=0 # Count of errors found export ERRORS_FOUND_CSS # Workaround SC2034 ERRORS_FOUND_COFFEESCRIPT=0 # Count of errors found @@ -1432,6 +1436,17 @@ if [ "${VALIDATE_COFFEE}" == "true" ]; then LintCodebase "COFFEESCRIPT" "coffeelint" "coffeelint -f ${COFFEESCRIPT_LINTER_RULES}" ".*\.\(coffee\)\$" "${FILE_ARRAY_COFFEESCRIPT[@]}" fi +################## +# CSHARP LINTING # +################## +if [ "${VALIDATE_CSHARP}" == "true" ]; then + ######################### + # Lint the C# files # + ######################### + # LintCodebase "FILE_TYPE" "LINTER_NAME" "LINTER_CMD" "FILE_TYPES_REGEX" "FILE_ARRAY" + LintCodebase "CSHARP" "dotnet-format" "dotnet-format --folder --check --exclude / --include" ".*\.\(cs\)\$" "${FILE_ARRAY_CSHARP[@]}" +fi + ############### # CSS LINTING # ############### diff --git a/lib/worker.sh b/lib/worker.sh index 7432f9b6..2e00c952 100755 --- a/lib/worker.sh +++ b/lib/worker.sh @@ -229,6 +229,14 @@ function LintCodebase() { R --slave -e "errors <- lintr::lint('$FILE');print(errors);quit(save = 'no', status = if (length(errors) > 0) 1 else 0)" 2>&1 ) #LINTER_COMMAND="lintr::lint('${FILE}')" + ######################################################### + # Corner case for C# as it writes to tty and not stdout # + ######################################################### + elif [[ ${FILE_TYPE} == "CSHARP" ]]; then + LINT_CMD=$( + cd "${DIR_NAME}" || exit + ${LINTER_COMMAND} "${FILE_NAME}" | tee /dev/tty2 2>&1; exit "${PIPESTATUS[0]}" + ) else ################################ # Lint the file with the rules # @@ -468,6 +476,14 @@ function TestCodebase() { cd "${GITHUB_WORKSPACE}" || exit R --slave -e "errors <- lintr::lint('$FILE');print(errors);quit(save = 'no', status = if (length(errors) > 0) 1 else 0)" 2>&1 ) + ######################################################### + # Corner case for C# as it writes to tty and not stdout # + ######################################################### + elif [[ ${FILE_TYPE} == "CSHARP" ]]; then + LINT_CMD=$( + cd "${DIR_NAME}" || exit + ${LINTER_COMMAND} "${FILE_NAME}" | tee /dev/tty2 2>&1; exit "${PIPESTATUS[0]}" + ) else ################################ # Lint the file with the rules # @@ -626,6 +642,7 @@ function RunTestCases() { TestCodebase "CLOUDFORMATION" "cfn-lint" "cfn-lint --config-file ${CLOUDFORMATION_LINTER_RULES}" ".*\.\(json\|yml\|yaml\)\$" "cloudformation" TestCodebase "CLOJURE" "clj-kondo" "clj-kondo --config ${CLOJURE_LINTER_RULES} --lint" ".*\.\(clj\|cljs\|cljc\|edn\)\$" "clojure" TestCodebase "COFFEESCRIPT" "coffeelint" "coffeelint -f ${COFFEESCRIPT_LINTER_RULES}" ".*\.\(coffee\)\$" "coffeescript" + TestCodebase "CSHARP" "dotnet-format" "dotnet-format --check --folder --exclude / --include" ".*\.\(cs\)\$" "csharp" TestCodebase "CSS" "stylelint" "stylelint --config ${CSS_LINTER_RULES}" ".*\.\(css\|scss\|sass\)\$" "css" TestCodebase "DART" "dart" "dartanalyzer --fatal-infos --fatal-warnings --options ${DART_LINTER_RULES}" ".*\.\(dart\)\$" "dart" TestCodebase "DOCKERFILE" "dockerfilelint" "dockerfilelint -c ${DOCKERFILE_LINTER_RULES}" ".*\(Dockerfile\)\$" "docker"