Skip to content

Commit

Permalink
feat: add repository visibility (public/private) to output
Browse files Browse the repository at this point in the history
Our priority was to archive public repositories that were not
updated in a certain amount of inactive days.  This PR adds
that information to the output.

- [x] update code/tests for new visibility column

Signed-off-by: jmeridth <[email protected]>
  • Loading branch information
jmeridth committed Feb 28, 2024
1 parent a67bb76 commit 893ab0d
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 20 deletions.
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Stale Repos Action

(Used by the `github` organization!)

This project identifies and reports repositories with no activity for configurable amount of time, in order to surface inactive repos to be considered for archival.
Expand Down Expand Up @@ -91,16 +92,17 @@ jobs:

The following repos have not had a push event for more than 3 days:

| Repository URL | Days Inactive | Last Push Date |
| --- | ---: | ---: |
| https://github.com/github/.github | 5 | 2020-1-30 |
| Repository URL | Days Inactive | Last Push Date | Visibility |
| --- | ---: | ---: | ---: |
| https://github.com/github/.github | 5 | 2020-1-30 | private |
```

### Using JSON instead of Markdown

The action outputs inactive repos in JSON format for further actions as seen below or use the JSON contents from the file: `stale_repos.json`.

Example usage:

```yaml
name: stale repo identifier

