Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add functionality to sync org members on GitHub #91

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

me-diru
Copy link

@me-diru me-diru commented Oct 31, 2024

Fixes #84

  • Added GitHub api functionality to list all org members and remove members from a GitHub org
  • Created a new Diff called OrgMembershipDiff to deal with difference on GitHub and toml members in teams.

@me-diru
Copy link
Author

me-diru commented Oct 31, 2024

Right now, the PR is incomplete, and I wanted to check in with you, @marcoieni, to see if I was going in the right direction.

I made a new Diff against teams as suggested. Many thanks for the notes. They helped me understand the task well!

I am not sure about the tests checking the debugging output, but I also took a stab at it. I would really appreciate your input and feedback :D

@@ -219,6 +233,16 @@ impl GithubRead for GithubMock {
.collect())
}

fn org_members(&self, org: &str) -> anyhow::Result<HashSet<u64>> {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

most of it, I took inspiration from org_owners

.expect("Team Not Found");
team_org = github_team.org.clone();
} else {
team_org = "rust_lang".to_string();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why this value?
Should we report an error if the team doesn't have any associated org?
Also the rust org is called "rust-lang"


for toml_team_member in toml_team_members {
if gh_org_members.contains(&toml_team_member.github_id.clone()) {
members_to_be_removed.insert(toml_team_member.github.clone());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doesn't this remove all members from the org?

@marcoieni
Copy link
Member

marcoieni commented Oct 31, 2024

The general direction looks great 👍👍👍
Imo you are very close 😃

@@ -189,6 +196,48 @@ impl SyncGitHub {
Ok(diffs)
}

fn diff_toml_teams(&self) -> anyhow::Result<Vec<OrgMembershipDiff>> {
Copy link
Contributor

@Kobzol Kobzol Oct 31, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that it would be simpler and more robust implementation would be to do this instead:

  1. Go through all teams and gather a set of all team members for each org that we find (so essentially a HashMap<Org, HashSet<u64>>)
  2. Go through each org, and do a set difference between its members and the team members found in 1). Users that come out of this operation (those that are not in the team) should be stored in the OrgMembershipDiff

@marcoieni
Copy link
Member

marcoieni commented Nov 15, 2024

Hey Rohit, do you still plan to work on this?
No pressure, you already did great progress.
I just wanted to check to know if we should reassign the issue 👍

@me-diru
Copy link
Author

me-diru commented Nov 15, 2024

Hey @marcoieni !

Sorry for disappearing. I will work on it over the weekend and get it past the finish line :D Appreciate your patience !

@marcoieni
Copy link
Member

No worries, thanks 😁

@me-diru me-diru force-pushed the sync-org-mems branch 4 times, most recently from b657699 to 470218d Compare November 24, 2024 07:07
model.create_team(TeamData::new("team-1").gh_team("members-gh", &[user, user2]));
let gh = model.gh_model();

// let gh_members = gh.org_members("rust-lang").unwrap();
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not able to get the gh_members, it returns an empty hashset

@me-diru me-diru marked this pull request as ready for review November 24, 2024 07:12
@me-diru me-diru changed the title [WIP] Add functionality to sync org members on GitHub Add functionality to sync org members on GitHub Nov 24, 2024
@me-diru me-diru requested review from marcoieni and Kobzol November 24, 2024 07:15
Copy link
Contributor

@Kobzol Kobzol left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for making the changes! Left a bunch of comments, mostly refactoring and some logic changes.

.expect("Team Not Found");
team_org = github_team.org.clone();
} else {
return Err(anyhow!(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should not be an error, some Rust teams simply don't have any GitHub team attached.

// get the team github org through the corresponding github team
if let Some(gh) = &team.github {
let github_teams = &gh.teams;
let github_team: &GitHubTeam = github_teams
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to go through all teams, not just ones that have the same name. You can see the structure here, take a look at the [[github]] section. You can see how you can iterate through every GitHub tam in diff_teams.

Copy link
Author

@me-diru me-diru Dec 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the feedback. I thought we have to go through all the toml teams first as per the notes by @marcoieni and then find the corresponding GitHubTeam and it's organisation through that.

I am not sure how to map the GitHub org to a respective toml team in a different way.

We could go through all the teams in TeamGitHub but if there are no corresponding toml team with the same name, I don't think it helps to go through all the teams.

Copy link
Contributor

@Kobzol Kobzol Dec 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that this was an error in the original description. Note that TeamGithub has nothing to do with the GitHub API. It's a representation of a GH team described in a TOML file. You can find that out easily from the fact that the corresponding data structure (TeamGitHub) is from the rust_team_data::v1 module. Everything that comes from this module is derived from the TOML files.

The logic should be something like this:

  1. Go through all TOML teams (v1::Team)
  2. For each TOML team, go through all its TOML GitHub teams (GitHubTeam)
  3. For each TOML GitHub team, add its members to the corresponding organization in org_team_members

src/github/mod.rs Show resolved Hide resolved
for (gh_org, toml_members_across_teams) in org_team_members.into_iter() {
let gh_org_members = self.org_members.get(&gh_org).unwrap();

let mut members_to_be_removed = HashSet::new();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about this?

let members_to_be_removed = (gh_org_members - &toml_members_across_teams)
                .into_iter()
                .map(|user| self.usernames_cache[&user].clone())
                .collect::<HashSet<String>>();

src/github/mod.rs Show resolved Hide resolved
.get_team("team-1")
.remove_gh_member("members-gh", user);

let gh_org_diff = model.diff_teams_gh_org(gh, gh_members);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function should only receive gh, not any additional parameters. The logic here is not fully correct, as you're passing GH members, but the function should diff team (TOML) members. The list of member should be taken from the GithubMock.


if let Some(gh) = &team.github {
for toml_gh_team in &gh.teams {
team_org = toml_gh_team.org.clone();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
team_org = toml_gh_team.org.clone();
let team_org = toml_gh_team.org.clone();

No need to have the variable in the external scope now :)

for (gh_org, toml_members_across_teams) in org_team_members.into_iter() {
let gh_org_members = self.org_members.get(&gh_org).unwrap();

let members_to_be_removed = (&toml_members_across_teams - gh_org_members)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's the other way around, we want to remove users (from GitHub) that are currently on GitHub, but are not in the TOML teams.

Suggested change
let members_to_be_removed = (&toml_members_across_teams - gh_org_members)
let members_to_be_removed = (gh_org_members - &toml_members_across_teams)


let org_team_members = sync.map_teams_to_org().unwrap();

sync.diff_teams_gh_org(org_team_members)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test won't work yet, because our test API is not finished yet and this uses the unfinished parts. We need to properly track GH users and GH org members in GithubMock, which doesn't happen currently :( I will work on it and send a PR so that you can write the test and check it locally

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Remove users without a team from GitHub
3 participants