way_of_working-code_linting-hdi 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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?("[
|
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
|