AI generated program that reports project and user story status
Some checks failed
Monorepo build / build-flake (push) Has been cancelled
Some checks failed
Monorepo build / build-flake (push) Has been cancelled
This commit is contained in:
parent
c1d65862a6
commit
c014c5eeba
28
Cargo.lock
generated
28
Cargo.lock
generated
@ -3118,6 +3118,15 @@ version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "scripts"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_yaml",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "security-framework"
|
||||
version = "2.11.1"
|
||||
@ -3259,6 +3268,19 @@ dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_yaml"
|
||||
version = "0.9.34+deprecated"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
"unsafe-libyaml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha1"
|
||||
version = "0.10.6"
|
||||
@ -3927,6 +3949,12 @@ version = "1.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
|
||||
|
||||
[[package]]
|
||||
name = "unsafe-libyaml"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861"
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.5.7"
|
||||
|
||||
@ -23,6 +23,7 @@ members = [
|
||||
# "hex-grid",
|
||||
# "icon-test",
|
||||
"l10n-db",
|
||||
"planning/scripts",
|
||||
# "memorycache",
|
||||
# "nom-training",
|
||||
# "otg/core",
|
||||
|
||||
@ -20,6 +20,10 @@ tasks:
|
||||
cmds:
|
||||
- cargo clippy
|
||||
|
||||
report:
|
||||
cmds:
|
||||
- cargo run --bin planning-report planning/
|
||||
|
||||
test-all:
|
||||
cmds:
|
||||
- which cargo
|
||||
@ -31,4 +35,5 @@ tasks:
|
||||
- cargo test -p l10n-db
|
||||
- cargo test -p memorycache
|
||||
- cd visions/server && task test
|
||||
- cd visions/visions-core && task test
|
||||
- cd visions/ui && task test
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
---
|
||||
id: US0000
|
||||
id: US0006
|
||||
type: userstory
|
||||
status: Done
|
||||
priority: P0
|
||||
|
||||
13
planning/scripts/Cargo.toml
Normal file
13
planning/scripts/Cargo.toml
Normal file
@ -0,0 +1,13 @@
|
||||
[package]
|
||||
name = "scripts"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
serde.workspace = true
|
||||
serde_yaml = "0.9.34"
|
||||
walkdir = "2.5.0"
|
||||
|
||||
[[bin]]
|
||||
name = "planning-report"
|
||||
path = "src/main.rs"
|
||||
74
planning/scripts/src/main.rs
Normal file
74
planning/scripts/src/main.rs
Normal file
@ -0,0 +1,74 @@
|
||||
use serde::Deserialize;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
ffi::OsStr,
|
||||
fs,
|
||||
path::{Component, Path},
|
||||
};
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct FrontMatter {
|
||||
id: String,
|
||||
#[serde(rename = "type")]
|
||||
item_type: String,
|
||||
status: String,
|
||||
story: Option<String>, // Only for tasks
|
||||
}
|
||||
|
||||
fn main() -> std::io::Result<()> {
|
||||
let planning_dir = std::env::args().skip(1).next().unwrap();
|
||||
let mut user_stories: HashMap<String, Vec<String>> = HashMap::new();
|
||||
|
||||
// Traverse the planning directory
|
||||
for entry in walkdir::WalkDir::new(planning_dir) {
|
||||
let entry = entry?;
|
||||
if entry.file_type().is_file() && !is_template(entry.path()) && is_markdown(entry.path()) {
|
||||
let content = fs::read_to_string(entry.path())?;
|
||||
if let Some(frontmatter) = extract_frontmatter(&content) {
|
||||
if frontmatter.item_type == "userstory" && frontmatter.status != "Done" {
|
||||
user_stories.entry(frontmatter.id.clone()).or_insert(vec![]);
|
||||
} else if frontmatter.item_type == "task" && frontmatter.status != "Done" {
|
||||
if let Some(story_id) = frontmatter.story {
|
||||
user_stories
|
||||
.entry(story_id)
|
||||
.or_insert(vec![])
|
||||
.push(frontmatter.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generate the report
|
||||
println!("Open User Stories Report:");
|
||||
for (story, tasks) in &user_stories {
|
||||
println!("\nUser Story: {}", story);
|
||||
if tasks.is_empty() {
|
||||
println!(" No open tasks.");
|
||||
} else {
|
||||
println!(" Open Tasks:");
|
||||
for task in tasks {
|
||||
println!(" - {}", task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn is_template(path: &Path) -> bool {
|
||||
path.components()
|
||||
.find(|component| *component == Component::Normal(OsStr::new("Templates")))
|
||||
.is_some()
|
||||
}
|
||||
|
||||
fn is_markdown(path: &Path) -> bool {
|
||||
path.extension().and_then(|s| s.to_str()) == Some("md")
|
||||
}
|
||||
|
||||
fn extract_frontmatter(content: &str) -> Option<FrontMatter> {
|
||||
let start = content.find("---")?;
|
||||
let end = content[start + 3..].find("---")? + start + 3;
|
||||
let yaml = &content[start + 3..end];
|
||||
serde_yaml::from_str(yaml).ok()
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user