# Path: blackbelt/handle_github.py
# def get_pr_info(pr_url):
#     match = re.match(r".*github.com/(?P<owner>\S+)/{1}(?P<name>\S+)/pull/{1}(?P<number>\d+).*$", pr_url)
#     if not match:
#         raise ValueError("Cannot parse pull request URL, bad format")
#     return match.groupdict()
# 
# def verify_merge(pr_url, headers, max_waiting_time=30, retry_time=0.1):
#     merge_url = get_pr_api_url(pr_url) + "/merge"  # https://api.github.com/repos/apiaryio/apiary/pulls/1234/merge
#     start_time = datetime.now()
#     succeeded = False
# 
#     def do_request():
#         r = requests.get(merge_url, headers=headers)
# 
#         if r.status_code == 404:
#             if datetime.now() < start_time + timedelta(seconds=max_waiting_time):
#                 sleep(retry_time)
#                 return False
#             else:
#                 raise ValueError("GitHub says PR hasn't been merged yet and I've reached the waiting time of %s seconds" % max_waiting_time)
# 
#         elif (r.status_code not in [200, 204]):
#             raise ValueError("Can't get PR merge info with status code %s" % r.status_code)
# 
#         else:
#             return True
# 
#     while not succeeded:
#         succeeded = do_request()
# 
# def get_pr_ticket_id(description):
#     match = re.search(PR_PHRASE_PREFIX + ' ' + r"\[.*\]\(https://trello.com/c/(?P<id>\w+)/.*\)", description)
#     if not match or not 'id' in match.groupdict():
#         raise ValueError("Can't find URL in the PR description")
# 
#     return match.groupdict()['id']
# 
# def verify_pr_state(pr_details):
#     pr_state = pr_details['state']
#     message = "PR state: %s" % pr_state
#     if pr_state != 'open':
#         raise ValueError(message)
# 
#     print(message)
#     return message
# 
# def verify_pr_required_checks(pr_details):
#     status_url = "https://api.github.com/repos/%(repo_full_name)s/commits/%(head_sha)s/status" % {
#         'repo_full_name': pr_details['base']['repo']['full_name'],
#         'head_sha': pr_details['head']['sha']}
# 
#     pr_checks_info = get_json_response(status_url)
#     message = "PR required checks (%(count)g): %(state)s" % {
#         'count': len(pr_checks_info['statuses']),
#         'state': pr_checks_info['state']}
#     if pr_checks_info['state'] != 'success':
#         raise ValueError(message)
# 
#     print(message)
#     return message
# 
# def verify_branch_required_checks(branch_name):
#     repo = get_github_repo()
#     repo_info = get_remote_repo_info(repo)
# 
#     status_url = "https://api.github.com/repos/%(owner)s/%(name)s/commits/%(branch_name)s/status" % {
#         'owner': repo_info['owner'],
#         'name': repo_info['name'],
#         'branch_name': branch_name}
#     branch = get_json_response(status_url)
#     message = "Branch required checks (%(count)g): %(state)s" % {
#         'count': len(branch['statuses']),
#         'state': branch['state']}
#     if branch['state'] != 'success':
#         raise ValueError(message)
# 
#     print(message)
#     return message
# 
# def run_grunt_in_parallel(grunt_commands):
#     """ Helper function to run grunt commands (e.g. deploy or slug manipulation) for multiple environments in parallel"""
# 
#     return_code = 0
# 
#     commands = []
#     for command in grunt_commands:
#         with tempfile.NamedTemporaryFile(delete=False) as f:
#             app = get_grunt_application_name(' '.join(command))
#             commands.append({'app': app, 'process': Popen(command, stdout=f), 'log': f.name})
#             print('Running `{}` with PID {}'.format(' '.join(command), commands[-1]['process'].pid))
# 
#     print('\n')
# 
#     while len(commands):
#         sleep(5)
#         next_round = []
#         for command in commands:
#             rc = command['process'].poll()
#             if rc == None:
#                 next_round.append(command)
#             else:
#                 if rc == 0:
#                     print('Grunt task for {} completed successfully.\n'.format(command['app']))
#                     os.remove(command['log'])
#                 else:
#                     return_code = rc
#                     print('Grunt task for {} failed with exit code {}.'.format(command['app'], rc))
#                     print('Logfile can be found at {}\n'.format(command['log']))
# 
#         commands = next_round
# 
# 
#     return return_code
# 
# def get_grunt_application_name(command):
#     app_search = re.search("(--app=|-a=)(\w+)", command, re.IGNORECASE)
#     app = app_search.group(2) if app_search else "production"
# 
#     return app


from nose.tools import assert_equal, assert_raises, assert_not_equal
from mock import patch, MagicMock
from blackbelt.handle_github import (
    get_pr_info,
    verify_merge,
    get_pr_ticket_id,
    verify_pr_state,
    verify_pr_required_checks,
    verify_branch_required_checks,
    run_grunt_in_parallel,
    get_grunt_application_name,
)
import requests
import json



class TestGithubPullRequestParsing(object):

    github_pr = 'https://github.com/apiaryio/apiary-test/pull/123'

    def setUp(self):
        self.parsed = get_pr_info(self.github_pr)

    def test_repo_owner(self):
        assert_equal('apiaryio', self.parsed['owner'])

    def test_repo_name(self):
        assert_equal('apiary-test', self.parsed['name'])

    def test_pr_number(self):
        assert_equal('123', self.parsed['number'])

    def test_files_link(self):

