Merge pull request #72 from lgvalle/master

Add alternative diff url for first branch commit
This commit is contained in:
Alastair Mooney 2021-08-26 18:43:05 +01:00 committed by GitHub
commit 1394166bbd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 59 additions and 44 deletions

View File

@ -15,7 +15,11 @@ inputs:
BEFORE: BEFORE:
description: "The SHA of the last pushed commit (automatically set)" description: "The SHA of the last pushed commit (automatically set)"
required: true required: true
default: "${{ github.event.before }}" default: "${{ github.event.before }}"
COMMITS:
description: "An array of commit objects describing the pushed commits"
required: true
default: "${{ toJSON(github.event.commits) }}"
SHA: SHA:
description: "The SHA of the latest commit (automatically set)" description: "The SHA of the latest commit (automatically set)"
required: true required: true

97
main.py
View File

@ -50,6 +50,7 @@ class GitHubClient(object):
self.repo = os.getenv('INPUT_REPO') self.repo = os.getenv('INPUT_REPO')
self.before = os.getenv('INPUT_BEFORE') self.before = os.getenv('INPUT_BEFORE')
self.sha = os.getenv('INPUT_SHA') self.sha = os.getenv('INPUT_SHA')
self.commits = json.loads(os.getenv('INPUT_COMMITS'))
self.token = os.getenv('INPUT_TOKEN') self.token = os.getenv('INPUT_TOKEN')
self.issues_url = f'{self.repos_url}{self.repo}/issues' self.issues_url = f'{self.repos_url}{self.repo}/issues'
self.issue_headers = { self.issue_headers = {
@ -61,9 +62,22 @@ class GitHubClient(object):
# Retrieve the existing repo issues now so we can easily check them later. # Retrieve the existing repo issues now so we can easily check them later.
self._get_existing_issues() self._get_existing_issues()
def get_timestamp(self, commit):
return commit.get('timestamp')
def get_last_diff(self): def get_last_diff(self):
"""Get the last diff based on the SHA of the last two commits.""" """Get the last diff."""
diff_url = f'{self.repos_url}{self.repo}/compare/{self.before}...{self.sha}' 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 = { diff_headers = {
'Accept': 'application/vnd.github.v3.diff', 'Accept': 'application/vnd.github.v3.diff',
'Authorization': f'token {self.token}' 'Authorization': f'token {self.token}'
@ -261,7 +275,6 @@ class GitHubClient(object):
else: else:
print('Issue card could not be added to project') print('Issue card could not be added to project')
class TodoParser(object): class TodoParser(object):
"""Parser for extracting information from a given diff file.""" """Parser for extracting information from a given diff file."""
FILE_HUNK_PATTERN = r'(?<=diff)(.*?)(?=diff\s--git\s)' FILE_HUNK_PATTERN = r'(?<=diff)(.*?)(?=diff\s--git\s)'
@ -590,44 +603,42 @@ class TodoParser(object):
projects = list(filter(None, projects.split(','))) projects = list(filter(None, projects.split(',')))
return projects return projects
if __name__ == "__main__": if __name__ == "__main__":
if os.getenv('INPUT_BEFORE') != '0000000000000000000000000000000000000000': # Create a basic client for communicating with GitHub, automatically initialised with environment variables.
# Create a basic client for communicating with GitHub, automatically initialised with environment variables. client = GitHubClient()
client = GitHubClient() # Get the diff from the last pushed commit.
# Get the diff from the last pushed commit. last_diff = StringIO(client.get_last_diff())
last_diff = StringIO(client.get_last_diff()) # Parse the diff for TODOs and create an Issue object for each.
# Parse the diff for TODOs and create an Issue object for each. raw_issues = TodoParser().parse(last_diff)
raw_issues = TodoParser().parse(last_diff) # This is a simple, non-perfect check to filter out any TODOs that have just been moved.
# 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 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.
# It is based on the assumption that TODOs will not have identical titles in identical files. issues_to_process = []
issues_to_process = [] for values, similar_issues in itertools.groupby(raw_issues, key=operator.attrgetter('title', 'file_name',
for values, similar_issues in itertools.groupby(raw_issues, key=operator.attrgetter('title', 'file_name', 'markdown_language')):
'markdown_language')): similar_issues = list(similar_issues)
similar_issues = list(similar_issues) if (len(similar_issues) == 2 and ((similar_issues[0].status == LineStatus.ADDED and
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.DELETED) or (similar_issues[1].status == LineStatus.ADDED and
(similar_issues[1].status == LineStatus.ADDED and similar_issues[0].status == LineStatus.DELETED))):
similar_issues[0].status == LineStatus.DELETED))): print(f'Issue "{values[0]}" appears as both addition and deletion. '
print(f'Issue "{values[0]}" appears as both addition and deletion. ' f'Assuming this issue has been moved so skipping.')
f'Assuming this issue has been moved so skipping.') continue
continue issues_to_process.extend(similar_issues)
issues_to_process.extend(similar_issues) # Cycle through the Issue objects and create or close a corresponding GitHub issue for each.
# Cycle through the Issue objects and create or close a corresponding GitHub issue for each. for j, raw_issue in enumerate(issues_to_process):
for j, raw_issue in enumerate(issues_to_process): print(f'Processing issue {j + 1} of {len(issues_to_process)}')
print(f'Processing issue {j + 1} of {len(issues_to_process)}') if raw_issue.status == LineStatus.ADDED:
if raw_issue.status == LineStatus.ADDED: status_code = client.create_issue(raw_issue)
status_code = client.create_issue(raw_issue) if status_code == 201:
if status_code == 201: print('Issue created')
print('Issue created') else:
else: print('Issue could not be created')
print('Issue could not be created') elif raw_issue.status == LineStatus.DELETED and os.getenv('INPUT_CLOSE_ISSUES', 'true') == 'true':
elif raw_issue.status == LineStatus.DELETED and os.getenv('INPUT_CLOSE_ISSUES', 'true') == 'true': status_code = client.close_issue(raw_issue)
status_code = client.close_issue(raw_issue) if status_code == 201:
if status_code == 201: print('Issue closed')
print('Issue closed') else:
else: print('Issue could not be closed')
print('Issue could not be closed') # Stagger the requests to be on the safe side.
# Stagger the requests to be on the safe side. sleep(1)
sleep(1)