Skip to content

Commit f2ce679

Browse files
committed
command to synchronize team-repository
1 parent 51001ca commit f2ce679

File tree

5 files changed

+146
-5
lines changed

5 files changed

+146
-5
lines changed

mdbook-goals/src/main.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ mod mdbook_preprocessor;
1212
mod re;
1313
mod rfc;
1414
mod team;
15+
mod team_repo;
1516
mod util;
1617

1718
#[derive(StructOpt, Debug)]
@@ -51,6 +52,17 @@ enum Command {
5152
commit: bool,
5253
},
5354

55+
/// Generate the project-goal-owners team based on the owners found in `paths`.
56+
TeamRepo {
57+
/// Paths to the directories containing the goals (e.g., `src/2024h2`)
58+
#[structopt(required = true, min_values = 1)]
59+
path: Vec<PathBuf>,
60+
61+
/// Paths to the teams repository checkout
62+
#[structopt(required = true, long = "team-repo")]
63+
team_repo_path: PathBuf,
64+
},
65+
5466
/// Checks that the goal documents are well-formed, intended for use within CI
5567
Check {},
5668
}
@@ -83,6 +95,13 @@ fn main() -> anyhow::Result<()> {
8395
rfc::generate_issues(&opt.repository, path, *commit, *sleep)?;
8496
}
8597

98+
Some(Command::TeamRepo {
99+
path,
100+
team_repo_path,
101+
}) => {
102+
team_repo::generate_team_repo(&path, team_repo_path)?;
103+
}
104+
86105
None => {
87106
handle_preprocessing(&GoalPreprocessor)?;
88107
}

mdbook-goals/src/mdbook_preprocessor.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ impl<'c> GoalPreprocessorWithContext<'c> {
314314
}
315315

316316
let display_name = match team::get_person_data(username)? {
317-
Some(person) => person.name.clone(),
317+
Some(person) => person.data.name.clone(),
318318
None => match GithubUserInfo::load(username)
319319
.with_context(|| format!("loading user info for {}", username))
320320
{

mdbook-goals/src/rfc.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use core::time;
21
use std::{
32
collections::BTreeSet,
43
fmt::Display,

mdbook-goals/src/team.rs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,31 @@ impl<T> Load<T> for OnceLock<anyhow::Result<T>> {
1616
}
1717
}
1818

19+
pub struct PersonData {
20+
/// NB: May be capitalized differently than what we get as input
21+
pub github_username: String,
22+
23+
/// Data from the Rust team repo
24+
pub data: v1::Person,
25+
}
26+
1927
/// Given a username like `@foo` finds the corresponding person data (if any).
20-
pub fn get_person_data(username: &str) -> anyhow::Result<Option<&'static v1::Person>> {
21-
static DATA: OnceLock<anyhow::Result<BTreeMap<String, v1::Person>>> = OnceLock::new();
28+
pub fn get_person_data(username: &str) -> anyhow::Result<Option<&'static PersonData>> {
29+
static DATA: OnceLock<anyhow::Result<BTreeMap<String, PersonData>>> = OnceLock::new();
2230
let people = DATA.load(|| {
2331
let data: v1::People = fetch("people.json")?;
2432
Ok(data
2533
.people
2634
.into_iter()
27-
.map(|(username, value)| (username.to_lowercase(), value))
35+
.map(|(username, value)| {
36+
(
37+
username.to_lowercase(),
38+
PersonData {
39+
github_username: username,
40+
data: value,
41+
},
42+
)
43+
})
2844
.collect())
2945
})?;
3046

mdbook-goals/src/team_repo.rs

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
use std::collections::BTreeSet;
2+
use std::fmt::Write;
3+
use std::process::Command;
4+
5+
use anyhow::Context;
6+
7+
use crate::{goal, team};
8+
9+
pub(crate) fn generate_team_repo(
10+
paths: &[std::path::PathBuf],
11+
team_repo_path: &std::path::PathBuf,
12+
) -> anyhow::Result<()> {
13+
if !team_repo_path.is_dir() {
14+
anyhow::bail!(
15+
"output path not a directory: `{}`",
16+
team_repo_path.display()
17+
);
18+
}
19+
20+
let mut goal_documents = vec![];
21+
for path in paths {
22+
goal_documents.extend(goal::goals_in_dir(path)?);
23+
}
24+
25+
let owners: BTreeSet<&str> = goal_documents
26+
.iter()
27+
.flat_map(|doc| doc.metadata.owner_usernames())
28+
.collect();
29+
30+
progress_bar::init_progress_bar(owners.len() + 1);
31+
32+
progress_bar::set_progress_bar_action(
33+
"Team file",
34+
progress_bar::Color::Blue,
35+
progress_bar::Style::Bold,
36+
);
37+
let team_file = team_file(&owners)?;
38+
let team_toml_file = team_repo_path.join("teams").join("goal-owners.toml");
39+
std::fs::write(&team_toml_file, team_file)
40+
.with_context(|| format!("writing to `{}`", team_toml_file.display()))?;
41+
progress_bar::inc_progress_bar();
42+
43+
// generate rudimentary people files if needed
44+
progress_bar::set_progress_bar_action(
45+
"People",
46+
progress_bar::Color::Blue,
47+
progress_bar::Style::Bold,
48+
);
49+
for owner in owners {
50+
ensure_person_file(owner, team_repo_path)?;
51+
progress_bar::inc_progress_bar();
52+
}
53+
54+
progress_bar::finalize_progress_bar();
55+
56+
Ok(())
57+
}
58+
59+
fn ensure_person_file(owner: &str, team_repo_path: &std::path::PathBuf) -> anyhow::Result<()> {
60+
let person_toml_file = team_repo_path
61+
.join("people")
62+
.join(&owner[1..])
63+
.with_extension("toml");
64+
65+
if person_toml_file.exists() {
66+
return Ok(());
67+
}
68+
69+
if team::get_person_data(owner)?.is_some() {
70+
return Ok(()); // person already exists
71+
}
72+
73+
let status = Command::new("cargo")
74+
.arg("run")
75+
.arg("-q")
76+
.arg("--")
77+
.arg("add-person")
78+
.arg(&owner[1..])
79+
.current_dir(team_repo_path)
80+
.status()
81+
.with_context(|| format!("running `cargo run add-person` for {owner}"))?;
82+
83+
if !status.success() {
84+
anyhow::bail!("`cargo run add-person` failed for {owner}");
85+
}
86+
87+
Ok(())
88+
}
89+
90+
fn team_file(owners: &BTreeSet<&str>) -> anyhow::Result<String> {
91+
let mut out = String::new();
92+
writeln!(out, "name = \"goal-owners\"")?;
93+
writeln!(out, "kind = \"marker-team\"")?;
94+
writeln!(out, "")?;
95+
writeln!(out, "[people]")?;
96+
writeln!(out, "leads = []")?;
97+
writeln!(out, "members = [")?;
98+
for owner in owners {
99+
match team::get_person_data(owner)? {
100+
Some(p) => writeln!(out, " \"{}\",", &p.github_username)?,
101+
None => writeln!(out, " \"{}\",", &owner[1..])?,
102+
}
103+
}
104+
writeln!(out, "]")?;
105+
writeln!(out, "included-teams = []")?;
106+
Ok(out)
107+
}

0 commit comments

Comments
 (0)