Skip to content

Commit

Permalink
Merge pull request #13 from arnica-ext/master
Browse files Browse the repository at this point in the history
Codeowners teams bug fix and distinct PR approvers
  • Loading branch information
nir-valtman authored Dec 28, 2021
2 parents 79d667e + 4643988 commit 58c097f
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 23 deletions.
15 changes: 11 additions & 4 deletions config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,6 @@ members:
- Chamomile-push
- Echinacea-pull
- Calendula-push

days_since_last_commit: []
- member_id: 90470369
login: archiet-gg
Expand All @@ -149,7 +148,7 @@ members:
- repo: Lavender
days: 14
branch: feature_L01
create_pr: True
create_pr: False
- repo: Chamomile
days: 0
branch: feature_C01
Expand Down Expand Up @@ -180,7 +179,11 @@ members:
create_pr: False
- repo: Lavender
days: 5
branch: feature_L02
branch: feature_L02a
create_pr: True
- repo: Lavender
days: 20
branch: feature_L02b
create_pr: True
- member_id: 90473779
login: codeyf-gg
Expand All @@ -202,7 +205,11 @@ members:
create_pr: True
- repo: Chamomile
days: 0
branch: feature_C03
branch: feature_C03a
create_pr: True
- repo: Chamomile
days: 14
branch: feature_C03b
create_pr: True
- repo: Calendula
days: 95
Expand Down
53 changes: 38 additions & 15 deletions run.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ async def create_repos(config, org):
await r.delete_existing_repos()
for repo_name in tqdm(config.repo_names, desc='Repos'):
await r.create(repo_name)
#logging.info(f'Created repository {repo_name} in org {org}.')
logging.info(f'Cloning GitGoat and pushing to org {org}.')
await r.clone_gitgoat()

Expand All @@ -54,7 +53,6 @@ async def create_teams(config, org):
for gp in repo['group_postfixes']:
await t.create(f'{repo["repo"]}-{gp}', [f'{org}/{repo["repo"]}'])
await t.add_repository_permission(f'{repo["repo"]}-{gp}', f'{org}/{repo["repo"]}', gp)
#logging.info(f'Created the team {repo["repo"]}-{gp} and added the permission {gp} to repo {org}/{repo["repo"]}')
for member in config.members:
if (f'{repo["repo"]}-{gp}' in member['member_of_groups']):
await t.add_member(f'{repo["repo"]}-{gp}',member['login'])
Expand All @@ -68,14 +66,12 @@ async def accept_invitations(config, org):
for member in tqdm(config.members, desc='Members'):
token = member['token'] if 'ghp_' in member['token'] else 'ghp_' + member['token']
await m.accept_invitation_to_org(token)
#logging.info(f'The user {member["login"]} accepted the invitation to join {org}')

async def add_direct_permissions(config, org):
dp = DirectPermission(org, config.filename)
for member in tqdm(config.members, desc='Direct Permission'):
if 'gitgoat_repo_permission' in member:
await dp.add_repository_permission('GitGoat',member['login'],member['gitgoat_repo_permission'])
#logging.info(f'The permission{member["gitgoat_repo_permission"]} is granted to user {member["login"]} in repo GitGoat in org {org}')

async def setup_actions(config, org):
a = Actions(org, config.filename)
Expand All @@ -101,7 +97,7 @@ async def configure_codeowners(config, org):
r = Repository(org, config.filename)
for repo_name in tqdm(config.repo_names, desc='CODEOWNERS'):
repo = await r.clone(repo_name, 'GitGoat', Config.get_pat(), 'GitGoat@gitgoat.tools')
co = CodeOwners(repo_name, repo, config.filename)
co = CodeOwners(org,repo_name, repo, config.filename)
filename = await co.generate_file()
await co.push_file(filename)

Expand All @@ -121,29 +117,53 @@ async def create_commits(config, org):
r = Repository(org, config.filename)
pr = PullRequest(org, config.filename)
for member in config.members:
token = member['token'] if 'ghp_' in member['token'] else 'ghp_' + member['token']
for commit_details in tqdm(member['days_since_last_commit'], desc=f'Commits for {member["login"]}'):
token = member['token'] if 'ghp_' in member['token'] else 'ghp_' + member['token']
repo = await r.clone(commit_details['repo'], member['login'], token, member['email'], commit_details['branch'])
c = Commit(repo)
c.generate_commits(50, commit_details['days'])
c.generate_commits(25, commit_details['days'])
if commit_details['create_pr']:
await pr.create_pull_request(token, commit_details['repo'], commit_details['branch'])
#logging.info(f'Created a PR by {member["login"]} from branch {commit_details["branch"]}')

