Bug 1392795 - [yamllint] Group paths to lint by their closest config and run each config group separately, r?Callek
This makes configuration files for yamllint work a bit better. It's still not perfect, but it's an improvement
on the current situation.
MozReview-Commit-ID: IKxgQm1a7bP
new file mode 100644
--- /dev/null
+++ b/.yamllint
@@ -0,0 +1,5 @@
+---
+ignore: |
+ *node_modules*
+
+extends: default
--- a/taskcluster/.yamllint
+++ b/taskcluster/.yamllint
@@ -1,9 +1,11 @@
---
+ignore: |
+ *node_modules*
extends: default
rules:
document-end:
present: false
# Checks currently failing
brackets: disable
--- a/tools/lint/yamllint_/__init__.py
+++ b/tools/lint/yamllint_/__init__.py
@@ -1,16 +1,17 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import re
import os
import signal
import subprocess
+from collections import defaultdict
import which
from mozprocess import ProcessHandlerMixin
from mozlint import result
here = os.path.abspath(os.path.dirname(__file__))
@@ -109,23 +110,45 @@ def run_process(config, cmd):
except KeyboardInterrupt:
proc.kill()
def gen_yamllint_args(cmdargs, paths=None, conf_file=None):
args = cmdargs[:]
if isinstance(paths, basestring):
paths = [paths]
- if conf_file:
+ if conf_file and conf_file != 'default':
return args + ['-c', conf_file] + paths
return args + paths
+def ancestors(path):
+ while path:
+ yield path
+ (path, child) = os.path.split(path)
+ if child == "":
+ break
+
+
+def get_relevant_configs(name, path, root):
+ """Returns a list of configuration files that exist in `path`'s ancestors,
+ sorted from closest->furthest.
+ """
+ configs = []
+ for path in ancestors(path):
+ if path == root:
+ break
+
+ config = os.path.join(path, name)
+ if os.path.isfile(config):
+ configs.append(config)
+ return configs
+
+
def lint(files, config, **lintargs):
-
if not reinstall_yamllint():
print(YAMLLINT_INSTALL_ERROR)
return 1
binary = get_yamllint_binary()
cmdargs = [
binary,
@@ -133,22 +156,17 @@ def lint(files, config, **lintargs):
]
config = config.copy()
config['root'] = lintargs['root']
# Run any paths with a .yamllint file in the directory separately so
# it gets picked up. This means only .yamllint files that live in
# directories that are explicitly included will be considered.
- no_config = []
+ paths_by_config = defaultdict(list)
for f in files:
- yamllint_config = os.path.join(f, '.yamllint')
- if not os.path.isfile(yamllint_config):
- no_config.append(f)
- continue
- run_process(config,
- gen_yamllint_args(cmdargs, conf_file=yamllint_config, paths=f))
+ conf_files = get_relevant_configs('.yamllint', f, config['root'])
+ paths_by_config[conf_files[0] if conf_files else 'default'].append(f)
- if no_config:
- run_process(config,
- gen_yamllint_args(cmdargs, paths=no_config))
+ for conf_file, paths in paths_by_config.items():
+ run_process(config, gen_yamllint_args(cmdargs, conf_file=conf_file, paths=paths))
return results