# Path: blackbelt/handle_github.py
# def get_pr_info(pr_url):
#     match = re.match(r".*github.com/(?P<owner>\S+)/{1}(?P<name>\S+)/pull/{1}(?P<number>\d+).*$", pr_url)
#     if not match:
#         raise ValueError("Cannot parse pull request URL, bad format")
#     return match.groupdict()
# 
# def verify_merge(pr_url, headers, max_waiting_time=30, retry_time=0.1):
#     merge_url = get_pr_api_url(pr_url) + "/merge"  # https://api.github.com/repos/apiaryio/apiary/pulls/1234/merge
#     start_time = datetime.now()
#     succeeded = False
# 
#     def do_request():
#         r = requests.get(merge_url, headers=headers)
# 
#         if r.status_code == 404:
#             if datetime.now() < start_time + timedelta(seconds=max_waiting_time):
#                 sleep(retry_time)
#                 return False
#             else:
#                 raise ValueError("GitHub says PR hasn't been merged yet and I've reached the waiting time of %s seconds" % max_waiting_time)
# 
#         elif (r.status_code not in [200, 204]):
#             raise ValueError("Can't get PR merge info with status code %s" % r.status_code)
# 
#         else:
#             return True
# 
#     while not succeeded:
#         succeeded = do_request()
# 
# def get_pr_ticket_id(description):
#     match = re.search(PR_PHRASE_PREFIX + ' ' + r"\[.*\]\(https://trello.com/c/(?P<id>\w+)/.*\)", description)
#     if not match or not 'id' in match.groupdict():
#         raise ValueError("Can't find URL in the PR description")
# 
#     return match.groupdict()['id']
# 
# def verify_pr_state(pr_details):
#     pr_state = pr_details['state']
#     message = "PR state: %s" % pr_state
#     if pr_state != 'open':
#         raise ValueError(message)
# 
#     print(message)
#     return message
# 
# def verify_pr_required_checks(pr_details):
#     status_url = "https://api.github.com/repos/%(repo_full_name)s/commits/%(head_sha)s/status" % {
#         'repo_full_name': pr_details['base']['repo']['full_name'],
#         'head_sha': pr_details['head']['sha']}
# 
#     pr_checks_info = get_json_response(status_url)
#     message = "PR required checks (%(count)g): %(state)s" % {
#         'count': len(pr_checks_info['statuses']),
#         'state': pr_checks_info['state']}
#     if pr_checks_info['state'] != 'success':
#         raise ValueError(message)
# 
#     print(message)
#     return message
# 
# def verify_branch_required_checks(branch_name):
#     repo = get_github_repo()
#     repo_info = get_remote_repo_info(repo)
# 
#     status_url = "https://api.github.com/repos/%(owner)s/%(name)s/commits/%(branch_name)s/status" % {
#         'owner': repo_info['owner'],
#         'name': repo_info['name'],
#         'branch_name': branch_name}
#     branch = get_json_response(status_url)
#     message = "Branch required checks (%(count)g): %(state)s" % {
#         'count': len(branch['statuses']),
#         'state': branch['state']}
#     if branch['state'] != 'success':
#         raise ValueError(message)
# 
#     print(message)
#     return message
# 
# def run_grunt_in_parallel(grunt_commands):
#     """ Helper function to run grunt commands (e.g. deploy or slug manipulation) for multiple environments in parallel"""
# 
#     return_code = 0
# 
#     commands = []
#     for command in grunt_commands:
#         with tempfile.NamedTemporaryFile(delete=False) as f:
#             app = get_grunt_application_name(' '.join(command))
#             commands.append({'app': app, 'process': Popen(command, stdout=f), 'log': f.name})
#             print('Running `{}` with PID {}'.format(' '.join(command), commands[-1]['process'].pid))
# 
#     print('\n')
# 
#     while len(commands):
#         sleep(5)
#         next_round = []
#         for command in commands:
#             rc = command['process'].poll()
#             if rc == None:
#                 next_round.append(command)
#             else:
#                 if rc == 0:
#                     print('Grunt task for {} completed successfully.\n'.format(command['app']))
#                     os.remove(command['log'])
#                 else:
#                     return_code = rc
#                     print('Grunt task for {} failed with exit code {}.'.format(command['app'], rc))
#                     print('Logfile can be found at {}\n'.format(command['log']))
# 
#         commands = next_round
# 
# 
#     return return_code
# 
# def get_grunt_application_name(command):
#     app_search = re.search("(--app=|-a=)(\w+)", command, re.IGNORECASE)
#     app = app_search.group(2) if app_search else "production"
# 
#     return app


# Path: test/test_github.py
from nose.tools import assert_equal, assert_raises, assert_not_equal
from mock import patch, MagicMock
from blackbelt.handle_github import (
    get_pr_info,
    verify_merge,
    get_pr_ticket_id,
    verify_pr_state,
    verify_pr_required_checks,
    verify_branch_required_checks,
    run_grunt_in_parallel,
    get_grunt_application_name,
)
import requests
import json




class TestGithubPullRequestParsing(object):

    github_pr = 'https://github.com/apiaryio/apiary-test/pull/123'

    def setUp(self):
        self.parsed = get_pr_info(self.github_pr)

    def test_repo_owner(self):
        assert_equal('apiaryio', self.parsed['owner'])

    def test_repo_name(self):
        assert_equal('apiary-test', self.parsed['name'])

    def test_pr_number(self):
        assert_equal('123', self.parsed['number'])

    def test_files_link(self):

        parsed = get_pr_info(self.github_pr + '/files')