From 6170f4713176f2ffe42baf7ba55876cb96ecff1a Mon Sep 17 00:00:00 2001 From: championshuttler Date: Tue, 16 Jul 2019 13:20:09 +0000 Subject: [PATCH] Bug 1527361 - Setup rst linter for the documentation. r=ahal Differential Revision: https://phabricator.services.mozilla.com/D36586 --HG-- extra : moz-landing-system : lando --- taskcluster/ci/source-test/mozlint.yml | 11 +++ tools/lint/docs/index.rst | 1 + tools/lint/docs/linters/rstlinter.rst | 25 +++++++ tools/lint/rst.yml | 12 ++++ tools/lint/rst/__init__.py | 92 ++++++++++++++++++++++++++ tools/lint/rst/requirements.txt | 6 ++ 6 files changed, 147 insertions(+) create mode 100644 tools/lint/docs/linters/rstlinter.rst create mode 100644 tools/lint/rst.yml create mode 100644 tools/lint/rst/__init__.py create mode 100644 tools/lint/rst/requirements.txt diff --git a/taskcluster/ci/source-test/mozlint.yml b/taskcluster/ci/source-test/mozlint.yml index 2866ca32555e..0f59375977d9 100644 --- a/taskcluster/ci/source-test/mozlint.yml +++ b/taskcluster/ci/source-test/mozlint.yml @@ -173,6 +173,17 @@ yaml: - '**/*.yaml' - '**/.ymllint' +rst: + description: rst lint run over the gecko codebase + platform: lint/opt + treeherder: + symbol: rst + run: + mach: lint -l rst -f treeherder -f json:/builds/worker/mozlint.json + when: + files-changed: + - '**/*.rst' + shellcheck: description: shellcheck run over the gecko codebase platform: lint/opt diff --git a/tools/lint/docs/index.rst b/tools/lint/docs/index.rst index 780d012e7d45..92baa0e294a8 100644 --- a/tools/lint/docs/index.rst +++ b/tools/lint/docs/index.rst @@ -29,6 +29,7 @@ like mach, mozreview and taskcluster. linters/eslint linters/flake8 linters/l10n + linters/rstlinter Indices and tables ================== diff --git a/tools/lint/docs/linters/rstlinter.rst b/tools/lint/docs/linters/rstlinter.rst new file mode 100644 index 000000000000..5e78a61d3b2c --- /dev/null +++ b/tools/lint/docs/linters/rstlinter.rst @@ -0,0 +1,25 @@ +RST Linter +========== + +`Restructuredtext lint`_ is a popular linter for restructuredtext. + + +Run Locally +----------- + +The mozlint integration of rst linter can be run using mach: + +.. parsed-literal:: + + $ mach lint --linter rst + + +Configuration +------------- + +All directories will have rst linter run against them. +If you wish to exclude a subdirectory of an included one, you can add it to the ``exclude`` +directive. + + +.. _Restructuredtext lint: https://github.com/twolfson/restructuredtext-lint diff --git a/tools/lint/rst.yml b/tools/lint/rst.yml new file mode 100644 index 000000000000..a83c2ecdf7a3 --- /dev/null +++ b/tools/lint/rst.yml @@ -0,0 +1,12 @@ +--- +rst: + description: RST linter + include: + - tools/lint/docs/usage.rst + exclude: [] + extensions: + - rst + support-files: + - 'tools/lint/rst/**' + type: external + payload: rst:lint diff --git a/tools/lint/rst/__init__.py b/tools/lint/rst/__init__.py new file mode 100644 index 000000000000..ad7d98c4a3f1 --- /dev/null +++ b/tools/lint/rst/__init__.py @@ -0,0 +1,92 @@ +# 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/. + +from __future__ import absolute_import + +import os +import subprocess +import json + +from mozlint import result + +# Error Levels +# (0, 'debug') +# (1, 'info') +# (2, 'warning') +# (3, 'error') +# (4, 'severe') + +abspath = os.path.abspath(os.path.dirname(__file__)) +rstlint_requirements_file = os.path.join(abspath, 'requirements.txt') + +RSTLINT_INSTALL_ERROR = """ +Unable to install required version of restructuredtext_lint and docutils +Try to install it manually with: + $ pip install -U --require-hashes -r {} +""".strip().format(rstlint_requirements_file) + + +def pip_installer(*args): + """ + Helper function that runs pip with subprocess + """ + try: + subprocess.check_output(['pip'] + list(args), + stderr=subprocess.STDOUT) + return True + except subprocess.CalledProcessError as e: + print(e.output) + return False + + +def install_rstlint(): + """ + Try to install rstlint and docutils at the target version, returns True on success + otherwise prints the otuput of the pip command and returns False + """ + if pip_installer('install', '-U', + '--require-hashes', '-r', + rstlint_requirements_file): + return True + + return False + + +def lint(files, config, **lintargs): + + if not install_rstlint(): + print(RSTLINT_INSTALL_ERROR) + return 1 + + config = config.copy() + config['root'] = lintargs['root'] + + cmdargs = [ + 'rst-lint', + '--format=json', + ] + files + + proc = subprocess.Popen(cmdargs, stdout=subprocess.PIPE, env=os.environ) + output = proc.communicate()[0] + + # all passed + if not output: + return [] + + results = [] + + for i in (json.loads(output)): + + # create a dictionary to append with mozlint.results + res = { + 'path': i['source'], + 'message': i['message'], + 'lineno': i['line'], + 'level': i['type'].lower(), + 'rule': i['level'], + } + + results.append(result.from_config(config, **res)) + + return results diff --git a/tools/lint/rst/requirements.txt b/tools/lint/rst/requirements.txt new file mode 100644 index 000000000000..c1586f9da9e9 --- /dev/null +++ b/tools/lint/rst/requirements.txt @@ -0,0 +1,6 @@ +restructuredtext-lint==1.3.0 \ + --hash=sha256:97b3da356d5b3a8514d8f1f9098febd8b41463bed6a1d9f126cf0a048b6fd908 +docutils==0.14 \ + --hash=sha256:02aec4bd92ab067f6ff27a38a38a41173bf01bed8f89157768c1573f53e474a6 \ + --hash=sha256:51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274 \ + --hash=sha256:7a4bd47eaf6596e1295ecb11361139febe29b084a87bf005bf899f9a42edc3c6