forge_notify: include reason field in all notification messages (closes #110)
This commit is contained in:
parent
7f97acf19e
commit
edf7f1602d
1 changed files with 27 additions and 15 deletions
|
|
@ -223,14 +223,19 @@ fn review_state_label(state: &str) -> Option<&str> {
|
|||
/// and should be silently discarded (and marked read by the caller).
|
||||
///
|
||||
/// Formats:
|
||||
/// - Comment: `[comment on PR #N repo] title\nurl: ...\n\nauthor: body\nassignee: user`
|
||||
/// - Review: `[PR approved #N repo] title\nurl: ...\n\nreviewer: body\nassignee: user`
|
||||
/// - New item: `[new issue #N repo] title\nurl: ...\nassignee: user`
|
||||
/// - State: `[PR merged #N repo] title\nurl: ...\nassignee: user`
|
||||
/// - Comment: `[comment on PR #N repo] title\nurl: ...\n\nauthor: body\nassignee: user\nreason: mention`
|
||||
/// - Review: `[PR approved #N repo] title\nurl: ...\n\nreviewer: body\nassignee: user\nreason: review_requested`
|
||||
/// - New item: `[new issue #N repo] title\nurl: ...\nassignee: user\nreason: author`
|
||||
/// - State: `[PR merged #N repo] title\nurl: ...\nassignee: user\nreason: subscribed`
|
||||
///
|
||||
/// Assignees (and, for PRs, `requested_reviewers`) are appended unconditionally
|
||||
/// on all issue/PR notifications (closes #256).
|
||||
///
|
||||
/// The `reason` field from the Forgejo notification is always appended (closes #110).
|
||||
/// Forgejo emits one notification entry per reason for the same event, so including
|
||||
/// it makes otherwise-identical messages distinguishable (e.g. `mention` vs
|
||||
/// `subscribed` both arriving for the same PR comment).
|
||||
///
|
||||
/// Number is extracted from `html_url` last path segment before any `#`.
|
||||
/// Repo slug (`owner/name`) is always included — agents may watch multiple repos.
|
||||
async fn format_notification(
|
||||
|
|
@ -277,13 +282,14 @@ async fn format_notification(
|
|||
};
|
||||
|
||||
let is_pr = matches!(notif_type, "Pull Request" | "Pull");
|
||||
let meta_suffix = build_meta_suffix(subject.as_ref(), is_pr);
|
||||
let reason = notif["reason"].as_str().unwrap_or("");
|
||||
let meta_suffix = build_meta_suffix(subject.as_ref(), is_pr, reason);
|
||||
|
||||
// Determine whether this notification was triggered by a comment/review or
|
||||
// by creation/state-change of the subject itself.
|
||||
let has_comment = !comment_api_url.is_empty() && comment_api_url != subject_api_url;
|
||||
|
||||
let meta = NotifMeta { title, notif_type, html_url, num, repo, meta_suffix, subject, is_pr };
|
||||
let meta = NotifMeta { title, notif_type, html_url, num, repo, meta_suffix, reason, subject, is_pr };
|
||||
if has_comment {
|
||||
format_comment_notification(client, token, &meta, comment_api_url, comment_html_url, own_login).await
|
||||
} else {
|
||||
|
|
@ -299,14 +305,18 @@ struct NotifMeta<'a> {
|
|||
num: String,
|
||||
repo: String,
|
||||
meta_suffix: String,
|
||||
/// Forgejo `reason` value (e.g. "mention", "assigned", "subscribed").
|
||||
/// Appended to every formatted message so that multiple notifications for
|
||||
/// the same event (each with a different reason) are distinguishable (closes #110).
|
||||
reason: &'a str,
|
||||
/// Fetched subject detail (issue/PR JSON); used for review-request detection.
|
||||
subject: Option<serde_json::Value>,
|
||||
is_pr: bool,
|
||||
}
|
||||
|
||||
/// Build the `\nassignee: ...` (and optionally `\nreviewer: ...`) suffix
|
||||
/// Build the `\nassignee: ...` (and optionally `\nreviewer: ...` and `\nreason: ...`) suffix
|
||||
/// appended to all notification kinds.
|
||||
fn build_meta_suffix(subject: Option<&serde_json::Value>, is_pr: bool) -> String {
|
||||
fn build_meta_suffix(subject: Option<&serde_json::Value>, is_pr: bool, reason: &str) -> String {
|
||||
let assignees: Vec<&str> = subject
|
||||
.and_then(|s| s["assignees"].as_array())
|
||||
.map(|arr| arr.iter().filter_map(|a| a["login"].as_str()).collect())
|
||||
|
|
@ -326,10 +336,13 @@ fn build_meta_suffix(subject: Option<&serde_json::Value>, is_pr: bool) -> String
|
|||
} else {
|
||||
None
|
||||
};
|
||||
match reviewer_line {
|
||||
Some(r) => format!("\n{assignee_line}\n{r}"),
|
||||
None => format!("\n{assignee_line}"),
|
||||
}
|
||||
// Always include reason so multiple notifications for the same event
|
||||
// (each with a different Forgejo reason) are distinguishable (closes #110).
|
||||
let reason_line = if reason.is_empty() { None } else { Some(format!("reason: {reason}")) };
|
||||
let mut out = format!("\n{assignee_line}");
|
||||
if let Some(r) = reviewer_line { write!(out, "\n{r}").ok(); }
|
||||
if let Some(r) = reason_line { write!(out, "\n{r}").ok(); }
|
||||
out
|
||||
}
|
||||
|
||||
/// Format a notification triggered by a new comment or review submission.
|
||||
|
|
@ -412,19 +425,18 @@ fn format_state_change_notification(
|
|||
// `pull_request.merged`, not top-level `merged`.
|
||||
// - Forgejo API type is "Pull" / "Issue", never "Pull Request".
|
||||
let notif_state = notif["subject"]["state"].as_str().unwrap_or("");
|
||||
let reason = notif["reason"].as_str().unwrap_or("");
|
||||
|
||||
// Self-notification filter (#230): skip new items we authored ourselves.
|
||||
// `reason == "author"` combined with open state means we just opened the
|
||||
// issue/PR. We do NOT filter merged/closed state changes — those are
|
||||
// triggered by someone else and we want them.
|
||||
let is_new = notif_state == "open" || notif_state.is_empty();
|
||||
if is_new && reason == "author" && !own_login.is_empty() {
|
||||
if is_new && meta.reason == "author" && !own_login.is_empty() {
|
||||
debug!(%own_login, "forge_notify: skipping self-authored new item");
|
||||
return None;
|
||||
}
|
||||
|
||||
let NotifMeta { title, notif_type, html_url, num, repo, meta_suffix, subject, is_pr } = meta;
|
||||
let NotifMeta { title, notif_type, html_url, num, repo, meta_suffix, reason: _, subject, is_pr } = meta;
|
||||
let label = notif_type_label(notif_type);
|
||||
let kind = match notif_state {
|
||||
"merged" => format!("{label} merged{num}{repo}"),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue