feat: add fetched-at timestamp to markdown header and json meta
This commit is contained in:
@@ -60,6 +60,7 @@ gitea-pr-review render-md --in pr.json --out pr.md
|
||||
# <repo> `#<pr-index>` <pr-title>
|
||||
|
||||
> Numbering: Review `<pr>.<review>`; Comment `<pr>.<review>.<comment>`; Reply `<pr>.<review>.<comment>.<reply>`
|
||||
> fetched at: <fetch-time-rfc3339>
|
||||
|
||||
<pr description>
|
||||
|
||||
|
||||
@@ -60,6 +60,7 @@ gitea-pr-review render-md --in pr.json --out pr.md
|
||||
# <repo> `#<pr-index>` <pr-title>
|
||||
|
||||
> 编号规则:Review `<pr>.<review>`;Comment `<pr>.<review>.<comment>`;Reply `<pr>.<review>.<comment>.<reply>`
|
||||
> fetched at: <fetch-time-rfc3339>
|
||||
|
||||
<pr 描述>
|
||||
|
||||
|
||||
+3
-1
@@ -1,6 +1,7 @@
|
||||
use std::env;
|
||||
use std::path::Path;
|
||||
|
||||
use chrono::Utc;
|
||||
use clap::Parser;
|
||||
|
||||
pub mod cli;
|
||||
@@ -35,7 +36,8 @@ pub fn run() -> anyhow::Result<()> {
|
||||
|
||||
let client = GiteaClient::new(base_url, token);
|
||||
let bundle = client.fetch_pr_bundle(&repo, args.pr_index)?;
|
||||
let doc = normalize_bundle(&repo, bundle);
|
||||
let fetched_at = Utc::now().to_rfc3339();
|
||||
let doc = normalize_bundle(&repo, fetched_at, bundle);
|
||||
|
||||
let rendered = match args.format {
|
||||
OutputFormat::Markdown => render_markdown(&doc),
|
||||
|
||||
@@ -15,6 +15,7 @@ pub struct PrMeta {
|
||||
pub pr_index: i64,
|
||||
pub title: String,
|
||||
pub description: Option<String>,
|
||||
pub fetched_at: Option<String>,
|
||||
pub state: String,
|
||||
pub author: String,
|
||||
pub base_branch: String,
|
||||
|
||||
+2
-1
@@ -9,7 +9,7 @@ use crate::model::{
|
||||
ReviewItem,
|
||||
};
|
||||
|
||||
pub fn normalize_bundle(repo: &str, bundle: PullBundleDto) -> PrReviewDocument {
|
||||
pub fn normalize_bundle(repo: &str, fetched_at: String, bundle: PullBundleDto) -> PrReviewDocument {
|
||||
let PullBundleDto {
|
||||
pull,
|
||||
reviews,
|
||||
@@ -33,6 +33,7 @@ pub fn normalize_bundle(repo: &str, bundle: PullBundleDto) -> PrReviewDocument {
|
||||
pr_index: pull.number,
|
||||
title: pull.title,
|
||||
description: pull.body,
|
||||
fetched_at: Some(fetched_at),
|
||||
state: pull.state,
|
||||
author: pull.user.login,
|
||||
base_branch: pull.base.ref_name,
|
||||
|
||||
@@ -65,6 +65,8 @@ pub fn render_markdown(doc: &PrReviewDocument) -> String {
|
||||
out.push_str(
|
||||
"> 编号规则:Review `<pr>.<review>`;Comment `<pr>.<review>.<comment>`;Reply `<pr>.<review>.<comment>.<reply>`\n\n",
|
||||
);
|
||||
let fetched_at = doc.meta.fetched_at.as_deref().unwrap_or("unknown");
|
||||
out.push_str(&format!("> fetched at: {fetched_at}\n\n"));
|
||||
let pr_description = doc
|
||||
.meta
|
||||
.description
|
||||
|
||||
@@ -13,6 +13,7 @@ fn render_md_reads_json_and_outputs_markdown_to_stdout() {
|
||||
"pr_index": 1,
|
||||
"title": "t",
|
||||
"description": "PR body",
|
||||
"fetched_at": "2026-04-08T12:34:56Z",
|
||||
"state": "open",
|
||||
"author": "a",
|
||||
"base_branch": "main",
|
||||
@@ -56,6 +57,7 @@ fn render_md_writes_to_out_file_when_requested() {
|
||||
"pr_index": 2,
|
||||
"title": "t2",
|
||||
"description": "PR body",
|
||||
"fetched_at": "2026-04-08T12:34:56Z",
|
||||
"state": "open",
|
||||
"author": "a",
|
||||
"base_branch": "main",
|
||||
@@ -220,6 +222,7 @@ fn fetch_writes_markdown_to_stdout_by_default() {
|
||||
|
||||
let stdout = String::from_utf8(assert.get_output().stdout.clone()).unwrap();
|
||||
assert!(stdout.contains("# org/repo `#7` Fix parser"));
|
||||
assert!(stdout.contains("> fetched at: "));
|
||||
assert!(stdout.contains("## Commits"));
|
||||
assert!(stdout.contains("## Diff Stat"));
|
||||
assert!(stdout.contains("## Review 7.1 (COMMENT)"));
|
||||
@@ -288,5 +291,6 @@ fn fetch_writes_json_to_out_file_when_requested() {
|
||||
let written = std::fs::read_to_string(output.path()).unwrap();
|
||||
assert!(written.contains("\"repo\": \"org/repo\""));
|
||||
assert!(written.contains("\"pr_index\": 8"));
|
||||
assert!(written.contains("\"fetched_at\":"));
|
||||
assert!(written.contains("\"head_branch\": \"feature/y\""));
|
||||
}
|
||||
|
||||
@@ -141,10 +141,11 @@ fn normalize_groups_replies_and_sorts_threads_by_time() {
|
||||
],
|
||||
};
|
||||
|
||||
let doc = normalize_bundle("org/repo", bundle);
|
||||
let doc = normalize_bundle("org/repo", "2026-04-08T12:34:56Z".into(), bundle);
|
||||
|
||||
assert_eq!(doc.meta.repo, "org/repo");
|
||||
assert_eq!(doc.meta.pr_index, 42);
|
||||
assert_eq!(doc.meta.fetched_at.as_deref(), Some("2026-04-08T12:34:56Z"));
|
||||
assert_eq!(doc.meta.base_branch, "main");
|
||||
assert_eq!(doc.meta.head_branch, "feature/x");
|
||||
|
||||
@@ -241,7 +242,7 @@ fn normalize_does_not_merge_unrelated_comments_on_same_file() {
|
||||
files: vec![],
|
||||
};
|
||||
|
||||
let doc = normalize_bundle("org/repo", bundle);
|
||||
let doc = normalize_bundle("org/repo", "2026-04-08T12:34:56Z".into(), bundle);
|
||||
|
||||
assert_eq!(doc.threads.len(), 2);
|
||||
assert_eq!(doc.threads[0].root_comment.id, 10);
|
||||
@@ -297,7 +298,7 @@ fn normalize_uses_non_zero_position_when_line_is_missing() {
|
||||
files: vec![],
|
||||
};
|
||||
|
||||
let doc = normalize_bundle("org/repo", bundle);
|
||||
let doc = normalize_bundle("org/repo", "2026-04-08T12:34:56Z".into(), bundle);
|
||||
assert_eq!(doc.threads.len(), 1);
|
||||
assert_eq!(doc.threads[0].root_comment.path.as_deref(), Some("src/main.rs"));
|
||||
assert_eq!(doc.threads[0].root_comment.line, Some(41));
|
||||
|
||||
@@ -10,6 +10,7 @@ fn model_json_roundtrip() {
|
||||
pr_index: 9,
|
||||
title: "feat: x".into(),
|
||||
description: Some("desc".into()),
|
||||
fetched_at: Some("2026-04-08T12:34:56Z".into()),
|
||||
state: "open".into(),
|
||||
author: "alice".into(),
|
||||
base_branch: "main".into(),
|
||||
@@ -50,5 +51,6 @@ fn model_json_roundtrip() {
|
||||
let encoded = serde_json::to_string(&doc).unwrap();
|
||||
let decoded: PrReviewDocument = serde_json::from_str(&encoded).unwrap();
|
||||
assert_eq!(decoded.meta.repo, "org/repo");
|
||||
assert_eq!(decoded.meta.fetched_at.as_deref(), Some("2026-04-08T12:34:56Z"));
|
||||
assert_eq!(decoded.threads[0].root_comment.body, "hello");
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ fn render_markdown_includes_expected_sections_and_preserves_comment_markdown() {
|
||||
pr_index: 7,
|
||||
title: "Fix parser".into(),
|
||||
description: Some("PR body".into()),
|
||||
fetched_at: Some("2026-04-08T12:34:56Z".into()),
|
||||
state: "open".into(),
|
||||
author: "alice".into(),
|
||||
base_branch: "main".into(),
|
||||
@@ -72,6 +73,7 @@ fn render_markdown_includes_expected_sections_and_preserves_comment_markdown() {
|
||||
|
||||
assert!(md.contains("# org/repo `#7` Fix parser"));
|
||||
assert!(md.contains("## Metadata"));
|
||||
assert!(md.contains("> fetched at: 2026-04-08T12:34:56Z"));
|
||||
assert!(md.contains("## Commits"));
|
||||
assert!(md.contains("## Diff Stat"));
|
||||
assert!(md.contains("> 编号规则:Review `<pr>.<review>`;Comment `<pr>.<review>.<comment>`;Reply `<pr>.<review>.<comment>.<reply>`"));
|
||||
@@ -99,6 +101,7 @@ fn render_markdown_uses_minimal_fence_for_plain_text() {
|
||||
pr_index: 1,
|
||||
title: "T".into(),
|
||||
description: None,
|
||||
fetched_at: None,
|
||||
state: "open".into(),
|
||||
author: "alice".into(),
|
||||
base_branch: "main".into(),
|
||||
|
||||
Reference in New Issue
Block a user