way_of_working-code_linting-hdi 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.alexrc +3 -0
- data/.mega-linter.yml +145 -0
- data/.rubocop +1 -0
- data/CHANGELOG.md +20 -0
- data/LICENSE.txt +21 -0
- data/README.md +58 -0
- data/Rakefile +16 -0
- data/code_safety.yml +186 -0
- data/docs/way_of_working/code-linting/index.md +39 -0
- data/docs/way_of_working/code-linting/linters.md +153 -0
- data/lib/way_of_working/code_linting/hdi/generators/document_linters.rb +81 -0
- data/lib/way_of_working/code_linting/hdi/generators/exec.rb +79 -0
- data/lib/way_of_working/code_linting/hdi/generators/init.rb +23 -0
- data/lib/way_of_working/code_linting/hdi/generators/init_linters.rb +103 -0
- data/lib/way_of_working/code_linting/hdi/github_audit_rule.rb +60 -0
- data/lib/way_of_working/code_linting/hdi/paths.rb +20 -0
- data/lib/way_of_working/code_linting/hdi/plugin.rb +1 -0
- data/lib/way_of_working/code_linting/hdi/supported_linter.rb +91 -0
- data/lib/way_of_working/code_linting/hdi/templates/.github/linters/.markdown-link-check.json +13 -0
- data/lib/way_of_working/code_linting/hdi/templates/.github/linters/rubocop_defaults.yml +55 -0
- data/lib/way_of_working/code_linting/hdi/templates/.github/workflows/mega-linter.yml +88 -0
- data/lib/way_of_working/code_linting/hdi/templates/.mega-linter.yml +145 -0
- data/lib/way_of_working/code_linting/hdi/templates/.rubocop +1 -0
- data/lib/way_of_working/code_linting/hdi/templates/docs/way_of_working/code-linting/index.md +39 -0
- data/lib/way_of_working/code_linting/hdi/templates/docs/way_of_working/code-linting/linters.md.tt +24 -0
- data/lib/way_of_working/code_linting/hdi/version.rb +9 -0
- data/lib/way_of_working/code_linting/hdi.rb +54 -0
- metadata +103 -0
@@ -0,0 +1,153 @@
|
|
1
|
+
---
|
2
|
+
layout: page
|
3
|
+
nav_order: 1
|
4
|
+
parent: Code Linting
|
5
|
+
---
|
6
|
+
|
7
|
+
# Linters
|
8
|
+
|
9
|
+
The following tables detail the linters that we are currently using:
|
10
|
+
|
11
|
+
## Languages
|
12
|
+
|
13
|
+
| Language | Linter | Details |
|
14
|
+
|:-------------|:--------------------------------------|:--------------------------------------------------------------------------------|
|
15
|
+
| Bash | BASH_EXEC | [bash-exec](https://megalinter.io/latest/descriptors/bash_bash_exec/) |
|
16
|
+
| Bash | BASH_SHELLCHECK | [shellcheck](https://megalinter.io/latest/descriptors/bash_shellcheck/) |
|
17
|
+
| Bash | BASH_SHFMT | [shfmt](https://megalinter.io/latest/descriptors/bash_shfmt/) |
|
18
|
+
| C | C_CLANG_FORMAT | [clang-format](https://megalinter.io/latest/descriptors/c_clang_format/) |
|
19
|
+
| C | C_CPPLINT | [cpplint](https://megalinter.io/latest/descriptors/c_cpplint/) |
|
20
|
+
| C# | CSHARP_CSHARPIER | [csharpier](https://megalinter.io/latest/descriptors/csharp_csharpier/) |
|
21
|
+
| C# | CSHARP_DOTNET_FORMAT | [dotnet-format](https://megalinter.io/latest/descriptors/csharp_dotnet_format/) |
|
22
|
+
| C# | CSHARP_ROSLYNATOR | [roslynator](https://megalinter.io/latest/descriptors/csharp_roslynator/) |
|
23
|
+
| C++ | CPP_CLANG_FORMAT | [clang-format](https://megalinter.io/latest/descriptors/cpp_clang_format/) |
|
24
|
+
| C++ | CPP_CPPLINT | [cpplint](https://megalinter.io/latest/descriptors/cpp_cpplint/) |
|
25
|
+
| Clojure | ~~CLOJURE_CLJSTYLE~~ | Not Used |
|
26
|
+
| Clojure | ~~CLOJURE_CLJ_KONDO~~ | Not Used |
|
27
|
+
| CoffeeScript | COFFEE_COFFEELINT | [coffeelint](https://megalinter.io/latest/descriptors/coffee_coffeelint/) |
|
28
|
+
| Dart | DART_DARTANALYZER | [dartanalyzer](https://megalinter.io/latest/descriptors/dart_dartanalyzer/) |
|
29
|
+
| Go | GO_GOLANGCI_LINT | [golangci-lint](https://megalinter.io/latest/descriptors/go_golangci_lint/) |
|
30
|
+
| Go | GO_REVIVE | [revive](https://megalinter.io/latest/descriptors/go_revive/) |
|
31
|
+
| Groovy | ~~GROOVY_NPM_GROOVY_LINT~~ | Not Used |
|
32
|
+
| Java | JAVA_CHECKSTYLE | [checkstyle](https://megalinter.io/latest/descriptors/java_checkstyle/) |
|
33
|
+
| Java | JAVA_PMD | [pmd](https://megalinter.io/latest/descriptors/java_pmd/) |
|
34
|
+
| JavaScript | JAVASCRIPT_ES | [eslint](https://megalinter.io/latest/descriptors/javascript_eslint/) |
|
35
|
+
| JavaScript | ~~JAVASCRIPT_PRETTIER~~ | Not Used |
|
36
|
+
| JavaScript | JAVASCRIPT_STANDARD | [standard](https://megalinter.io/latest/descriptors/javascript_standard/) |
|
37
|
+
| JSX | JSX_ESLINT | [eslint](https://megalinter.io/latest/descriptors/jsx_eslint/) |
|
38
|
+
| Kotlin | KOTLIN_DETEKT | [detekt](https://megalinter.io/latest/descriptors/kotlin_detekt/) |
|
39
|
+
| Kotlin | KOTLIN_KTLINT | [ktlint](https://megalinter.io/latest/descriptors/kotlin_ktlint/) |
|
40
|
+
| Lua | ~~LUA_LUACHECK~~ | Not Used |
|
41
|
+
| Lua | ~~LUA_SELENE~~ | Not Used |
|
42
|
+
| Lua | ~~LUA_STYLUA~~ | Not Used |
|
43
|
+
| Makefile | MAKEFILE_CHECKMAKE | [checkmake](https://megalinter.io/latest/descriptors/makefile_checkmake/) |
|
44
|
+
| Perl | ~~PERL_PERLCRITIC~~ | Not Used |
|
45
|
+
| PHP | ~~PHP_PHPCS~~ | Not Used |
|
46
|
+
| PHP | ~~PHP_PHPCSFIXER~~ | Not Used |
|
47
|
+
| PHP | ~~PHP_PHPLINT~~ | Not Used |
|
48
|
+
| PHP | ~~PHP_PHPSTAN~~ | Not Used |
|
49
|
+
| PHP | ~~PHP_PSALM~~ | Not Used |
|
50
|
+
| Powershell | ~~POWERSHELL_POWERSHELL~~ | Not Used |
|
51
|
+
| Powershell | ~~POWERSHELL_POWERSHELL_FORMATTER~~ | Not Used |
|
52
|
+
| Python | PYTHON_BANDIT | [bandit](https://megalinter.io/latest/descriptors/python_bandit/) |
|
53
|
+
| Python | PYTHON_BLACK | [black](https://megalinter.io/latest/descriptors/python_black/) |
|
54
|
+
| Python | PYTHON_FLAKE8 | [flake8](https://megalinter.io/latest/descriptors/python_flake8/) |
|
55
|
+
| Python | PYTHON_ISORT | [isort](https://megalinter.io/latest/descriptors/python_isort/) |
|
56
|
+
| Python | PYTHON_MYPY | [mypy](https://megalinter.io/latest/descriptors/python_mypy/) |
|
57
|
+
| Python | PYTHON_PYLINT | [pylint](https://megalinter.io/latest/descriptors/python_pylint/) |
|
58
|
+
| Python | PYTHON_PYRIGHT | [pyright](https://megalinter.io/latest/descriptors/python_pyright/) |
|
59
|
+
| Python | PYTHON_RUFF | [ruff](https://megalinter.io/latest/descriptors/python_ruff/) |
|
60
|
+
| R | R_LINTR | [lintr](https://megalinter.io/latest/descriptors/r_lintr/) |
|
61
|
+
| Raku | ~~RAKU_RAKU~~ | Not Used |
|
62
|
+
| Ruby | ~~RUBY_RUBOCOP~~ | Not Used (RuboCop is used directly) |
|
63
|
+
| Rust | RUST_CLIPPY | [clippy](https://megalinter.io/latest/descriptors/rust_clippy/) |
|
64
|
+
| Salesforce | ~~SALESFORCE_LIGHTNING_FLOW_SCANNER~~ | Not Used |
|
65
|
+
| Salesforce | ~~SALESFORCE_SFDX_SCANNER_APEX~~ | Not Used |
|
66
|
+
| Salesforce | ~~SALESFORCE_SFDX_SCANNER_AURA~~ | Not Used |
|
67
|
+
| Salesforce | ~~SALESFORCE_SFDX_SCANNER_LWC~~ | Not Used |
|
68
|
+
| Scala | SCALA_SCALAFIX | [scalafix](https://megalinter.io/latest/descriptors/scala_scalafix/) |
|
69
|
+
| SQL | SQL_SQLFLUFF | [sqlfluff](https://megalinter.io/latest/descriptors/sql_sqlfluff/) |
|
70
|
+
| SQL | SQL_TSQLLINT | [tsqllint](https://megalinter.io/latest/descriptors/sql_tsqllint/) |
|
71
|
+
| Swift | SWIFT_SWIFTLINT | [swiftlint](https://megalinter.io/latest/descriptors/swift_swiftlint/) |
|
72
|
+
| TSX | TSX_ESLINT | [eslint](https://megalinter.io/latest/descriptors/tsx_eslint/) |
|
73
|
+
| TypeScript | TYPESCRIPT_ES | [eslint](https://megalinter.io/latest/descriptors/typescript_eslint/) |
|
74
|
+
| TypeScript | ~~TYPESCRIPT_PRETTIER~~ | Not Used |
|
75
|
+
| TypeScript | TYPESCRIPT_STANDARD | [ts-standard](https://megalinter.io/latest/descriptors/typescript_ts_standard/) |
|
76
|
+
| VB.Net | ~~VBDOTNET_DOTNET_FORMAT~~ | Not Used |
|
77
|
+
|
78
|
+
## Formats
|
79
|
+
|
80
|
+
| Format | Linter | Details |
|
81
|
+
|:-----------------|:----------------------------------|:--------------------------------------------------------------------------------------------------------|
|
82
|
+
| CSS | CSS_STYLELINT | [stylelint](https://megalinter.io/latest/descriptors/css_stylelint/) |
|
83
|
+
| ENV | ENV_DOTENV_LINTER | [dotenv-linter](https://megalinter.io/latest/descriptors/env_dotenv_linter/) |
|
84
|
+
| GraphQL | ~~GRAPHQL_GRAPHQL_SCHEMA_LINTER~~ | Not Used |
|
85
|
+
| HTML | ~~HTML_DJLINT~~ | Not Used (Refuses to see config file) |
|
86
|
+
| HTML | HTML_HTMLHINT | [htmlhint](https://megalinter.io/latest/descriptors/html_htmlhint/) |
|
87
|
+
| JSON | JSON_ESLINT_PLUGIN_JSONC | [eslint-plugin-jsonc](https://megalinter.io/latest/descriptors/json_eslint_plugin_jsonc/) |
|
88
|
+
| JSON | JSON_JSONLINT | [jsonlint](https://megalinter.io/latest/descriptors/json_jsonlint/) |
|
89
|
+
| JSON | JSON_NPM_PACKAGE_JSON_LINT | [npm-package-json-lint](https://megalinter.io/latest/descriptors/json_npm_package_json_lint/) |
|
90
|
+
| JSON | ~~JSON_PRETTIER~~ | Not Used |
|
91
|
+
| JSON | JSON_V8R | [v8r](https://megalinter.io/latest/descriptors/json_v8r/) |
|
92
|
+
| LaTeX | ~~LATEX_CHKTEX~~ | Not Used |
|
93
|
+
| Markdown | MARKDOWN_MARKDOWNLINT | [markdownlint](https://megalinter.io/latest/descriptors/markdown_markdownlint/) |
|
94
|
+
| Markdown | MARKDOWN_MARKDOWN_LINK_CHECK | [markdown-link-check](https://megalinter.io/latest/descriptors/markdown_markdown_link_check/) |
|
95
|
+
| Markdown | MARKDOWN_MARKDOWN_TABLE_FORMATTER | [markdown-table-formatter](https://megalinter.io/latest/descriptors/markdown_markdown_table_formatter/) |
|
96
|
+
| Markdown | MARKDOWN_REMARK_LINT | [remark-lint](https://megalinter.io/latest/descriptors/markdown_remark_lint/) |
|
97
|
+
| Protocol Buffers | ~~PROTOBUF_PROTOLINT~~ | Not Used |
|
98
|
+
| reStructuredText | ~~RST_RSTCHECK~~ | Not Used |
|
99
|
+
| reStructuredText | ~~RST_RSTFMT~~ | Not Used |
|
100
|
+
| reStructuredText | ~~RST_RST_LINT~~ | Not Used |
|
101
|
+
| XML | XML_XMLLINT | [xmllint](https://megalinter.io/latest/descriptors/xml_xmllint/) |
|
102
|
+
| YAML | ~~YAML_PRETTIER~~ | Not Used |
|
103
|
+
| YAML | YAML_V8R | [v8r](https://megalinter.io/latest/descriptors/yaml_v8r/) |
|
104
|
+
| YAML | YAML_YAMLLINT | [yamllint](https://megalinter.io/latest/descriptors/yaml_yamllint/) |
|
105
|
+
|
106
|
+
## Tooling formats
|
107
|
+
|
108
|
+
| Tooling format | Linter | Details |
|
109
|
+
|:---------------|:----------------------------------|:----------------------------------------------------------------------------------------------------|
|
110
|
+
| GitHub Action | ACTION_ACTIONLINT | [actionlint](https://megalinter.io/latest/descriptors/action_actionlint/) |
|
111
|
+
| Ansible | ANSIBLE_ANSIBLE_LINT | [ansible-lint](https://megalinter.io/latest/descriptors/ansible_ansible_lint/) |
|
112
|
+
| Api | API_SPECTRAL | [spectral](https://megalinter.io/latest/descriptors/api_spectral/) |
|
113
|
+
| ARM Templates | ARM_ARM_TTK | [arm-ttk](https://megalinter.io/latest/descriptors/arm_arm_ttk/) |
|
114
|
+
| Bicep | ~~BICEP_BICEP_LINTER~~ | Not Used |
|
115
|
+
| CloudFormation | CLOUDFORMATION_CFN_LINT | [cfn-lint](https://megalinter.io/latest/descriptors/cloudformation_cfn_lint/) |
|
116
|
+
| Dockerfile | DOCKERFILE_HADOLINT | [hadolint](https://megalinter.io/latest/descriptors/dockerfile_hadolint/) |
|
117
|
+
| EditorConfig | EDITORCONFIG_EDITORCONFIG_CHECKER | [editorconfig-checker](https://megalinter.io/latest/descriptors/editorconfig_editorconfig_checker/) |
|
118
|
+
| Gherkin | ~~GHERKIN_GHERKIN_LINT~~ | Not Used |
|
119
|
+
| Kubernetes | KUBERNETES_HELM | [helm](https://megalinter.io/latest/descriptors/kubernetes_helm/) |
|
120
|
+
| Kubernetes | KUBERNETES_KUBECONFORM | [kubeconform](https://megalinter.io/latest/descriptors/kubernetes_kubeconform/) |
|
121
|
+
| Kubernetes | KUBERNETES_KUBESCAPE | [kubescape](https://megalinter.io/latest/descriptors/kubernetes_kubescape/) |
|
122
|
+
| Puppet | PUPPET_PUPPET_LINT | [puppet-lint](https://megalinter.io/latest/descriptors/puppet_puppet_lint/) |
|
123
|
+
| Snakemake | ~~SNAKEMAKE_LINT~~ | Not Used |
|
124
|
+
| Snakemake | ~~SNAKEMAKE_SNAKEFMT~~ | Not Used |
|
125
|
+
| Tekton | ~~TEKTON_TEKTON_LINT~~ | Not Used |
|
126
|
+
| Terraform | TERRAFORM_TERRAFORM_FMT | [terraform-fmt](https://megalinter.io/latest/descriptors/terraform_terraform_fmt/) |
|
127
|
+
| Terraform | TERRAFORM_TERRAGRUNT | [terragrunt](https://megalinter.io/latest/descriptors/terraform_terragrunt/) |
|
128
|
+
| Terraform | TERRAFORM_TERRASCAN | [terrascan](https://megalinter.io/latest/descriptors/terraform_terrascan/) |
|
129
|
+
| Terraform | TERRAFORM_TFLINT | [tflint](https://megalinter.io/latest/descriptors/terraform_tflint/) |
|
130
|
+
|
131
|
+
## Other
|
132
|
+
|
133
|
+
| Other | Linter | Details |
|
134
|
+
|:-----------|:----------------------|:------------------------------------------------------------------------------|
|
135
|
+
| Copypaste | COPYPASTE_JSCPD | [jscpd](https://megalinter.io/latest/descriptors/copypaste_jscpd/) |
|
136
|
+
| Repository | REPOSITORY_CHECKOV | [checkov](https://megalinter.io/latest/descriptors/repository_checkov/) |
|
137
|
+
| Repository | REPOSITORY_DEVSKIM | [devskim](https://megalinter.io/latest/descriptors/repository_devskim/) |
|
138
|
+
| Repository | REPOSITORY_DUSTILOCK | [dustilock](https://megalinter.io/latest/descriptors/repository_dustilock/) |
|
139
|
+
| Repository | REPOSITORY_GITLEAKS | [gitleaks](https://megalinter.io/latest/descriptors/repository_gitleaks/) |
|
140
|
+
| Repository | REPOSITORY_GIT_DIFF | [git_diff](https://megalinter.io/latest/descriptors/repository_git_diff/) |
|
141
|
+
| Repository | REPOSITORY_GRYPE | [grype](https://megalinter.io/latest/descriptors/repository_grype/) |
|
142
|
+
| Repository | REPOSITORY_KICS | [kics](https://megalinter.io/latest/descriptors/repository_kics/) |
|
143
|
+
| Repository | REPOSITORY_LS_LINT | [ls-lint](https://megalinter.io/latest/descriptors/repository_ls_lint/) |
|
144
|
+
| Repository | REPOSITORY_SECRETLINT | [secretlint](https://megalinter.io/latest/descriptors/repository_secretlint/) |
|
145
|
+
| Repository | REPOSITORY_SEMGREP | [semgrep](https://megalinter.io/latest/descriptors/repository_semgrep/) |
|
146
|
+
| Repository | REPOSITORY_SYFT | [syft](https://megalinter.io/latest/descriptors/repository_syft/) |
|
147
|
+
| Repository | REPOSITORY_TRIVY | [trivy](https://megalinter.io/latest/descriptors/repository_trivy/) |
|
148
|
+
| Repository | REPOSITORY_TRIVY_SBOM | [trivy-sbom](https://megalinter.io/latest/descriptors/repository_trivy_sbom/) |
|
149
|
+
| Repository | REPOSITORY_TRUFFLEHOG | [trufflehog](https://megalinter.io/latest/descriptors/repository_trufflehog/) |
|
150
|
+
| Spelling | ~~SPELL_CSPELL~~ | Not Used |
|
151
|
+
| Spelling | SPELL_LYCHEE | [lychee](https://megalinter.io/latest/descriptors/spell_lychee/) |
|
152
|
+
| Spelling | SPELL_PROSELINT | [proselint](https://megalinter.io/latest/descriptors/spell_proselint/) |
|
153
|
+
| Spelling | SPELL_VALE | [vale](https://megalinter.io/latest/descriptors/spell_vale/) |
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support'
|
4
|
+
require 'active_support/core_ext/string'
|
5
|
+
require 'nokogiri'
|
6
|
+
require 'open-uri'
|
7
|
+
require 'thor'
|
8
|
+
require 'way_of_working/paths'
|
9
|
+
|
10
|
+
module WayOfWorking
|
11
|
+
module CodeLinting
|
12
|
+
module Hdi
|
13
|
+
module Generators
|
14
|
+
# This class is responsible for generating linter documentation
|
15
|
+
class DocumentLinters < Thor::Group
|
16
|
+
include Thor::Actions # Mixin for action methods provided by Thor
|
17
|
+
|
18
|
+
# Set the source root for the templates
|
19
|
+
source_root ::WayOfWorking::CodeLinting::Hdi.source_root
|
20
|
+
|
21
|
+
# URL of the supported linters
|
22
|
+
SUPPORTED_LINTERS_URL = 'https://megalinter.io/latest/supported-linters/'
|
23
|
+
|
24
|
+
# Method to prepare the list of linters from the supported linters URL
|
25
|
+
def prepare_linter_lists
|
26
|
+
# Initialize an empty hash for linter types
|
27
|
+
@types = {}
|
28
|
+
|
29
|
+
# Iterate over each linter type in the parsed HTML
|
30
|
+
parse_linter_types_html do |type, html_rows|
|
31
|
+
@types[type] = []
|
32
|
+
|
33
|
+
parse_linter_rows(html_rows) do |constant_name, language, name, link|
|
34
|
+
# Create a new linter object and add it to the list
|
35
|
+
@types[type] << SupportedLinter.new(language, constant_name, name, link,
|
36
|
+
enabled_linters)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Method to create the linter documentation using a template
|
42
|
+
def create_linters_documentation
|
43
|
+
template 'docs/way_of_working/code-linting/linters.md'
|
44
|
+
copy_file 'docs/way_of_working/code-linting/index.md'
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def parse_linter_types_html
|
50
|
+
# Parse HTML from the supported linters URL
|
51
|
+
doc = Nokogiri::HTML(URI.parse(SUPPORTED_LINTERS_URL).read)
|
52
|
+
|
53
|
+
doc.css('article h2').each do |h2|
|
54
|
+
type = h2.text.strip
|
55
|
+
|
56
|
+
yield type, h2.next_element.css('tbody tr')
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def parse_linter_rows(html_rows)
|
61
|
+
# Iterate over each linter in the current type
|
62
|
+
html_rows.each do |tr|
|
63
|
+
tds = tr.css('td')
|
64
|
+
constant_name = tds[2].css('a')[1].text
|
65
|
+
language = tds[1].text.sub(/\s\([^)]+\)\z/, '')
|
66
|
+
name = tds[2].css('a')[0].text
|
67
|
+
link = tds[2].css('a')[0].attributes['href'].value.sub(/\A\.\./, 'https://megalinter.io/latest')
|
68
|
+
|
69
|
+
yield constant_name, language, name, link
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Load enabled linters from the YAML config file
|
74
|
+
def enabled_linters
|
75
|
+
@enabled_linters ||= YAML.load_file('.mega-linter.yml')['ENABLE_LINTERS']
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'thor'
|
4
|
+
require 'rainbow'
|
5
|
+
|
6
|
+
module WayOfWorking
|
7
|
+
module CodeLinting
|
8
|
+
module Hdi
|
9
|
+
module Generators
|
10
|
+
# This generator runs the linter
|
11
|
+
class Exec < Thor::Group
|
12
|
+
argument :path, type: :string, required: false, desc: 'Optional path of the file to lint'
|
13
|
+
|
14
|
+
desc 'This runs the linter on this project'
|
15
|
+
|
16
|
+
def run_first
|
17
|
+
@start_time = Time.now
|
18
|
+
|
19
|
+
say(Rainbow("Limiting linters to #{path}\n").yellow) if path
|
20
|
+
end
|
21
|
+
|
22
|
+
# Run RuboCop
|
23
|
+
def prep_and_run_rubocop
|
24
|
+
say(Rainbow('Running RuboCop...').yellow)
|
25
|
+
|
26
|
+
@rubocop_ok = run_rubocop(ARGV[2..])
|
27
|
+
end
|
28
|
+
|
29
|
+
# Run MegaLinter
|
30
|
+
def prep_and_run_megalinter
|
31
|
+
command = ['npx', 'mega-linter-runner', '--remove-container']
|
32
|
+
# Configure MegaLinter to only lint a specific file or folder, if defined
|
33
|
+
command.prepend("MEGALINTER_FILES_TO_LINT=\"#{path}\"") if path
|
34
|
+
# We only want reports created in the working directory
|
35
|
+
command.prepend('env', "GITHUB_WORKSPACE=\"#{Dir.pwd}\"")
|
36
|
+
|
37
|
+
say(Rainbow("\nRunning MegaLinter...").yellow)
|
38
|
+
|
39
|
+
@megalinter_ok = run_megalinter(command)
|
40
|
+
end
|
41
|
+
|
42
|
+
# We run this last to enable all the linters to run first
|
43
|
+
def run_last
|
44
|
+
say(Rainbow("\nTotal time taken: #{(Time.now - @start_time).to_i} seconds").yellow)
|
45
|
+
|
46
|
+
if !@rubocop_ok || !@megalinter_ok
|
47
|
+
abort(Rainbow("\nLinter failed!").red)
|
48
|
+
else
|
49
|
+
say(Rainbow("\nLinter Succeeded!").green)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def path_directory
|
56
|
+
return path if File.directory?(path)
|
57
|
+
|
58
|
+
File.dirname(path)
|
59
|
+
end
|
60
|
+
|
61
|
+
def run_rubocop(arguments)
|
62
|
+
# We lazy-load RuboCop so that the task doesn't dramatically impact the
|
63
|
+
# load time of our commands.
|
64
|
+
require 'rubocop'
|
65
|
+
|
66
|
+
cli = RuboCop::CLI.new
|
67
|
+
!cli.run(arguments).nonzero?
|
68
|
+
end
|
69
|
+
|
70
|
+
def run_megalinter(arguments)
|
71
|
+
arguments.prepend('time')
|
72
|
+
|
73
|
+
system(*arguments)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'thor'
|
4
|
+
require 'way_of_working/paths'
|
5
|
+
|
6
|
+
module WayOfWorking
|
7
|
+
module CodeLinting
|
8
|
+
module Hdi
|
9
|
+
module Generators
|
10
|
+
# This generator initialises the linter
|
11
|
+
class Init < Thor::Group
|
12
|
+
# include Thor::Actions
|
13
|
+
|
14
|
+
# Intialise the linters
|
15
|
+
invoke InitLinters
|
16
|
+
|
17
|
+
# Document the linters
|
18
|
+
invoke DocumentLinters
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'thor'
|
4
|
+
require 'way_of_working/paths'
|
5
|
+
|
6
|
+
module WayOfWorking
|
7
|
+
module CodeLinting
|
8
|
+
module Hdi
|
9
|
+
module Generators
|
10
|
+
# This generator initialises the linter
|
11
|
+
class InitLinters < Thor::Group
|
12
|
+
include Thor::Actions
|
13
|
+
|
14
|
+
source_root ::WayOfWorking::CodeLinting::Hdi.source_root
|
15
|
+
|
16
|
+
LINTING_BUILD_PHASE =
|
17
|
+
" 2F0882F42AAB152D00DB0B2B /* ShellScript */,\n"
|
18
|
+
LINTING_BUILD_PHASE_DETAILS = <<~CONFIG
|
19
|
+
/* Begin PBXShellScriptBuildPhase section */
|
20
|
+
\t\t2F0882F42AAB152D00DB0B2B /* ShellScript */ = {
|
21
|
+
\t\t\tisa = PBXShellScriptBuildPhase;
|
22
|
+
\t\t\tbuildActionMask = 2147483647;
|
23
|
+
\t\t\tfiles = (
|
24
|
+
\t\t\t);
|
25
|
+
\t\t\tinputFileListPaths = (
|
26
|
+
\t\t\t);
|
27
|
+
\t\t\tinputPaths = (
|
28
|
+
\t\t\t);
|
29
|
+
\t\t\toutputFileListPaths = (
|
30
|
+
\t\t\t);
|
31
|
+
\t\t\toutputPaths = (
|
32
|
+
\t\t\t);
|
33
|
+
\t\t\trunOnlyForDeploymentPostprocessing = 0;
|
34
|
+
\t\t\tshellPath = /bin/sh;
|
35
|
+
\t\t\tshellScript = "if [[ \\"$(uname -m)\\" == arm64 ]]; then\\n export PATH=\\"/opt/homebrew/bin:$PATH\\"\\nfi\\n\\nif which swiftlint > /dev/null; then\\n swiftlint\\nelse\\n echo \\"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\\"\\nfi\\n";
|
36
|
+
\t\t};
|
37
|
+
/* End PBXShellScriptBuildPhase section */
|
38
|
+
|
39
|
+
CONFIG
|
40
|
+
|
41
|
+
# TODO: copy_rubocop_github_workflow_action
|
42
|
+
|
43
|
+
def copy_github_linters_rubocop_config_file
|
44
|
+
copy_file '.github/linters/rubocop_defaults.yml'
|
45
|
+
end
|
46
|
+
|
47
|
+
def copy_github_linters_markdown_link_check_config_file
|
48
|
+
copy_file '.github/linters/.markdown-link-check.json'
|
49
|
+
end
|
50
|
+
|
51
|
+
def copy_megalinter_github_workflow_action
|
52
|
+
copy_file '.github/workflows/mega-linter.yml'
|
53
|
+
end
|
54
|
+
|
55
|
+
def copy_megalinter_dot_file
|
56
|
+
copy_file '.mega-linter.yml'
|
57
|
+
end
|
58
|
+
|
59
|
+
def create_gitignore_if_missing
|
60
|
+
create_file_if_missing '.gitignore'
|
61
|
+
end
|
62
|
+
|
63
|
+
def gitignore_reports_folder
|
64
|
+
append_to_file '.gitignore', "megalinter-reports/\n"
|
65
|
+
end
|
66
|
+
|
67
|
+
def gitignore_rubocop_cached_file
|
68
|
+
append_to_file '.gitignore', ".rubocop-https---*\n"
|
69
|
+
end
|
70
|
+
|
71
|
+
def copy_rubocop_options_file
|
72
|
+
copy_file '.rubocop'
|
73
|
+
end
|
74
|
+
|
75
|
+
def inject_swiftlint_into_xcode_project_build_process
|
76
|
+
return unless xcode_project_file && File.exist?(xcode_project_file)
|
77
|
+
|
78
|
+
inject_into_file xcode_project_file,
|
79
|
+
LINTING_BUILD_PHASE,
|
80
|
+
after: "buildPhases = (\n"
|
81
|
+
|
82
|
+
inject_into_file xcode_project_file,
|
83
|
+
LINTING_BUILD_PHASE_DETAILS,
|
84
|
+
after: "/* End PBXResourcesBuildPhase section */\n\n"
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def xcode_project_file
|
90
|
+
Dir.glob(File.join(destination_root, '*.xcodeproj/project.pbxproj')).first
|
91
|
+
end
|
92
|
+
|
93
|
+
def create_file_if_missing(path)
|
94
|
+
path = File.join(destination_root, path)
|
95
|
+
return if behavior == :revoke || File.exist?(path)
|
96
|
+
|
97
|
+
File.open(path, 'w', &:write)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'way_of_working/audit/github/rules/base'
|
4
|
+
|
5
|
+
module WayOfWorking
|
6
|
+
module CodeLinting
|
7
|
+
# The namespace for this plugin
|
8
|
+
module Hdi
|
9
|
+
# This rule checks for the MegaLinter workflow action and README badge.
|
10
|
+
class GithubAuditRule < ::WayOfWorking::Audit::Github::Rules::Base
|
11
|
+
source_root WayOfWorking::CodeLinting::Hdi.source_root
|
12
|
+
|
13
|
+
def validate
|
14
|
+
workflows = @client.workflows(@repo_name).workflows
|
15
|
+
@errors << 'No HDI MegaLinter GitHub Action' unless workflows.map(&:name).include?('MegaLinter')
|
16
|
+
|
17
|
+
@errors << 'No HDI MegaLinter README Badge' unless megalinter_badge?
|
18
|
+
|
19
|
+
validate_repo_file_contains_source_file(
|
20
|
+
'.github/linters/rubocop_defaults.yml',
|
21
|
+
'.mega-linter.yml',
|
22
|
+
'.rubocop'
|
23
|
+
)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def repo_file_contains_source_file?(path)
|
29
|
+
repo_file_contains?(path, File.read(self.class.source_root.join(path)))
|
30
|
+
end
|
31
|
+
|
32
|
+
def repo_file_contains?(path, text)
|
33
|
+
remote_content = repo_file_contents(path)
|
34
|
+
return false if remote_content.nil?
|
35
|
+
|
36
|
+
remote_content.include?(text)
|
37
|
+
end
|
38
|
+
|
39
|
+
def validate_repo_file_contains_source_file(*paths)
|
40
|
+
paths.each do |path|
|
41
|
+
if repo_file_contents(path).nil?
|
42
|
+
@errors << "#{path} missing"
|
43
|
+
next
|
44
|
+
end
|
45
|
+
|
46
|
+
@errors << "#{path} does not match the source template" unless repo_file_contains_source_file?(path)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def megalinter_badge?
|
51
|
+
readme_content.include?("[![MegaLinter](https://github.com/#{@repo_name}/workflows/MegaLinter/badge.svg")
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
::WayOfWorking::Audit::Github::Rules::Registry.register(
|
56
|
+
GithubAuditRule, 'HDI MegaLinter GitHub Action and README badge'
|
57
|
+
)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'pathname'
|
4
|
+
|
5
|
+
module WayOfWorking
|
6
|
+
module CodeLinting
|
7
|
+
# Mixin that provides a couple of pathname convenience methods
|
8
|
+
module Hdi
|
9
|
+
class << self
|
10
|
+
def root
|
11
|
+
Pathname.new(File.expand_path('../../../..', __dir__))
|
12
|
+
end
|
13
|
+
|
14
|
+
def source_root
|
15
|
+
root.join('lib', 'way_of_working', 'code_linting', 'hdi', 'templates')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'way_of_working/code_linting/hdi'
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module WayOfWorking
|
2
|
+
module CodeLinting
|
3
|
+
module Hdi
|
4
|
+
# Struct to hold linter data
|
5
|
+
class SupportedLinter
|
6
|
+
# Reasons why certain linters are not used
|
7
|
+
NOT_USED_REASON = {
|
8
|
+
'CSS_SCSS_LINT' => 'scss-lint recommends using stylelint',
|
9
|
+
'HTML_DJLINT' => 'Refuses to see config file',
|
10
|
+
'RUBY_RUBOCOP' => 'RuboCop is used directly'
|
11
|
+
}.freeze
|
12
|
+
|
13
|
+
# Acronyms for languages
|
14
|
+
TLA_LANGUAGES = %w[
|
15
|
+
CSS
|
16
|
+
ENV
|
17
|
+
HTML
|
18
|
+
JSON
|
19
|
+
JSX
|
20
|
+
PHP
|
21
|
+
SQL
|
22
|
+
TSX
|
23
|
+
XML
|
24
|
+
YAML
|
25
|
+
].freeze
|
26
|
+
|
27
|
+
# Mapping for languages
|
28
|
+
LANGUAGE_MAPPINGS = {
|
29
|
+
'Action' => 'GitHub Action',
|
30
|
+
'Arm' => 'ARM Templates',
|
31
|
+
'Cloudformation' => 'CloudFormation',
|
32
|
+
'Coffee' => 'CoffeeScript',
|
33
|
+
'Editorconfig' => 'EditorConfig',
|
34
|
+
'Graphql' => 'GraphQL',
|
35
|
+
'Javascript' => 'JavaScript',
|
36
|
+
'Latex' => 'LaTeX',
|
37
|
+
'Protobuf' => 'Protocol Buffers',
|
38
|
+
'Rst' => 'reStructuredText',
|
39
|
+
'Spell' => 'Spelling',
|
40
|
+
'Typescript' => 'TypeScript',
|
41
|
+
'Visual Basic .Net' => 'VB.Net'
|
42
|
+
}.freeze
|
43
|
+
|
44
|
+
attr_accessor :name, :link, :enabled_linters, :sorter
|
45
|
+
|
46
|
+
def initialize(language, constant_name, name, link, enabled_linters)
|
47
|
+
@original_language = language
|
48
|
+
@original_constant_name = constant_name
|
49
|
+
@name = name
|
50
|
+
@link = link
|
51
|
+
@enabled_linters = enabled_linters
|
52
|
+
|
53
|
+
# Array used for sorting
|
54
|
+
@sorter = [@original_language, @original_constant_name]
|
55
|
+
end
|
56
|
+
|
57
|
+
def language
|
58
|
+
language = @original_language
|
59
|
+
|
60
|
+
# Titleize language unless it is an acronym
|
61
|
+
language = language.titleize unless TLA_LANGUAGES.include?(language)
|
62
|
+
|
63
|
+
# Use mapped language name if available
|
64
|
+
language = LANGUAGE_MAPPINGS[language] if LANGUAGE_MAPPINGS.key?(language)
|
65
|
+
|
66
|
+
language
|
67
|
+
end
|
68
|
+
|
69
|
+
def constant_name
|
70
|
+
return @original_constant_name if enabled_linters.include?(@original_constant_name)
|
71
|
+
|
72
|
+
# Strike-through the constant name if the linter is not used
|
73
|
+
"~~#{@original_constant_name}~~"
|
74
|
+
end
|
75
|
+
|
76
|
+
def details
|
77
|
+
return "[#{name}](#{link})" if enabled_linters.include?(@original_constant_name)
|
78
|
+
|
79
|
+
details = 'Not Used'
|
80
|
+
|
81
|
+
# Add reason if available
|
82
|
+
if NOT_USED_REASON.key?(@original_constant_name)
|
83
|
+
details = "#{details} (#{NOT_USED_REASON[@original_constant_name]})"
|
84
|
+
end
|
85
|
+
|
86
|
+
details
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|