From bf9679c592bf46c8105f8eddbe4dbb8fedf78fbc Mon Sep 17 00:00:00 2001 From: Harrison Cook Date: Wed, 16 Oct 2024 18:09:12 +0100 Subject: [PATCH 01/10] Update README.md --- README.md | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index efab3d9..46e6e04 100644 --- a/README.md +++ b/README.md @@ -1,29 +1,24 @@ -# Contributors action +# Contributors sorted by Organisation action -[![Python package](https://github.com/github/contributors/actions/workflows/python-ci.yml/badge.svg)](https://github.com/github/contributors/actions/workflows/python-ci.yml) -[![Docker Image CI](https://github.com/github/contributors/actions/workflows/docker-ci.yml/badge.svg)](https://github.com/github/contributors/actions/workflows/docker-ci.yml) -[![CodeQL](https://github.com/github/contributors/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/github/contributors/actions/workflows/github-code-scanning/codeql)[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/github/contributors/badge)](https://scorecard.dev/viewer/?uri=github.com/github/contributors) +[![Python package](https://github.com/hcookie/contributors/actions/workflows/python-ci.yml/badge.svg)](https://github.com/github/contributors/actions/workflows/python-ci.yml) +[![Docker Image CI](https://github.com/hcookie/contributors/actions/workflows/docker-ci.yml/badge.svg)](https://github.com/github/contributors/actions/workflows/docker-ci.yml) +[![CodeQL](https://github.com/hcookie/contributors/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/github/contributors/actions/workflows/github-code-scanning/codeql)[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/github/contributors/badge)](https://scorecard.dev/viewer/?uri=github.com/github/contributors) -This is a GitHub Action that given an organization or specified repositories, produces information about the [contributors](https://chaoss.community/kb/metric-contributors/) over the specified time period. +This is a GitHub Action that given an organization or specified repositories, produces information about the [contributors](https://chaoss.community/kb/metric-contributors/) sorted by organisation. Similar actions to help you recognize contributors by putting them into a `README` or `CONTRIBUTORS.md` include: - [contributor-list](https://github.com/marketplace/actions/contribute-list) - -This action was developed by the GitHub OSPO for our own use and developed in a way that we could open source it that it might be useful to you as well! If you want to know more about how we use it, reach out in an issue in this repository. +- [contributors](https://github.com/github/contributors) ## Example use cases -- As a maintainer, you may want to acknowledge recent contributors in a discussion post -- As an OSPO or maintainer, you may want to know who candidates are for new maintainers - -## Support +- As a maintainer, you may want to acknowledge contributors from various organisations in a discussion post -If you need support using this project or have questions about it, please [open up an issue in this repository](https://github.com/github/contributors/issues). Requests made directly to GitHub staff or support team will be redirected here to open an issue. GitHub SLA's and support/services contracts do not apply to this repository. -### OSPO GitHub Actions as a Whole +## Support -All feedback regarding our GitHub Actions, as a whole, should be communicated through [issues on our github-ospo repository](https://github.com/github/github-ospo/issues/new). +If you need support using this project or have questions about it, please [open up an issue in this repository](https://github.com/github/contributors/issues). ## What is a contributor? From b7c4145a699ffbf6e931e3ea52cf4e018149983a Mon Sep 17 00:00:00 2001 From: Harrison Cook Date: Wed, 16 Oct 2024 18:10:10 +0100 Subject: [PATCH 02/10] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 46e6e04..70319ca 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # Contributors sorted by Organisation action -[![Python package](https://github.com/hcookie/contributors/actions/workflows/python-ci.yml/badge.svg)](https://github.com/github/contributors/actions/workflows/python-ci.yml) -[![Docker Image CI](https://github.com/hcookie/contributors/actions/workflows/docker-ci.yml/badge.svg)](https://github.com/github/contributors/actions/workflows/docker-ci.yml) -[![CodeQL](https://github.com/hcookie/contributors/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/github/contributors/actions/workflows/github-code-scanning/codeql)[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/github/contributors/badge)](https://scorecard.dev/viewer/?uri=github.com/github/contributors) +[![Python package](https://github.com/hcookie/contributors/actions/workflows/python-ci.yml/badge.svg)](https://github.com/hcookie/contributors/actions/workflows/python-ci.yml) +[![Docker Image CI](https://github.com/hcookie/contributors/actions/workflows/docker-ci.yml/badge.svg)](https://github.com/hcookie/contributors/actions/workflows/docker-ci.yml) +[![CodeQL](https://github.com/hcookie/contributors/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/hcookie/contributors/actions/workflows/github-code-scanning/codeql)[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/github/contributors/badge)](https://scorecard.dev/viewer/?uri=github.com/github/contributors) This is a GitHub Action that given an organization or specified repositories, produces information about the [contributors](https://chaoss.community/kb/metric-contributors/) sorted by organisation. From ddd487754e2a56aa253805d01a527eb8b96e53fc Mon Sep 17 00:00:00 2001 From: Harrison Cook Date: Wed, 16 Oct 2024 18:13:06 +0100 Subject: [PATCH 03/10] Update config.yml --- .github/ISSUE_TEMPLATE/config.yml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index d4fe799..a5bb6de 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -2,8 +2,5 @@ blank_issues_enabled: false contact_links: - name: Ask a question - url: https://github.com/github/contributors/discussions/new - about: Ask a question or start a discussion - - name: GitHub OSPO GitHub Action Overall Issue - url: https://github.com/github/github-ospo/issues/new - about: File issue for multiple GitHub OSPO GitHub Actions + url: https://github.com/hcookie/contributors/discussions/new + about: Ask a question or start a discussion \ No newline at end of file From 47f7fcdca3f7986704a8c9224abd1abe03c75d6a Mon Sep 17 00:00:00 2001 From: Harrison Cook Date: Wed, 16 Oct 2024 16:17:07 +0100 Subject: [PATCH 04/10] Initial Testing with Organisation Sorting --- .github/ISSUE_TEMPLATE/config.yml | 4 +- .github/workflows/contributors_report.yaml | 26 +++++--- .../contributors_report_testing.yaml | 62 +++++++++++++++++++ contributors/__init__.py | 0 contributors/__main__.py | 3 + auth.py => contributors/auth.py | 0 .../contributor_stats.py | 49 +++------------ .../contributors.py | 39 ++++++------ env.py => contributors/env.py | 15 ++++- json_writer.py => contributors/json_writer.py | 0 markdown.py => contributors/markdown.py | 46 ++++++++++++-- tests/__init__.py | 0 test_auth.py => tests/test_auth.py | 2 +- .../test_contributor_stats.py | 6 +- .../test_contributors.py | 4 +- test_env.py => tests/test_env.py | 2 +- .../test_env_get_bool.py | 2 +- .../test_json_writer.py | 4 +- test_markdown.py => tests/test_markdown.py | 4 +- 19 files changed, 181 insertions(+), 87 deletions(-) create mode 100644 .github/workflows/contributors_report_testing.yaml create mode 100644 contributors/__init__.py create mode 100644 contributors/__main__.py rename auth.py => contributors/auth.py (100%) rename contributor_stats.py => contributors/contributor_stats.py (76%) rename contributors.py => contributors/contributors.py (88%) rename env.py => contributors/env.py (91%) rename json_writer.py => contributors/json_writer.py (100%) rename markdown.py => contributors/markdown.py (86%) create mode 100644 tests/__init__.py rename test_auth.py => tests/test_auth.py (98%) rename test_contributor_stats.py => tests/test_contributor_stats.py (97%) rename test_contributors.py => tests/test_contributors.py (97%) rename test_env.py => tests/test_env.py (99%) rename test_env_get_bool.py => tests/test_env_get_bool.py (97%) rename test_json_writer.py => tests/test_json_writer.py (94%) rename test_markdown.py => tests/test_markdown.py (98%) diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index a5bb6de..2d0e85f 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,6 +1,6 @@ -blank_issues_enabled: false +blank_issues_enabled: true contact_links: - name: Ask a question url: https://github.com/hcookie/contributors/discussions/new - about: Ask a question or start a discussion \ No newline at end of file + about: Ask a question or start a discussion diff --git a/.github/workflows/contributors_report.yaml b/.github/workflows/contributors_report.yaml index e77cd36..b5939fe 100644 --- a/.github/workflows/contributors_report.yaml +++ b/.github/workflows/contributors_report.yaml @@ -4,7 +4,9 @@ on: workflow_dispatch: schedule: - cron: "3 2 1 * *" - +# on: +# push: +# branches: [testing] permissions: contents: read @@ -35,13 +37,17 @@ jobs: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} START_DATE: ${{ env.START_DATE }} END_DATE: ${{ env.END_DATE }} - REPOSITORY: github/contributors - SPONSOR_INFO: "true" + REPOSITORY: ecmwf/anemoi-training + # SPONSOR_INFO: "true" + + - name: Show Contributor + shell: bash + run: cat contributors.md >> $GITHUB_STEP_SUMMARY - - name: Create issue - uses: peter-evans/create-issue-from-file@e8ef132d6df98ed982188e460ebb3b5d4ef3a9cd - with: - title: Monthly contributor report - token: ${{ secrets.GITHUB_TOKEN }} - content-filepath: ./contributors.md - assignees: zkoppert + # - name: Create issue + # uses: peter-evans/create-issue-from-file@e8ef132d6df98ed982188e460ebb3b5d4ef3a9cd + # with: + # title: Monthly contributor report + # token: ${{ secrets.GITHUB_TOKEN }} + # content-filepath: ./contributors.md + # # assignees: zkoppert diff --git a/.github/workflows/contributors_report_testing.yaml b/.github/workflows/contributors_report_testing.yaml new file mode 100644 index 0000000..37aa0b6 --- /dev/null +++ b/.github/workflows/contributors_report_testing.yaml @@ -0,0 +1,62 @@ +--- +name: Testing contributor report +# on: +# workflow_dispatch: +# schedule: +# - cron: "3 2 1 * *" +on: + push: + branches: [testing] +permissions: + contents: read + +jobs: + contributor_report: + name: contributor report + runs-on: ubuntu-latest + permissions: + issues: write + + steps: + - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1 + + - name: Get dates for last month + shell: bash + run: | + # Calculate the first day of the previous month + start_date=$(date -d "last month" +%Y-%m-01) + + # Calculate the last day of the previous month + end_date=$(date -d "$start_date +1 month -1 day" +%Y-%m-%d) + + #Set an environment variable with the date range + echo "START_DATE=$start_date" >> "$GITHUB_ENV" + echo "END_DATE=$end_date" >> "$GITHUB_ENV" + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + + - name: Run Contributors + run: python -m contributors + + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + START_DATE: ${{ env.START_DATE }} + END_DATE: ${{ env.END_DATE }} + REPOSITORY: ecmwf/anemoi-training + SHOW_ORGANISATIONS: ecmwf + # SPONSOR_INFO: "true" + + - name: Show Contributor + shell: bash + run: cat contributors.md >> $GITHUB_STEP_SUMMARY + + # - name: Create issue + # uses: peter-evans/create-issue-from-file@e8ef132d6df98ed982188e460ebb3b5d4ef3a9cd + # with: + # title: Monthly contributor report + # token: ${{ secrets.GITHUB_TOKEN }} + # content-filepath: ./contributors.md + # # assignees: zkoppert diff --git a/contributors/__init__.py b/contributors/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/contributors/__main__.py b/contributors/__main__.py new file mode 100644 index 0000000..349597a --- /dev/null +++ b/contributors/__main__.py @@ -0,0 +1,3 @@ +from contributors.contributors import main + +main() diff --git a/auth.py b/contributors/auth.py similarity index 100% rename from auth.py rename to contributors/auth.py diff --git a/contributor_stats.py b/contributors/contributor_stats.py similarity index 76% rename from contributor_stats.py rename to contributors/contributor_stats.py index 1d7b1db..aca2204 100644 --- a/contributor_stats.py +++ b/contributors/contributor_stats.py @@ -15,8 +15,10 @@ from typing import List import requests +from dataclasses import dataclass, field +@dataclass class ContributorStats: """ A class to represent a contributor_stats object correlating to a single contributors stats. @@ -31,47 +33,14 @@ class ContributorStats: """ - def __new__(cls, *args, **kwargs): # pylint: disable=unused-argument - """Create a new contributor_stats object""" - return super().__new__(cls) - - def __init__( - self, - username: str, - new_contributor: bool, - avatar_url: str, - contribution_count: int, - commit_url: str, - sponsor_info: str, - ): - """Initialize the contributor_stats object""" - new_contributor = False - self.username = username - self.new_contributor = new_contributor - self.avatar_url = avatar_url - self.contribution_count = contribution_count - self.commit_url = commit_url - self.sponsor_info = sponsor_info - - def __repr__(self) -> str: - """Return the representation of the contributor_stats object""" - return ( - f"contributor_stats(username={self.username}, " - f"new_contributor={self.new_contributor}, " - f"avatar_url={self.avatar_url}, " - f"contribution_count={self.contribution_count}, commit_url={self.commit_url})" - f"sponsor_info={self.sponsor_info})" - ) + username: str + avatar_url: str + contribution_count: int + commit_url: str + sponsor_info: str + organisations: list[str] = field(default_factory=list) - def __eq__(self, other) -> bool: - """Check if two contributor_stats objects are equal""" - return ( - self.username == other.username - and self.new_contributor == other.new_contributor - and self.avatar_url == other.avatar_url - and self.contribution_count == other.contribution_count - and self.commit_url == other.commit_url - ) + new_contributor: bool = False def is_new_contributor(username: str, returning_contributors: list) -> bool: diff --git a/contributors.py b/contributors/contributors.py similarity index 88% rename from contributors.py rename to contributors/contributors.py index 6518fbc..d66edf5 100644 --- a/contributors.py +++ b/contributors/contributors.py @@ -3,11 +3,15 @@ from typing import List -import auth -import contributor_stats -import env -import json_writer -import markdown +import github3.repos +import github3.users +import github3 + +from . import auth +from . import contributor_stats +from . import env +from . import json_writer +from . import markdown def main(): @@ -26,10 +30,11 @@ def main(): end_date, sponsor_info, link_to_profile, + show_organisations_list, ) = env.get_env_vars() # Auth to GitHub.com - github_connection = auth.auth_to_github( + github_connection: github3.GitHub = auth.auth_to_github( gh_app_id, gh_app_installation_id, gh_app_private_key_bytes, token, ghe ) @@ -72,6 +77,7 @@ def main(): repository_list, sponsor_info, link_to_profile, + show_organisations_list, ) json_writer.write_to_json( filename="contributors.json", @@ -90,7 +96,7 @@ def get_all_contributors( repository_list: List[str], start_date: str, end_date: str, - github_connection: object, + github_connection: github3.GitHub, ): """ Get all contributors from the organization or repository @@ -129,7 +135,7 @@ def get_all_contributors( def get_contributors( - repo: object, + repo: github3.repos.Repository, start_date: str, end_date: str, ): @@ -172,12 +178,13 @@ def get_contributors( f"https://github.com/{repo.full_name}/commits?author={user.login}" ) contributor = contributor_stats.ContributorStats( - user.login, - False, - user.avatar_url, - user.contributions_count, - commit_url, - "", + username=user.login, + new_contributor=False, + avatar_url=user.avatar_url, + contribution_count=user.contributions_count, + commit_url=commit_url, + sponsor_info="", + organisations=list(map(lambda x: x.url.split('/')[-1], user.organizations())), ) contributors.append(contributor) except Exception as e: @@ -186,7 +193,3 @@ def get_contributors( return None return contributors - - -if __name__ == "__main__": - main() diff --git a/env.py b/contributors/env.py similarity index 91% rename from env.py rename to contributors/env.py index 3842ada..dc86301 100644 --- a/env.py +++ b/contributors/env.py @@ -8,6 +8,7 @@ from os.path import dirname, join from dotenv import load_dotenv +from dataclasses import dataclass def get_bool_env_var(env_var_name: str, default: bool = False) -> bool: @@ -70,10 +71,15 @@ def validate_date_format(env_var_name: str) -> str: return date_to_validate +@dataclass +class env: + organization: str + repositories_list: list[str] + def get_env_vars( test: bool = False, ) -> tuple[ - str | None, list[str], int | None, int | None, bytes, str, str, str, str, bool, bool + str | None, list[str], int | None, int | None, bytes, str, str, str, str, bool, bool, list ]: """ Get the environment variables for use in the action. @@ -93,6 +99,7 @@ def get_env_vars( str: the end date to get contributor information to. str: whether to get sponsor information on the contributor str: whether to link username to Github profile in markdown output + list: organisations to show """ @@ -127,6 +134,7 @@ def get_env_vars( raise ValueError("GH_TOKEN environment variable not set") ghe = os.getenv("GH_ENTERPRISE_URL", default="").strip() + show_organisations = os.getenv("SHOW_ORGANISATIONS", default="").strip() start_date = validate_date_format("START_DATE") end_date = validate_date_format("END_DATE") @@ -140,6 +148,10 @@ def get_env_vars( repositories_list = [ repository.strip() for repository in repositories_str.split(",") ] + + show_organisations_list = [] + if show_organisations: + show_organisations_list = [org.strip() for org in show_organisations.split(",")] return ( organization, @@ -153,4 +165,5 @@ def get_env_vars( end_date, sponsor_info, link_to_profile, + show_organisations_list, ) diff --git a/json_writer.py b/contributors/json_writer.py similarity index 100% rename from json_writer.py rename to contributors/json_writer.py diff --git a/markdown.py b/contributors/markdown.py similarity index 86% rename from markdown.py rename to contributors/markdown.py index 1e13cec..ef76b72 100644 --- a/markdown.py +++ b/contributors/markdown.py @@ -2,6 +2,11 @@ """This module contains the functions needed to write the output to markdown files.""" +from collections import defaultdict + +from .contributor_stats import ContributorStats + + def write_to_markdown( collaborators, filename, @@ -11,6 +16,7 @@ def write_to_markdown( repository, sponsor_info, link_to_profile, + show_organisations_list, ): """ This function writes a list of collaborators to a markdown file in table format. @@ -26,6 +32,7 @@ def write_to_markdown( 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_organisations_list (list): Organisations to show Returns: None @@ -40,6 +47,7 @@ def write_to_markdown( repository, sponsor_info, link_to_profile, + show_organisations_list, ) # Put together the summary table including # of new contributions, # of new contributors, % new contributors, % returning contributors @@ -84,9 +92,15 @@ def write_markdown_file( markdown_file.write(f"- Repository: {repository}\n") markdown_file.write("\n") markdown_file.write(summary_table) - markdown_file.write(table) + if len(table) == 1 and 'Independent' in table: + markdown_file.write(table['Independent']) + else: + for key, t in table.items(): + org_title = f"## [{key}](https://github.com/{key})\n" if not key == 'Independent' else f"## {key} \n" + markdown_file.write(org_title) + markdown_file.write(t) markdown_file.write( - "\n _this file was generated by the [Contributors GitHub Action](https://github.com/github/contributors)_\n" + "\n _this file was generated by the [Contributors GitHub Action](https://github.com/HCookie/contributors)_\n" ) @@ -134,14 +148,19 @@ def get_summary_table(collaborators, start_date, end_date, total_contributions): return summary_table +def make_row(*args) -> str: + return "| " + "|".join(args) + "|" + + def get_contributor_table( - collaborators, + collaborators: list[ContributorStats], start_date, end_date, organization, repository, sponsor_info, link_to_profile, + show_organisations_list, ): """ This function returns a string containing a markdown table of the contributors and the total contribution count. @@ -174,9 +193,10 @@ def get_contributor_table( headers = "| " + " | ".join(columns) + " |\n" headers += "| " + " | ".join(["---"] * len(columns)) + " |\n" - table = headers total_contributions = 0 + organisation_contributors = defaultdict(list) + for collaborator in collaborators: total_contributions += collaborator.contribution_count username = collaborator.username @@ -205,5 +225,19 @@ def get_contributor_table( row += f" [Sponsor Link]({collaborator.sponsor_info}) |" row += f" {commit_urls} |\n" - table += row - return table, total_contributions + added_to_org: bool = False + print(username, collaborator.organisations) + for org in collaborator.organisations or []: + if org in show_organisations_list: + organisation_contributors[org].append(row) + added_to_org = True + + if not added_to_org: + organisation_contributors["Independent"].append(row) + + tables = { + org: headers + "".join(rows) for org, rows in organisation_contributors.items() + } + + # table += row + return tables, total_contributions diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/test_auth.py b/tests/test_auth.py similarity index 98% rename from test_auth.py rename to tests/test_auth.py index 69fc9f5..89b981a 100644 --- a/test_auth.py +++ b/tests/test_auth.py @@ -3,7 +3,7 @@ import unittest from unittest.mock import MagicMock, patch -import auth +from contributors import auth import github3.github diff --git a/test_contributor_stats.py b/tests/test_contributor_stats.py similarity index 97% rename from test_contributor_stats.py rename to tests/test_contributor_stats.py index adcd0a5..d43126f 100644 --- a/test_contributor_stats.py +++ b/tests/test_contributor_stats.py @@ -2,7 +2,11 @@ import unittest -from contributor_stats import ContributorStats, is_new_contributor, merge_contributors +from contributors.contributor_stats import ( + ContributorStats, + is_new_contributor, + merge_contributors, +) class TestContributorStats(unittest.TestCase): diff --git a/test_contributors.py b/tests/test_contributors.py similarity index 97% rename from test_contributors.py rename to tests/test_contributors.py index ab75d0c..9411549 100644 --- a/test_contributors.py +++ b/tests/test_contributors.py @@ -3,8 +3,8 @@ import unittest from unittest.mock import MagicMock, patch -from contributor_stats import ContributorStats -from contributors import get_all_contributors, get_contributors +from contributors.contributor_stats import ContributorStats +from contributors.contributors import get_all_contributors, get_contributors class TestContributors(unittest.TestCase): diff --git a/test_env.py b/tests/test_env.py similarity index 99% rename from test_env.py rename to tests/test_env.py index 7632c41..0ec59b9 100644 --- a/test_env.py +++ b/tests/test_env.py @@ -4,7 +4,7 @@ import unittest from unittest.mock import patch -import env +from contributors import env class TestEnv(unittest.TestCase): diff --git a/test_env_get_bool.py b/tests/test_env_get_bool.py similarity index 97% rename from test_env_get_bool.py rename to tests/test_env_get_bool.py index 3165de1..80bb0f7 100644 --- a/test_env_get_bool.py +++ b/tests/test_env_get_bool.py @@ -4,7 +4,7 @@ import unittest from unittest.mock import patch -from env import get_bool_env_var +from contributors.env import get_bool_env_var class TestEnv(unittest.TestCase): diff --git a/test_json_writer.py b/tests/test_json_writer.py similarity index 94% rename from test_json_writer.py rename to tests/test_json_writer.py index 1071ea1..a07e3e1 100644 --- a/test_json_writer.py +++ b/tests/test_json_writer.py @@ -4,8 +4,8 @@ import os import unittest -from contributor_stats import ContributorStats -from json_writer import write_to_json +from contributors.contributor_stats import ContributorStats +from contributors.json_writer import write_to_json class TestWriteToJson(unittest.TestCase): diff --git a/test_markdown.py b/tests/test_markdown.py similarity index 98% rename from test_markdown.py rename to tests/test_markdown.py index f4e46cb..b36769f 100644 --- a/test_markdown.py +++ b/tests/test_markdown.py @@ -3,8 +3,8 @@ import unittest from unittest.mock import mock_open, patch -import contributor_stats -from markdown import write_to_markdown +from contributors import contributor_stats +from contributors.markdown import write_to_markdown class TestMarkdown(unittest.TestCase): From 0087f2f0813c5b0a7c1fe1dc263d394eb7daa9fd Mon Sep 17 00:00:00 2001 From: Harrison Cook Date: Wed, 16 Oct 2024 19:22:23 +0100 Subject: [PATCH 05/10] Test with multiple repos --- .github/workflows/contributors_report_testing.yaml | 2 +- README.md | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/contributors_report_testing.yaml b/.github/workflows/contributors_report_testing.yaml index 37aa0b6..09b20b3 100644 --- a/.github/workflows/contributors_report_testing.yaml +++ b/.github/workflows/contributors_report_testing.yaml @@ -45,7 +45,7 @@ jobs: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} START_DATE: ${{ env.START_DATE }} END_DATE: ${{ env.END_DATE }} - REPOSITORY: ecmwf/anemoi-training + REPOSITORY: ecmwf/anemoi-training,ecmwf/anemoi-datasets SHOW_ORGANISATIONS: ecmwf # SPONSOR_INFO: "true" diff --git a/README.md b/README.md index 70319ca..9e0ee08 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Similar actions to help you recognize contributors by putting them into a `READM ## Example use cases - As a maintainer, you may want to acknowledge contributors from various organisations in a discussion post - +- A repository wants to track contributions from organisations ## Support @@ -80,8 +80,8 @@ 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" | - -**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. +| `SHOW_ORGANISATIONS` | False | [] | Organisations to show in the contributors table. Will be evaluated in order, and a user only added to only the first one they are a part of. Any contributors with no organisation will be shown in independent. Set to 'all' to show all organisations. +| `CONTRIB_FILENAME` | False | "contibutors" | Filename to add contributors to. Will create both an 'md', and 'json' file with contents. **Performance Note:** Using start and end dates will reduce speed of the action by approximately 63X. ie without dates if the action takes 1.7 seconds, it will take 1 minute and 47 seconds. From cec4b0b044db7e22f3872c0a9c0dbbcdc054d516 Mon Sep 17 00:00:00 2001 From: Harrison Cook Date: Wed, 16 Oct 2024 19:27:29 +0100 Subject: [PATCH 06/10] Test impact of removing dates --- .github/workflows/contributors_report_testing.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/contributors_report_testing.yaml b/.github/workflows/contributors_report_testing.yaml index 09b20b3..bf1c747 100644 --- a/.github/workflows/contributors_report_testing.yaml +++ b/.github/workflows/contributors_report_testing.yaml @@ -43,8 +43,8 @@ jobs: env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - START_DATE: ${{ env.START_DATE }} - END_DATE: ${{ env.END_DATE }} + # START_DATE: ${{ env.START_DATE }} + # END_DATE: ${{ env.END_DATE }} REPOSITORY: ecmwf/anemoi-training,ecmwf/anemoi-datasets SHOW_ORGANISATIONS: ecmwf # SPONSOR_INFO: "true" From 678cd4e121a2a5661ea55ae264b2e5bd2d1b4a4b Mon Sep 17 00:00:00 2001 From: Harrison Cook Date: Wed, 16 Oct 2024 20:38:05 +0100 Subject: [PATCH 07/10] Fix for env vars --- .github/workflows/contributors_report_testing.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/contributors_report_testing.yaml b/.github/workflows/contributors_report_testing.yaml index bf1c747..c0c6c6e 100644 --- a/.github/workflows/contributors_report_testing.yaml +++ b/.github/workflows/contributors_report_testing.yaml @@ -30,8 +30,8 @@ jobs: end_date=$(date -d "$start_date +1 month -1 day" +%Y-%m-%d) #Set an environment variable with the date range - echo "START_DATE=$start_date" >> "$GITHUB_ENV" - echo "END_DATE=$end_date" >> "$GITHUB_ENV" + # echo "START_DATE=$start_date" >> "$GITHUB_ENV" + # echo "END_DATE=$end_date" >> "$GITHUB_ENV" - name: Install dependencies run: | From 7607424dadb5bc16f30d0686688d0e19d8361d23 Mon Sep 17 00:00:00 2001 From: Harrison Cook Date: Wed, 16 Oct 2024 20:40:47 +0100 Subject: [PATCH 08/10] Fix typing - Change env to dataclass --- contributors/auth.py | 4 +- contributors/contributor_stats.py | 19 ++----- contributors/contributors.py | 91 +++++++++++++------------------ contributors/env.py | 89 ++++++++++++++++++------------ contributors/markdown.py | 39 +++++-------- 5 files changed, 109 insertions(+), 133 deletions(-) diff --git a/contributors/auth.py b/contributors/auth.py index 825ff14..d4b4fdc 100644 --- a/contributors/auth.py +++ b/contributors/auth.py @@ -25,9 +25,7 @@ def auth_to_github( """ if gh_app_id and gh_app_private_key_bytes and gh_app_installation_id: gh = github3.github.GitHub() - gh.login_as_app_installation( - gh_app_private_key_bytes, gh_app_id, gh_app_installation_id - ) + gh.login_as_app_installation(gh_app_private_key_bytes, gh_app_id, gh_app_installation_id) github_connection = gh elif ghe and token: github_connection = github3.github.GitHubEnterprise(ghe, token=token) diff --git a/contributors/contributor_stats.py b/contributors/contributor_stats.py index aca2204..c861386 100644 --- a/contributors/contributor_stats.py +++ b/contributors/contributor_stats.py @@ -60,7 +60,7 @@ def is_new_contributor(username: str, returning_contributors: list) -> bool: return True -def merge_contributors(contributors: list) -> list: +def merge_contributors(contributors: list[list[ContributorStats]]) -> list[ContributorStats]: """ Merge contributors with the same username from multiple repositories. @@ -78,19 +78,12 @@ def merge_contributors(contributors: list) -> list: for merged_contributor in merged_contributors: if merged_contributor.username == contributor.username: # Merge the contribution counts via addition - merged_contributor.contribution_count += ( - contributor.contribution_count - ) + merged_contributor.contribution_count += contributor.contribution_count # Merge the commit urls via concatenation - merged_contributor.commit_url = ( - merged_contributor.commit_url - + ", " - + contributor.commit_url - ) + merged_contributor.commit_url = merged_contributor.commit_url + ", " + contributor.commit_url # Merge the new_contributor attribute via OR merged_contributor.new_contributor = ( - merged_contributor.new_contributor - or contributor.new_contributor + merged_contributor.new_contributor or contributor.new_contributor ) else: @@ -140,8 +133,6 @@ def get_sponsor_information(contributors: list, token: str) -> list: # if the user has a sponsor page, add it to the contributor object if data["repositoryOwner"]["hasSponsorsListing"]: - contributor.sponsor_info = ( - f"https://github.com/sponsors/{contributor.username}" - ) + contributor.sponsor_info = f"https://github.com/sponsors/{contributor.username}" return contributors diff --git a/contributors/contributors.py b/contributors/contributors.py index d66edf5..082b667 100644 --- a/contributors/contributors.py +++ b/contributors/contributors.py @@ -7,55 +7,42 @@ import github3.users import github3 -from . import auth -from . import contributor_stats -from . import env -from . import json_writer -from . import markdown +from . import auth, contributor_stats, env, json_writer, markdown def main(): """Run the main program""" # Get environment variables - ( - organization, - repository_list, - gh_app_id, - gh_app_installation_id, - gh_app_private_key_bytes, - token, - ghe, - start_date, - end_date, - sponsor_info, - link_to_profile, - show_organisations_list, - ) = env.get_env_vars() + environment = env.get_env_vars() # Auth to GitHub.com github_connection: github3.GitHub = auth.auth_to_github( - gh_app_id, gh_app_installation_id, gh_app_private_key_bytes, token, ghe + environment.gh_app_id, + environment.gh_app_installation_id, + environment.gh_app_private_key_bytes, + environment.token, + environment.ghe, ) # Get the contributors contributors = get_all_contributors( - organization, - repository_list, - start_date, - end_date, + environment.organization, + environment.repositories_list, + environment.start_date, + environment.end_date, github_connection, ) # Check for new contributor if user provided start_date and end_date - if start_date and end_date: + if environment.start_date and environment.end_date: # get the list of contributors from before start_date # so we can see if contributors after start_date are new or returning returning_contributors = get_all_contributors( - organization, - repository_list, + environment.organization, + environment.repositories_list, start_date="2008-02-29", # GitHub was founded on 2008-02-29 - end_date=start_date, + end_date=environment.start_date, github_connection=github_connection, ) for contributor in contributors: @@ -64,29 +51,29 @@ def main(): ) # Get sponsor information on the contributor - if sponsor_info == "true": - contributors = contributor_stats.get_sponsor_information(contributors, token) + if environment.sponsor_info == "true": + contributors = contributor_stats.get_sponsor_information(contributors, environment.token) # Output the contributors information - # print(contributors) markdown.write_to_markdown( contributors, - "contributors.md", - start_date, - end_date, - organization, - repository_list, - sponsor_info, - link_to_profile, - show_organisations_list, + f"{environment.filename}.md", + environment.start_date, + environment.end_date, + environment.organization, + environment.repositories_list, + environment.sponsor_info, + environment.link_to_profile, + environment.show_organisations_list, ) + #TODO HCookie Fix to json json_writer.write_to_json( - filename="contributors.json", - start_date=start_date, - end_date=end_date, - organization=organization, - repository_list=repository_list, - sponsor_info=sponsor_info, - link_to_profile=link_to_profile, + filename="{environment.filename}.json", + start_date=environment.start_date, + end_date=environment.end_date, + organization=environment.organization, + repository_list=environment.repositories_list, + sponsor_info=environment.sponsor_info, + link_to_profile=environment.link_to_profile, contributors=contributors, ) @@ -138,7 +125,7 @@ def get_contributors( repo: github3.repos.Repository, start_date: str, end_date: str, -): +) -> list[contributor_stats.ContributorStats]: """ Get contributors from a single repository and filter by start end dates if present. @@ -160,9 +147,7 @@ def get_contributors( # Check if user has commits in the date range if start_date and end_date: - user_commits = repo.commits( - author=user.login, since=start_date, until=end_date - ) + user_commits = repo.commits(author=user.login, since=start_date, until=end_date) # If the user has no commits in the date range, skip them try: @@ -174,9 +159,7 @@ def get_contributors( if start_date and end_date: commit_url = f"https://github.com/{repo.full_name}/commits?author={user.login}&since={start_date}&until={end_date}" else: - commit_url = ( - f"https://github.com/{repo.full_name}/commits?author={user.login}" - ) + commit_url = f"https://github.com/{repo.full_name}/commits?author={user.login}" contributor = contributor_stats.ContributorStats( username=user.login, new_contributor=False, @@ -184,7 +167,7 @@ def get_contributors( contribution_count=user.contributions_count, commit_url=commit_url, sponsor_info="", - organisations=list(map(lambda x: x.url.split('/')[-1], user.organizations())), + organisations=list(map(lambda x: x.url.split("/")[-1], user.organizations())), ) contributors.append(contributor) except Exception as e: diff --git a/contributors/env.py b/contributors/env.py index dc86301..13c8027 100644 --- a/contributors/env.py +++ b/contributors/env.py @@ -65,22 +65,34 @@ def validate_date_format(env_var_name: str) -> str: try: datetime.datetime.strptime(date_to_validate, pattern) except ValueError as exc: - raise ValueError( - f"{env_var_name} environment variable not in the format YYYY-MM-DD" - ) from exc + raise ValueError(f"{env_var_name} environment variable not in the format YYYY-MM-DD") from exc return date_to_validate @dataclass -class env: +class EnvironmentConfig: + """ + Environment Configuration + """ + organization: str repositories_list: list[str] + gh_app_id: int | None + gh_app_installation_id: int | None + gh_app_private_key_bytes: bytes + token: str + ghe: str + start_date: str + end_date: str + sponsor_info: str + link_to_profile: str + show_organisations_list: list[str] + filename: str = 'contributors' + def get_env_vars( test: bool = False, -) -> tuple[ - str | None, list[str], int | None, int | None, bytes, str, str, str, str, bool, bool, list -]: +) -> EnvironmentConfig: """ Get the environment variables for use in the action. @@ -88,18 +100,31 @@ def get_env_vars( None Returns: - str: the organization to get contributor information for - List[str]: A list of the repositories to get contributor information for - int|None: the GitHub App ID to use for authentication - int|None: the GitHub App Installation ID to use for authentication - bytes: the GitHub App Private Key as bytes to use for authentication - str: the GitHub token to use for authentication - str: the GitHub Enterprise URL to use for authentication - str: the start date to get contributor information from - str: the end date to get contributor information to. - str: whether to get sponsor information on the contributor - str: whether to link username to Github profile in markdown output - list: organisations to show + EnvironmentConfig: + organization, str: + the organization to get contributor information for + repositories_list, List[str]: + A list of the repositories to get contributor information for + gh_app_id, int|None: + the GitHub App ID to use for authentication + gh_app_installation_id, int|None: + the GitHub App Installation ID to use for authentication + gh_app_private_key_bytes, bytes: + the GitHub App Private Key as bytes to use for authentication + token, str: + the GitHub token to use for authentication + ghe, str: + the GitHub Enterprise URL to use for authentication + start_date, str, + the start date to get contributor information from + 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_organisations_list, list: + Organisations to show in order of preference """ @@ -111,29 +136,22 @@ def get_env_vars( repositories_str = os.getenv("REPOSITORY") # Either organization or repository must be set if not organization and not repositories_str: - raise ValueError( - "ORGANIZATION and REPOSITORY environment variables were not set. Please set one" - ) + raise ValueError("ORGANIZATION and REPOSITORY environment variables were not set. Please set one") gh_app_id = get_int_env_var("GH_APP_ID") gh_app_private_key_bytes = os.environ.get("GH_APP_PRIVATE_KEY", "").encode("utf8") gh_app_installation_id = get_int_env_var("GH_APP_INSTALLATION_ID") if gh_app_id and (not gh_app_private_key_bytes or not gh_app_installation_id): - raise ValueError( - "GH_APP_ID set and GH_APP_INSTALLATION_ID or GH_APP_PRIVATE_KEY variable not set" - ) + raise ValueError("GH_APP_ID set and GH_APP_INSTALLATION_ID or GH_APP_PRIVATE_KEY variable not set") token = os.getenv("GH_TOKEN", "") - if ( - not gh_app_id - and not gh_app_private_key_bytes - and not gh_app_installation_id - and not token - ): + if not gh_app_id and not gh_app_private_key_bytes and not gh_app_installation_id and not token: raise ValueError("GH_TOKEN environment variable not set") ghe = os.getenv("GH_ENTERPRISE_URL", default="").strip() + filename = os.getenv("CONTRIB_FILENAME", default="contributors").strip() + show_organisations = os.getenv("SHOW_ORGANISATIONS", default="").strip() start_date = validate_date_format("START_DATE") @@ -145,15 +163,13 @@ def get_env_vars( # Separate repositories_str into a list based on the comma separator repositories_list = [] if repositories_str: - repositories_list = [ - repository.strip() for repository in repositories_str.split(",") - ] - + repositories_list = [repository.strip() for repository in repositories_str.split(",")] + show_organisations_list = [] if show_organisations: show_organisations_list = [org.strip() for org in show_organisations.split(",")] - return ( + return EnvironmentConfig( organization, repositories_list, gh_app_id, @@ -166,4 +182,5 @@ def get_env_vars( sponsor_info, link_to_profile, show_organisations_list, + filename = filename, ) diff --git a/contributors/markdown.py b/contributors/markdown.py index ef76b72..6cdea0a 100644 --- a/contributors/markdown.py +++ b/contributors/markdown.py @@ -51,19 +51,13 @@ def write_to_markdown( ) # Put together the summary table including # of new contributions, # of new contributors, % new contributors, % returning contributors - summary_table = get_summary_table( - collaborators, start_date, end_date, total_contributions - ) + summary_table = get_summary_table(collaborators, start_date, end_date, total_contributions) # Write the markdown file - write_markdown_file( - filename, start_date, end_date, organization, repository, table, summary_table - ) + write_markdown_file(filename, start_date, end_date, organization, repository, table, summary_table) -def write_markdown_file( - filename, start_date, end_date, organization, repository, table, summary_table -): +def write_markdown_file(filename, start_date, end_date, organization, repository, table, summary_table): """ This function writes all the tables and data to a markdown file with tables to organizae the information. @@ -83,20 +77,18 @@ def write_markdown_file( with open(filename, "w", encoding="utf-8") as markdown_file: markdown_file.write("# Contributors\n\n") if start_date and end_date: - markdown_file.write( - f"- Date range for contributor list: {start_date} to {end_date}\n" - ) + markdown_file.write(f"- Date range for contributor list: {start_date} to {end_date}\n") if organization: markdown_file.write(f"- Organization: {organization}\n") if repository: markdown_file.write(f"- Repository: {repository}\n") markdown_file.write("\n") markdown_file.write(summary_table) - if len(table) == 1 and 'Independent' in table: - markdown_file.write(table['Independent']) + if len(table) == 1 and "Independent" in table: + markdown_file.write(table["Independent"]) else: for key, t in table.items(): - org_title = f"## [{key}](https://github.com/{key})\n" if not key == 'Independent' else f"## {key} \n" + org_title = f"## [{key}](https://github.com/{key})\n" if not key == "Independent" else f"## {key} \n" markdown_file.write(org_title) markdown_file.write(t) markdown_file.write( @@ -123,9 +115,7 @@ def get_summary_table(collaborators, start_date, end_date, total_contributions): summary_table = "| Total Contributors | Total Contributions | % New Contributors |\n| --- | --- | --- |\n" if len(collaborators) > 0: new_contributors_percentage = round( - (len([x for x in collaborators if x.new_contributor is True])) - / len(collaborators) - * 100, + (len([x for x in collaborators if x.new_contributor is True])) / len(collaborators) * 100, 2, ) else: @@ -141,9 +131,7 @@ def get_summary_table(collaborators, start_date, end_date, total_contributions): ) else: summary_table = "| Total Contributors | Total Contributions |\n| --- | --- |\n" - summary_table += ( - "| " + str(len(collaborators)) + " | " + str(total_contributions) + " |\n\n" - ) + summary_table += "| " + str(len(collaborators)) + " | " + str(total_contributions) + " |\n\n" return summary_table @@ -226,18 +214,17 @@ def get_contributor_table( row += f" {commit_urls} |\n" added_to_org: bool = False - print(username, collaborator.organisations) + for org in collaborator.organisations or []: - if org in show_organisations_list: + if org in show_organisations_list or "all" in show_organisations_list: organisation_contributors[org].append(row) added_to_org = True + break if not added_to_org: organisation_contributors["Independent"].append(row) - tables = { - org: headers + "".join(rows) for org, rows in organisation_contributors.items() - } + tables = {org: headers + "".join(rows) for org, rows in organisation_contributors.items()} # table += row return tables, total_contributions From 9a5d3ce8d15de74f81aa0cc7cbbccd8d22d9c467 Mon Sep 17 00:00:00 2001 From: Harrison Cook Date: Wed, 16 Oct 2024 21:04:10 +0100 Subject: [PATCH 09/10] Fix some tests --- contributors/__init__.py | 1 + contributors/contributor_stats.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/contributors/__init__.py b/contributors/__init__.py index e69de29..12928a2 100644 --- a/contributors/__init__.py +++ b/contributors/__init__.py @@ -0,0 +1 @@ +"""Contributors Module""" \ No newline at end of file diff --git a/contributors/contributor_stats.py b/contributors/contributor_stats.py index c861386..8bbea00 100644 --- a/contributors/contributor_stats.py +++ b/contributors/contributor_stats.py @@ -34,13 +34,13 @@ class ContributorStats: """ username: str + new_contributor: bool avatar_url: str contribution_count: int commit_url: str sponsor_info: str organisations: list[str] = field(default_factory=list) - new_contributor: bool = False def is_new_contributor(username: str, returning_contributors: list) -> bool: From 3d4b6a0dda314a8c0fe6243b6ea142c6579e3c15 Mon Sep 17 00:00:00 2001 From: Harrison Cook Date: Wed, 16 Oct 2024 21:05:08 +0100 Subject: [PATCH 10/10] Fix some more tests --- tests/test_contributors.py | 12 ++---- tests/test_env.py | 76 +++++++++++++------------------------- tests/test_markdown.py | 15 +++----- 3 files changed, 35 insertions(+), 68 deletions(-) diff --git a/tests/test_contributors.py b/tests/test_contributors.py index 9411549..d0ef6e0 100644 --- a/tests/test_contributors.py +++ b/tests/test_contributors.py @@ -57,9 +57,7 @@ def test_get_all_contributors_with_organization(self, mock_get_contributors): ), ] - result = get_all_contributors( - "org", "", "2022-01-01", "2022-12-31", mock_github_connection - ) + result = get_all_contributors("org", "", "2022-01-01", "2022-12-31", mock_github_connection) self.assertEqual( result, @@ -95,9 +93,7 @@ def test_get_all_contributors_with_repository(self, mock_get_contributors): ) ] - result = get_all_contributors( - "", ["owner/repo"], "2022-01-01", "2022-12-31", mock_github_connection - ) + result = get_all_contributors("", ["owner/repo"], "2022-01-01", "2022-12-31", mock_github_connection) self.assertEqual( result, @@ -112,9 +108,7 @@ def test_get_all_contributors_with_repository(self, mock_get_contributors): ), ], ) - mock_get_contributors.assert_called_once_with( - "repo", "2022-01-01", "2022-12-31" - ) + mock_get_contributors.assert_called_once_with("repo", "2022-01-01", "2022-12-31") @patch("contributors.contributor_stats.ContributorStats") def test_get_contributors_skip_users_with_no_commits(self, mock_contributor_stats): diff --git a/tests/test_env.py b/tests/test_env.py index 0ec59b9..73486c4 100644 --- a/tests/test_env.py +++ b/tests/test_env.py @@ -51,31 +51,19 @@ def test_get_env_vars(self): Test the get_env_vars function when all environment variables are set correctly. """ - ( - organization, - repository_list, - gh_app_id, - gh_app_installation_id, - gh_app_private_key_bytes, - token, - ghe, - start_date, - end_date, - sponsor_info, - link_to_profile, - ) = env.get_env_vars() - - self.assertEqual(organization, "org") - self.assertEqual(repository_list, ["repo", "repo2"]) - self.assertIsNone(gh_app_id) - self.assertIsNone(gh_app_installation_id) - self.assertEqual(gh_app_private_key_bytes, b"") - self.assertEqual(token, "token") - self.assertEqual(ghe, "") - self.assertEqual(start_date, "2022-01-01") - self.assertEqual(end_date, "2022-12-31") - self.assertFalse(sponsor_info) - self.assertTrue(link_to_profile) + environment = env.get_env_vars() + + self.assertEqual(environment.organization, "org") + self.assertEqual(environment.repositories_list, ["repo", "repo2"]) + self.assertIsNone(environment.gh_app_id) + self.assertIsNone(environment.gh_app_installation_id) + self.assertEqual(environment.gh_app_private_key_bytes, b"") + self.assertEqual(environment.token, "token") + self.assertEqual(environment.ghe, "") + self.assertEqual(environment.start_date, "2022-01-01") + self.assertEqual(environment.end_date, "2022-12-31") + self.assertFalse(environment.sponsor_info) + self.assertTrue(environment.link_to_profile) @patch.dict( os.environ, @@ -159,31 +147,19 @@ def test_get_env_vars_no_dates(self): and start_date and end_date are not set. """ - ( - organization, - repository_list, - gh_app_id, - gh_app_installation_id, - gh_app_private_key_bytes, - token, - ghe, - start_date, - end_date, - sponsor_info, - link_to_profile, - ) = env.get_env_vars() - - self.assertEqual(organization, "org") - self.assertEqual(repository_list, ["repo", "repo2"]) - self.assertIsNone(gh_app_id) - self.assertIsNone(gh_app_installation_id) - self.assertEqual(gh_app_private_key_bytes, b"") - self.assertEqual(token, "token") - self.assertEqual(ghe, "") - self.assertEqual(start_date, "") - self.assertEqual(end_date, "") - self.assertFalse(sponsor_info) - self.assertTrue(link_to_profile) + environment = env.get_env_vars() + + self.assertEqual(environment.organization, "org") + self.assertEqual(environment.repositories_list, ["repo", "repo2"]) + self.assertIsNone(environment.gh_app_id) + self.assertIsNone(environment.gh_app_installation_id) + self.assertEqual(environment.gh_app_private_key_bytes, b"") + self.assertEqual(environment.token, "token") + self.assertEqual(environment.ghe, "") + self.assertEqual(environment.start_date, "") + self.assertEqual(environment.end_date, "") + self.assertFalse(environment.sponsor_info) + self.assertTrue(environment.link_to_profile) if __name__ == "__main__": diff --git a/tests/test_markdown.py b/tests/test_markdown.py index b36769f..3e441ad 100644 --- a/tests/test_markdown.py +++ b/tests/test_markdown.py @@ -49,13 +49,12 @@ def test_write_to_markdown(self, mock_file): "org/repo", "false", "true", + [], ) mock_file.assert_called_once_with("filename", "w", encoding="utf-8") mock_file().write.assert_any_call("# Contributors\n\n") - mock_file().write.assert_any_call( - "- Date range for contributor list: 2023-01-01 to 2023-01-02\n" - ) + mock_file().write.assert_any_call("- Date range for contributor list: 2023-01-01 to 2023-01-02\n") mock_file().write.assert_any_call( "| Total Contributors | Total Contributions | % New Contributors |\n| --- | --- | --- |\n| 2 | 300 | 50.0% |\n\n" ) @@ -103,13 +102,12 @@ def test_write_to_markdown_with_sponsors(self, mock_file): "org/repo", "true", "true", + [] ) mock_file.assert_called_once_with("filename", "w", encoding="utf-8") mock_file().write.assert_any_call("# Contributors\n\n") - mock_file().write.assert_any_call( - "- Date range for contributor list: 2023-01-01 to 2023-01-02\n" - ) + mock_file().write.assert_any_call("- Date range for contributor list: 2023-01-01 to 2023-01-02\n") mock_file().write.assert_any_call( "| Total Contributors | Total Contributions | % New Contributors |\n| --- | --- | --- |\n| 2 | 300 | 50.0% |\n\n" ) @@ -157,13 +155,12 @@ def test_write_to_markdown_without_link_to_profile(self, mock_file): "org/repo", "false", "false", + [] ) mock_file.assert_called_once_with("filename", "w", encoding="utf-8") mock_file().write.assert_any_call("# Contributors\n\n") - mock_file().write.assert_any_call( - "- Date range for contributor list: 2023-01-01 to 2023-01-02\n" - ) + mock_file().write.assert_any_call("- Date range for contributor list: 2023-01-01 to 2023-01-02\n") mock_file().write.assert_any_call( "| Total Contributors | Total Contributions | % New Contributors |\n| --- | --- | --- |\n| 2 | 300 | 50.0% |\n\n" )