├── LICENSE.rst ├── README.rst ├── action.yml ├── sphinx_matcher.json └── test_matcher.js /LICENSE.rst: -------------------------------------------------------------------------------- 1 | Licence for Sphinx problem matcher 2 | ================================== 3 | 4 | **BSD 2-Clause License** 5 | 6 | Copyright (c) 2020 by the Sphinx team. 7 | All rights reserved. 8 | 9 | Redistribution and use in source and binary forms, with or without 10 | modification, are permitted provided that the following conditions are met: 11 | 12 | 1. Redistributions of source code must retain the above copyright notice, this 13 | list of conditions and the following disclaimer. 14 | 15 | 2. Redistributions in binary form must reproduce the above copyright notice, 16 | this list of conditions and the following disclaimer in the documentation 17 | and/or other materials provided with the distribution. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 23 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 26 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 27 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | Sphinx Problem Matcher 2 | ====================== 3 | 4 | This action adds a problem matcher that catches Sphinx warnings 5 | to show them neatly inside your pull requests. 6 | 7 | Usage 8 | ----- 9 | 10 | We suggest using the action as shown below, 11 | simply running the action before building your documentation. 12 | 13 | **Note: This action does not handle actually building your docs.** 14 | 15 | .. code-block:: yaml 16 | 17 | - uses: sphinx-doc/github-problem-matcher@master 18 | 19 | - name: "Build docs" 20 | run: | 21 | cd docs 22 | make html 23 | 24 | Example 25 | ------- 26 | 27 | After using the action, files in pull requests will be annotated: 28 | 29 | .. image:: https://i.imgur.com/xkUMS1a.png 30 | :alt: Example Screenshot 31 | -------------------------------------------------------------------------------- /action.yml: -------------------------------------------------------------------------------- 1 | name: Sphinx Problem Matcher 2 | description: Attaches a problem matcher that looks for errors during Sphinx builds 3 | author: Ammar Askar 4 | branding: 5 | icon: book 6 | color: yellow 7 | runs: 8 | using: composite 9 | steps: 10 | - name: Activate the problem matcher 11 | run: echo '::add-matcher::${{ github.action_path }}/sphinx_matcher.json' 12 | shell: sh 13 | -------------------------------------------------------------------------------- /sphinx_matcher.json: -------------------------------------------------------------------------------- 1 | { 2 | "problemMatcher": [ 3 | { 4 | "owner": "sphinx-problem-matcher", 5 | "pattern": [ 6 | { 7 | "regexp": "^(.*):(\\d+):\\s+(\\w*):\\s+(.*)$", 8 | "file": 1, 9 | "line": 2, 10 | "severity": 3, 11 | "message": 4 12 | } 13 | ] 14 | }, 15 | { 16 | "owner": "sphinx-problem-matcher-loose", 17 | "pattern": [ 18 | { 19 | "_comment": "A bit of a looser pattern, doesn't look for line numbers, just looks for file names relying on them to start with / and end with .rst", 20 | "regexp": "(\/.*\\.rst):\\s+(\\w*):\\s+(.*)$", 21 | "file": 1, 22 | "severity": 2, 23 | "message": 3 24 | } 25 | ] 26 | }, 27 | { 28 | "owner": "sphinx-problem-matcher-loose-no-severity", 29 | "pattern": [ 30 | { 31 | "_comment": "Looks for file names ending with .rst and line numbers but without severity", 32 | "regexp": "^(.*\\.rst):(\\d+):(.*)$", 33 | "file": 1, 34 | "line": 2, 35 | "message": 3 36 | } 37 | ] 38 | } 39 | ] 40 | } 41 | -------------------------------------------------------------------------------- /test_matcher.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var fs = require('fs'); 3 | 4 | const matcherJSON = fs.readFileSync('sphinx_matcher.json'); 5 | const matcher = JSON.parse(matcherJSON); 6 | 7 | let patterns = []; 8 | for (const problemMatcher of matcher.problemMatcher) { 9 | patterns.push(problemMatcher.pattern[0]); 10 | } 11 | 12 | for (const pattern of patterns) { 13 | console.log("Patterns under test: ", pattern.regexp); 14 | } 15 | 16 | const sphinx_log = 17 | `/tmp/spam/warnings_and_errors/index.rst:16: WARNING: Error in "code-block" directive: 18 | maximum 1 argument(s) allowed, 2 supplied. 19 | .. code-block:: ruby 20 | as 21 | 22 | /tmp/spam/warnings/index.rst:22: WARNING: Problems with "include" directive path: 23 | InputError: [Errno 2] No such file or directory: 'I_DONT_EXIST'. 24 | 25 | 26 | /tmp/spam/warnings/index.rst:24: WARNING: Unknown directive type "BADDIRECTIVE". 27 | .. BADDIRECTIVE:: asdf 28 | 29 | checking consistency... /tmp/spam/warnings/notintoc.rst: WARNING: document isn't included in any toctree`; 30 | 31 | 32 | const expected_matches = [ 33 | { 34 | 'file': '/tmp/spam/warnings_and_errors/index.rst', 35 | 'line': '16', 36 | 'severity': 'WARNING', 37 | 'message': 'Error in "code-block" directive:' 38 | }, 39 | { 40 | 'file': '/tmp/spam/warnings/index.rst', 41 | 'line': '22', 42 | 'severity': 'WARNING', 43 | 'message': 'Problems with "include" directive path:' 44 | }, 45 | { 46 | 'file': '/tmp/spam/warnings/index.rst', 47 | 'line': '24', 48 | 'severity': 'WARNING', 49 | 'message': 'Unknown directive type "BADDIRECTIVE".', 50 | }, 51 | { 52 | 'file': '/tmp/spam/warnings/notintoc.rst', 53 | 'line': null, 54 | 'severity': 'WARNING', 55 | 'message': "document isn't included in any toctree" 56 | } 57 | ] 58 | 59 | function perform_match(pattern_object, line) { 60 | const match = line.match(pattern_object.regexp); 61 | 62 | if (!match) { 63 | return null; 64 | } 65 | 66 | return { 67 | file: pattern_object.file ? match[pattern_object.file] : null, 68 | line: pattern_object.line ? match[pattern_object.line] : null, 69 | severity: pattern_object.severity ? match[pattern_object.severity] : null, 70 | message: pattern_object.message ? match[pattern_object.message] : null 71 | }; 72 | } 73 | 74 | let matches = []; 75 | for (const line of sphinx_log.split(/\n/)) { 76 | for (const pattern_object of patterns) { 77 | const match = perform_match(pattern_object, line); 78 | if (match) { 79 | matches.push(match); 80 | } 81 | } 82 | } 83 | 84 | console.log("Matches: ", matches); 85 | console.log("Expected matches: ", expected_matches); 86 | assert.deepEqual(expected_matches, matches); 87 | 88 | console.log("[x] All good!"); 89 | --------------------------------------------------------------------------------