gws: add diff for google accounts#2445
Conversation
Dry-run check results |
|
If you are changing the data structures, please make sure that the changes are not going to break serde deserialization (adding a field is fine; removing or renaming a field isn't). If you must do a breaking change to the format, make sure to coordinate it with all the users of the |
| } | ||
| } | ||
| "google-workspace" => { | ||
| println!("Nothing to diff"); |
There was a problem hiding this comment.
| println!("Nothing to diff"); | |
| println!("google-workspace: Nothing to diff"); |
Otherwise, CI will print just "Nothing to diff" and that's confusing.
Btw I assume the diff itself will be implemented in a later PR 👍
There was a problem hiding this comment.
Indeed, but happy to change it to make it clear
| pub is_lead: bool, | ||
| #[serde(skip_serializing_if = "Vec::is_empty", default)] | ||
| pub roles: Vec<String>, | ||
| pub google_workspace: Option<GoogleWorkspace>, |
There was a problem hiding this comment.
| pub google_workspace: Option<GoogleWorkspace>, | |
| #[serde(skip_serializing_if = "Option::is_none")] | |
| pub google_workspace: Option<GoogleWorkspace>, |
Otherwise the response contains "google_workspace": null
| .filter_map(|team| match team.google_workspace_saml_group { | ||
| None => None, | ||
| Some(opt_in) => { | ||
| if opt_in { | ||
| Some(&team.members) | ||
| } else { | ||
| None | ||
| } | ||
| } | ||
| }) | ||
| .flatten() |
There was a problem hiding this comment.
| .filter_map(|team| match team.google_workspace_saml_group { | |
| None => None, | |
| Some(opt_in) => { | |
| if opt_in { | |
| Some(&team.members) | |
| } else { | |
| None | |
| } | |
| } | |
| }) | |
| .flatten() | |
| .filter(|team| team.google_workspace_saml_group.unwrap_or_default()) | |
| .flat_map(|team| &team.members) |
obtained by just asking codex 5.5 low reasoning "make this more idiomatic"
| pub struct GoogleWorkspace { | ||
| pub name: String, | ||
| pub surname: String, | ||
| pub account_handle: String, |
There was a problem hiding this comment.
why do we have a mismatch between these fields and the fields in the schema?
Isn't it easier if we call them the same? 🤔
There was a problem hiding this comment.
No particular reason, I can make them equal for simplicity! :)
| GoogleWorkspace { | ||
| name: gws.first_name, | ||
| surname: gws.last_name, | ||
| account_handle: gws.account_handle, |
There was a problem hiding this comment.
this code is duplicated from above. Maybe we can have a From implementation or something like this?
| github_id: person.github_id(), | ||
| is_lead: leads.contains(github_name), | ||
| roles: website_roles.get(*github_name).cloned().unwrap_or_default(), | ||
| google_workspace: person.google_workspace().clone().map(|gws| { |
There was a problem hiding this comment.
I noticed that the function google_workspace() returns &Option<Something>, but Option<&Something> is more idiomatic.
We could change the function like this:
pub(crate) fn google_workspace(&self) -> Option<&GoogleWorkspace> {
self.google_workspace.as_ref()
}
| users.iter().any(|account| account.primary_email == email) | ||
| } | ||
|
|
||
| fn matches_by_saml_group(&self, target: &Group, groups: &[Group]) -> bool { |
| let declared_users = members_from_gws_enabled_teams | ||
| .iter() | ||
| .filter_map(|member| member.google_workspace.as_ref().map(User::from)) | ||
| .collect::<Vec<_>>(); |
There was a problem hiding this comment.
| let declared_users = members_from_gws_enabled_teams | |
| .iter() | |
| .filter_map(|member| member.google_workspace.as_ref().map(User::from)) | |
| .collect::<Vec<_>>(); | |
| let mut seen_primary_emails = BTreeSet::new(); | |
| let declared_users = members_from_gws_enabled_teams | |
| .iter() | |
| .filter_map(|member| member.google_workspace.as_ref().map(User::from)) | |
| .filter(|user| seen_primary_emails.insert(user.primary_email.clone())) | |
| .collect::<Vec<_>>(); |
Should we deduplicated by some kind of criteria (eg email)?
So that we don't try to create users multiple times?
There was a problem hiding this comment.
I did not focused on dedup because, in practice, the number of users will be quite small (~ 30 after everyone onboarded). But happy to try a better approach. Commit to follow
First PR to enable diffs betwen our configuration and Google Workspace state.
The whole feature would be a much bigger PR, so I decided to split it. This PR looks big but it brings a non negletable amount of boilterplate, so hopefully it is not hard to read. I hope the code style is familiar enough compared with other services we also diff and sync.
For now, this PR adds support for diffing google workspace users, supporting
creationanddeletionoperations. Everything is still detached from the app entrypoint, and integration will come after we are able to run live dry-runs in CI (which requires further configuration on Github Actions).To make it sure we can define and safely test some rules we want to encode as part of the diff logic, I added a fake GWS API similar approach similar to what we use in
github.Towards #2363