Skip to content

Commit f5302c2

Browse files
authored
✨fix the rule (#5)
* fix the rule * listen edited event
1 parent a9acdc2 commit f5302c2

16 files changed

+88
-123
lines changed

.github/workflows/pr-lint.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: Commitlint PR Title
22

33
on:
44
pull_request:
5-
types: [opened, labeled, unlabeled]
5+
types: [opened, labeled, unlabeled, edited]
66

77
jobs:
88
commitlint:

src/pr_lint/formatter.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import re
2+
3+
from github.PullRequest import PullRequest
4+
5+
emoji_pattern = re.compile(
6+
"["
7+
"\U0001F600-\U0001F64F" # Emoticons
8+
"\U0001F300-\U0001F5FF" # Symbols & pictographs
9+
"\U0001F680-\U0001F6FF" # Transport & map symbols
10+
"\U0001F1E0-\U0001F1FF" # Flags (iOS)
11+
"\U0001F900-\U0001F9FF" # Supplemental Symbols and Pictographs
12+
"\U0001FA70-\U0001FAFF" # Symbols and Pictographs Extended-A
13+
"\u2600-\u26FF" # Miscellaneous Symbols
14+
"\u2700-\u27BF" # Dingbats
15+
"]"
16+
)
17+
18+
19+
def format(pr: PullRequest) -> None:
20+
"""
21+
Format a pull request:
22+
23+
1. Extract emojis from labels and insert them to the PR title
24+
25+
Args:
26+
pr: The pull request to format
27+
"""
28+
29+
labels = pr.get_labels()
30+
# remove all emojis from the left of title
31+
cleaned_title = pr.title.lstrip("".join(emoji_pattern.findall(pr.title))).strip()
32+
33+
emojis = set()
34+
for label in labels:
35+
if _emjojis := emoji_pattern.findall(label.name):
36+
emojis.update(_emjojis)
37+
38+
new_title = f"{''.join(emojis)} {cleaned_title}"
39+
if new_title != pr.title:
40+
pr.edit(title=new_title)
41+
print(f"Updated PR title: {pr.title} -> {new_title}")

src/pr_lint/linter.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import re
2+
3+
from github.Label import Label
4+
from github.PullRequest import PullRequest
5+
6+
7+
def lint(pr: PullRequest) -> None:
8+
"""
9+
Lint a pull request:
10+
1. checks if the PR title ends with a username (owner)
11+
2. The username must be a collaborator
12+
3. checks if there is exactly one Type label
13+
4. checks if there is exactly one Impact label
14+
15+
Args:
16+
pr: The pull request to lint
17+
"""
18+
19+
title = pr.title
20+
repo = pr.base.repo
21+
22+
pr_owners = re.findall(r"(@[\w]+)$", title)
23+
assert pr_owners, "PR title should end with a GitHub username"
24+
pr_owner = pr_owners[0][1:]
25+
assert repo.has_in_collaborators(pr_owner), f"{pr_owner} is not a collaborator"
26+
27+
labels = pr.get_labels()
28+
29+
type_labels: list[Label] = []
30+
impact_labels: list[Label] = []
31+
32+
for label in labels:
33+
if "Type:" in label.name:
34+
type_labels.append(label)
35+
elif "Impact:" in label.name:
36+
impact_labels.append(label)
37+
38+
assert len(type_labels) == 1, "There should be exactly one Type label"
39+
assert len(impact_labels) == 1, "There should be exactly one Impact label"
40+
41+
# TODO: check if the PR title is in the correct format (e.g. commitlint convention)

src/pr_lint/main.py

Lines changed: 5 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,14 @@
11
import os
2-
import re
32

43
import typer
5-
from github import Github, Label
4+
from github import Github
65

7-
emoji_pattern = re.compile(
8-
"["
9-
"\U0001F600-\U0001F64F" # Emoticons
10-
"\U0001F300-\U0001F5FF" # Symbols & pictographs
11-
"\U0001F680-\U0001F6FF" # Transport & map symbols
12-
"\U0001F1E0-\U0001F1FF" # Flags (iOS)
13-
"\U0001F900-\U0001F9FF" # Supplemental Symbols and Pictographs
14-
"\U0001FA70-\U0001FAFF" # Symbols and Pictographs Extended-A
15-
"\u2600-\u26FF" # Miscellaneous Symbols
16-
"\u2700-\u27BF" # Dingbats
17-
"]+"
18-
)
6+
from .formatter import format
7+
from .linter import lint
198

209
app = typer.Typer()
2110

2211

23-
def extract_emoji(string: str) -> set[str]:
24-
"""
25-
Extracts emojis from a string
26-
27-
Args:
28-
string: The string to extract emojis from
29-
30-
Returns:
31-
A set of emojis
32-
"""
33-
return set(emoji_pattern.findall(string))
34-
35-
36-
def clean_title(input_string: str) -> str:
37-
# remove starting and ending emojis
38-
input_string = input_string.strip().rstrip("".join(extract_emoji(input_string)))
39-
input_string = input_string.strip().lstrip("".join(extract_emoji(input_string)))
40-
input_string = input_string.strip()
41-
42-
# TODO:
43-
# rewrite title's type and scope?
44-
# remove starting type and scope [\w]+:
45-
# input_string = re.sub(r"^[\w\-\(\)\.]+:", "", input_string).strip()
46-
return input_string
47-
48-
4912
@app.command()
5013
def main() -> None:
5114
token = os.getenv("GITHUB_TOKEN")
@@ -65,34 +28,8 @@ def main() -> None:
6528
# Get the pull request
6629
pr = repo.get_pull(int(pr_number))
6730

68-
labels = pr.get_labels()
69-
70-
type_labels: list[Label.Label] = []
71-
other_labels: list[Label.Label] = []
72-
73-
for label in labels:
74-
if "Type:" in label.name:
75-
type_labels.append(label)
76-
else:
77-
other_labels.append(label)
78-
79-
assert len(type_labels) == 1, "There should be exactly one Type label"
80-
81-
# format new title as [Type Emoji][Title][Other Emojis]
82-
type_emoji = "".join(extract_emoji(type_labels[0].name))
83-
other_emojis = set()
84-
for label in other_labels:
85-
other_emojis.update(extract_emoji(label.name))
86-
other_emojis_result = "".join(other_emojis)
87-
88-
new_title = clean_title(pr.title)
89-
new_title = f"{type_emoji}{new_title}{other_emojis_result}"
90-
91-
if new_title != pr.title:
92-
pr.edit(title=new_title)
93-
print(f"Title changed from {pr.title} to {new_title}")
94-
else:
95-
print("Title is already correctly formatted")
31+
lint(pr)
32+
format(pr)
9633

9734

9835
if __name__ == "__main__":

src/pr_lint/tests/__init__.py

Whitespace-only changes.

src/pr_lint/tests/__snapshots__/test_main/test_clean_title[U0001f34eupdate(v2.0) version updateU0001f34e].json

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/pr_lint/tests/__snapshots__/test_main/test_clean_title[U0001f41bfix correct typoU0001f41b].json

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/pr_lint/tests/__snapshots__/test_main/test_clean_title[U0001f41bu4feeu590d correct typoU0001f41b].json

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/pr_lint/tests/__snapshots__/test_main/test_clean_title[U0001f680feature(add-new) add a new featureU0001f680].json

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/pr_lint/tests/__snapshots__/test_main/test_clean_title[bug fix issue U0001f41e].json

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)