summaryrefslogtreecommitdiffstats
path: root/hacking/build_library/build_ansible/command_plugins/file_deprecated_issues.py
diff options
context:
space:
mode:
Diffstat (limited to 'hacking/build_library/build_ansible/command_plugins/file_deprecated_issues.py')
-rw-r--r--hacking/build_library/build_ansible/command_plugins/file_deprecated_issues.py153
1 files changed, 153 insertions, 0 deletions
diff --git a/hacking/build_library/build_ansible/command_plugins/file_deprecated_issues.py b/hacking/build_library/build_ansible/command_plugins/file_deprecated_issues.py
new file mode 100644
index 0000000..139ecc4
--- /dev/null
+++ b/hacking/build_library/build_ansible/command_plugins/file_deprecated_issues.py
@@ -0,0 +1,153 @@
+# -*- coding: utf-8 -*-
+# (c) 2017, Matt Martz <matt@sivel.net>
+# (c) 2019, Ansible Project
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+
+import argparse
+import os
+import time
+
+from collections import defaultdict
+
+from ansible.release import __version__ as ansible_version
+
+# Pylint doesn't understand Python3 namespace modules.
+from ..commands import Command # pylint: disable=relative-beyond-top-level
+from .. import errors # pylint: disable=relative-beyond-top-level
+
+ANSIBLE_MAJOR_VERSION = '.'.join(ansible_version.split('.')[:2])
+
+
+def get_token(token_file):
+ if token_file:
+ return token_file.read().strip()
+
+ token = os.getenv('GITHUB_TOKEN').strip()
+ if not token:
+ raise errors.MissingUserInput(
+ 'Please provide a file containing a github oauth token with public_repo scope'
+ ' via the --github-token argument or set the GITHUB_TOKEN env var with your'
+ ' github oauth token'
+ )
+ return token
+
+
+def parse_deprecations(problems_file_handle):
+ deprecated = defaultdict(list)
+ deprecation_errors = problems_file_handle.read()
+ for line in deprecation_errors.splitlines():
+ path = line.split(':')[0]
+ if path.endswith('__init__.py'):
+ component = os.path.basename(os.path.dirname(path))
+ else:
+ component, dummy = os.path.splitext(os.path.basename(path).lstrip('_'))
+
+ title = (
+ '%s contains deprecated call to be removed in %s' %
+ (component, ANSIBLE_MAJOR_VERSION)
+ )
+ deprecated[component].append(
+ dict(title=title, path=path, line=line)
+ )
+ return deprecated
+
+
+def find_project_todo_column(repo, project_name):
+ project = None
+ for project in repo.projects():
+ if project.name.lower() == project_name:
+ break
+ else:
+ raise errors.InvalidUserInput('%s was an invalid project name' % project_name)
+
+ for project_column in project.columns():
+ column_name = project_column.name.lower()
+ if 'todo' in column_name or 'backlog' in column_name or 'to do' in column_name:
+ return project_column
+
+ raise Exception('Unable to determine the todo column in'
+ ' project %s' % project_name)
+
+
+def create_issues(deprecated, body_tmpl, repo):
+ issues = []
+
+ for component, items in deprecated.items():
+ title = items[0]['title']
+ path = '\n'.join(set((i['path']) for i in items))
+ line = '\n'.join(i['line'] for i in items)
+ body = body_tmpl % dict(component=component, path=path,
+ line=line,
+ version=ANSIBLE_MAJOR_VERSION)
+
+ issue = repo.create_issue(title, body=body, labels=['deprecated'])
+ print(issue)
+ issues.append(issue)
+
+ # Sleep a little, so that the API doesn't block us
+ time.sleep(0.5)
+
+ return issues
+
+
+class FileDeprecationTickets(Command):
+ name = 'file-deprecation-tickets'
+
+ @classmethod
+ def init_parser(cls, add_parser):
+ parser = add_parser(cls.name, description='File tickets to cleanup deprecated features for'
+ ' the next release')
+ parser.add_argument('--template', default='deprecated_issue_template.md',
+ type=argparse.FileType('r'),
+ help='Path to markdown file template to be used for issue '
+ 'body. Default: %(default)s')
+ parser.add_argument('--project-name', default='', type=str,
+ help='Name of a github project to assign all issues to')
+ parser.add_argument('--github-token', type=argparse.FileType('r'),
+ help='Path to file containing a github token with public_repo scope.'
+ ' This token in this file will be used to open the deprcation'
+ ' tickets and add them to the github project. If not given,'
+ ' the GITHUB_TOKEN environment variable will be tried')
+ parser.add_argument('problems', type=argparse.FileType('r'),
+ help='Path to file containing pylint output for the '
+ 'ansible-deprecated-version check')
+
+ @staticmethod
+ def main(args):
+ try:
+ from github3 import GitHub
+ except ImportError:
+ raise errors.DependencyError(
+ 'This command needs the github3.py library installed to work'
+ )
+
+ token = get_token(args.github_token)
+ args.github_token.close()
+
+ deprecated = parse_deprecations(args.problems)
+ args.problems.close()
+
+ body_tmpl = args.template.read()
+ args.template.close()
+
+ project_name = args.project_name.strip().lower()
+
+ gh_conn = GitHub(token=token)
+ repo = gh_conn.repository('abadger', 'ansible')
+
+ if project_name:
+ project_column = find_project_todo_column(repo, project_name)
+
+ issues = create_issues(deprecated, body_tmpl, repo)
+
+ if project_column:
+ for issue in issues:
+ project_column.create_card_with_issue(issue)
+ time.sleep(0.5)
+
+ return 0