ultralytics-actions 0.1.5__tar.gz → 0.1.6__tar.gz

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.

Potentially problematic release.


This version of ultralytics-actions might be problematic. Click here for more details.

Files changed (36) hide show
  1. {ultralytics_actions-0.1.5 → ultralytics_actions-0.1.6}/PKG-INFO +1 -1
  2. {ultralytics_actions-0.1.5 → ultralytics_actions-0.1.6}/actions/__init__.py +1 -1
  3. {ultralytics_actions-0.1.5 → ultralytics_actions-0.1.6}/actions/review_pr.py +25 -2
  4. {ultralytics_actions-0.1.5 → ultralytics_actions-0.1.6}/actions/utils/github_utils.py +8 -7
  5. {ultralytics_actions-0.1.5 → ultralytics_actions-0.1.6}/actions/utils/openai_utils.py +2 -0
  6. {ultralytics_actions-0.1.5 → ultralytics_actions-0.1.6}/tests/test_github_utils.py +2 -0
  7. {ultralytics_actions-0.1.5 → ultralytics_actions-0.1.6}/tests/test_openai_utils.py +2 -0
  8. {ultralytics_actions-0.1.5 → ultralytics_actions-0.1.6}/ultralytics_actions.egg-info/PKG-INFO +1 -1
  9. {ultralytics_actions-0.1.5 → ultralytics_actions-0.1.6}/LICENSE +0 -0
  10. {ultralytics_actions-0.1.5 → ultralytics_actions-0.1.6}/README.md +0 -0
  11. {ultralytics_actions-0.1.5 → ultralytics_actions-0.1.6}/actions/dispatch_actions.py +0 -0
  12. {ultralytics_actions-0.1.5 → ultralytics_actions-0.1.6}/actions/first_interaction.py +0 -0
  13. {ultralytics_actions-0.1.5 → ultralytics_actions-0.1.6}/actions/summarize_pr.py +0 -0
  14. {ultralytics_actions-0.1.5 → ultralytics_actions-0.1.6}/actions/summarize_release.py +0 -0
  15. {ultralytics_actions-0.1.5 → ultralytics_actions-0.1.6}/actions/update_file_headers.py +0 -0
  16. {ultralytics_actions-0.1.5 → ultralytics_actions-0.1.6}/actions/update_markdown_code_blocks.py +0 -0
  17. {ultralytics_actions-0.1.5 → ultralytics_actions-0.1.6}/actions/utils/__init__.py +0 -0
  18. {ultralytics_actions-0.1.5 → ultralytics_actions-0.1.6}/actions/utils/common_utils.py +0 -0
  19. {ultralytics_actions-0.1.5 → ultralytics_actions-0.1.6}/actions/utils/version_utils.py +0 -0
  20. {ultralytics_actions-0.1.5 → ultralytics_actions-0.1.6}/pyproject.toml +0 -0
  21. {ultralytics_actions-0.1.5 → ultralytics_actions-0.1.6}/setup.cfg +0 -0
  22. {ultralytics_actions-0.1.5 → ultralytics_actions-0.1.6}/tests/test_cli_commands.py +0 -0
  23. {ultralytics_actions-0.1.5 → ultralytics_actions-0.1.6}/tests/test_common_utils.py +0 -0
  24. {ultralytics_actions-0.1.5 → ultralytics_actions-0.1.6}/tests/test_dispatch_actions.py +0 -0
  25. {ultralytics_actions-0.1.5 → ultralytics_actions-0.1.6}/tests/test_file_headers.py +0 -0
  26. {ultralytics_actions-0.1.5 → ultralytics_actions-0.1.6}/tests/test_first_interaction.py +0 -0
  27. {ultralytics_actions-0.1.5 → ultralytics_actions-0.1.6}/tests/test_init.py +0 -0
  28. {ultralytics_actions-0.1.5 → ultralytics_actions-0.1.6}/tests/test_summarize_pr.py +0 -0
  29. {ultralytics_actions-0.1.5 → ultralytics_actions-0.1.6}/tests/test_summarize_release.py +0 -0
  30. {ultralytics_actions-0.1.5 → ultralytics_actions-0.1.6}/tests/test_update_markdown_codeblocks.py +0 -0
  31. {ultralytics_actions-0.1.5 → ultralytics_actions-0.1.6}/tests/test_urls.py +0 -0
  32. {ultralytics_actions-0.1.5 → ultralytics_actions-0.1.6}/ultralytics_actions.egg-info/SOURCES.txt +0 -0
  33. {ultralytics_actions-0.1.5 → ultralytics_actions-0.1.6}/ultralytics_actions.egg-info/dependency_links.txt +0 -0
  34. {ultralytics_actions-0.1.5 → ultralytics_actions-0.1.6}/ultralytics_actions.egg-info/entry_points.txt +0 -0
  35. {ultralytics_actions-0.1.5 → ultralytics_actions-0.1.6}/ultralytics_actions.egg-info/requires.txt +0 -0
  36. {ultralytics_actions-0.1.5 → ultralytics_actions-0.1.6}/ultralytics_actions.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ultralytics-actions