async def review_pull_requests(config, org):
pr = PullRequest(org, config.filename)
for member in tqdm(config.members, desc=f'Members Reviewing PRs'):
pr_reviews_map = await get_pr_reviews_map(pr, config)
for member in tqdm(config.members, desc=f'Members Review PRs'):
token = member['token'] if 'ghp_' in member['token'] else 'ghp_' + member['token']
for repo in config.repo_names:
token = member['token'] if 'ghp_' in member['token'] else 'ghp_' + member['token']
if is_member_allowed_to_review(config, member, repo):
prs = await pr.get_pull_requests(token,repo)
member_reviewed_prs_of_login = []
prs = await pr.get_pull_requests(token,repo)
if is_member_codeowner(config, member, repo):
for p in prs:
if prs[p] != member['login']:
if prs[p] != member['login'] and prs[p] not in member_reviewed_prs_of_login and not pr_reviews_map[repo][p]:
await pr.review(token, repo, p)
pr_reviews_map[repo][p] = True
member_reviewed_prs_of_login.append(prs[p])
elif can_members_review(config, repo):
for p in prs:
if prs[p] != member['login'] and not pr_reviews_map[repo][p]:
await pr.review(token, repo, p)
pr_reviews_map[repo][p] = True
member_reviewed_prs_of_login.append(prs[p])
await review_pull_requests_by_owner(pr_reviews_map, pr)

async def review_pull_requests_by_owner(pr_reviews_map, pr):
for repo in tqdm(pr_reviews_map, desc=f'Owner Reviews PRs'):
for pr_id in pr_reviews_map[repo]:
if not pr_reviews_map[repo][pr_id]:
await pr.review(Config.get_pat(), repo, pr_id)

async def get_pr_reviews_map(pr, config):
pr_reviews_map = {}
for repo in config.repo_names:
pr_reviews_map[repo] = {}
for pr_id in await pr.get_pull_requests(Config.get_pat(),repo):
pr_reviews_map[repo][pr_id] = False
return pr_reviews_map

async def merge_pull_requests(config, org):
pr = PullRequest(org, config.filename)
for member in tqdm(config.members, desc=f'Members Merging PRs'):
for member in tqdm(config.members, desc=f'Members Merge PRs'):
for repo in config.repo_names:
token = member['token'] if 'ghp_' in member['token'] else 'ghp_' + member['token']
if is_member_allowed_to_merge(config, member, repo):
Expand All @@ -153,9 +173,12 @@ async def merge_pull_requests(config, org):
if not merged:
logging.warning(f'Did NOT merge the PR id {p} in repository {repo} by {member["login"]}')

def is_member_allowed_to_review(config, member, repo):
def can_members_review(config, repo):
if 'branch_protection_restirctions' in config.repo_configs[repo] and 'require_code_owner_reviews' in config.repo_configs[repo]['branch_protection_restirctions'] and not config.repo_configs[repo]['branch_protection_restirctions']['require_code_owner_reviews']:
return True
return False

def is_member_codeowner(config, member, repo):
if 'codeowners' in config.repo_configs[repo] and 'owners' in config.repo_configs[repo]['codeowners']:
for owner in config.repo_configs[repo]['codeowners']['owners']:
for u in owner['users']:
Expand Down
5 changes: 3 additions & 2 deletions src/codeowners.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ class CodeOwners:

filename = 'CODEOWNERS'

def __init__(self, repo_name: str, repository: git.Repo, config_file = None):
def __init__(self, organization: str, repo_name: str, repository: git.Repo, config_file = None):
self.config = Config() if config_file is None else Config(config_file)
self.org = organization
self.repo = repository
self.repo_name = repo_name
self.repo.git.add(update=True)
Expand All @@ -35,7 +36,7 @@ async def generate_file(self):
for u in owner['users']:
rules += f'@{u} '
for t in owner['teams']:
rules += f'@{self.repo_name}-{t} '
rules += f'@{self.org}/{self.repo_name}-{t} '
rules += '\n'
with open(filename, 'w') as f:
f.write(rules)
Expand Down
2 changes: 1 addition & 1 deletion src/pull_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ async def get_pull_requests(self, pat, repository):
resp = await conn.get(endpoint)
for pr in resp:
if pr['state'] == 'open':
pr_ids[pr['number']] = pr['user']['login']
pr_ids[str(pr['number'])] = pr['user']['login']
return pr_ids

async def create_pull_request(self, pat, repository, head_branch):
Expand Down
2 changes: 1 addition & 1 deletion src/teams.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ async def create(self, name, repo_names = []):
data = {
'name': name,
'repo_names': repo_names,
'privacy': 'secret'
'privacy': 'closed'
}
resp = await self.conn.post(self.endpoint, json_data=data)
return resp
Expand Down

0 comments on commit 58c097f

Please sign in to comment.