From 30f81ca3e0fb212601d1e58e0f5f13ed22676c94 Mon Sep 17 00:00:00 2001 From: "Luis G. Valle" <354372+lgvalle@users.noreply.github.com> Date: Wed, 11 Aug 2021 07:52:36 +0200 Subject: [PATCH 1/4] Add diff url for first branch commit --- main.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/main.py b/main.py index 6c36f92..0ff3566 100644 --- a/main.py +++ b/main.py @@ -63,7 +63,11 @@ class GitHubClient(object): def get_last_diff(self): """Get the last diff based on the SHA of the last two commits.""" - diff_url = f'{self.repos_url}{self.repo}/compare/{self.before}...{self.sha}' + if not self.before or self.before.startswith('000000'): + # Last commit SHA is empty which means this is the first commit of the branch + diff_url = f'{self.repos_url}{self.repo}/commits/{self.sha}' + else: + diff_url = f'{self.repos_url}{self.repo}/compare/{self.before}...{self.sha}' diff_headers = { 'Accept': 'application/vnd.github.v3.diff', 'Authorization': f'token {self.token}' From 12e626ea05df409a687c913e7dac5f965313b80b Mon Sep 17 00:00:00 2001 From: "Luis G. Valle" <354372+lgvalle@users.noreply.github.com> Date: Thu, 12 Aug 2021 08:09:33 +0200 Subject: [PATCH 2/4] Remove empty BEFORE sha check --- main.py | 77 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 38 insertions(+), 39 deletions(-) diff --git a/main.py b/main.py index 0ff3566..e18e7cf 100644 --- a/main.py +++ b/main.py @@ -596,42 +596,41 @@ class TodoParser(object): if __name__ == "__main__": - if os.getenv('INPUT_BEFORE') != '0000000000000000000000000000000000000000': - # Create a basic client for communicating with GitHub, automatically initialised with environment variables. - client = GitHubClient() - # Get the diff from the last pushed commit. - last_diff = StringIO(client.get_last_diff()) - # Parse the diff for TODOs and create an Issue object for each. - raw_issues = TodoParser().parse(last_diff) - # This is a simple, non-perfect check to filter out any TODOs that have just been moved. - # It looks for items that appear in the diff as both an addition and deletion. - # It is based on the assumption that TODOs will not have identical titles in identical files. - issues_to_process = [] - for values, similar_issues in itertools.groupby(raw_issues, key=operator.attrgetter('title', 'file_name', - 'markdown_language')): - similar_issues = list(similar_issues) - if (len(similar_issues) == 2 and ((similar_issues[0].status == LineStatus.ADDED and - similar_issues[1].status == LineStatus.DELETED) or - (similar_issues[1].status == LineStatus.ADDED and - similar_issues[0].status == LineStatus.DELETED))): - print(f'Issue "{values[0]}" appears as both addition and deletion. ' - f'Assuming this issue has been moved so skipping.') - continue - issues_to_process.extend(similar_issues) - # Cycle through the Issue objects and create or close a corresponding GitHub issue for each. - for j, raw_issue in enumerate(issues_to_process): - print(f'Processing issue {j + 1} of {len(issues_to_process)}') - if raw_issue.status == LineStatus.ADDED: - status_code = client.create_issue(raw_issue) - if status_code == 201: - print('Issue created') - else: - print('Issue could not be created') - elif raw_issue.status == LineStatus.DELETED and os.getenv('INPUT_CLOSE_ISSUES', 'true') == 'true': - status_code = client.close_issue(raw_issue) - if status_code == 201: - print('Issue closed') - else: - print('Issue could not be closed') - # Stagger the requests to be on the safe side. - sleep(1) + # Create a basic client for communicating with GitHub, automatically initialised with environment variables. + client = GitHubClient() + # Get the diff from the last pushed commit. + last_diff = StringIO(client.get_last_diff()) + # Parse the diff for TODOs and create an Issue object for each. + raw_issues = TodoParser().parse(last_diff) + # This is a simple, non-perfect check to filter out any TODOs that have just been moved. + # It looks for items that appear in the diff as both an addition and deletion. + # It is based on the assumption that TODOs will not have identical titles in identical files. + issues_to_process = [] + for values, similar_issues in itertools.groupby(raw_issues, key=operator.attrgetter('title', 'file_name', + 'markdown_language')): + similar_issues = list(similar_issues) + if (len(similar_issues) == 2 and ((similar_issues[0].status == LineStatus.ADDED and + similar_issues[1].status == LineStatus.DELETED) or + (similar_issues[1].status == LineStatus.ADDED and + similar_issues[0].status == LineStatus.DELETED))): + print(f'Issue "{values[0]}" appears as both addition and deletion. ' + f'Assuming this issue has been moved so skipping.') + continue + issues_to_process.extend(similar_issues) + # Cycle through the Issue objects and create or close a corresponding GitHub issue for each. + for j, raw_issue in enumerate(issues_to_process): + print(f'Processing issue {j + 1} of {len(issues_to_process)}') + if raw_issue.status == LineStatus.ADDED: + status_code = client.create_issue(raw_issue) + if status_code == 201: + print('Issue created') + else: + print('Issue could not be created') + elif raw_issue.status == LineStatus.DELETED and os.getenv('INPUT_CLOSE_ISSUES', 'true') == 'true': + status_code = client.close_issue(raw_issue) + if status_code == 201: + print('Issue closed') + else: + print('Issue could not be closed') + # Stagger the requests to be on the safe side. + sleep(1) From c159a716fd5c710ecb982b42f1cdd1c198eac640 Mon Sep 17 00:00:00 2001 From: "Luis G. Valle" <354372+lgvalle@users.noreply.github.com> Date: Tue, 17 Aug 2021 08:10:04 +0200 Subject: [PATCH 3/4] Replace /compare with /commits to fetch the last diff --- action.yml | 4 ---- main.py | 9 ++------- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/action.yml b/action.yml index ce41451..9fe2eee 100644 --- a/action.yml +++ b/action.yml @@ -12,10 +12,6 @@ inputs: description: "The path to the repository where the action will be used, e.g. 'alstr/my-repo' (automatically set)" required: true default: "${{ github.repository }}" - BEFORE: - description: "The SHA of the last pushed commit (automatically set)" - required: true - default: "${{ github.event.before }}" SHA: description: "The SHA of the latest commit (automatically set)" required: true diff --git a/main.py b/main.py index e18e7cf..c13e8f9 100644 --- a/main.py +++ b/main.py @@ -48,7 +48,6 @@ class GitHubClient(object): def __init__(self): self.repo = os.getenv('INPUT_REPO') - self.before = os.getenv('INPUT_BEFORE') self.sha = os.getenv('INPUT_SHA') self.token = os.getenv('INPUT_TOKEN') self.issues_url = f'{self.repos_url}{self.repo}/issues' @@ -62,12 +61,8 @@ class GitHubClient(object): self._get_existing_issues() def get_last_diff(self): - """Get the last diff based on the SHA of the last two commits.""" - if not self.before or self.before.startswith('000000'): - # Last commit SHA is empty which means this is the first commit of the branch - diff_url = f'{self.repos_url}{self.repo}/commits/{self.sha}' - else: - diff_url = f'{self.repos_url}{self.repo}/compare/{self.before}...{self.sha}' + """Get the last commit diff.""" + diff_url = f'{self.repos_url}{self.repo}/commits/{self.sha}' diff_headers = { 'Accept': 'application/vnd.github.v3.diff', 'Authorization': f'token {self.token}' From 83d97eeea1ca7c206eba457e526cad0462af6d88 Mon Sep 17 00:00:00 2001 From: "Luis G. Valle" <354372+lgvalle@users.noreply.github.com> Date: Thu, 26 Aug 2021 10:45:28 +0200 Subject: [PATCH 4/4] Support new branches with multiple commits (#25) Add support for newly created branches with multiple commits --- action.yml | 8 ++++++++ main.py | 21 +++++++++++++++++---- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/action.yml b/action.yml index 9fe2eee..c2cd07f 100644 --- a/action.yml +++ b/action.yml @@ -12,6 +12,14 @@ inputs: description: "The path to the repository where the action will be used, e.g. 'alstr/my-repo' (automatically set)" required: true default: "${{ github.repository }}" + BEFORE: + description: "The SHA of the last pushed commit (automatically set)" + required: true + default: "${{ github.event.before }}" + COMMITS: + description: "An array of commit objects describing the pushed commits" + required: true + default: "${{ toJSON(github.event.commits) }}" SHA: description: "The SHA of the latest commit (automatically set)" required: true diff --git a/main.py b/main.py index c13e8f9..dbfb684 100644 --- a/main.py +++ b/main.py @@ -48,7 +48,9 @@ class GitHubClient(object): def __init__(self): self.repo = os.getenv('INPUT_REPO') + self.before = os.getenv('INPUT_BEFORE') self.sha = os.getenv('INPUT_SHA') + self.commits = json.loads(os.getenv('INPUT_COMMITS')) self.token = os.getenv('INPUT_TOKEN') self.issues_url = f'{self.repos_url}{self.repo}/issues' self.issue_headers = { @@ -60,9 +62,22 @@ class GitHubClient(object): # Retrieve the existing repo issues now so we can easily check them later. self._get_existing_issues() + def get_timestamp(self, commit): + return commit.get('timestamp') + def get_last_diff(self): - """Get the last commit diff.""" - diff_url = f'{self.repos_url}{self.repo}/commits/{self.sha}' + """Get the last diff.""" + if self.before != '0000000000000000000000000000000000000000': + # There is a valid before SHA to compare with + diff_url = f'{self.repos_url}{self.repo}/compare/{self.before}...{self.sha}' + elif len(self.commits) == 1: + # There is only one commit + diff_url = f'{self.repos_url}{self.repo}/commits/{self.sha}' + else: + # There are several commits: compare with the oldest one + oldest = sorted(self.commits, key=self.get_timestamp)[0]['id'] + diff_url = f'{self.repos_url}{self.repo}/compare/{oldest}...{self.sha}' + diff_headers = { 'Accept': 'application/vnd.github.v3.diff', 'Authorization': f'token {self.token}' @@ -260,7 +275,6 @@ class GitHubClient(object): else: print('Issue card could not be added to project') - class TodoParser(object): """Parser for extracting information from a given diff file.""" FILE_HUNK_PATTERN = r'(?<=diff)(.*?)(?=diff\s--git\s)' @@ -589,7 +603,6 @@ class TodoParser(object): projects = list(filter(None, projects.split(','))) return projects - if __name__ == "__main__": # Create a basic client for communicating with GitHub, automatically initialised with environment variables. client = GitHubClient()