Skip to content

Commit 9bd4134

Browse files
authored
Fix and speedup diff-shades integration (#2773)
1 parent 8c22d23 commit 9bd4134

File tree

6 files changed

+68
-41
lines changed

6 files changed

+68
-41
lines changed

.github/mypyc-requirements.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
mypy == 0.920
2+
3+
# A bunch of packages for type information
4+
mypy-extensions >= 0.4.3
5+
tomli >= 0.10.2
6+
types-typed-ast >= 1.4.2
7+
types-dataclasses >= 0.1.3
8+
typing-extensions > 3.10.0.1
9+
click >= 8.0.0
10+
platformdirs >= 2.1.0
11+
12+
# And because build isolation is disabled, we'll need to pull this too
13+
setuptools-scm[toml] >= 6.3.1
14+
wheel

.github/workflows/diff_shades.yml

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ name: diff-shades
33
on:
44
push:
55
branches: [main]
6-
paths-ignore: ["docs/**", "tests/**", "*.md"]
6+
paths-ignore: ["docs/**", "tests/**", "**.md", "**.rst"]
77

88
pull_request:
9-
paths-ignore: ["docs/**", "tests/**", "*.md"]
9+
paths-ignore: ["docs/**", "tests/**", "**.md", "**.rst"]
1010

1111
workflow_dispatch:
1212
inputs:
@@ -27,10 +27,18 @@ on:
2727
description: "Custom Black arguments (eg. -S)"
2828
required: false
2929

30+
concurrency:
31+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
32+
cancel-in-progress: true
33+
3034
jobs:
3135
analysis:
3236
name: analysis / linux
3337
runs-on: ubuntu-latest
38+
env:
39+
# Clang is less picky with the C code it's given than gcc (and may
40+
# generate faster binaries too).
41+
CC: clang-12
3442

3543
steps:
3644
- name: Checkout this repository (full clone)
@@ -45,6 +53,7 @@ jobs:
4553
python -m pip install pip --upgrade
4654
python -m pip install https://github.com/ichard26/diff-shades/archive/stable.zip
4755
python -m pip install click packaging urllib3
56+
python -m pip install -r .github/mypyc-requirements.txt
4857
# After checking out old revisions, this might not exist so we'll use a copy.
4958
cat scripts/diff_shades_gha_helper.py > helper.py
5059
git config user.name "diff-shades-gha"
@@ -66,22 +75,28 @@ jobs:
6675
path: ${{ steps.config.outputs.baseline-analysis }}
6776
key: ${{ steps.config.outputs.baseline-cache-key }}
6877

69-
- name: Install baseline revision
78+
- name: Build and install baseline revision
7079
if: steps.baseline-cache.outputs.cache-hit != 'true'
7180
env:
7281
GITHUB_TOKEN: ${{ github.token }}
73-
run: ${{ steps.config.outputs.baseline-setup-cmd }} && python -m pip install .
82+
run: >
83+
${{ steps.config.outputs.baseline-setup-cmd }}
84+
&& python setup.py --use-mypyc bdist_wheel
85+
&& python -m pip install dist/*.whl && rm build dist -r
7486
7587
- name: Analyze baseline revision
7688
if: steps.baseline-cache.outputs.cache-hit != 'true'
7789
run: >
7890
diff-shades analyze -v --work-dir projects-cache/
7991
${{ steps.config.outputs.baseline-analysis }} -- ${{ github.event.inputs.baseline-args }}
8092
81-
- name: Install target revision
93+
- name: Build and install target revision
8294
env:
8395
GITHUB_TOKEN: ${{ github.token }}
84-
run: ${{ steps.config.outputs.target-setup-cmd }} && python -m pip install .
96+
run: >
97+
${{ steps.config.outputs.target-setup-cmd }}
98+
&& python setup.py --use-mypyc bdist_wheel
99+
&& python -m pip install dist/*.whl
85100
86101
- name: Analyze target revision
87102
run: >
@@ -118,13 +133,14 @@ jobs:
118133
python helper.py comment-body
119134
${{ steps.config.outputs.baseline-analysis }} ${{ steps.config.outputs.target-analysis }}
120135
${{ steps.config.outputs.baseline-sha }} ${{ steps.config.outputs.target-sha }}
136+
${{ github.event.pull_request.number }}
121137
122138
- name: Upload summary file (PR only)
123139
if: github.event_name == 'pull_request'
124140
uses: actions/upload-artifact@v2
125141
with:
126-
name: .pr-comment-body.md
127-
path: .pr-comment-body.md
142+
name: .pr-comment.json
143+
path: .pr-comment.json
128144

129145
# This is last so the diff-shades-comment workflow can still work even if we
130146
# end up detecting failed files and failing the run.

.github/workflows/diff_shades_comment.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,15 @@ jobs:
3131
- name: Try to find pre-existing PR comment
3232
if: steps.metadata.outputs.needs-comment == 'true'
3333
id: find-comment
34-
uses: peter-evans/find-comment@v1
34+
uses: peter-evans/find-comment@d2dae40ed151c634e4189471272b57e76ec19ba8
3535
with:
3636
issue-number: ${{ steps.metadata.outputs.pr-number }}
3737
comment-author: "github-actions[bot]"
3838
body-includes: "diff-shades"
3939

4040
- name: Create or update PR comment
4141
if: steps.metadata.outputs.needs-comment == 'true'
42-
uses: peter-evans/create-or-update-comment@v1
42+
uses: peter-evans/create-or-update-comment@a35cf36e5301d70b76f316e867e7788a55a31dae
4343
with:
4444
comment-id: ${{ steps.find-comment.outputs.comment-id }}
4545
issue-number: ${{ steps.metadata.outputs.pr-number }}

docs/contributing/gauging_changes.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ to further information. If there's a pre-existing diff-shades comment, it'll be
7474
instead the next time the workflow is triggered on the same PR.
7575

7676
The workflow uploads 3-4 artifacts upon completion: the two generated analyses (they
77-
have the .json file extension), `diff.html`, and `.pr-comment-body.md` if triggered by a
77+
have the .json file extension), `diff.html`, and `.pr-comment.json` if triggered by a
7878
PR. The last one is downloaded by the `diff-shades-comment` workflow and shouldn't be
7979
downloaded locally. `diff.html` comes in handy for push-based or manually triggered
8080
runs. And the analyses exist just in case you want to do further analysis using the

scripts/diff_shades_gha_helper.py

Lines changed: 25 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
import zipfile
2424
from io import BytesIO
2525
from pathlib import Path
26-
from typing import Any, Dict, Optional, Tuple
26+
from typing import Any, Optional, Tuple
2727

2828
import click
2929
import urllib3
@@ -34,7 +34,7 @@
3434
else:
3535
from typing_extensions import Final, Literal
3636

37-
COMMENT_BODY_FILE: Final = ".pr-comment-body.md"
37+
COMMENT_FILE: Final = ".pr-comment.json"
3838
DIFF_STEP_NAME: Final = "Generate HTML diff report"
3939
DOCS_URL: Final = (
4040
"https://black.readthedocs.io/en/latest/"
@@ -55,19 +55,16 @@ def set_output(name: str, value: str) -> None:
5555
print(f"::set-output name={name}::{value}")
5656

5757

58-
def http_get(
59-
url: str,
60-
is_json: bool = True,
61-
headers: Optional[Dict[str, str]] = None,
62-
**kwargs: Any,
63-
) -> Any:
64-
headers = headers or {}
58+
def http_get(url: str, is_json: bool = True, **kwargs: Any) -> Any:
59+
headers = kwargs.get("headers") or {}
6560
headers["User-Agent"] = USER_AGENT
6661
if "github" in url:
6762
if GH_API_TOKEN:
6863
headers["Authorization"] = f"token {GH_API_TOKEN}"
6964
headers["Accept"] = "application/vnd.github.v3+json"
70-
r = http.request("GET", url, headers=headers, **kwargs)
65+
kwargs["headers"] = headers
66+
67+
r = http.request("GET", url, **kwargs)
7168
if is_json:
7269
data = json.loads(r.data.decode("utf-8"))
7370
else:
@@ -199,8 +196,9 @@ def config(
199196
@click.argument("target", type=click.Path(exists=True, path_type=Path))
200197
@click.argument("baseline-sha")
201198
@click.argument("target-sha")
199+
@click.argument("pr-num", type=int)
202200
def comment_body(
203-
baseline: Path, target: Path, baseline_sha: str, target_sha: str
201+
baseline: Path, target: Path, baseline_sha: str, target_sha: str, pr_num: int
204202
) -> None:
205203
# fmt: off
206204
cmd = [
@@ -225,45 +223,43 @@ def comment_body(
225223
f"[**What is this?**]({DOCS_URL}) | [Workflow run]($workflow-run-url) |"
226224
" [diff-shades documentation](https://github.com/ichard26/diff-shades#readme)"
227225
)
228-
print(f"[INFO]: writing half-completed comment body to {COMMENT_BODY_FILE}")
229-
with open(COMMENT_BODY_FILE, "w", encoding="utf-8") as f:
230-
f.write(body)
226+
print(f"[INFO]: writing comment details to {COMMENT_FILE}")
227+
with open(COMMENT_FILE, "w", encoding="utf-8") as f:
228+
json.dump({"body": body, "pr-number": pr_num}, f)
231229

232230

233231
@main.command("comment-details", help="Get PR comment resources from a workflow run.")
234232
@click.argument("run-id")
235233
def comment_details(run_id: str) -> None:
236234
data = http_get(f"https://api.github.com/repos/{REPO}/actions/runs/{run_id}")
237-
if data["event"] != "pull_request":
235+
if data["event"] != "pull_request" or data["conclusion"] == "cancelled":
238236
set_output("needs-comment", "false")
239237
return
240238

241239
set_output("needs-comment", "true")
242-
pulls = data["pull_requests"]
243-
assert len(pulls) == 1
244-
pr_number = pulls[0]["number"]
245-
set_output("pr-number", str(pr_number))
246-
247-
jobs_data = http_get(data["jobs_url"])
248-
assert len(jobs_data["jobs"]) == 1, "multiple jobs not supported nor tested"
249-
job = jobs_data["jobs"][0]
240+
jobs = http_get(data["jobs_url"])["jobs"]
241+
assert len(jobs) == 1, "multiple jobs not supported nor tested"
242+
job = jobs[0]
250243
steps = {s["name"]: s["number"] for s in job["steps"]}
251244
diff_step = steps[DIFF_STEP_NAME]
252245
diff_url = job["html_url"] + f"#step:{diff_step}:1"
253246

254247
artifacts_data = http_get(data["artifacts_url"])["artifacts"]
255248
artifacts = {a["name"]: a["archive_download_url"] for a in artifacts_data}
256-
body_url = artifacts[COMMENT_BODY_FILE]
257-
body_zip = BytesIO(http_get(body_url, is_json=False))
258-
with zipfile.ZipFile(body_zip) as zfile:
259-
with zfile.open(COMMENT_BODY_FILE) as rf:
260-
body = rf.read().decode("utf-8")
249+
comment_url = artifacts[COMMENT_FILE]
250+
comment_zip = BytesIO(http_get(comment_url, is_json=False))
251+
with zipfile.ZipFile(comment_zip) as zfile:
252+
with zfile.open(COMMENT_FILE) as rf:
253+
comment_data = json.loads(rf.read().decode("utf-8"))
254+
255+
set_output("pr-number", str(comment_data["pr-number"]))
256+
body = comment_data["body"]
261257
# It's more convenient to fill in these fields after the first workflow is done
262258
# since this command can access the workflows API (doing it in the main workflow
263259
# while it's still in progress seems impossible).
264260
body = body.replace("$workflow-run-url", data["html_url"])
265261
body = body.replace("$job-diff-url", diff_url)
266-
# # https://github.community/t/set-output-truncates-multiline-strings/16852/3
262+
# https://github.community/t/set-output-truncates-multiline-strings/16852/3
267263
escaped = body.replace("%", "%25").replace("\n", "%0A").replace("\r", "%0D")
268264
set_output("comment-body", escaped)
269265

src/black/parsing.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ def stringify_ast(node: Union[ast.AST, ast3.AST], depth: int = 0) -> Iterator[st
206206
break
207207

208208
try:
209-
value = getattr(node, field)
209+
value: object = getattr(node, field)
210210
except AttributeError:
211211
continue
212212

@@ -237,6 +237,7 @@ def stringify_ast(node: Union[ast.AST, ast3.AST], depth: int = 0) -> Iterator[st
237237
yield from stringify_ast(value, depth + 2)
238238

239239
else:
240+
normalized: object
240241
# Constant strings may be indented across newlines, if they are
241242
# docstrings; fold spaces after newlines when comparing. Similarly,
242243
# trailing and leading space may be removed.

0 commit comments

Comments
 (0)