Skip to content

Commit de8ebe1

Browse files
authored
improve no-cheat CI check (#2127)
## Changes improve no-cheat CI check Currently we get blocked when we change a line of code that already contains a cheat. For example, changing from: `some_function("abc") # pylint: disable=some-code` to: `some_function("xyz") # pylint: disable=some-code` triggers a no-cheat erroneously. We want to avoid that, and also get better feedback on the new cheats. The current script diffs the incoming branch with main, not the target branch. This PR changes that by using `$GITHUB_BASE_REF`. The logic is too complex for bash, so delegating the analysis to python. ### Linked issues None ### Functionality None ### Tests - [x] manually tested --------- Co-authored-by: Eric Vergnaud <[email protected]>
1 parent 4e6fcc8 commit de8ebe1

File tree

3 files changed

+122
-5
lines changed

3 files changed

+122
-5
lines changed

.github/workflows/no-cheat.yml

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,13 @@ jobs:
2020
with:
2121
fetch-depth: 0
2222

23-
- name: Verify no lint is disabled in the new code
23+
- name: Verify no additional disabled lint in the new code
2424
run: |
25-
NEW_CODE=$(git diff origin/main..$(git branch --show-current) | grep -e '^+')
26-
CHEAT=$(echo "${NEW_CODE}" | grep '# pylint: disable' | grep -v "CHEAT" | wc -c)
27-
if [ "${CHEAT}" -ne 0 ]; then
28-
echo "Do not cheat the linter: ${CHEAT}"
25+
git fetch origin $GITHUB_BASE_REF:$GITHUB_BASE_REF
26+
git diff $GITHUB_BASE_REF...$(git branch --show-current) >> diff_data.txt
27+
python tests/unit/no_cheat.py diff_data.txt >> cheats.txt
28+
COUNT=$(cat cheats.txt | wc -c)
29+
if [ ${COUNT} -gt 1 ]; then
30+
cat cheats.txt
2931
exit 1
3032
fi

tests/unit/no_cheat.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import sys
2+
from pathlib import Path
3+
4+
DISABLE_TAG = '# pylint: disable='
5+
6+
7+
def no_cheat(diff_text: str) -> str:
8+
lines = diff_text.split('\n')
9+
removed: dict[str, int] = {}
10+
added: dict[str, int] = {}
11+
for line in lines:
12+
if not (line.startswith("-") or line.startswith("+")):
13+
continue
14+
idx = line.find(DISABLE_TAG)
15+
if idx < 0:
16+
continue
17+
codes = line[idx + len(DISABLE_TAG) :].split(',')
18+
for code in codes:
19+
code = code.strip().strip('\n').strip('"').strip("'")
20+
if line.startswith("-"):
21+
removed[code] = removed.get(code, 0) + 1
22+
continue
23+
added[code] = added.get(code, 0) + 1
24+
results: list[str] = []
25+
for code, count in added.items():
26+
count -= removed.get(code, 0)
27+
if count > 0:
28+
results.append(f"Do not cheat the linter: found {count} additional {DISABLE_TAG}{code}")
29+
return '\n'.join(results)
30+
31+
32+
if __name__ == "__main__":
33+
diff_data = sys.argv[1]
34+
path = Path(diff_data)
35+
if path.exists():
36+
diff_data = path.read_text("utf-8")
37+
print(no_cheat(diff_data))

tests/unit/test_no_cheat.py

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
from tests.unit.no_cheat import no_cheat
2+
3+
4+
def test_no_cheat_returns_empty_string_for_empty_diff():
5+
diff_data = ""
6+
result = no_cheat(diff_data)
7+
assert not result
8+
9+
10+
def test_no_cheat_returns_empty_string_for_no_cheat_diff():
11+
diff_data = """
12+
+some code
13+
-some other code
14+
"""
15+
result = no_cheat(diff_data)
16+
assert not result
17+
18+
19+
def test_no_cheat_returns_empty_string_for_removed_cheat():
20+
diff_data = """
21+
+some code
22+
-some other code # pylint: disable=some-rule
23+
"""
24+
result = no_cheat(diff_data)
25+
assert not result
26+
27+
28+
def test_no_cheat_returns_empty_string_for_replaced_cheat():
29+
diff_data = """
30+
+some code # pylint: disable=some-rule
31+
-some other code # pylint: disable=some-rule
32+
"""
33+
result = no_cheat(diff_data)
34+
assert not result
35+
36+
37+
def test_no_cheat_returns_message_for_single_cheat():
38+
diff_data = """
39+
+some code # pylint: disable=some-rule
40+
-some other code
41+
"""
42+
result = no_cheat(diff_data)
43+
assert result == "Do not cheat the linter: found 1 additional # pylint: disable=some-rule"
44+
45+
46+
def test_no_cheat_returns_message_for_multiple_same_cheat():
47+
diff_data = """
48+
+some code # pylint: disable=some-rule
49+
-some other code
50+
+some code # pylint: disable=some-rule
51+
"""
52+
result = no_cheat(diff_data)
53+
assert result == "Do not cheat the linter: found 2 additional # pylint: disable=some-rule"
54+
55+
56+
def test_no_cheat_returns_message_for_multiple_cheats_in_different_lines():
57+
diff_data = """
58+
+some code # pylint: disable=some-rule
59+
-some other code
60+
+some code # pylint: disable=some-other-rule
61+
"""
62+
result = no_cheat(diff_data)
63+
assert result == (
64+
"Do not cheat the linter: found 1 additional # pylint: disable=some-rule\n"
65+
"Do not cheat the linter: found 1 additional # pylint: disable=some-other-rule"
66+
)
67+
68+
69+
def test_no_cheat_returns_message_for_multiple_cheats_in_same_lines():
70+
diff_data = """
71+
+some code # pylint: disable=some-rule, some-other-rule
72+
-some other code
73+
"""
74+
result = no_cheat(diff_data)
75+
assert result == (
76+
"Do not cheat the linter: found 1 additional # pylint: disable=some-rule\n"
77+
"Do not cheat the linter: found 1 additional # pylint: disable=some-other-rule"
78+
)

0 commit comments

Comments
 (0)