ultralytics-actions 0.0.30__py3-none-any.whl → 0.0.32__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- actions/__init__.py +1 -1
- actions/summarize_pr.py +43 -38
- actions/utils/openai_utils.py +2 -2
- {ultralytics_actions-0.0.30.dist-info → ultralytics_actions-0.0.32.dist-info}/METADATA +1 -1
- {ultralytics_actions-0.0.30.dist-info → ultralytics_actions-0.0.32.dist-info}/RECORD +9 -9
- {ultralytics_actions-0.0.30.dist-info → ultralytics_actions-0.0.32.dist-info}/LICENSE +0 -0
- {ultralytics_actions-0.0.30.dist-info → ultralytics_actions-0.0.32.dist-info}/WHEEL +0 -0
- {ultralytics_actions-0.0.30.dist-info → ultralytics_actions-0.0.32.dist-info}/entry_points.txt +0 -0
- {ultralytics_actions-0.0.30.dist-info → ultralytics_actions-0.0.32.dist-info}/top_level.txt +0 -0
actions/__init__.py
CHANGED
actions/summarize_pr.py
CHANGED
@@ -20,13 +20,8 @@ SUMMARY_START = (
|
|
20
20
|
)
|
21
21
|
|
22
22
|
|
23
|
-
def generate_merge_message(
|
23
|
+
def generate_merge_message(pr_summary=None, pr_credit=None):
|
24
24
|
"""Generates a thank-you message for merged PR contributors."""
|
25
|
-
contributors_str = ", ".join(f"@{c}" for c in contributors if c != pr_author)
|
26
|
-
mention_str = f"@{pr_author}"
|
27
|
-
if contributors_str:
|
28
|
-
mention_str += f" and {contributors_str}"
|
29
|
-
|
30
25
|
messages = [
|
31
26
|
{
|
32
27
|
"role": "system",
|
@@ -34,10 +29,10 @@ def generate_merge_message(pr_author, contributors, pr_summary=None):
|
|
34
29
|
},
|
35
30
|
{
|
36
31
|
"role": "user",
|
37
|
-
"content": f"Write a friendly thank you for a merged PR by
|
32
|
+
"content": f"Write a friendly thank you for a merged GitHub PR by {pr_credit}. "
|
38
33
|
f"Context from PR:\n{pr_summary}\n\n"
|
39
34
|
f"Start with the exciting message that this PR is now merged, and weave in an inspiring quote "
|
40
|
-
f"from a famous figure
|
35
|
+
f"from a famous figure from science, art, philosophy or stoicism. "
|
41
36
|
f"Keep the message concise yet relevant to the specific contributions in this PR. "
|
42
37
|
f"We want the contributors to feel their effort is appreciated and will make a difference in the world.",
|
43
38
|
},
|
@@ -45,15 +40,15 @@ def generate_merge_message(pr_author, contributors, pr_summary=None):
|
|
45
40
|
return get_completion(messages)
|
46
41
|
|
47
42
|
|
48
|
-
def post_merge_message(pr_number,
|
43
|
+
def post_merge_message(pr_number, summary, pr_credit):
|
49
44
|
"""Posts thank you message on PR after merge."""
|
50
|
-
message = generate_merge_message(
|
45
|
+
message = generate_merge_message(summary, pr_credit)
|
51
46
|
comment_url = f"{GITHUB_API_URL}/repos/{GITHUB_REPOSITORY}/issues/{pr_number}/comments"
|
52
47
|
response = requests.post(comment_url, json={"body": message}, headers=GITHUB_HEADERS)
|
53
48
|
return response.status_code == 201
|
54
49
|
|
55
50
|
|
56
|
-
def generate_issue_comment(pr_url, pr_summary):
|
51
|
+
def generate_issue_comment(pr_url, pr_summary, pr_credit):
|
57
52
|
"""Generates a personalized issue comment using based on the PR context."""
|
58
53
|
messages = [
|
59
54
|
{
|
@@ -62,15 +57,16 @@ def generate_issue_comment(pr_url, pr_summary):
|
|
62
57
|
},
|
63
58
|
{
|
64
59
|
"role": "user",
|
65
|
-
"content": f"Write a GitHub issue comment announcing a potential fix
|
60
|
+
"content": f"Write a GitHub issue comment announcing a potential fix for this issue is now merged in linked PR {pr_url} by {pr_credit}\n\n"
|
66
61
|
f"Context from PR:\n{pr_summary}\n\n"
|
67
62
|
f"Include:\n"
|
68
63
|
f"1. An explanation of key changes from the PR that may resolve this issue\n"
|
69
|
-
f"2.
|
64
|
+
f"2. Credit to the PR author and contributors\n"
|
65
|
+
f"3. Options for testing if PR changes have resolved this issue:\n"
|
70
66
|
f" - pip install git+https://github.com/ultralytics/ultralytics.git@main # test latest changes\n"
|
71
67
|
f" - or await next official PyPI release\n"
|
72
|
-
f"
|
73
|
-
f"
|
68
|
+
f"4. Request feedback on whether the PR changes resolve the issue\n"
|
69
|
+
f"5. Thank 🙏 for reporting the issue and welcome any further feedback if the issue persists\n\n",
|
74
70
|
},
|
75
71
|
]
|
76
72
|
return get_completion(messages)
|
@@ -129,49 +125,60 @@ def update_pr_description(repo_name, pr_number, new_summary, max_retries=2):
|
|
129
125
|
|
130
126
|
|
131
127
|
def label_fixed_issues(pr_number, pr_summary):
|
132
|
-
"""Labels issues closed by
|
128
|
+
"""Labels issues closed by PR when merged, notifies users, returns PR contributors."""
|
133
129
|
query = """
|
134
130
|
query($owner: String!, $repo: String!, $pr_number: Int!) {
|
135
131
|
repository(owner: $owner, name: $repo) {
|
136
132
|
pullRequest(number: $pr_number) {
|
137
|
-
closingIssuesReferences(first: 50) {
|
138
|
-
nodes {
|
139
|
-
number
|
140
|
-
}
|
141
|
-
}
|
133
|
+
closingIssuesReferences(first: 50) { nodes { number } }
|
142
134
|
url
|
143
135
|
body
|
144
136
|
author { login, __typename }
|
145
|
-
reviews(first: 50) {
|
146
|
-
|
147
|
-
}
|
148
|
-
comments(first: 50) {
|
149
|
-
nodes { author { login, __typename } }
|
150
|
-
}
|
137
|
+
reviews(first: 50) { nodes { author { login, __typename } } }
|
138
|
+
comments(first: 50) { nodes { author { login, __typename } } }
|
139
|
+
commits(first: 100) { nodes { commit { author { user { login } }, committer { user { login } } } } }
|
151
140
|
}
|
152
141
|
}
|
153
142
|
}
|
154
143
|
"""
|
155
|
-
|
156
144
|
owner, repo = GITHUB_REPOSITORY.split("/")
|
157
145
|
variables = {"owner": owner, "repo": repo, "pr_number": pr_number}
|
158
146
|
graphql_url = "https://api.github.com/graphql"
|
159
147
|
response = requests.post(graphql_url, json={"query": query, "variables": variables}, headers=GITHUB_HEADERS)
|
148
|
+
|
160
149
|
if response.status_code != 200:
|
161
150
|
print(f"Failed to fetch linked issues. Status code: {response.status_code}")
|
162
151
|
return [], None
|
163
152
|
|
164
153
|
try:
|
165
154
|
data = response.json()["data"]["repository"]["pullRequest"]
|
166
|
-
comments = data["reviews"]["nodes"] + data["comments"]["nodes"]
|
167
|
-
|
155
|
+
comments = data["reviews"]["nodes"] + data["comments"]["nodes"]
|
156
|
+
token_username = get_github_username() # get GITHUB_TOKEN username
|
157
|
+
author = data["author"]["login"] if data["author"]["__typename"] != "Bot" else None
|
168
158
|
|
169
159
|
# Get unique contributors from reviews and comments
|
170
160
|
contributors = {x["author"]["login"] for x in comments if x["author"]["__typename"] != "Bot"}
|
171
|
-
|
161
|
+
|
162
|
+
# Add commit authors and committers that have GitHub accounts linked
|
163
|
+
for commit in data["commits"]["nodes"]:
|
164
|
+
commit_data = commit["commit"]
|
165
|
+
for user_type in ["author", "committer"]:
|
166
|
+
if user := commit_data[user_type].get("user"):
|
167
|
+
if login := user.get("login"):
|
168
|
+
contributors.add(login)
|
169
|
+
|
170
|
+
contributors.discard(author)
|
171
|
+
contributors.discard(token_username)
|
172
|
+
|
173
|
+
# Write credit string
|
174
|
+
pr_credit = "" # i.e. "@user1 with contributions from @user2, @user3"
|
175
|
+
if author and author != token_username:
|
176
|
+
pr_credit += f"@{author}"
|
177
|
+
if contributors:
|
178
|
+
pr_credit += (" with contributions from " if pr_credit else "") + ", ".join(f"@{c}" for c in contributors)
|
172
179
|
|
173
180
|
# Generate personalized comment
|
174
|
-
comment = generate_issue_comment(pr_url=data["url"], pr_summary=pr_summary)
|
181
|
+
comment = generate_issue_comment(pr_url=data["url"], pr_summary=pr_summary, pr_credit=pr_credit)
|
175
182
|
|
176
183
|
# Update linked issues
|
177
184
|
for issue in data["closingIssuesReferences"]["nodes"]:
|
@@ -192,7 +199,7 @@ query($owner: String!, $repo: String!, $pr_number: Int!) {
|
|
192
199
|
f"Comment status: {comment_response.status_code}"
|
193
200
|
)
|
194
201
|
|
195
|
-
return
|
202
|
+
return pr_credit
|
196
203
|
except KeyError as e:
|
197
204
|
print(f"Error parsing GraphQL response: {e}")
|
198
205
|
return [], None
|
@@ -228,14 +235,12 @@ def main():
|
|
228
235
|
# Update linked issues and post thank you message if merged
|
229
236
|
if PR.get("merged"):
|
230
237
|
print("PR is merged, labeling fixed issues...")
|
231
|
-
|
238
|
+
pr_credit = label_fixed_issues(pr_number, summary)
|
232
239
|
print("Removing TODO label from PR...")
|
233
240
|
remove_todos_on_merge(pr_number)
|
234
|
-
|
235
|
-
if author and author != username:
|
241
|
+
if pr_credit:
|
236
242
|
print("Posting PR author thank you message...")
|
237
|
-
|
238
|
-
post_merge_message(pr_number, author, contributors, summary)
|
243
|
+
post_merge_message(pr_number, summary, pr_credit)
|
239
244
|
|
240
245
|
|
241
246
|
if __name__ == "__main__":
|
actions/utils/openai_utils.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# Ultralytics Actions 🚀, AGPL-3.0 license https://ultralytics.com/license
|
2
2
|
|
3
3
|
import os
|
4
|
-
import
|
4
|
+
import time
|
5
5
|
from typing import Dict, List
|
6
6
|
|
7
7
|
import requests
|
@@ -25,7 +25,7 @@ def get_completion(
|
|
25
25
|
content = ""
|
26
26
|
max_retries = 2
|
27
27
|
for attempt in range(max_retries + 2): # attempt = [0, 1, 2, 3], 2 random retries before asking for no links
|
28
|
-
data = {"model": OPENAI_MODEL, "messages": messages, "seed":
|
28
|
+
data = {"model": OPENAI_MODEL, "messages": messages, "seed": int(time.time() * 1000)}
|
29
29
|
|
30
30
|
r = requests.post(url, headers=headers, json=data)
|
31
31
|
r.raise_for_status()
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: ultralytics-actions
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.32
|
4
4
|
Summary: Ultralytics Actions for GitHub automation and PR management.
|
5
5
|
Author-email: Glenn Jocher <glenn.jocher@ultralytics.com>
|
6
6
|
Maintainer-email: Ultralytics <hello@ultralytics.com>
|
@@ -1,15 +1,15 @@
|
|
1
|
-
actions/__init__.py,sha256=
|
1
|
+
actions/__init__.py,sha256=fsXAqPALIJ8ixqg50W8n_vgFPI61MnTVMp54zIX08b8,749
|
2
2
|
actions/first_interaction.py,sha256=ehHkFwWr-14LgesGmO4lOthu8z626FgvV9e6fiyzN8Q,17648
|
3
|
-
actions/summarize_pr.py,sha256=
|
3
|
+
actions/summarize_pr.py,sha256=wCNpdHM7MIsIYUFK8W1Ama_ctV8OF4_6hf4QvY6zPFg,11067
|
4
4
|
actions/summarize_release.py,sha256=l8NBdTAXLysfNKl1Kf_1tyuBRmeEBLyzTDXS6s5_eQg,8350
|
5
5
|
actions/update_markdown_code_blocks.py,sha256=WBNcMD_KKsZS-qSPBn6O1G0ggQ_VrT-jTQffbg7xH_M,6369
|
6
6
|
actions/utils/__init__.py,sha256=e3vKraD3_YpFiVUn3B3KR0diqG1ZrXMV9eXQYikObxo,1025
|
7
7
|
actions/utils/common_utils.py,sha256=XT8GG0SWBtlZLruA0nKrY4AJpkitvPbM8zndE8etuDo,3548
|
8
8
|
actions/utils/github_utils.py,sha256=QBNBx_qb3cbMwYmAQqEmUmGj33jir8Hjc6dr8Jk3vws,6286
|
9
|
-
actions/utils/openai_utils.py,sha256=
|
10
|
-
ultralytics_actions-0.0.
|
11
|
-
ultralytics_actions-0.0.
|
12
|
-
ultralytics_actions-0.0.
|
13
|
-
ultralytics_actions-0.0.
|
14
|
-
ultralytics_actions-0.0.
|
15
|
-
ultralytics_actions-0.0.
|
9
|
+
actions/utils/openai_utils.py,sha256=CU0FdeUW6qeZsxYCC2NUcGjns7w6hDvT8PwaRlG7j9E,1829
|
10
|
+
ultralytics_actions-0.0.32.dist-info/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
|
11
|
+
ultralytics_actions-0.0.32.dist-info/METADATA,sha256=Fq-Ggn3aFoMBQ7iMMcuSXhmw7ZQ1LiT_HpMdUaYWDUk,10591
|
12
|
+
ultralytics_actions-0.0.32.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
13
|
+
ultralytics_actions-0.0.32.dist-info/entry_points.txt,sha256=GowvOFplj0C7JmsjbKcbpgLpdf2r921pcaOQkAHWZRA,378
|
14
|
+
ultralytics_actions-0.0.32.dist-info/top_level.txt,sha256=5apM5x80QlJcGbACn1v3fkmIuL1-XQCKcItJre7w7Tw,8
|
15
|
+
ultralytics_actions-0.0.32.dist-info/RECORD,,
|
File without changes
|
File without changes
|
{ultralytics_actions-0.0.30.dist-info → ultralytics_actions-0.0.32.dist-info}/entry_points.txt
RENAMED
File without changes
|
File without changes
|