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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ This action can be configured to authenticate with GitHub App Installation or Pe
| `END_DATE` | False | Current Date | The date at which you want to stop gathering contributor information. Must be later than the `START_DATE`. ie. Aug 2nd, 2023 would be `2023-08-02` |
| `SPONSOR_INFO` | False | False | If you want to include sponsor information in the output. This will include the sponsor count and the sponsor URL. This will impact action performance. ie. SPONSOR_INFO = "False" or SPONSOR_INFO = "True" |
| `LINK_TO_PROFILE` | False | True | If you want to link usernames to their GitHub profiles in the output. ie. LINK_TO_PROFILE = "True" or LINK_TO_PROFILE = "False" |
| `SHOW_AVATAR` | False | False | If you want to show profile images in the markdown output. ie. SHOW_AVATAR = "True" or SHOW_AVATAR = "False" |

**Note**: If `start_date` and `end_date` are specified then the action will determine if the contributor is new. A new contributor is one that has contributed in the date range specified but not before the start date.

Expand Down
2 changes: 2 additions & 0 deletions contributors.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ def main():
end_date,
sponsor_info,
link_to_profile,
show_avatar,
) = env.get_env_vars()

# Auth to GitHub.com
Expand Down Expand Up @@ -83,6 +84,7 @@ def main():
sponsor_info,
link_to_profile,
ghe,
show_avatar,
)
json_writer.write_to_json(
filename="contributors.json",
Expand Down
4 changes: 4 additions & 0 deletions env.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ def get_env_vars(
str,
bool,
bool,
bool,
]:
"""
Get the environment variables for use in the action.
Expand All @@ -105,6 +106,7 @@ def get_env_vars(
end_date (str): The end date to get contributor information to.
sponsor_info (str): Whether to get sponsor information on the contributor
link_to_profile (str): Whether to link username to Github profile in markdown output
show_avatar (str): Whether to show contributor avatars in markdown output
"""

if not test:
Expand Down Expand Up @@ -145,6 +147,7 @@ def get_env_vars(

sponsor_info = get_bool_env_var("SPONSOR_INFO", False)
link_to_profile = get_bool_env_var("LINK_TO_PROFILE", False)
show_avatar = get_bool_env_var("SHOW_AVATAR", False)

# Separate repositories_str into a list based on the comma separator
repositories_list = []
Expand All @@ -166,4 +169,5 @@ def get_env_vars(
end_date,
sponsor_info,
link_to_profile,
show_avatar,
)
31 changes: 28 additions & 3 deletions markdown.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@
import os


def _is_truthy(value) -> bool:
if isinstance(value, str):
return value.strip().lower() == "true"
return value is True


def write_to_markdown(
collaborators,
filename,
Expand All @@ -14,6 +20,7 @@ def write_to_markdown(
sponsor_info,
link_to_profile,
ghe,
show_avatar=False,
):
"""
This function writes a list of collaborators to a markdown file in table format
Expand All @@ -40,6 +47,8 @@ def write_to_markdown(
link_to_profile (str): True if the user wants the username linked to
Github profile in the report
ghe (str): The GitHub Enterprise instance URL, if applicable.
show_avatar (str): True if the user wants to show profile images in
the report

Returns:
None
Expand All @@ -55,6 +64,7 @@ def write_to_markdown(
sponsor_info,
link_to_profile,
ghe,
show_avatar,
)

# Put together the summary table including # of new contributions,
Expand Down Expand Up @@ -196,6 +206,7 @@ def get_contributor_table(
sponsor_info,
link_to_profile,
ghe,
show_avatar=False,
):
"""
This function returns a string containing a markdown table of the contributors and the total contribution count.
Expand All @@ -209,16 +220,22 @@ def get_contributor_table(
repository (str): The repository for which the contributors are being listed.
sponsor_info (str): True if the user wants the sponsor_url shown in the report
link_to_profile (str): True if the user wants the username linked to Github profile in the report
show_avatar (str): True if the user wants to show profile images in the report

Returns:
table (str): A string containing a markdown table of the contributors and the total contribution count.
total_contributions (int): The total number of contributions made by all of the contributors.

"""
sponsor_info = _is_truthy(sponsor_info)
show_avatar = _is_truthy(show_avatar)
link_to_profile = _is_truthy(link_to_profile)
columns = ["Username", "All Time Contribution Count"]
if show_avatar:
columns.insert(0, "Avatar")
if start_date and end_date:
columns += ["New Contributor"]
if sponsor_info == "true":
if sponsor_info:
columns += ["Sponsor URL"]
if start_date and end_date:
columns += [f"Commits between {start_date} and {end_date}"]
Expand Down Expand Up @@ -250,8 +267,16 @@ def get_contributor_table(
commit_urls += f"{url}, "
new_contributor = collaborator.new_contributor

row = (
f"| {'' if not link_to_profile else '@'}{username} | {contribution_count} |"
row = "| "
if show_avatar:
avatar_cell = (
f'<img src="{collaborator.avatar_url}" width="32" height="32" />'
if collaborator.avatar_url
else ""
)
row += f"{avatar_cell} | "
row += (
f"{'' if not link_to_profile else '@'}{username} | {contribution_count} |"
)
if "New Contributor" in columns:
row += f" {new_contributor} |"
Expand Down
9 changes: 9 additions & 0 deletions test_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ def setUp(self):
"ORGANIZATION",
"REPOSITORY",
"START_DATE",
"SHOW_AVATAR",
]
for key in env_keys:
if key in os.environ:
Expand All @@ -44,6 +45,7 @@ def setUp(self):
"END_DATE": "2022-12-31",
"SPONSOR_INFO": "False",
"LINK_TO_PROFILE": "True",
"SHOW_AVATAR": "False",
},
clear=True,
)
Expand All @@ -65,6 +67,7 @@ def test_get_env_vars(self):
end_date,
sponsor_info,
link_to_profile,
show_avatar,
) = env.get_env_vars()

self.assertEqual(organization, "org")
Expand All @@ -79,6 +82,7 @@ def test_get_env_vars(self):
self.assertEqual(end_date, "2022-12-31")
self.assertFalse(sponsor_info)
self.assertTrue(link_to_profile)
self.assertFalse(show_avatar)

@patch.dict(
os.environ,
Expand All @@ -94,6 +98,7 @@ def test_get_env_vars(self):
"END_DATE": "2022-12-31",
"SPONSOR_INFO": "False",
"LINK_TO_PROFILE": "True",
"SHOW_AVATAR": "False",
},
clear=True,
)
Expand Down Expand Up @@ -122,6 +127,7 @@ def test_get_env_vars_missing_values(self):
"END_DATE": "2022-12-31",
"SPONSOR_INFO": "False",
"LINK_TO_PROFILE": "True",
"SHOW_AVATAR": "False",
},
clear=True,
)
Expand Down Expand Up @@ -153,6 +159,7 @@ def test_get_env_vars_invalid_start_date(self):
"END_DATE": "",
"SPONSOR_INFO": "False",
"LINK_TO_PROFILE": "True",
"SHOW_AVATAR": "False",
},
clear=True,
)
Expand All @@ -175,6 +182,7 @@ def test_get_env_vars_no_dates(self):
end_date,
sponsor_info,
link_to_profile,
show_avatar,
) = env.get_env_vars()

self.assertEqual(organization, "org")
Expand All @@ -189,6 +197,7 @@ def test_get_env_vars_no_dates(self):
self.assertEqual(end_date, "")
self.assertFalse(sponsor_info)
self.assertTrue(link_to_profile)
self.assertFalse(show_avatar)

@patch.dict(os.environ, {})
def test_get_env_vars_missing_org_or_repo(self):
Expand Down
79 changes: 74 additions & 5 deletions test_markdown.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def test_write_to_markdown(
"commit url2",
"sponsor_url_2",
)
# Set person2 as a new contributor since this cannot be set on initiatization of the object
# Set person2 as a new contributor since this cannot be set on initialization of the object
person2.new_contributor = True
collaborators = [
person1,
Expand Down Expand Up @@ -104,7 +104,7 @@ def test_write_to_markdown_with_sponsors(
"commit url2",
"",
)
# Set person2 as a new contributor since this cannot be set on initiatization of the object
# Set person2 as a new contributor since this cannot be set on initialization of the object
person2.new_contributor = True
collaborators = [
person1,
Expand Down Expand Up @@ -144,6 +144,75 @@ def test_write_to_markdown_with_sponsors(
)
mock_file().write.assert_called_once_with(expected_content)

@patch(
"markdown.os.environ.get", return_value=None
) # Mock GITHUB_STEP_SUMMARY to None
@patch("builtins.open", new_callable=mock_open)
def test_write_to_markdown_with_avatars(
self, mock_file, mock_env_get
): # pylint: disable=unused-argument
"""
Test the write_to_markdown function with avatar images turned on.
"""
person1 = contributor_stats.ContributorStats(
"user1",
False,
"https://avatars.example.com/user1.png",
100,
"commit url",
"sponsor_url_1",
)
person2 = contributor_stats.ContributorStats(
"user2",
False,
"https://avatars.example.com/user2.png",
200,
"commit url2",
"sponsor_url_2",
)
# Set person2 as a new contributor since this cannot be set on initialization of the object
person2.new_contributor = True
collaborators = [
person1,
person2,
]
ghe = ""

write_to_markdown(
collaborators,
"filename",
"2023-01-01",
"2023-01-02",
None,
"org/repo",
"false",
True,
ghe,
show_avatar=True,
)

mock_file.assert_called_once_with("filename", "w", encoding="utf-8")
# With the new implementation, content is written as a single string
expected_content = (
"# Contributors\n\n"
"- Date range for contributor list: 2023-01-01 to 2023-01-02\n"
"- Repository: org/repo\n\n"
"| Total Contributors | Total Contributions | % New Contributors |\n"
"| --- | --- | --- |\n"
"| 2 | 300 | 50.0% |\n\n"
"| Avatar | Username | All Time Contribution Count | New Contributor | "
"Commits between 2023-01-01 and 2023-01-02 |\n"
"| --- | --- | --- | --- | --- |\n"
'| <img src="https://avatars.example.com/user1.png" width="32" height="32" /> | '
"@user1 | 100 | False | commit url |\n"
'| <img src="https://avatars.example.com/user2.png" width="32" height="32" /> | '
"@user2 | 200 | True | commit url2 |\n"
"\n _this file was generated by the "
"[Contributors GitHub Action]"
"(https://github.com/github/contributors)_\n"
)
mock_file().write.assert_called_once_with(expected_content)

@patch(
"markdown.os.environ.get", return_value=None
) # Mock GITHUB_STEP_SUMMARY to None
Expand All @@ -170,7 +239,7 @@ def test_write_to_markdown_without_link_to_profile(
"commit url2",
"sponsor_url_2",
)
# Set person2 as a new contributor since this cannot be set on initiatization of the object
# Set person2 as a new contributor since this cannot be set on initialization of the object
person2.new_contributor = True
collaborators = [
person1,
Expand Down Expand Up @@ -235,7 +304,7 @@ def test_write_to_github_summary(
"commit url2",
"sponsor_url_2",
)
# Set person2 as a new contributor since this cannot be set on initiatization of the object
# Set person2 as a new contributor since this cannot be set on initialization of the object
person2.new_contributor = True
collaborators = [
person1,
Expand Down Expand Up @@ -296,7 +365,7 @@ def test_write_to_markdown_with_organization(
"https://github.com/org3/repo3/commits?author=user2",
"sponsor_url_2",
)
# Set person2 as a new contributor since this cannot be set on initiatization of the object
# Set person2 as a new contributor since this cannot be set on initialization of the object
person2.new_contributor = True
collaborators = [
person1,
Expand Down
Loading