Skip to content

Commit 57f4538

Browse files
KooShnooem-eight
authored andcommitted
Update dtk-template from 57f5777 to 4b9499a
adds the `ninja changes` feature to find regressions locally
1 parent 2978fbf commit 57f4538

File tree

4 files changed

+249
-136
lines changed

4 files changed

+249
-136
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -36,23 +36,7 @@ jobs:
3636
run: |
3737
python configure.py --map --version ${{ matrix.version }} \
3838
--binutils /binutils --compilers /compilers
39-
ninja all_source build/${{ matrix.version }}/progress.json \
40-
build/${{ matrix.version }}/report.json
41-
42-
# Upload progress if we're on the main branch
43-
- name: Upload progress
44-
# If you're using a different branch, change this to match
45-
if: github.ref == 'refs/heads/main'
46-
continue-on-error: true
47-
env:
48-
# Replace with your project slug
49-
PROGRESS_SLUG: prime
50-
# Set the API key in your repository secrets
51-
PROGRESS_API_KEY: ${{ secrets.PROGRESS_API_KEY }}
52-
run: |
53-
python tools/upload_progress.py -b https://progress.decomp.club/ \
54-
-p $PROGRESS_SLUG -v ${{ matrix.version }} \
55-
build/${{ matrix.version }}/progress.json
39+
ninja all_source progress build/${{ matrix.version }}/report.json
5640
5741
# Upload map files
5842
- name: Upload map

tools/changes_fmt.py

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
#!/usr/bin/env python3
2+
3+
from argparse import ArgumentParser
4+
import os
5+
import json
6+
from pathlib import Path
7+
from typing import Optional, Tuple
8+
9+
script_dir = os.path.dirname(os.path.realpath(__file__))
10+
root_dir = os.path.abspath(os.path.join(script_dir, ".."))
11+
12+
13+
UNIT_KEYS_TO_DIFF = [
14+
"fuzzy_match_percent",
15+
"matched_code_percent",
16+
"matched_data_percent",
17+
"complete_code_percent",
18+
"complete_data_percent",
19+
]
20+
21+
FUNCTION_KEYS_TO_DIFF = [
22+
"fuzzy_match_percent",
23+
]
24+
25+
Change = Tuple[str, str, float, float]
26+
27+
28+
def format_float(value: float) -> str:
29+
if value < 100.0 and value > 99.99:
30+
value = 99.99
31+
return "%6.2f" % value
32+
33+
34+
def get_changes(changes_file: str) -> Tuple[list[Change], list[Change]]:
35+
changes_file = os.path.relpath(changes_file, root_dir)
36+
with open(changes_file, "r") as f:
37+
changes_json = json.load(f)
38+
39+
regressions = []
40+
progressions = []
41+
42+
def diff_key(object_name: Optional[str], object: dict, key: str):
43+
from_value = object.get("from", {}).get(key, 0.0)
44+
to_value = object.get("to", {}).get(key, 0.0)
45+
key = key.removesuffix("_percent")
46+
change = (object_name, key, from_value, to_value)
47+
if from_value > to_value:
48+
regressions.append(change)
49+
elif to_value > from_value:
50+
progressions.append(change)
51+
52+
for key in UNIT_KEYS_TO_DIFF:
53+
diff_key(None, changes_json, key)
54+
55+
for unit in changes_json.get("units", []):
56+
unit_name = unit["name"]
57+
for key in UNIT_KEYS_TO_DIFF:
58+
diff_key(unit_name, unit, key)
59+
# Ignore sections
60+
for func in unit.get("functions", []):
61+
func_name = func["name"]
62+
for key in FUNCTION_KEYS_TO_DIFF:
63+
diff_key(func_name, func, key)
64+
65+
return regressions, progressions
66+
67+
68+
def generate_changes_plaintext(changes: list[Change]) -> str:
69+
if len(changes) == 0:
70+
return ""
71+
72+
table_total_width = 136
73+
percents_max_len = 7 + 4 + 7
74+
key_max_len = max(len(key) for _, key, _, _ in changes)
75+
name_max_len = max(len(name or "Total") for name, _, _, _ in changes)
76+
max_width_for_name_col = table_total_width - 3 - key_max_len - 3 - percents_max_len
77+
name_max_len = min(max_width_for_name_col, name_max_len)
78+
79+
out_lines = []
80+
for name, key, from_value, to_value in changes:
81+
if name is None:
82+
name = "Total"
83+
if len(name) > name_max_len:
84+
name = name[: name_max_len - len("[...]")] + "[...]"
85+
out_lines.append(
86+
f"{name:>{name_max_len}} | {key:<{key_max_len}} | {format_float(from_value)}% -> {format_float(to_value)}%"
87+
)
88+
89+
return "\n".join(out_lines)
90+
91+
92+
def generate_changes_markdown(changes: list[Change], description: str) -> str:
93+
if len(changes) == 0:
94+
return ""
95+
96+
out_lines = []
97+
name_max_len = 100
98+
99+
out_lines.append("<details>")
100+
out_lines.append(
101+
f"<summary>Detected {len(changes)} {description} compared to the base:</summary>"
102+
)
103+
out_lines.append("") # Must include a blank line before a table
104+
out_lines.append("| Name | Type | Before | After |")
105+
out_lines.append("| ---- | ---- | ------ | ----- |")
106+
107+
for name, key, from_value, to_value in changes:
108+
if name is None:
109+
name = "Total"
110+
else:
111+
if len(name) > name_max_len:
112+
name = name[: name_max_len - len("...")] + "..."
113+
name = f"`{name}`" # Surround with backticks
114+
key = key.replace("_", " ").capitalize()
115+
out_lines.append(
116+
f"| {name} | {key} | {format_float(from_value)}% | {format_float(to_value)}% |"
117+
)
118+
119+
out_lines.append("</details>")
120+
121+
return "\n".join(out_lines)
122+
123+
124+
def main():
125+
parser = ArgumentParser(description="Format objdiff-cli report changes.")
126+
parser.add_argument(
127+
"report_changes_file",
128+
type=Path,
129+
help="""path to the JSON file containing the changes, generated by objdiff-cli.""",
130+
)
131+
parser.add_argument(
132+
"-o",
133+
"--output",
134+
type=Path,
135+
help="""Output file (prints to console if unspecified)""",
136+
)
137+
parser.add_argument(
138+
"--all",
139+
action="store_true",
140+
help="""Includes progressions as well.""",
141+
)
142+
args = parser.parse_args()
143+
144+
regressions, progressions = get_changes(args.report_changes_file)
145+
146+
if args.output:
147+
markdown_output = generate_changes_markdown(regressions, "regressions")
148+
if args.all:
149+
markdown_output += generate_changes_markdown(progressions, "progressions")
150+
with open(args.output, "w", encoding="utf-8") as f:
151+
f.write(markdown_output)
152+
else:
153+
if args.all:
154+
changes = progressions + regressions
155+
else:
156+
changes = regressions
157+
text_output = generate_changes_plaintext(changes)
158+
print(text_output)
159+
160+
161+
if __name__ == "__main__":
162+
main()

0 commit comments

Comments
 (0)