From 60e2561b15d92de1a0a6bd9ba52d4d80b0d5fa36 Mon Sep 17 00:00:00 2001 From: Antonio Yang Date: Tue, 9 Mar 2021 04:13:04 +0800 Subject: [PATCH] Add clippy for rust (#1277) * Add clippy for Rust * Update ARM test cases - fix arm good test case - update tap report * Lint github workflows release config --- .automation/test/arm/arm_good_1.json | 79 +++++++------------ .automation/test/arm/reports/expected-ARM.tap | 2 +- .automation/test/rust_clippy/README.md | 18 +++++ .automation/test/rust_clippy/bad/Cargo.toml | 9 +++ .automation/test/rust_clippy/bad/src/main.rs | 4 + .automation/test/rust_clippy/good/Cargo.toml | 9 +++ .automation/test/rust_clippy/good/src/main.rs | 3 + .../reports/expected-RUST_CLIPPY.tap | 7 ++ .github/workflows/deploy-RELEASE.yml | 2 +- Dockerfile | 29 ++++--- README.md | 3 +- lib/functions/buildFileList.sh | 9 +++ lib/functions/linterVersions.sh | 2 + lib/functions/worker.sh | 20 +++++ lib/linter.sh | 4 +- 15 files changed, 138 insertions(+), 62 deletions(-) create mode 100644 .automation/test/rust_clippy/README.md create mode 100644 .automation/test/rust_clippy/bad/Cargo.toml create mode 100644 .automation/test/rust_clippy/bad/src/main.rs create mode 100644 .automation/test/rust_clippy/good/Cargo.toml create mode 100644 .automation/test/rust_clippy/good/src/main.rs create mode 100644 .automation/test/rust_clippy/reports/expected-RUST_CLIPPY.tap diff --git a/.automation/test/arm/arm_good_1.json b/.automation/test/arm/arm_good_1.json index 635144fa..9d5bfb83 100644 --- a/.automation/test/arm/arm_good_1.json +++ b/.automation/test/arm/arm_good_1.json @@ -1,53 +1,34 @@ { - "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", - "contentVersion": "1.0.0.0", - "parameters": { - "Network.Config": { - "type": "object", - "metadata": { - "description": "Properties object for the Virtual Network" - } - } + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "storageAccountType": { + "type": "string", + "defaultValue": "Standard_LRS", + "allowedValues": [ + "Standard_LRS", + "Standard_GRS", + "Standard_ZRS", + "Premium_LRS" + ] }, - "variables": { - "Network.Name": "[parameters('Network.Config').name]", - "Network.Location": "[parameters('Network.Config').location]", - "Network.Tags": "[parameters('Network.Config').tags]", - "Network.Properties.AddressSpace.AddressPrefixes": "[parameters('Network.Config').addressPrefixes]", - "Network.Properties.DhcpOptions.DnsServers": "[parameters('Network.Config').dnsServers]", - "copy": [ - { - "name": "Network.Properties.Subnets", - "count": "[length(parameters('Network.Config').subnetConfig)]", - "input": { - "name": "[concat(parameters('Network.Config').subnetConfig[copyIndex('Network.Properties.Subnets')].aksId,'-',parameters('Network.Config').locationId)]", - "properties": "[parameters('Network.Config').subnetConfig[copyIndex('Network.Properties.Subnets')].properties]" - } - } - ] - }, - "resources": [ - { - "name": "[variables('Network.Name')]", - "type": "Microsoft.Network/virtualNetworks", - "apiVersion": "2019-12-01", - "location": "[variables('Network.Location')]", - "tags": "[variables('Network.Tags')]", - "properties": { - "addressSpace": { - "addressPrefixes": "[variables('Network.Properties.AddressSpace.AddressPrefixes')]" - }, - "dhcpOptions": { - "dnsServers": "[variables('Network.Properties.DhcpOptions.DnsServers')]" - }, - "subnets": "[variables('Network.Properties.Subnets')]" - } - } - ], - "outputs": { - "state": { - "type": "object", - "value": "[reference(resourceId('Microsoft.Network/virtualNetworks',variables('Network.Name')), '2019-12-01', 'Full')]" - } + "location": { + "type": "string", + "metadata": { + "description": "Location for the resources." + } } + }, + "resources": [ + { + "type": "Microsoft.Storage/storageAccounts", + "apiVersion": "2019-06-01", + "name": "[concat('store', uniquestring(resourceGroup().id))]", + "location": "[parameters('location')]", + "kind": "StorageV2", + "sku": { + "name": "[parameters('storageAccountType')]" + } + } + ] } diff --git a/.automation/test/arm/reports/expected-ARM.tap b/.automation/test/arm/reports/expected-ARM.tap index a2b49d48..806733da 100644 --- a/.automation/test/arm/reports/expected-ARM.tap +++ b/.automation/test/arm/reports/expected-ARM.tap @@ -2,6 +2,6 @@ TAP version 13 1..2 not ok 1 - arm_bad_1.json --- - message: \nValidating arm\arm_bad_1.json\n deploymentTemplate\n [+] adminUsername Should Not Be A Literal\n [+] apiVersions Should Be Recent\n [+] artifacts parameter\n [+] CommandToExecute Must Use ProtectedSettings For Secrets\n [+] DependsOn Best Practices\n [+] Deployment Resources Must Not Be Debug\n [+] DeploymentTemplate Must Not Contain Hardcoded Uri\n [+] DeploymentTemplate Schema Is Correct\n [+] Dynamic Variable References Should Not Use Concat\n [+] IDs Should Be Derived From ResourceIDs\n [+] Location Should Not Be Hardcoded\n [+] ManagedIdentityExtension must not be used\n [+] Min And Max Value Are Numbers\n [+] Outputs Must Not Contain Secrets\n [+] Parameters Must Be Referenced\n [+] Parameters Property Must Exist\n [+] providers apiVersions Is Not Permitted\n [+] ResourceIds should not contain\n [+] Resources Should Have Location\n [+] Secure String Parameters Cannot Have Default\n [-] Template Should Not Contain Blanks\n Empty property [] found on line 28 Index 1331\n Empty property "" found on line 3 Index 121\n\n [-] Variables Must Be Referenced\n Unreferenced variable Network.Location\n Unreferenced variable Test.Blank.Variable\n\n [+] Virtual Machines Should Not Be Preview\n [+] VM Images Should Use Latest Version\n [+] VM Size Should Be A Parameter\n \n + message: \nValidating arm\arm_bad_1.json\n deploymentTemplate\n [+] adminUsername Should Not Be A Literal\n [+] apiVersions Should Be Recent\n [+] artifacts parameter\n [+] CommandToExecute Must Use ProtectedSettings For Secrets\n [+] DependsOn Best Practices\n [+] Deployment Resources Must Not Be Debug\n [+] DeploymentTemplate Must Not Contain Hardcoded Uri\n [+] DeploymentTemplate Schema Is Correct\n [+] Dynamic Variable References Should Not Use Concat\n [+] IDs Should Be Derived From ResourceIDs\n [+] Location Should Not Be Hardcoded\n [+] ManagedIdentityExtension must not be used\n [+] Min And Max Value Are Numbers\n [+] Outputs Must Not Contain Secrets\n [+] Parameters Must Be Referenced\n [+] Parameters Property Must Exist\n [+] providers apiVersions Is Not Permitted\n [+] ResourceIds should not contain\n [+] Resources Should Have Location\n [+] Resources Should Not Be Ambiguous\n [+] Secure String Parameters Cannot Have Default\n [-] Template Should Not Contain Blanks\n Empty property [] found on line 28 Index 1331\n Empty property "" found on line 3 Index 121\n\n [-] Variables Must Be Referenced\n Unreferenced variable Network.Location\n Unreferenced variable Test.Blank.Variable\n\n [+] Virtual Machines Should Not Be Preview\n [+] VM Images Should Use Latest Version\n [+] VM Size Should Be A Parameter\n \n ... ok 2 - arm_good_1.json diff --git a/.automation/test/rust_clippy/README.md b/.automation/test/rust_clippy/README.md new file mode 100644 index 00000000..9bdebc24 --- /dev/null +++ b/.automation/test/rust_clippy/README.md @@ -0,0 +1,18 @@ +# Rust Project Test Cases + +This folder holds the test cases for **Rust**. + +## Additional Docs + +Due to the nature of the naming of files, we have `2` subfolders in this directory. + +- `good` is for working, and correct project +- `bad` is for invalid, and incorrect project + +## Good Test Cases + +- **Note:** They are linted utilizing the default linter rules. + +## Bad Test Cases + +- **Note:** They are linted utilizing the default linter rules. diff --git a/.automation/test/rust_clippy/bad/Cargo.toml b/.automation/test/rust_clippy/bad/Cargo.toml new file mode 100644 index 00000000..4e3d25c1 --- /dev/null +++ b/.automation/test/rust_clippy/bad/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "bad" +version = "0.1.0" +authors = ["Antonio Yang "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/.automation/test/rust_clippy/bad/src/main.rs b/.automation/test/rust_clippy/bad/src/main.rs new file mode 100644 index 00000000..ccc88353 --- /dev/null +++ b/.automation/test/rust_clippy/bad/src/main.rs @@ -0,0 +1,4 @@ +fn main() { + let x = 3.14; + let _y = 1_f64 / x; +} diff --git a/.automation/test/rust_clippy/good/Cargo.toml b/.automation/test/rust_clippy/good/Cargo.toml new file mode 100644 index 00000000..7df83e11 --- /dev/null +++ b/.automation/test/rust_clippy/good/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "good" +version = "0.1.0" +authors = ["Antonio Yang "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/.automation/test/rust_clippy/good/src/main.rs b/.automation/test/rust_clippy/good/src/main.rs new file mode 100644 index 00000000..e7a11a96 --- /dev/null +++ b/.automation/test/rust_clippy/good/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/.automation/test/rust_clippy/reports/expected-RUST_CLIPPY.tap b/.automation/test/rust_clippy/reports/expected-RUST_CLIPPY.tap new file mode 100644 index 00000000..86e3b738 --- /dev/null +++ b/.automation/test/rust_clippy/reports/expected-RUST_CLIPPY.tap @@ -0,0 +1,7 @@ +TAP version 13 +1..2 +not ok 1 - Cargo.toml + --- + message: /tmp/lint/.automation/test/rust_clippy/bad /tmp/lint/.automation/test\n Checking bad v0.1.0 (/tmp/lint/.automation/test/rust_clippy/bad)\nerror approximate value of `f{32, 64} consts PI` found. Consider using it directly\n --> src/main.rs 2 13\n |\n2 | let x = 3.14;\n | ^^^^\n |\n = note `#[deny(clippy approx_constant)]` on by default\n = help for further information visit https //rust-lang.github.io/rust-clippy/master/index.html#approx_constant\n\nerror aborting due to previous error\n\nerror could not compile `bad`\n\nTo learn more, run the command again with --verbose.\n/tmp/lint/.automation/test\n + ... +ok 2 - Cargo.toml diff --git a/.github/workflows/deploy-RELEASE.yml b/.github/workflows/deploy-RELEASE.yml index ebff5b02..dedc6e6f 100644 --- a/.github/workflows/deploy-RELEASE.yml +++ b/.github/workflows/deploy-RELEASE.yml @@ -82,7 +82,7 @@ jobs: name: Deploy Docker Image - Release # Set the agent to run on runs-on: ubuntu-latest - + ##################################################################### # Only run if Admin start job and it was the Release Issue template # ##################################################################### diff --git a/Dockerfile b/Dockerfile index c5a96c6e..89839746 100644 --- a/Dockerfile +++ b/Dockerfile @@ -81,7 +81,6 @@ ARG GLIBC_VERSION='2.31-r0' #################### RUN apk add --no-cache \ bash \ - cargo \ coreutils \ curl \ file \ @@ -112,6 +111,26 @@ RUN apk add --no-cache \ rustup \ zlib zlib-dev +############################## +# Install rustfmt & clippy # +############################## +ENV CRYPTOGRAPHY_DONT_BUILD_RUST=1 +RUN ln -s /usr/bin/rustup-init /usr/bin/rustup \ + && rustup toolchain install stable-x86_64-unknown-linux-musl \ + && rustup component add rustfmt --toolchain=stable-x86_64-unknown-linux-musl \ + && rustup component add clippy --toolchain=stable-x86_64-unknown-linux-musl \ + && ln -s /root/.rustup/toolchains/stable-x86_64-unknown-linux-musl/bin/rustfmt /usr/bin/rustfmt \ + && ln -s /root/.rustup/toolchains/stable-x86_64-unknown-linux-musl/bin/rustc /usr/bin/rustc \ + && ln -s /root/.rustup/toolchains/stable-x86_64-unknown-linux-musl/bin/cargo /usr/bin/cargo \ + && ln -s /root/.rustup/toolchains/stable-x86_64-unknown-linux-musl/bin/cargo-clippy /usr/bin/cargo-clippy \ + && echo '#!/usr/bin/env bash' > /usr/bin/clippy \ + && echo 'pushd $(dirname $1)' >> /usr/bin/clippy \ + && echo 'cargo-clippy' >> /usr/bin/clippy \ + && echo 'rc=$?' >> /usr/bin/clippy \ + && echo 'popd' >> /usr/bin/clippy \ + && echo 'exit $rc' >> /usr/bin/clippy \ + && chmod +x /usr/bin/clippy + ######################################## # Copy dependencies files to container # ######################################## @@ -142,14 +161,6 @@ ENV PATH="/node_modules/.bin:${PATH}" ############################## RUN bundle install -############################## -# Install rustfmt # -############################## -RUN ln -s /usr/bin/rustup-init /usr/bin/rustup \ - && rustup toolchain install stable-x86_64-unknown-linux-musl \ - && rustup component add rustfmt --toolchain=stable-x86_64-unknown-linux-musl \ - && ln -s /root/.rustup/toolchains/stable-x86_64-unknown-linux-musl/bin/rustfmt /usr/bin/rustfmt - ################################### # Install DotNet and Dependencies # ################################### diff --git a/README.md b/README.md index 69695227..488ceac1 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,7 @@ Developers on **GitHub** can call the **GitHub Action** to lint their code base | **R** | [lintr](https://github.com/jimhester/lintr) | | **Raku** | [Raku](https://raku.org) | | **Ruby** | [RuboCop](https://github.com/rubocop-hq/rubocop) | -| **Rust** | [Rustfmt](https://github.com/rust-lang/rustfmt) | +| **Rust** | [Rustfmt](https://github.com/rust-lang/rustfmt) / [Clippy](https://github.com/rust-lang/rust-clippy) | | **Shell** | [Shellcheck](https://github.com/koalaman/shellcheck) / [executable bit check] / [shfmt](https://github.com/mvdan/sh) | | **Snakemake** | [snakefmt](https://github.com/snakemake/snakefmt/) / [snakemake --lint](https://snakemake.readthedocs.io/en/stable/snakefiles/writing_snakefiles.html#best-practices) | | **SQL** | [sql-lint](https://github.com/joereynolds/sql-lint) | @@ -288,6 +288,7 @@ But if you wish to select or exclude specific linters, we give you full control | **VALIDATE_RUBY** | `true` | Flag to enable or disable the linting process of the Ruby language. | | **VALIDATE_RUST_2015** | `true` | Flag to enable or disable the linting process of the Rust language. (edition: 2015) | | **VALIDATE_RUST_2018** | `true` | Flag to enable or disable the linting process of Rust language. (edition: 2018) | +| **VALIDATE_RUST_CLIPPY** | `true` | Flag to enable or disable the clippy linting process of Rust language. | | **VALIDATE_SHELL_SHFMT** | `true` | Flag to enable or disable the linting process of Shell scripts. (Utilizing: shfmt) | | **VALIDATE_SNAKEMAKE_LINT** | `true` | Flag to enable or disable the linting process of Snakefiles. (Utilizing: snakemake --lint) | | **VALIDATE_SNAKEMAKE_SNAKEFMT** | `true` | Flag to enable or disable the linting process of Snakefiles. (Utilizing: snakefmt) | diff --git a/lib/functions/buildFileList.sh b/lib/functions/buildFileList.sh index bab2f533..6659bbc1 100755 --- a/lib/functions/buildFileList.sh +++ b/lib/functions/buildFileList.sh @@ -601,6 +601,15 @@ function BuildFileList() { FILE_ARRAY_RUST_2015+=("${FILE}") FILE_ARRAY_RUST_2018+=("${FILE}") + ####################### + # Get the RUST crates # + ####################### + elif [ "${BASE_FILE}" == "cargo.toml" ]; then + ############################################### + # Append the crate manifest file to the array # + ############################################### + FILE_ARRAY_RUST_CLIPPY+=("${FILE}") + ########################### # Get the SNAKEMAKE files # ########################### diff --git a/lib/functions/linterVersions.sh b/lib/functions/linterVersions.sh index c46c33d1..5d51a8f1 100755 --- a/lib/functions/linterVersions.sh +++ b/lib/functions/linterVersions.sh @@ -87,6 +87,8 @@ BuildLinterVersions() { GET_VERSION_CMD="$("${LINTER}" version 2>&1)" elif [[ ${LINTER} == "checkstyle" ]]; then GET_VERSION_CMD="$(java -jar "/usr/bin/${LINTER}" --version 2>&1)" + elif [[ ${LINTER} == "clippy" ]]; then + GET_VERSION_CMD="$(cargo-clippy --version 2>&1)" else # Standard version command GET_VERSION_CMD="$("${LINTER}" --version 2>&1)" diff --git a/lib/functions/worker.sh b/lib/functions/worker.sh index 813e1cf0..72538abb 100755 --- a/lib/functions/worker.sh +++ b/lib/functions/worker.sh @@ -121,6 +121,26 @@ function LintCodebase() { fi fi + ####################################### + # Check if Cargo.toml for Rust Clippy # + ####################################### + if [[ ${FILE_TYPE} == *"RUST"* ]] && [[ ${LINTER_NAME} == "clippy" ]]; then + debug "FILE_TYPE for FILE ${FILE} is related to Rust Clippy: ${FILE_TYPE}" + if [[ ${FILE} == *"good"* ]]; then + debug "Setting FILE_STATUS for FILE ${FILE} to 'good'" + ############# + # Good file # + ############# + FILE_STATUS='good' + elif [[ ${FILE} == *"bad"* ]]; then + debug "Setting FILE_STATUS for FILE ${FILE} to 'bad'" + ############ + # Bad file # + ############ + FILE_STATUS='bad' + fi + fi + ######################################################### # If not found, assume it should be linted successfully # ######################################################### diff --git a/lib/linter.sh b/lib/linter.sh index 019daff1..e1461648 100755 --- a/lib/linter.sh +++ b/lib/linter.sh @@ -185,7 +185,7 @@ LANGUAGE_ARRAY=('ANSIBLE' 'ARM' 'BASH' 'BASH_EXEC' 'CLOUDFORMATION' 'CLOJURE' 'C 'JAVA' 'JAVASCRIPT_ES' "${JAVASCRIPT_STYLE_NAME}" 'JSCPD' 'JSON' 'JSX' 'KUBERNETES_KUBEVAL' 'KOTLIN' 'LATEX' 'LUA' 'MARKDOWN' 'OPENAPI' 'PERL' 'PHP_BUILTIN' 'PHP_PHPCS' 'PHP_PHPSTAN' 'PHP_PSALM' 'POWERSHELL' 'PROTOBUF' 'PYTHON_BLACK' 'PYTHON_PYLINT' 'PYTHON_FLAKE8' 'PYTHON_ISORT' - 'R' 'RAKU' 'RUBY' 'RUST_2015' 'RUST_2018' + 'R' 'RAKU' 'RUBY' 'RUST_2015' 'RUST_2018' 'RUST_CLIPPY' 'SHELL_SHFMT' 'SNAKEMAKE_LINT' 'SNAKEMAKE_SNAKEFMT' 'STATES' 'SQL' 'TEKTON' 'TERRAFORM' 'TERRAFORM_TERRASCAN' 'TERRAGRUNT' 'TSX' 'TYPESCRIPT_ES' 'TYPESCRIPT_STANDARD' 'XML' 'YAML') @@ -239,6 +239,7 @@ LINTER_NAMES_ARRAY['RAKU']="raku" LINTER_NAMES_ARRAY['RUBY']="rubocop" LINTER_NAMES_ARRAY['RUST_2015']="rustfmt" LINTER_NAMES_ARRAY['RUST_2018']="rustfmt" +LINTER_NAMES_ARRAY['RUST_CLIPPY']="clippy" LINTER_NAMES_ARRAY['SHELL_SHFMT']="shfmt" LINTER_NAMES_ARRAY['SNAKEMAKE_LINT']="snakemake" LINTER_NAMES_ARRAY['SNAKEMAKE_SNAKEFMT']="snakefmt" @@ -825,6 +826,7 @@ LINTER_COMMANDS_ARRAY['RAKU']="raku" LINTER_COMMANDS_ARRAY['RUBY']="rubocop -c ${RUBY_LINTER_RULES} --force-exclusion" LINTER_COMMANDS_ARRAY['RUST_2015']="rustfmt --check --edition 2015" LINTER_COMMANDS_ARRAY['RUST_2018']="rustfmt --check --edition 2018" +LINTER_COMMANDS_ARRAY['RUST_CLIPPY']="clippy" LINTER_COMMANDS_ARRAY['SHELL_SHFMT']="shfmt -d" LINTER_COMMANDS_ARRAY['SNAKEMAKE_LINT']="snakemake --lint -s" LINTER_COMMANDS_ARRAY['SNAKEMAKE_SNAKEFMT']="snakefmt --config ${SNAKEMAKE_SNAKEFMT_LINTER_RULES} --check --compact-diff"