Expand Down
22 changes: 13 additions & 9 deletions stale_repos.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@ def get_inactive_repos(github_connection, inactive_days_threshold, organization)
organization: The name of the organization to retrieve repositories from.
Returns:
A list of tuples containing the repo, days inactive, and the date of the last push.
A list of tuples containing the repo, days inactive, the date of the last push and
repository visibility (public/private).
"""
inactive_repos = []
Expand Down Expand Up @@ -132,8 +133,9 @@ def get_inactive_repos(github_connection, inactive_days_threshold, organization)

active_date_disp = active_date.date().isoformat()
days_inactive = (datetime.now(timezone.utc) - active_date).days
private = "private" if repo.private else "public"
if days_inactive > int(inactive_days_threshold) and not repo.archived:
inactive_repos.append((repo.html_url, days_inactive, active_date_disp))
inactive_repos.append((repo.html_url, days_inactive, active_date_disp, private))
print(f"{repo.html_url}: {days_inactive} days inactive") # type: ignore
if organization:
print(f"Found {len(inactive_repos)} stale repos in {organization}")
Expand Down Expand Up @@ -179,7 +181,7 @@ def write_to_markdown(inactive_repos, inactive_days_threshold, file=None):
Args:
inactive_repos: A list of tuples containing the repo, days inactive,
and the date of the last push.
the date of the last push, and repository visibility (public/private).
inactive_days_threshold: The threshold (in days) for considering a repo as inactive.
file: A file object to write to. If None, a new file will be created.
Expand All @@ -191,10 +193,10 @@ def write_to_markdown(inactive_repos, inactive_days_threshold, file=None):
f"The following repos have not had a push event for more than "
f"{inactive_days_threshold} days:\n\n"
)
file.write("| Repository URL | Days Inactive | Last Push Date |\n")
file.write("| --- | --- | ---: |\n")
for repo_url, days_inactive, last_push_date in inactive_repos:
file.write(f"| {repo_url} | {days_inactive} | {last_push_date} |\n")
file.write("| Repository URL | Days Inactive | Last Push Date | Visibility |\n")
file.write("| --- | --- | --- | ---: |\n")
for repo_url, days_inactive, last_push_date, private in inactive_repos:
file.write(f"| {repo_url} | {days_inactive} | {last_push_date} | {private} |\n")
print("Wrote stale repos to stale_repos.md")


Expand All @@ -203,7 +205,8 @@ def output_to_json(inactive_repos, file=None):
Args:
inactive_repos: A list of tuples containing the repo,
days inactive, and the date of the last push.
days inactive, the date of the last push, and
visiblity of the repository (public/private).
Returns:
JSON formatted string of the list of inactive repos.
Expand All @@ -218,12 +221,13 @@ def output_to_json(inactive_repos, file=None):
# }
# ]
inactive_repos_json = []
for repo_url, days_inactive, last_push_date in inactive_repos:
for repo_url, days_inactive, last_push_date, private in inactive_repos:
inactive_repos_json.append(
{
"url": repo_url,
"daysInactive": days_inactive,
"lastPushDate": last_push_date,
"visibility": private,
}
)
inactive_repos_json = json.dumps(inactive_repos_json)
Expand Down
40 changes: 32 additions & 8 deletions test_stale_repos.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,18 +176,21 @@ def test_get_inactive_repos_with_inactive_repos(self):
html_url="https://github.com/example/repo1",
pushed_at=twenty_days_ago.isoformat(),
archived=False,
private=True,
)
mock_repo1.topics().names = []
mock_repo2 = MagicMock(
html_url="https://github.com/example/repo2",
pushed_at=forty_days_ago.isoformat(),
archived=False,
private=True,
)
mock_repo2.topics().names = []
mock_repo3 = MagicMock(
html_url="https://github.com/example/repo3",
pushed_at=forty_days_ago.isoformat(),
archived=True,
private=True,
)
mock_repo3.topics().names = []

Expand All @@ -205,7 +208,7 @@ def test_get_inactive_repos_with_inactive_repos(self):

# Check that the function returns the expected list of inactive repos
expected_inactive_repos = [
("https://github.com/example/repo2", 40, forty_days_ago.date().isoformat()),
("https://github.com/example/repo2", 40, forty_days_ago.date().isoformat(), "private"),
]
assert inactive_repos == expected_inactive_repos

Expand Down Expand Up @@ -318,18 +321,21 @@ def test_get_inactive_repos_with_no_organization_set(self):
html_url="https://github.com/example/repo1",
pushed_at=twenty_days_ago.isoformat(),
archived=False,
private=True,
)
mock_repo1.topics().names = []
mock_repo2 = MagicMock(
html_url="https://github.com/example/repo2",
pushed_at=forty_days_ago.isoformat(),
archived=False,
private=True,
)
mock_repo2.topics().names = []
mock_repo3 = MagicMock(
html_url="https://github.com/example/repo3",
pushed_at=forty_days_ago.isoformat(),
archived=True,
private=True,
)
mock_repo3.topics().names = []

Expand All @@ -346,7 +352,7 @@ def test_get_inactive_repos_with_no_organization_set(self):

# Check that the function returns the expected list of inactive repos
expected_inactive_repos = [
("https://github.com/example/repo2", 40, forty_days_ago.date().isoformat()),
("https://github.com/example/repo2", 40, forty_days_ago.date().isoformat(), "private"),
]
assert inactive_repos == expected_inactive_repos

Expand Down Expand Up @@ -376,6 +382,7 @@ def test_get_inactive_repos_with_default_branch_updated(self):
html_url="https://github.com/example/repo1",
default_branch="master",
archived=False,
private=True,
)
mock_repo1.topics().names = []
mock_repo1.branch().commit.commit.as_dict = MagicMock(
Expand All @@ -384,6 +391,7 @@ def test_get_inactive_repos_with_default_branch_updated(self):
mock_repo2 = MagicMock(
html_url="https://github.com/example/repo2",
archived=False,
private=True,
)
mock_repo2.topics().names = []
mock_repo2.branch().commit.commit.as_dict = MagicMock(
Expand All @@ -392,6 +400,7 @@ def test_get_inactive_repos_with_default_branch_updated(self):
mock_repo3 = MagicMock(
html_url="https://github.com/example/repo3",
archived=True,
private=True,
)
mock_repo3.topics().names = []
mock_repo3.branch().commit.commit.as_dict = MagicMock(
Expand All @@ -412,7 +421,7 @@ def test_get_inactive_repos_with_default_branch_updated(self):

# Check that the function returns the expected list of inactive repos
expected_inactive_repos = [
("https://github.com/example/repo2", 40, forty_days_ago.date().isoformat()),
("https://github.com/example/repo2", 40, forty_days_ago.date().isoformat(), "private"),
]
assert inactive_repos == expected_inactive_repos

Expand All @@ -435,11 +444,12 @@ def test_write_to_markdown(self):
thirty_days_ago = datetime.now(timezone.utc) - timedelta(days=30)
# Create a list of inactive repos
inactive_repos = [
("https://github.com/example/repo2", 40, forty_days_ago.date().isoformat()),
("https://github.com/example/repo2", 40, forty_days_ago.date().isoformat(), "public"),
(
"https://github.com/example/repo1",
30,
thirty_days_ago.date().isoformat(),
"private",
),
]

Expand All @@ -457,15 +467,17 @@ def test_write_to_markdown(self):
call.write(
"The following repos have not had a push event for more than 365 days:\n\n"
),
call.write("| Repository URL | Days Inactive | Last Push Date |\n"),
call.write("| --- | --- | ---: |\n"),
call.write("| Repository URL | Days Inactive | Last Push Date | Visibility |\n"),
call.write("| --- | --- | --- | ---: |\n"),
call.write(
f"| https://github.com/example/repo2 | 40 | "
f"{forty_days_ago.date().isoformat()} |\n"
f"{forty_days_ago.date().isoformat()} | "
f"public |\n"
),
call.write(
f"| https://github.com/example/repo1 | 30 | "
f"{thirty_days_ago.date().isoformat()} |\n"
f"{thirty_days_ago.date().isoformat()} | "
f"private |\n"
),
]
mock_file.__enter__.return_value.assert_has_calls(expected_calls)
Expand Down Expand Up @@ -516,16 +528,19 @@ def test_output_to_json(self):
"https://github.com/example/repo1",
31,
thirty_one_days_ago.date().isoformat(),
"private",
),
(
"https://github.com/example/repo2",
30,
thirty_days_ago.date().isoformat(),
"private",
),
(
"https://github.com/example/repo3",
29,
twenty_nine_days_ago.date().isoformat(),
"public",
),
]

Expand All @@ -536,16 +551,19 @@ def test_output_to_json(self):
"url": "https://github.com/example/repo1",
"daysInactive": 31,
"lastPushDate": thirty_one_days_ago.date().isoformat(),
"visibility": "private",
},
{
"url": "https://github.com/example/repo2",
"daysInactive": 30,
"lastPushDate": thirty_days_ago.date().isoformat(),
"visibility": "private",
},
{
"url": "https://github.com/example/repo3",
"daysInactive": 29,
"lastPushDate": twenty_nine_days_ago.date().isoformat(),
"visibility": "public",
},
]
)
Expand All @@ -567,16 +585,19 @@ def test_json_file(self):
"https://github.com/example/repo1",
31,
thirty_one_days_ago.date().isoformat(),
"private",
),
(
"https://github.com/example/repo2",
30,
thirty_days_ago.date().isoformat(),
"private",
),
(
"https://github.com/example/repo3",
29,
twenty_nine_days_ago.date().isoformat(),
"public",
),
]

Expand All @@ -587,16 +608,19 @@ def test_json_file(self):
"url": "https://github.com/example/repo1",
"daysInactive": 31,
"lastPushDate": thirty_one_days_ago.date().isoformat(),
"visibility": "private",
},
{
"url": "https://github.com/example/repo2",
"daysInactive": 30,
"lastPushDate": thirty_days_ago.date().isoformat(),
"visibility": "private",
},
{
"url": "https://github.com/example/repo3",
"daysInactive": 29,
"lastPushDate": twenty_nine_days_ago.date().isoformat(),
"visibility": "public",
},
]
)
Expand Down

0 comments on commit 893ab0d

Please sign in to comment.