From 7bf758f421b926b6df5a6b4b82b60d295f1ca94c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Mon, 17 Nov 2025 21:10:28 +0100 Subject: [PATCH] Append link to gitlab to create link between open project and gitlab --- Cargo.lock | 39 +++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/planning/utils.rs | 32 ++++++++++++++++++++++++++++---- src/webext.rs | 20 ++++++++++---------- 4 files changed, 78 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1c031e4..07426af 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,15 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + [[package]] name = "android_system_properties" version = "0.1.5" @@ -180,6 +189,7 @@ dependencies = [ "gitlab", "log", "open", + "regex", "reqwest", "serde", "serde_json", @@ -1155,6 +1165,35 @@ dependencies = [ "getrandom 0.3.4", ] +[[package]] +name = "regex" +version = "1.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" + [[package]] name = "reqwest" version = "0.12.24" diff --git a/Cargo.toml b/Cargo.toml index 6d7d948..092679d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ simple-home-dir = "0.5.2" log = "0.4.28" open = "5.3.2" serde_json = "1.0.145" +regex = "1.12.2" [package.metadata.deb] maintainer = "Julien Fastré " diff --git a/src/planning/utils.rs b/src/planning/utils.rs index ef8dbf4..243264e 100644 --- a/src/planning/utils.rs +++ b/src/planning/utils.rs @@ -65,10 +65,30 @@ fn add_related_issues_section(issue: &IssueRelated) -> Vec { fn convert_issue_link_items(issue: &IssueRelated) -> String { match issue { - IssueRelated::OpenProjectIssue(issue_url) => format!("- [{}]({})", issue_url, issue_url), + IssueRelated::OpenProjectIssue(issue_url) => { + let m = format!("- [{}]({})", issue_url, issue_url); + match extract_id(issue_url) { + Some(n) => format!("{}\n- OP#{}", m, n), + None => m, + } + } } } +use regex::Regex; + +fn extract_id(url: &str) -> Option { + // Cette regex capture le dernier segment numérique si l’URL se termine par : + // - /work_packages/ + // - /wp/ + // Et accepte n'importe quel segment avant. + let re = Regex::new(r"/(?:work_packages|wp)/(\d+)$").unwrap(); + + re.captures(url) + .and_then(|caps| caps.get(1)) + .and_then(|m| m.as_str().parse::().ok()) +} + #[cfg(test)] mod tests { use crate::planning::utils::{append_related_issues, IssueRelated}; @@ -80,7 +100,8 @@ mod tests { r#" ## Related issues -- [https://example/wp/1](https://example/wp/1)"#, +- [https://example/wp/1](https://example/wp/1) +- OP#1"#, append_related_issues(&issue, &("".to_string())) ); } @@ -97,7 +118,8 @@ Some content ## Related issues -- [https://example/wp/1](https://example/wp/1)"#, +- [https://example/wp/1](https://example/wp/1) +- OP#1"#, append_related_issues( &issue, &"Something happens.\n\ @@ -123,7 +145,8 @@ Some content ## Related issues - [https://example/wp/2](https://example/wp/2) -- [https://example/wp/1](https://example/wp/1)"#, +- [https://example/wp/1](https://example/wp/1) +- OP#1"#, append_related_issues( &issue, &r#"Something happens. @@ -154,6 +177,7 @@ Some content - [https://example/wp/2](https://example/wp/2) - [https://example/wp/1](https://example/wp/1) +- OP#1 ## Other content diff --git a/src/webext.rs b/src/webext.rs index e1156cd..112eaf2 100644 --- a/src/webext.rs +++ b/src/webext.rs @@ -172,10 +172,10 @@ mod tests { fn deserializes_issue2work_variant() { // Given: a JSON with the external tag "type" matching the enum variant name let payload = json!({ - "type": "Issue2Work", - "url": "https://example.com/issues/123", - "project": "test" - }); + "type": "Issue2Work", + "url": "https://example.com/issues/123", + "project": "test" + }); // When: deserializing to InputMessage let msg: InputMessage = serde_json::from_value(payload).expect("valid enum JSON"); @@ -192,10 +192,10 @@ mod tests { #[test] fn fails_on_unknown_type_tag() { let payload = json!({ - "type": "Unknown", - "url": "https://example.com/issues/123", - "project": "test" - }); + "type": "Unknown", + "url": "https://example.com/issues/123", + "project": "test" + }); let err = serde_json::from_value::(payload).unwrap_err(); // Basic sanity check that it's a data error mentioning the unrecognized variant @@ -210,8 +210,8 @@ mod tests { fn fails_when_missing_required_fields() { // Missing "url" and "project" let payload = json!({ - "type": "Issue2Work" - }); + "type": "Issue2Work" + }); let err = serde_json::from_value::(payload).unwrap_err(); let msg = err.to_string();