Skip to content
Closed
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
92 changes: 85 additions & 7 deletions stale_repos.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def main(): # pragma: no cover

# Iterate over repos in the org, acquire inactive days,
# and print out the repo url and days inactive if it's over the threshold (inactive_days)
inactive_repos = get_inactive_repos(
inactive_repos, exception_repos = get_inactive_repos(
github_connection, inactive_days_threshold, organization, additional_metrics
)

Expand All @@ -79,6 +79,10 @@ def main(): # pragma: no cover
else:
print("No stale repos found")

if exception_repos:
output_to_json_exception_repos(exception_repos)



def is_repo_exempt(repo, exempt_repos, exempt_topics):
"""Check if a repo is exempt from the stale repo check.
Expand Down Expand Up @@ -129,6 +133,8 @@ def get_inactive_repos(

"""
inactive_repos = []
exception_repos = []

if organization:
repos = github_connection.organization(organization).repositories()
else:
Expand All @@ -153,22 +159,28 @@ def get_inactive_repos(

# Get last active date
active_date = get_active_date(repo)
visibility = "private" if repo.private else "public"

if active_date is None:
exception_repos.append(set_repo_data(
repo, None, None, visibility, None
))
continue

active_date_disp = active_date.date().isoformat()
days_inactive = (datetime.now(timezone.utc) - active_date).days
visibility = "private" if repo.private else "public"
if days_inactive > int(inactive_days_threshold):
repo_data = set_repo_data(
repo, days_inactive, active_date_disp, visibility, additional_metrics
)
inactive_repos.append(repo_data)
if organization:
print(f"Found {len(inactive_repos)} stale repos in {organization}")
print(f"Found {len(exception_repos)} repos where was unable to get last activity date in {organization}")
else:
print(f"Found {len(inactive_repos)} stale repos")
return inactive_repos
print(f"Found {len(exception_repos)} repos where was unable to get last activity date")
return inactive_repos,exception_repos


def get_days_since_last_release(repo):
Expand Down Expand Up @@ -262,15 +274,15 @@ def write_to_markdown(
f"{inactive_days_threshold} days:\n\n"
)
markdown_file.write(
"| Repository URL | Days Inactive | Last Push Date | Visibility |"
"| Repository URL | Days Inactive | Last Push Date | Visibility | Last Committer"
)
# Include additional metrics columns if configured
if additional_metrics:
if "release" in additional_metrics:
markdown_file.write(" Days Since Last Release |")
if "pr" in additional_metrics:
markdown_file.write(" Days Since Last PR |")
markdown_file.write("\n| --- | --- | --- | --- |")
markdown_file.write("\n| --- | --- | --- | --- | --- |")
if additional_metrics:
if "release" in additional_metrics:
markdown_file.write(" --- |")
Expand All @@ -282,7 +294,8 @@ def write_to_markdown(
f"| {repo_data['url']} \
| {repo_data['days_inactive']} \
| {repo_data['last_push_date']} \
| {repo_data['visibility']} |"
| {repo_data['visibility']} \
| {repo_data['last_committer']} |"
)
if additional_metrics:
if "release" in additional_metrics:
Expand Down Expand Up @@ -316,13 +329,17 @@ def output_to_json(inactive_repos, file=None):
# "daysSinceLastPR": "10"
# }
# ]
# Instead of looping through an array and then using json dump
# why not just inactive_repos_json = json.dumps(inactive_repos)
# and then remove line 323-335 NOTE: FOR ADAM AND BORIS
inactive_repos_json = []
for repo_data in inactive_repos:
repo_json = {
"url": repo_data["url"],
"daysInactive": repo_data["days_inactive"],
"lastPushDate": repo_data["last_push_date"],
"visibility": repo_data["visibility"],
"last_committer":repo_data["last_committer"],
}
if "release" in repo_data:
repo_json["daysSinceLastRelease"] = repo_data["days_since_last_release"]
Expand All @@ -345,6 +362,42 @@ def output_to_json(inactive_repos, file=None):
return inactive_repos_json


def output_to_json_exception_repos(exception_repos, file=None):
"""Convert the list of exception repos to a json string.

Args:
exception_repos: A list of dictionaries containing the repo,
visiblity of the repository (public/private), last_committer.

Returns:
JSON formatted string of the list of exception repos.

"""

exception_repos_json = []
for repo_data in exception_repos:
repo_json = {
"url": repo_data["url"],
"visibility": repo_data["visibility"],
"last_committer":repo_data["last_committer"],
}
exception_repos_json.append(repo_json)
exception_repos_json = json.dumps(exception_repos_json)

# add output to github action output
# pylint: disable=unspecified-encoding
if os.environ.get("GITHUB_OUTPUT"):
with open(os.environ["GITHUB_OUTPUT"], "a") as file_handle:
print(f"exceptionRepos={exception_repos_json}", file=file_handle)

with file or open("exception_repos.json", "w", encoding="utf-8") as json_file:
json_file.write(exception_repos_json)

print("Wrote exception repos to exception_repos.json")

return exception_repos_json


def get_int_env_var(env_var_name):
"""Get an integer environment variable.

Expand Down Expand Up @@ -389,6 +442,7 @@ def set_repo_data(
# Fetch and include additional metrics if configured
repo_data["days_since_last_release"] = None
repo_data["days_since_last_pr"] = None
repo_data["last_committer"] = get_committer(repo)
if additional_metrics:
if "release" in additional_metrics:
try:
Expand All @@ -406,10 +460,34 @@ def set_repo_data(
f"{repo.html_url} had an exception trying to get the last PR.\
Potentially caused by ghost user."
)

print(f"{repo.html_url}: {days_inactive} days inactive") # type: ignore
return repo_data


def get_committer(repo):
"""Get the committer of the last commit on the default branch.

Args:
repo: A Github repository object.

Returns:
A dictionary with the committer's name and email.
"""
try:

commit = repo.branch(repo.default_branch).commit

if hasattr(commit.commit, '_author_name'):
return commit.commit._author_name
elif "name" in commit.commit.author:
return commit.commit.author["name"]
elif hasattr(commit.commit, 'login'):
return commit.author.login
else:
return "None"

except github3.exceptions.GitHubException:
return "None"

if __name__ == "__main__":
main()
Loading