@misterhuydo/sentinel 1.6.15 → 1.6.16
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.
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "1.6.
|
|
1
|
+
__version__ = "1.6.16"
|
package/python/sentinel/main.py
CHANGED
|
@@ -61,6 +61,27 @@ def _project_lock(project_name: str) -> "asyncio.Lock":
|
|
|
61
61
|
return _project_locks[project_name]
|
|
62
62
|
|
|
63
63
|
|
|
64
|
+
def _notify_skip(sentinel: SentinelConfig, event: "IssueEvent", reason: str) -> None:
|
|
65
|
+
"""Tell the submitter (and channel) when an issue is skipped via dedupe.
|
|
66
|
+
|
|
67
|
+
Without this, Boss's "I'll @-mention you when it completes" promise breaks —
|
|
68
|
+
the user is left waiting indefinitely after a silent skip.
|
|
69
|
+
"""
|
|
70
|
+
from .notify import slack_alert as _alert
|
|
71
|
+
submitter = getattr(event, "submitter_user_id", "")
|
|
72
|
+
channel = getattr(event, "origin_channel", "") or sentinel.slack_channel
|
|
73
|
+
if not channel or not sentinel.slack_bot_token:
|
|
74
|
+
return
|
|
75
|
+
mention = f"<@{submitter}> " if submitter else ""
|
|
76
|
+
_alert(
|
|
77
|
+
sentinel.slack_bot_token, channel,
|
|
78
|
+
f":fast_forward: {mention}*Issue skipped* — fingerprint `{event.fingerprint[:8]}`. "
|
|
79
|
+
f"{reason}. To force a new attempt, use `retry_issue` (it clears prior `failed` rows). "
|
|
80
|
+
f"If a successful fix already shipped for this fingerprint, the retry will still skip "
|
|
81
|
+
f"unless an admin clears the `applied` row.",
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
|
|
64
85
|
def _restart_via_execv() -> None:
|
|
65
86
|
"""Re-exec the current process, preserving the original `python -m sentinel.main` invocation.
|
|
66
87
|
|
|
@@ -582,6 +603,7 @@ async def _handle_issue(event: IssueEvent, cfg_loader: ConfigLoader, store: Stat
|
|
|
582
603
|
"(use Boss `retry_issue` to clear the prior row and re-attempt)",
|
|
583
604
|
event.source, event.fingerprint,
|
|
584
605
|
)
|
|
606
|
+
_notify_skip(sentinel, event, "An attempt was already made in the last 24h")
|
|
585
607
|
mark_done(event.issue_file)
|
|
586
608
|
return
|
|
587
609
|
|
|
@@ -643,6 +665,7 @@ async def _handle_issue_locked(event, repo, cfg_loader, store):
|
|
|
643
665
|
"Issue %s skipped (post-lock recheck) — fingerprint %s already attempted",
|
|
644
666
|
event.source, event.fingerprint,
|
|
645
667
|
)
|
|
668
|
+
_notify_skip(sentinel, event, "Another worker already attempted this in the last 24h")
|
|
646
669
|
mark_done(event.issue_file)
|
|
647
670
|
return None
|
|
648
671
|
|
|
@@ -2603,25 +2603,37 @@ async def _run_tool(name: str, inputs: dict, cfg_loader, store, slack_client=Non
|
|
|
2603
2603
|
if store:
|
|
2604
2604
|
try:
|
|
2605
2605
|
with store._conn() as _c:
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2606
|
+
# Check for a successful fix in the last 24h FIRST. We can't
|
|
2607
|
+
# use ORDER BY timestamp DESC LIMIT 1 because a spurious
|
|
2608
|
+
# 'failed' row inserted by a post-success exception (see
|
|
2609
|
+
# the catch-all in main.py) sorts ahead of the real
|
|
2610
|
+
# 'applied' row by milliseconds, hiding the success.
|
|
2611
|
+
_applied = _c.execute(
|
|
2612
|
+
"SELECT status, commit_hash FROM fixes "
|
|
2613
|
+
"WHERE fingerprint=? AND status IN ('applied', 'merged') "
|
|
2614
|
+
"AND timestamp >= datetime('now', '-24 hours') "
|
|
2615
|
+
"ORDER BY timestamp DESC LIMIT 1",
|
|
2609
2616
|
(_fp,),
|
|
2610
2617
|
).fetchone()
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
if _status in ("merged", "applied"):
|
|
2614
|
-
_commit = _row["commit_hash"] or ""
|
|
2618
|
+
if _applied:
|
|
2619
|
+
_commit = _applied["commit_hash"] or ""
|
|
2615
2620
|
return json.dumps({
|
|
2616
2621
|
"error": (
|
|
2617
2622
|
f"Already fixed — this issue was resolved "
|
|
2618
2623
|
+ (f"in commit `{_commit[:8]}`" if _commit else "successfully")
|
|
2619
|
-
+ f". Status: `{
|
|
2624
|
+
+ f". Status: `{_applied['status']}`. "
|
|
2620
2625
|
f"If the problem recurred, describe it as a new issue."
|
|
2621
2626
|
)
|
|
2622
2627
|
})
|
|
2623
|
-
|
|
2624
|
-
|
|
2628
|
+
_pending = _c.execute(
|
|
2629
|
+
"SELECT pr_url FROM fixes "
|
|
2630
|
+
"WHERE fingerprint=? AND status='pending' "
|
|
2631
|
+
"AND timestamp >= datetime('now', '-24 hours') "
|
|
2632
|
+
"ORDER BY timestamp DESC LIMIT 1",
|
|
2633
|
+
(_fp,),
|
|
2634
|
+
).fetchone()
|
|
2635
|
+
if _pending:
|
|
2636
|
+
_pr = _pending["pr_url"] or ""
|
|
2625
2637
|
return json.dumps({
|
|
2626
2638
|
"error": (
|
|
2627
2639
|
f"There is already an open PR for this issue"
|