Skip to content

Commit 51faa83

Browse files
authored
Merge pull request #2062 from vivekjami/add-team-and-alumni-name-check
Add validation for duplicate team entries
2 parents 2d2858e + c318366 commit 51faa83

File tree

2 files changed

+66
-0
lines changed

2 files changed

+66
-0
lines changed

src/schema.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,10 @@ impl Team {
529529
self.people.alumni.as_ref().map_or(&[], Vec::as_slice)
530530
}
531531

532+
pub(crate) fn explicit_leads(&self) -> &[String] {
533+
&self.people.leads
534+
}
535+
532536
pub(crate) fn contains_person(&self, data: &Data, person: &Person) -> Result<bool, Error> {
533537
let members = self.members(data)?;
534538
Ok(members.contains(person.github()))

src/validate.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ static CHECKS: &[Check<fn(&Data, &mut Vec<String>)>] = checks![
2828
validate_subteam_of,
2929
validate_team_leads,
3030
validate_team_members,
31+
validate_duplicate_team_entries,
3132
validate_alumni,
3233
validate_archived_teams,
3334
validate_inactive_members,
@@ -240,6 +241,67 @@ fn validate_team_members(data: &Data, errors: &mut Vec<String>) {
240241
});
241242
}
242243

244+
/// Helper for checking duplicates in a list
245+
fn check_duplicates<'a, I>(team_name: &str, label: &str, items: I) -> Result<(), Error>
246+
where
247+
I: IntoIterator<Item = &'a str>,
248+
{
249+
let mut seen = HashSet::new();
250+
let mut duplicates = HashSet::new();
251+
252+
for item in items {
253+
if !seen.insert(item) {
254+
duplicates.insert(item);
255+
}
256+
}
257+
258+
if !duplicates.is_empty() {
259+
let dup_list: Vec<&str> = duplicates.into_iter().collect();
260+
bail!(
261+
"team `{}` has duplicate {}: {}",
262+
team_name,
263+
label,
264+
dup_list.join(", ")
265+
);
266+
}
267+
268+
Ok(())
269+
}
270+
271+
/// Ensure no duplicate entries in team leads, members and alumni
272+
fn validate_duplicate_team_entries(data: &Data, errors: &mut Vec<String>) {
273+
wrapper(data.teams(), errors, |team, errors| {
274+
// Check leads for duplicates
275+
if let Err(e) = check_duplicates(
276+
team.name(),
277+
"leads",
278+
team.explicit_leads().iter().map(|s| s.as_str()),
279+
) {
280+
errors.push(e.to_string());
281+
}
282+
283+
// Check members for duplicates
284+
if let Err(e) = check_duplicates(
285+
team.name(),
286+
"members",
287+
team.explicit_members().iter().map(|m| m.github.as_str()),
288+
) {
289+
errors.push(e.to_string());
290+
}
291+
292+
// Check alumni for duplicates
293+
if let Err(e) = check_duplicates(
294+
team.name(),
295+
"alumni",
296+
team.explicit_alumni().iter().map(|a| a.github.as_str()),
297+
) {
298+
errors.push(e.to_string());
299+
}
300+
301+
Ok(())
302+
});
303+
}
304+
243305
/// Alumni team must consist only of automatically populated alumni from the other teams
244306
fn validate_alumni(data: &Data, errors: &mut Vec<String>) {
245307
let Some(alumni_team) = data.team("alumni") else {

0 commit comments

Comments
 (0)