diff --git a/.gitlab-ci/test/gitlab-ci.yml b/.gitlab-ci/test/gitlab-ci.yml index fd159830db5..6b946e6eab7 100644 --- a/.gitlab-ci/test/gitlab-ci.yml +++ b/.gitlab-ci/test/gitlab-ci.yml @@ -71,6 +71,25 @@ python-test: - changes: *bin_ci_files when: manual +toml-lint: + extends: + - python-test + - .no-auto-retry # this job can't be flaky + before_script: + - echo "If your change looks right but this script rejects it, contact @eric (GitLab) / eric_engestrom (IRC)." + - python3 bin/toml_lint.py + rules: + - !reference [.disable-farm-mr-rules, rules] + - !reference [.never-post-merge-rules, rules] + - if: $GITLAB_USER_LOGIN == "marge-bot" + changes: &toml_lint_files + - .gitlab-ci/test/gitlab-ci.yml + - bin/toml_lint.py + - src/**/ci/*.toml + when: on_success + - changes: *toml_lint_files + when: manual + .test-gl: extends: - .test diff --git a/bin/toml_lint.py b/bin/toml_lint.py new file mode 100755 index 00000000000..344228477ee --- /dev/null +++ b/bin/toml_lint.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 + +import argparse +import pathlib +import re + + +def detect_misleading_indentation( + toml_path: str, + toml_lines: list[str], +) -> bool: + issue_detected = False + previous_indentation = 0 + for line_number, line in enumerate(toml_lines, start=1): + if match := re.match(r'^(\s*)\S', line): + line_indentation = len(match.group(1)) + if line_indentation < previous_indentation: + # Allow de-indenting when starting a new section (`[`) or + # terminating a multi-line list (`]`) + if not re.match(r'^\s*(\[|\])', line): + print(f'{toml_path}:{line_number}: ' + f'Misleading indentation found') + issue_detected = True + else: + line_indentation = 0 + previous_indentation = line_indentation + + return issue_detected + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + 'toml_files', + type=pathlib.Path, + nargs=argparse.ZERO_OR_MORE, + help='*.toml files to lint (default: src/**/ci/*.toml)', + ) + + args = parser.parse_args() + + if not args.toml_files: + args.toml_files = pathlib.Path('src').glob('**/ci/*.toml') + + error = False + + for path in args.toml_files: + with path.open('r') as toml_file: + toml_lines = toml_file.readlines() + if detect_misleading_indentation(path.as_posix(), toml_lines): + error = True + + if error: + exit(1) + + +if __name__ == '__main__': + main()