|
2 | 2 | #
|
3 | 3 | # __init__.py
|
4 | 4 | """
|
5 |
| -GitHub Action to run flake8. |
| 5 | +GitHub Actions integration for flake8. |
6 | 6 | """
|
7 | 7 | #
|
8 | 8 | # Copyright © 2020 Dominic Davis-Foster <dominic@davis-foster.co.uk>
|
|
27 | 27 | #
|
28 | 28 |
|
29 | 29 | # stdlib
|
30 |
| -import json |
31 |
| -from typing import List, Tuple, Union |
| 30 | +from functools import partial |
| 31 | +from gettext import ngettext |
32 | 32 |
|
33 | 33 | # 3rd party
|
34 |
| -import click |
35 |
| -import dulwich.errors |
36 |
| -from apeye import URL |
37 |
| -from domdf_python_tools.iterative import chunks |
38 |
| -from domdf_python_tools.secrets import Secret |
39 |
| -from dulwich.repo import Repo |
40 |
| -from requests import Response |
41 |
| - |
42 |
| -# this package |
43 |
| -from flake8_github_action.annotation import Annotation |
44 |
| -from flake8_github_action.checks import Checks |
45 |
| -from flake8_github_action.flake8_app import Application |
| 34 | +from flake8.formatting.base import BaseFormatter # type: ignore |
46 | 35 |
|
47 | 36 | __author__: str = "Dominic Davis-Foster"
|
48 | 37 | __copyright__: str = "2020 Dominic Davis-Foster"
|
49 | 38 | __license__: str = "MIT License"
|
50 | 39 | __version__: str = "0.0.0"
|
51 | 40 | __email__: str = "dominic@davis-foster.co.uk"
|
52 | 41 |
|
53 |
| -__all__ = ["action"] |
54 |
| - |
55 |
| - |
56 |
| -def action( |
57 |
| - token: Union[str, Secret], |
58 |
| - repo: Union[str, URL, None] = None, |
59 |
| - *args, |
60 |
| - ) -> Tuple[Response, int]: |
61 |
| - r""" |
62 |
| - Action! |
63 |
| -
|
64 |
| - :param token: The token to authenticate with the GitHub API. |
65 |
| - :param repo: The repository name (in the format <username>/<repository>) or the complete GitHub URL. |
66 |
| - :param \*args: flake8 command line arguments. |
67 |
| - """ |
68 |
| - |
69 |
| - if not isinstance(token, Secret): |
70 |
| - token = Secret(token) |
71 |
| - |
72 |
| - dulwich_repo = Repo('.') |
73 |
| - |
74 |
| - if repo is None: |
75 |
| - try: |
76 |
| - config = dulwich_repo.get_config() |
77 |
| - repo = URL(config.get(("remote", "origin"), "url").decode("UTF-8")) |
78 |
| - except dulwich.errors.NotGitRepository as e: |
79 |
| - raise click.UsageError(str(e)) |
80 |
| - |
81 |
| - elif not isinstance(repo, URL): |
82 |
| - repo = URL(repo) |
83 |
| - |
84 |
| - if repo.suffix == ".git": |
85 |
| - repo = repo.with_suffix('') |
86 |
| - |
87 |
| - repo_name = repo.name |
88 |
| - |
89 |
| - # first case is for full url, second for github/hello_world |
90 |
| - github_username = repo.parent.name or repo.domain.domain |
91 |
| - |
92 |
| - check = Checks( |
93 |
| - owner=github_username, |
94 |
| - repository_name=repo_name, |
95 |
| - check_name="Flake8", |
96 |
| - head_sha=dulwich_repo.head().decode("UTF-8"), |
97 |
| - token=token.value, |
98 |
| - ) |
99 |
| - |
100 |
| - # check_run_id = check.create_check_run() |
101 |
| - check_run_id = check.find_run_for_action() |
102 |
| - |
103 |
| - flake8_app = Application() |
104 |
| - flake8_app.run(args) |
105 |
| - flake8_app.exit() |
106 |
| - |
107 |
| - annotations: List[Annotation] = [] |
108 |
| - |
109 |
| - json_annotations = json.loads(flake8_app.formatter.output_fd.getvalue()).items() |
110 |
| - for filename, raw_annotations in json_annotations: |
111 |
| - annotations.extend(Annotation.from_flake8json(filename, ann) for ann in raw_annotations) |
112 |
| - |
113 |
| - # Github limits updates to 50 annotations at a time |
114 |
| - annotation_chunks = list(chunks(annotations, 50)) |
115 |
| - |
116 |
| - if flake8_app.result_count: |
117 |
| - conclusion = "failure" |
118 |
| - ret = 1 |
119 |
| - else: |
120 |
| - conclusion = "success" |
121 |
| - ret = 0 |
122 |
| - |
123 |
| - for chunk in annotation_chunks[:-1]: |
124 |
| - check.update_check_run( |
125 |
| - check_run_id, |
126 |
| - conclusion=conclusion, |
127 |
| - output={ |
128 |
| - "title": "Flake8 checks", |
129 |
| - "summary": "Output from Flake8", |
130 |
| - "annotations": [a.to_dict() for a in chunk], |
131 |
| - }, |
132 |
| - ) |
133 |
| - |
134 |
| - output = { |
135 |
| - "title": "Flake8 checks", |
136 |
| - "summary": "Output from Flake8", |
137 |
| - "annotations": [a.to_dict() for a in annotation_chunks[-1]], |
138 |
| - } |
139 |
| - |
140 |
| - # TODO: reflect flake8 output |
141 |
| - return check.complete_check_run(check_run_id, conclusion="success", output=output), ret |
| 42 | +__all__ = ["GitHubFormatter"] |
| 43 | + |
| 44 | +_error = partial(ngettext, "error", "errors") |
| 45 | +_file = partial(ngettext, "file", "files") |
| 46 | + |
| 47 | + |
| 48 | +class GitHubFormatter(BaseFormatter): |
| 49 | + |
| 50 | + def write_line(self, line): |
| 51 | + """ |
| 52 | + Override write for convenience. |
| 53 | + """ |
| 54 | + self.write(line, None) |
| 55 | + |
| 56 | + def start(self): |
| 57 | + super().start() |
| 58 | + self.files_reported_count = 0 |
| 59 | + |
| 60 | + def beginning(self, filename): |
| 61 | + """ |
| 62 | + We're starting a new file. |
| 63 | + """ |
| 64 | + |
| 65 | + self.reported_errors_count = 0 |
| 66 | + |
| 67 | + def finished(self, filename): |
| 68 | + """ |
| 69 | + We've finished processing a file. |
| 70 | + """ |
| 71 | + |
| 72 | + self.files_reported_count += 1 |
| 73 | + |
| 74 | + def format(self, violation): |
| 75 | + """ |
| 76 | + Format a violation. |
| 77 | + """ |
| 78 | + |
| 79 | + if self.reported_errors_count == 0: |
| 80 | + self.write_line(violation.filename) |
| 81 | + |
| 82 | + self.write_line( |
| 83 | + f"::warning " |
| 84 | + f"file={violation.filename},line={violation.line_number},col={violation.column_number}" |
| 85 | + f"::{violation.code}: {violation.text}" |
| 86 | + ) |
| 87 | + |
| 88 | + self.reported_errors_count += 1 |
0 commit comments