huskies: merge 964

This commit is contained in:
dave
2026-05-13 14:51:39 +00:00
parent c811672e18
commit dcb43c465a
24 changed files with 234 additions and 188 deletions
+68 -58
View File
@@ -30,12 +30,16 @@ pub fn stage_display_name(stage: &Stage) -> &'static str {
/// Returns `(plain_text, html)` suitable for `ChatTransport::send_message`.
pub fn format_stage_notification(
item_id: &str,
story_name: Option<&str>,
story_name: &str,
from_stage: &Stage,
to_stage: &Stage,
) -> (String, String) {
let number = extract_item_number(item_id).unwrap_or(item_id);
let effective_name = story_name.filter(|n| !n.is_empty());
let effective_name = if story_name.is_empty() {
None
} else {
Some(story_name)
};
let name_plain = effective_name.map(|n| format!("{n} ")).unwrap_or_default();
let name_html = effective_name
.map(|n| format!("<em>{n}</em> "))
@@ -61,11 +65,15 @@ pub fn format_stage_notification(
/// Returns `(plain_text, html)` suitable for `ChatTransport::send_message`.
pub fn format_error_notification(
item_id: &str,
story_name: Option<&str>,
story_name: &str,
reason: &str,
) -> (String, String) {
let number = extract_item_number(item_id).unwrap_or(item_id);
let effective_name = story_name.filter(|n| !n.is_empty());
let effective_name = if story_name.is_empty() {
None
} else {
Some(story_name)
};
let name_plain = effective_name.map(|n| format!("{n} ")).unwrap_or_default();
let name_html = effective_name
.map(|n| format!("<em>{n}</em> "))
@@ -81,11 +89,15 @@ pub fn format_error_notification(
/// Returns `(plain_text, html)` suitable for `ChatTransport::send_message`.
pub fn format_blocked_notification(
item_id: &str,
story_name: Option<&str>,
story_name: &str,
reason: &str,
) -> (String, String) {
let number = extract_item_number(item_id).unwrap_or(item_id);
let effective_name = story_name.filter(|n| !n.is_empty());
let effective_name = if story_name.is_empty() {
None
} else {
Some(story_name)
};
let name_plain = effective_name.map(|n| format!("{n} ")).unwrap_or_default();
let name_html = effective_name
.map(|n| format!("<em>{n}</em> "))
@@ -102,11 +114,15 @@ pub fn format_blocked_notification(
/// Returns `(plain_text, html)` suitable for `ChatTransport::send_message`.
pub fn format_rate_limit_notification(
item_id: &str,
story_name: Option<&str>,
story_name: &str,
agent_name: &str,
) -> (String, String) {
let number = extract_item_number(item_id).unwrap_or(item_id);
let effective_name = story_name.filter(|n| !n.is_empty());
let effective_name = if story_name.is_empty() {
None
} else {
Some(story_name)
};
let name_plain = effective_name.map(|n| format!("{n} ")).unwrap_or_default();
let name_html = effective_name
.map(|n| format!("<em>{n}</em> "))
@@ -149,11 +165,15 @@ pub fn format_oauth_accounts_exhausted(earliest_reset_msg: &str) -> (String, Str
/// Returns `(plain_text, html)` suitable for `ChatTransport::send_message`.
pub fn format_agent_started_notification(
item_id: &str,
story_name: Option<&str>,
story_name: &str,
agent_name: &str,
) -> (String, String) {
let number = extract_item_number(item_id).unwrap_or(item_id);
let effective_name = story_name.filter(|n| !n.is_empty());
let effective_name = if story_name.is_empty() {
None
} else {
Some(story_name)
};
let name_plain = effective_name.map(|n| format!("{n} ")).unwrap_or_default();
let name_html = effective_name
.map(|n| format!("<em>{n}</em> "))
@@ -171,12 +191,16 @@ pub fn format_agent_started_notification(
/// Returns `(plain_text, html)` suitable for `ChatTransport::send_message`.
pub fn format_agent_completed_notification(
item_id: &str,
story_name: Option<&str>,
story_name: &str,
agent_name: &str,
success: bool,
) -> (String, String) {
let number = extract_item_number(item_id).unwrap_or(item_id);
let effective_name = story_name.filter(|n| !n.is_empty());
let effective_name = if story_name.is_empty() {
None
} else {
Some(story_name)
};
let name_plain = effective_name.map(|n| format!("{n} ")).unwrap_or_default();
let name_html = effective_name
.map(|n| format!("<em>{n}</em> "))
@@ -243,7 +267,7 @@ mod tests {
fn format_notification_done_stage_includes_party_emoji() {
let (plain, html) = format_stage_notification(
"353_story_done",
Some("Done Story"),
"Done Story",
&merge_stage(),
&done_stage(),
);
@@ -261,7 +285,7 @@ mod tests {
fn format_notification_non_done_stage_has_no_emoji() {
let (plain, _html) = format_stage_notification(
"42_story_thing",
Some("Some Story"),
"Some Story",
&Stage::Backlog,
&Stage::Coding,
);
@@ -272,7 +296,7 @@ mod tests {
fn format_notification_with_story_name() {
let (plain, html) = format_stage_notification(
"261_story_bot_notifications",
Some("Bot notifications"),
"Bot notifications",
&Stage::Upcoming,
&Stage::Coding,
);
@@ -289,19 +313,15 @@ mod tests {
#[test]
fn format_stage_notification_without_story_name_falls_back_to_number() {
let (plain, html) =
format_stage_notification("42_bug_fix_thing", None, &Stage::Coding, &Stage::Qa);
format_stage_notification("42_bug_fix_thing", "", &Stage::Coding, &Stage::Qa);
assert_eq!(plain, "#42 \u{2014} Current \u{2192} QA");
assert_eq!(html, "<strong>#42</strong> \u{2014} Current \u{2192} QA");
}
#[test]
fn format_notification_non_numeric_id_uses_full_id() {
let (plain, _html) = format_stage_notification(
"abc_story_thing",
Some("Some Story"),
&Stage::Qa,
&merge_stage(),
);
let (plain, _html) =
format_stage_notification("abc_story_thing", "Some Story", &Stage::Qa, &merge_stage());
assert_eq!(
plain,
"#abc_story_thing Some Story \u{2014} QA \u{2192} Merge"
@@ -312,14 +332,14 @@ mod tests {
fn format_stage_notification_long_name_is_preserved() {
let long_name = "A".repeat(300);
let (plain, _html) =
format_stage_notification("1_story_long", Some(&long_name), &Stage::Coding, &Stage::Qa);
format_stage_notification("1_story_long", &long_name, &Stage::Coding, &Stage::Qa);
assert!(plain.contains(&long_name));
}
#[test]
fn format_stage_notification_empty_story_name_falls_back_to_number() {
let (plain, html) =
format_stage_notification("42_story_empty", Some(""), &Stage::Coding, &Stage::Qa);
format_stage_notification("42_story_empty", "", &Stage::Coding, &Stage::Qa);
assert_eq!(plain, "#42 \u{2014} Current \u{2192} QA");
assert_eq!(html, "<strong>#42</strong> \u{2014} Current \u{2192} QA");
}
@@ -328,7 +348,7 @@ mod tests {
fn format_stage_notification_unicode_name() {
let (plain, html) = format_stage_notification(
"7_story_i18n",
Some("Ünïcödé Ñämé 🎉"),
"Ünïcödé Ñämé 🎉",
&Stage::Qa,
&merge_stage(),
);
@@ -342,7 +362,7 @@ mod tests {
fn format_error_notification_with_story_name() {
let (plain, html) = format_error_notification(
"262_story_bot_errors",
Some("Bot error notifications"),
"Bot error notifications",
"merge conflict in src/main.rs",
);
assert_eq!(
@@ -357,7 +377,7 @@ mod tests {
#[test]
fn format_error_notification_without_story_name_falls_back_to_number() {
let (plain, html) = format_error_notification("42_bug_fix_thing", None, "tests failed");
let (plain, html) = format_error_notification("42_bug_fix_thing", "", "tests failed");
assert_eq!(plain, "\u{274c} #42 \u{2014} tests failed");
assert_eq!(html, "\u{274c} <strong>#42</strong> \u{2014} tests failed");
}
@@ -365,7 +385,7 @@ mod tests {
#[test]
fn format_error_notification_non_numeric_id_uses_full_id() {
let (plain, _html) =
format_error_notification("abc_story_thing", Some("Some Story"), "clippy errors");
format_error_notification("abc_story_thing", "Some Story", "clippy errors");
assert_eq!(
plain,
"\u{274c} #abc_story_thing Some Story \u{2014} clippy errors"
@@ -375,21 +395,19 @@ mod tests {
#[test]
fn format_error_notification_long_reason_preserved() {
let long_reason = "x".repeat(500);
let (plain, _html) = format_error_notification("1_story_foo", None, &long_reason);
let (plain, _html) = format_error_notification("1_story_foo", "", &long_reason);
assert!(plain.contains(&long_reason));
}
#[test]
fn format_error_notification_unicode_reason() {
let (plain, _html) =
format_error_notification("5_story_foo", Some("Foo"), "错误:合并冲突");
let (plain, _html) = format_error_notification("5_story_foo", "Foo", "错误:合并冲突");
assert!(plain.contains("错误:合并冲突"));
}
#[test]
fn format_error_notification_empty_story_name_falls_back_to_number() {
let (plain, _html) =
format_error_notification("42_bug_fix_thing", Some(""), "tests failed");
let (plain, _html) = format_error_notification("42_bug_fix_thing", "", "tests failed");
assert_eq!(plain, "\u{274c} #42 \u{2014} tests failed");
}
@@ -399,7 +417,7 @@ mod tests {
fn format_blocked_notification_with_story_name() {
let (plain, html) = format_blocked_notification(
"425_story_blocking_reason",
Some("Blocking Reason Story"),
"Blocking Reason Story",
"Retry limit exceeded (3/3) at coder stage",
);
assert_eq!(
@@ -414,7 +432,7 @@ mod tests {
#[test]
fn format_blocked_notification_falls_back_to_number() {
let (plain, html) = format_blocked_notification("42_story_thing", None, "empty diff");
let (plain, html) = format_blocked_notification("42_story_thing", "", "empty diff");
assert_eq!(plain, "\u{1f6ab} #42 \u{2014} BLOCKED: empty diff");
assert_eq!(
html,
@@ -424,13 +442,13 @@ mod tests {
#[test]
fn format_blocked_notification_empty_story_name_falls_back_to_number() {
let (plain, _html) = format_blocked_notification("42_story_thing", Some(""), "empty diff");
let (plain, _html) = format_blocked_notification("42_story_thing", "", "empty diff");
assert_eq!(plain, "\u{1f6ab} #42 \u{2014} BLOCKED: empty diff");
}
#[test]
fn format_blocked_notification_unicode_reason() {
let (plain, _html) = format_blocked_notification("3_story_x", Some("X"), "理由:空の差分");
let (plain, _html) = format_blocked_notification("3_story_x", "X", "理由:空の差分");
assert!(plain.contains("BLOCKED: 理由:空の差分"));
}
@@ -439,7 +457,7 @@ mod tests {
#[test]
fn format_rate_limit_notification_includes_agent_and_story() {
let (plain, html) =
format_rate_limit_notification("365_story_my_feature", Some("My Feature"), "coder-2");
format_rate_limit_notification("365_story_my_feature", "My Feature", "coder-2");
assert_eq!(
plain,
"\u{26a0}\u{fe0f} #365 My Feature \u{2014} coder-2 hit an API rate limit"
@@ -452,7 +470,7 @@ mod tests {
#[test]
fn format_rate_limit_notification_falls_back_to_number() {
let (plain, html) = format_rate_limit_notification("42_story_thing", None, "coder-1");
let (plain, html) = format_rate_limit_notification("42_story_thing", "", "coder-1");
assert_eq!(
plain,
"\u{26a0}\u{fe0f} #42 \u{2014} coder-1 hit an API rate limit"
@@ -465,7 +483,7 @@ mod tests {
#[test]
fn format_rate_limit_notification_empty_story_name_falls_back_to_number() {
let (plain, _html) = format_rate_limit_notification("42_story_thing", Some(""), "coder-1");
let (plain, _html) = format_rate_limit_notification("42_story_thing", "", "coder-1");
assert_eq!(
plain,
"\u{26a0}\u{fe0f} #42 \u{2014} coder-1 hit an API rate limit"
@@ -474,7 +492,7 @@ mod tests {
#[test]
fn format_rate_limit_notification_unicode_agent_name() {
let (plain, _html) = format_rate_limit_notification("9_story_foo", Some("Foo"), "агент-1");
let (plain, _html) = format_rate_limit_notification("9_story_foo", "Foo", "агент-1");
assert!(plain.contains("агент-1"));
assert!(plain.contains("hit an API rate limit"));
}
@@ -484,7 +502,7 @@ mod tests {
#[test]
fn format_agent_started_notification_with_story_name() {
let (plain, html) =
format_agent_started_notification("42_story_foo", Some("My Feature"), "coder-1");
format_agent_started_notification("42_story_foo", "My Feature", "coder-1");
assert_eq!(plain, "\u{1F916} #42 My Feature \u{2014} coder-1 started");
assert_eq!(
html,
@@ -494,7 +512,7 @@ mod tests {
#[test]
fn format_agent_started_notification_falls_back_to_number() {
let (plain, html) = format_agent_started_notification("42_story_foo", None, "coder-1");
let (plain, html) = format_agent_started_notification("42_story_foo", "", "coder-1");
assert_eq!(plain, "\u{1F916} #42 \u{2014} coder-1 started");
assert_eq!(
html,
@@ -504,7 +522,7 @@ mod tests {
#[test]
fn format_agent_started_notification_empty_name_falls_back_to_number() {
let (plain, _html) = format_agent_started_notification("42_story_foo", Some(""), "coder-1");
let (plain, _html) = format_agent_started_notification("42_story_foo", "", "coder-1");
assert_eq!(plain, "\u{1F916} #42 \u{2014} coder-1 started");
}
@@ -512,12 +530,8 @@ mod tests {
#[test]
fn format_agent_completed_notification_success_with_story_name() {
let (plain, html) = format_agent_completed_notification(
"42_story_foo",
Some("My Feature"),
"coder-1",
true,
);
let (plain, html) =
format_agent_completed_notification("42_story_foo", "My Feature", "coder-1", true);
assert_eq!(plain, "\u{2705} #42 My Feature \u{2014} coder-1 completed");
assert_eq!(
html,
@@ -527,19 +541,15 @@ mod tests {
#[test]
fn format_agent_completed_notification_failure_with_story_name() {
let (plain, _html) = format_agent_completed_notification(
"42_story_foo",
Some("My Feature"),
"coder-1",
false,
);
let (plain, _html) =
format_agent_completed_notification("42_story_foo", "My Feature", "coder-1", false);
assert_eq!(plain, "\u{274C} #42 My Feature \u{2014} coder-1 failed");
}
#[test]
fn format_agent_completed_notification_falls_back_to_number() {
let (plain, html) =
format_agent_completed_notification("42_story_foo", None, "coder-1", true);
format_agent_completed_notification("42_story_foo", "", "coder-1", true);
assert_eq!(plain, "\u{2705} #42 \u{2014} coder-1 completed");
assert_eq!(
html,
@@ -550,7 +560,7 @@ mod tests {
#[test]
fn format_agent_completed_notification_empty_name_falls_back_to_number() {
let (plain, _html) =
format_agent_completed_notification("42_story_foo", Some(""), "coder-1", false);
format_agent_completed_notification("42_story_foo", "", "coder-1", false);
assert_eq!(plain, "\u{274C} #42 \u{2014} coder-1 failed");
}
}