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

feat: add repository visibility (public/private) to output #87

Merged
merged 6 commits into from
Mar 1, 2024
Merged
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
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
26 changes: 17 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,11 @@ 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
visibility = "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, visibility)
)
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 +183,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 +195,12 @@ 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, visibility in inactive_repos:
file.write(
f"| {repo_url} | {days_inactive} | {last_push_date} | {visibility} |\n"
)
print("Wrote stale repos to stale_repos.md")


Expand All @@ -203,7 +209,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 +225,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, visibility in inactive_repos:
inactive_repos_json.append(
{
"url": repo_url,
"daysInactive": days_inactive,
"lastPushDate": last_push_date,
"visibility": visibility,
}
)
inactive_repos_json = json.dumps(inactive_repos_json)
Expand Down
62 changes: 54 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,12 @@ 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 +326,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 +357,12 @@ 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 +392,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 +401,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 +410,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 +431,12 @@ 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 +459,17 @@ 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 +487,19 @@ 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 +550,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 +573,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 +607,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 +630,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