diff --git a/CHANGELOG.md b/CHANGELOG.md index f031905..9bad2c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] ### Added - Add Python 3.12 support ([#315](https://github.com/warpnet/salt-lint/pull/315)). +- Lookup configuration file in parent directory ([#305](https://github.com/warpnet/salt-lint/pull/305)). ### Fixed - Ignore false positive result in rule 210 ([#303](https://github.com/warpnet/salt-lint/pull/303)). diff --git a/docs/index.md b/docs/index.md index c3edb6a..ebbe1e3 100644 --- a/docs/index.md +++ b/docs/index.md @@ -136,6 +136,8 @@ jobs: Salt-lint supports local configuration via a `.salt-lint` configuration file. Salt-lint checks the working directory for the presence of this file and applies any configuration found there. The configuration file location can also be overridden via the `-c path/to/file` CLI flag. +If salt-lint cannot find a configuration file in the current directory it attempts to locate it in a parent directory. However salt-lint does not try to load configuration that is outside the git repository. + If a value is provided on both the command line and via a configuration file, the values will be merged (if a list like **exclude_paths**), or the **True** value will be preferred, in the case of something like **quiet**. The following values are supported, and function identically to their CLI counterparts: diff --git a/saltlint/config.py b/saltlint/config.py index 0b72acf..d385774 100644 --- a/saltlint/config.py +++ b/saltlint/config.py @@ -20,13 +20,15 @@ class Configuration(object): def __init__(self, options={}): self._options = options - # Configuration file to use, defaults to ".salt-lint". config = options.get('c') - file = config if config is not None else '.salt-lint' - # Read the file contents - if os.path.exists(file): - with open(file, 'r', encoding="UTF-8") as f: + # Configuration file is not set, defaults to ".salt-lint". + if config is None: + config = get_config_path() + + # Read the configuration file contents if it exists. + if config and os.path.exists(config): + with open(config, 'r', encoding="UTF-8") as f: content = f.read() else: content = None @@ -130,3 +132,19 @@ def is_file_ignored(self, filepath, rule): if rule not in self.rules or 'ignore' not in self.rules[rule]: return False return self.rules[rule]['ignore'].match_file(filepath) + + +def get_config_path(): + """Return local configuration file.""" + dirname = basename = os.getcwd() + while basename: + filename = os.path.abspath(os.path.join(dirname, ".salt-lint")) + if os.path.exists(filename): + return filename + if os.path.exists(os.path.abspath(os.path.join(dirname, ".git"))): + # Avoid looking outside .git folders as we do not want end-up + # picking config files from upper level projects if current + # project has no config. + return None + (dirname, basename) = os.path.split(dirname) + return None