diff --git a/playbooks/airship-airshipctl-check-github-issues.yaml b/playbooks/airship-airshipctl-check-github-issues.yaml new file mode 100644 index 000000000..52ee9fd13 --- /dev/null +++ b/playbooks/airship-airshipctl-check-github-issues.yaml @@ -0,0 +1,32 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +- hosts: primary + tasks: + - name: Install python setuptools + package: + name: + - python3-pip + - python3-setuptools + state: present + become: yes + + - name: Install script dependencies + pip: + name: + - PyGithub==1.46 + executable: pip3 + - name: Run python script + script: > + check_github_issues.py "{{ zuul.message | b64decode }}" + args: + executable: python3 diff --git a/playbooks/files/check_github_issues.py b/playbooks/files/check_github_issues.py new file mode 100755 index 000000000..90ff43240 --- /dev/null +++ b/playbooks/files/check_github_issues.py @@ -0,0 +1,65 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import logging +import re +import sys + +import github + +ZUUL_MESSAGE = sys.argv[1] + +def construct_issue_list(match_list: list) -> list: + new_list = [] + for _issue in match_list: + try: + new_list.append(int(_issue)) + except ValueError: + logging.warning(f'Value {_issue} could not be converted to `int` type') + return new_list + + +def parse_issue_number(commit_msg: str) -> dict: + # Searches for Relates-To or Closes tags first to match and return + logging.debug(f'Parsing commit message: {commit_msg}') + related = re.findall(r'(?<=Relates-To: #)([0-9]+?)(?=\n)', commit_msg) + logging.debug(f'Captured related issues: {related}') + closes = re.findall(r'(?<=Closes: #)([0-9]+?)(?=\n)', commit_msg) + logging.debug(f'Captured closes issues: {closes}') + if related or closes: + return { + 'related': construct_issue_list(related), + 'closes': construct_issue_list(closes) + } + # If no Relates-To or Closes tags are defined, find legacy [#X] style tags + logging.debug('Falling back to legacy tags') + legacy_matches = re.findall(r'(?<=\[#)([0-9]+?)(?=\])', commit_msg) + logging.debug(f'Captured legacy issues: {legacy_matches}') + if not legacy_matches: + return {} + return { + 'related': construct_issue_list(legacy_matches) + } + + +def remove_duplicated_issue_numbers(issue_dict: dict) -> dict: + if 'closes' in issue_dict: + issue_dict['related'] = [x for x in issue_dict.get('related', []) if x not in issue_dict['closes']] + return issue_dict + +if __name__ == '__main__': + issue_number_dict = parse_issue_number(ZUUL_MESSAGE) + issue_number_dict = remove_duplicated_issue_numbers(issue_number_dict) + + if not issue_number_dict: + logging.debug( + f'ERROR: Use Tag(Relates-To or Closes) in the commit message with issue number to link GitHub Issue.') + sys.exit(1) diff --git a/zuul.d/jobs.yaml b/zuul.d/jobs.yaml index 55bdb84f7..25508fc12 100644 --- a/zuul.d/jobs.yaml +++ b/zuul.d/jobs.yaml @@ -43,6 +43,13 @@ nodeset: airship-airshipctl-single-node files: *gofiles +- job: + name: airship-airshipctl-check-github-issues + description: Checks if a Github issue is referenced in the commit message + run: playbooks/airship-airshipctl-check-github-issues.yaml + nodeset: airship-airshipctl-single-node + voting: false + - job: name: airship-airshipctl-update-github-issues description: Updates and/or closes related issues on Github on merge diff --git a/zuul.d/projects.yaml b/zuul.d/projects.yaml index 65dbc3072..681901901 100644 --- a/zuul.d/projects.yaml +++ b/zuul.d/projects.yaml @@ -22,6 +22,7 @@ - airship-airshipctl-lint - airship-airshipctl-unit - airship-airshipctl-roles-test + - airship-airshipctl-check-github-issues - airship-airshipctl-build-image - airship-airshipctl-validate-site-docs # - airship-airshipctl-functional-existing-k8s TODO: Enable this when functional tests exist, and a cluster is up