Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,8 @@ metrics-env/
metrics-env/**
output/**
update_gsheet.py
*.csv
*.csv

.env

.DS_Store
4 changes: 2 additions & 2 deletions export_traffic.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def test_push_access(organization, authToken):
if orgs.login == organization:
print("Checking push access for", orgs.name, "repositories. \n")
for repo in orgs.get_repos():
if repo.fork == False and repo.private == False:
if repo.fork == False and repo.archived == False:
currentrepo = repo.name
r = s.get("https://api.github.com/repos/" + organization + "/" + currentrepo + "/traffic/views")
r_views = json.loads(r.text)
Expand Down Expand Up @@ -70,7 +70,7 @@ def export_traffic(directory, organization, repos_ok, authtoken):
for repo in allrepos:
repo_owner = str(repo.owner)
repo_owner = (repo_owner.replace('NamedUser(login="', "")).replace('")', "")
if repo.fork == False and repo.private == False and repo_owner == organization and repo.name in repos_ok:
if repo.fork == False and repo.archived == False and repo_owner == organization and repo.name in repos_ok:
reposlist.append(repo.name)

count=0
Expand Down
126 changes: 126 additions & 0 deletions github_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,129 @@ def export_community_engagement(directory, organization, authToken):
[todaystr, organization, repo.name, repo.forks_count, repo.stargazers_count, countcommit,
countcollab])

def export_repo_metrics(directory,organization, authToken):
g = Github(authToken)
dt_today = datetime.datetime.now()
today = dt_today.date()
today = str(today).replace("-", "")

totalrepos = 0
allorgs = g.get_user().get_orgs()

with open(directory + "/github_repo_metrics_" + organization + "_" + today+ ".csv", 'w', encoding='utf-8') as csvfile:
csvwriter = csv.writer(csvfile, delimiter=',')
csvwriter.writerow(
["date", "org", "repo", "open prs", "pr avg age", "pr max age", "newest pr created", "closed prs", "avg time to close",
"pr \% in org", "pr \% non org", "pr \% bot",
"open issues", "issue avg age", "issue max age", "newest issue opened", "issue \% in org", "issue \% non org", "issue \% bot"])
for orgs in allorgs:
if orgs.login == organization:
print("Gathering repository metrics for", orgs.login)
members = orgs.get_members()
for repo in orgs.get_repos():
if not repo.archived:
pr_open_count = 0
pr_max_open = 0
pr_max_date = datetime.datetime.min
pr_open_total_days = 0
pr_closed_count = 0
pr_closed_total_days = 0
pr_in_org = 0
pr_non_org = 0
pr_bot = 0
pulls = repo.get_pulls(state='all', sort='created')
for pr in pulls:
owner = pr.user
if owner.login and "bot" in owner.login.lower():
pr_bot += 1
elif owner in members:
pr_in_org += 1
else:
pr_non_org += 1

if pr.created_at > pr_max_date:
pr_max_date = pr.created_at

if pr.state == 'open':
pr_open_count += 1

days_open = (dt_today - pr.created_at).days
pr_open_total_days += days_open
if days_open > pr_max_open:
pr_max_open = days_open

else:
pr_closed_count += 1

closed = pr.closed_at if pr.closed_at else datetime.datetime.min
merged = pr.merged_at if pr.merged_at else datetime.datetime.min
end_date = max(closed, merged)
days_open = (end_date- pr.created_at).days
pr_closed_total_days += days_open
if days_open > pr_max_open:
pr_max_open = days_open

print(f"{repo.name} - {pulls.totalCount} - {pr_open_count}")

pr_avg_open = f"{pr_open_total_days/pr_open_count:.2f}" if pr_open_count > 0 else 0
pr_avg_close_time = f"{pr_closed_total_days/pr_closed_count:.2f}" if pr_closed_count > 0 else 0
pr_pct_org = f"{(pr_in_org/(pr_open_count + pr_closed_count)) * 100:.2f}" if pr_closed_count + pr_open_count > 0 else 0
pr_pct_non_org = f"{(pr_non_org/(pr_open_count + pr_closed_count)) * 100:.2f}" if pr_closed_count + pr_open_count > 0 else 0
pr_pct_bot = f"{(pr_bot/(pr_open_count + pr_closed_count)) * 100:.2f}" if pr_closed_count + pr_open_count > 0 else 0
pr_display_date = pr_max_date.date() if pr_max_date != datetime.datetime.min else "N/A"

i_open_count = 0
i_max_open = 0
i_max_date = datetime.datetime.min
i_open_total_days = 0
i_closed_count = 0
i_closed_total_days = 0
i_in_org = 0
i_non_org = 0
i_bot = 0
for iss in repo.get_issues(state='all', sort='created'):
owner = iss.user
if owner.login and "bot" in owner.login.lower():
i_bot += 1
elif owner in members:
i_in_org += 1
else:
i_non_org += 1

if iss.created_at > i_max_date:
i_max_date = iss.created_at

if iss.state == 'open':
i_open_count += 1

# print(f'{pr.created_at}')
days_open = (dt_today - iss.created_at).days
i_open_total_days += days_open
if days_open > i_max_open:
i_max_open = days_open

else:
i_closed_count += 1

days_open = (iss.closed_at- iss.created_at).days
i_closed_total_days += days_open
# if days_open > pr_max_open:
# pr_max_open = days_open
# if pr.created_at > pr_max_date:
# pr_max_date = pr.created_at

i_avg_open = f"{i_open_total_days/i_open_count:.2f}" if i_open_count > 0 else 0
i_avg_close_time = f"{i_closed_total_days/i_closed_count:.2f}" if i_closed_count > 0 else 0
i_pct_org = f"{(i_in_org/(i_open_count + i_closed_count)) * 100:.2f}" if i_closed_count + i_open_count > 0 else 0
i_pct_non_org = f"{(i_non_org/(i_open_count + i_closed_count)) * 100:.2f}" if i_closed_count + i_open_count > 0 else 0
i_pct_bot = f"{(i_bot/(i_open_count + i_closed_count)) * 100:.2f}" if i_closed_count + i_open_count > 0 else 0
i_display_date = i_max_date.date() if i_max_date != datetime.datetime.min else "N/A"

csvwriter.writerow(
[todaystr, organization, repo.name, pr_open_count, pr_avg_open, pr_max_open, pr_display_date,
pr_closed_count, pr_avg_close_time, pr_pct_org, pr_pct_non_org, pr_pct_bot, i_open_count,
i_avg_open, i_max_open, i_display_date, i_pct_org, i_pct_non_org, i_pct_bot])

def list_unique_collaborators(directory, organization, authToken):
g = Github(authToken)
with open(directory + "/github_unique_collaborators_" + organization + ".csv", "w", encoding="utf-8") as csvfile:
Expand Down Expand Up @@ -200,11 +323,14 @@ def main():

try:
print("Valid token. Starting process. \n")
print("")
list_org_members(organization, authToken)
print("")
export_code_frequency(directory, organization, authToken)
print("")
export_community_engagement(directory, organization, authToken)
print("")
export_repo_metrics(directory, organization, authToken)
except Exception as e:
print(e)

Expand Down
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ oauthlib==3.1.0
opt-einsum==3.3.0
packaging==20.9
pandocfilters==1.4.3
pandas==1.3.1
parso==0.8.2
pexpect==4.8.0
pickleshare==0.7.5
Expand All @@ -63,6 +64,7 @@ pyasn1==0.4.8
pyasn1-modules==0.2.8
pycparser==2.20
Pygments==2.8.1
PyGithub==1.55
pyparsing==2.4.7
pyrsistent==0.17.3
python-dateutil==2.8.1
Expand Down