3
- Version: 0.1.5
3
+ Version: 0.1.6
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>
@@ -23,4 +23,4 @@
23
23
  # ├── test_summarize_pr.py
24
24
  # └── ...
25
25
 
26
- __version__ = "0.1.5"
26
+ __version__ = "0.1.6"
@@ -8,6 +8,7 @@ import re
8
8
  from .utils import GITHUB_API_URL, MAX_PROMPT_CHARS, Action, get_completion, remove_html_comments
9
9
 
10
10
  REVIEW_MARKER = "🔍 PR Review"
11
+ ERROR_MARKER = "⚠️ Review generation encountered an error"
11
12
  EMOJI_MAP = {"CRITICAL": "❗", "HIGH": "⚠️", "MEDIUM": "💡", "LOW": "📝", "SUGGESTION": "💭"}
12
13
  SKIP_PATTERNS = [
13
14
  r"\.lock$", # Lock files
@@ -179,7 +180,7 @@ def generate_pr_review(repository: str, diff_text: str, pr_title: str, pr_descri
179
180
  error_details = traceback.format_exc()
180
181
  print(f"Review generation failed: {e}\n{error_details}")
181
182
  summary = (
182
- f"⚠️ Review generation encountered an error: `{type(e).__name__}`\n\n"
183
+ f"{ERROR_MARKER}: `{type(e).__name__}`\n\n"
183
184
  f"<details><summary>Debug Info</summary>\n\n```\n{error_details}\n```\n</details>"
184
185
  )
185
186
  return {"comments": [], "summary": summary}
@@ -219,7 +220,29 @@ def post_review_summary(event: Action, review_data: dict, review_number: int) ->
219
220
 
220
221
  review_title = f"{REVIEW_MARKER} {review_number}" if review_number > 1 else REVIEW_MARKER
221
222
  comments = review_data.get("comments", [])
222
- event_type = "COMMENT" if any(c.get("severity") not in ["LOW", "SUGGESTION", None] for c in comments) else "APPROVE"
223
+ summary = review_data.get("summary") or ""
224
+
225
+ # Don't approve if error occurred or if there are critical/high severity issues
226
+ has_error = not summary or ERROR_MARKER in summary
227
+ has_issues = any(c.get("severity") not in ["LOW", "SUGGESTION", None] for c in comments)
228
+ requests_changes = any(
229
+ phrase in summary.lower()
230
+ for phrase in [
231
+ "please",
232
+ "should",
233
+ "must",
234
+ "need to",
235
+ "needs to",
236
+ "before merging",
237
+ "fix",
238
+ "error",
239
+ "issue",
240
+ "problem",
241
+ "warning",
242
+ "concern",
243
+ ]
244
+ )
245
+ event_type = "COMMENT" if (has_error or has_issues or requests_changes) else "APPROVE"
223
246
 
224
247
  body = (
225
248
  f"## {review_title}\n\n"
@@ -125,21 +125,22 @@ class Action:
125
125
 
126
126
  def _request(self, method: str, url: str, headers=None, expected_status=None, hard=False, **kwargs):
127
127
  """Unified request handler with error checking."""
128
- response = getattr(requests, method)(url, headers=headers or self.headers, **kwargs)
128
+ r = getattr(requests, method)(url, headers=headers or self.headers, **kwargs)
129
129
  expected = expected_status or self._default_status[method]
130
- success = response.status_code in expected
130
+ success = r.status_code in expected
131
131
 
132
132
  if self.verbose:
133
- print(f"{'✓' if success else '✗'} {method.upper()} {url} → {response.status_code}")
133
+ elapsed = r.elapsed.total_seconds()
134
+ print(f"{'✓' if success else '✗'} {method.upper()} {url} → {r.status_code} ({elapsed:.1f}s)")
134
135
  if not success:
135
136
  try:
136
- print(f" ❌ Error: {response.json().get('message', 'Unknown error')}")
137
+ print(f" ❌ Error: {r.json().get('message', 'Unknown error')}")
137
138
  except Exception:
138
- print(f" ❌ Error: {response.text[:200]}")
139
+ print(f" ❌ Error: {r.text[:200]}")
139
140
 
140
141
  if not success and hard:
141
- response.raise_for_status()
142
- return response
142
+ r.raise_for_status()
143
+ return r
143
144
 
144
145
  def get(self, url, **kwargs):
145
146
  """Performs GET request with error handling."""
@@ -125,6 +125,8 @@ def get_completion(
125
125
 
126
126
  try:
127
127
  r = requests.post(url, json=data, headers=headers, timeout=600)
128
+ success = r.status_code == 200
129
+ print(f"{'✓' if success else '✗'} POST {url} → {r.status_code} ({r.elapsed.total_seconds():.1f}s)")
128
130
  r.raise_for_status()
129
131
 
130
132
  # Parse response
@@ -15,6 +15,7 @@ def test_check_pypi_version():
15
15
  with patch("requests.get") as mock_get:
16
16
  mock_response = MagicMock()
17
17
  mock_response.status_code = 200
18
+ mock_response.elapsed.total_seconds.return_value = 0.5
18
19
  mock_response.json.return_value = {"info": {"version": "0.9.0"}}
19
20
  mock_get.return_value = mock_response
20
21
 
@@ -43,6 +44,7 @@ def test_action_request_methods():
43
44
  with patch("requests.get") as mock_get:
44
45
  mock_response = MagicMock()
45
46
  mock_response.status_code = 200
47
+ mock_response.elapsed.total_seconds.return_value = 0.3
46
48
  mock_get.return_value = mock_response
47
49
 
48
50
  action = Action(token="test-token")
@@ -28,6 +28,7 @@ def test_get_completion(mock_post):
28
28
  # Setup mock response with Responses API structure
29
29
  mock_response = MagicMock()
30
30
  mock_response.status_code = 200
31
+ mock_response.elapsed.total_seconds.return_value = 1.5
31
32
  mock_response.json.return_value = {
32
33
  "output": [
33
34
  {
@@ -57,6 +58,7 @@ def test_get_completion_with_link_check(mock_check_links, mock_post):
57
58
  # Setup mocks with Responses API structure
58
59
  mock_response = MagicMock()
59
60
  mock_response.status_code = 200
61
+ mock_response.elapsed.total_seconds.return_value = 2.0
60
62
  mock_response.json.return_value = {
61
63
  "output": [
62
64
  {
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ultralytics-actions
3
- Version: 0.1.5
3
+ Version: 0.1.6
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>