|
| 1 | +import re |
| 2 | +from git import Repo |
| 3 | + |
| 4 | +from optparse import make_option |
| 5 | + |
| 6 | +from xml.etree import cElementTree as ElementTree |
| 7 | + |
| 8 | +from django.core.management.base import BaseCommand |
| 9 | + |
| 10 | + |
| 11 | +class Command(BaseCommand): |
| 12 | + |
| 13 | + help = 'Creates JIRA issues for every failed case for specified branch' |
| 14 | + result_file = 'nosetests.xml' |
| 15 | + failure_row_re = re.compile(r'\s*File\s"(.*)",\sline\s(.*),.*') |
| 16 | + |
| 17 | + option_list = BaseCommand.option_list + ( |
| 18 | + make_option( |
| 19 | + '-b', |
| 20 | + '--branches', |
| 21 | + action='store', |
| 22 | + dest='branches', |
| 23 | + help='Affected branches', |
| 24 | + ), |
| 25 | + make_option( |
| 26 | + '-t', |
| 27 | + '--target-branch', |
| 28 | + action='store', |
| 29 | + dest='target_branch', |
| 30 | + help='Target branch', |
| 31 | + ) |
| 32 | + ) |
| 33 | + |
| 34 | + @staticmethod |
| 35 | + def parse_test_path(path): |
| 36 | + path, classname = path.rsplit('.', 1) |
| 37 | + path = path.replace('.', '/') |
| 38 | + return path, classname |
| 39 | + |
| 40 | + def handle(self, *args, **options): |
| 41 | + repo = Repo() |
| 42 | + try: |
| 43 | + branches = [repo.heads[x] for x in options['branches'].split(',')] |
| 44 | + target = repo.heads[options['target_branch']] |
| 45 | + except IndexError as e: |
| 46 | + return 'Cannot find branch with error "{0}"'.format(e) |
| 47 | + if target != repo.head.ref: |
| 48 | + return 'Current branch "{0}" does not match provided CircleCI branch "{1}"'.format( |
| 49 | + repo.head.ref, target |
| 50 | + ) |
| 51 | + elif target not in branches: |
| 52 | + return 'Skipping check for branch "{0}"'.format(repo.head.ref) |
| 53 | + |
| 54 | + try: |
| 55 | + root = ElementTree.parse(self.result_file).getroot() |
| 56 | + if root.attrib['errors']: |
| 57 | + for testcase in root: |
| 58 | + for failure in testcase: |
| 59 | + print('Failure for {}'. format(testcase.attrib['name'])) |
| 60 | + path, classname = self.parse_test_path(testcase.attrib['classname']) |
| 61 | + print path, classname |
| 62 | + for (file_path, line_number) in re.findall(self.failure_row_re, failure.text): |
| 63 | + if path in file_path: |
| 64 | + print repo.git.blame('HEAD', file_path) |
| 65 | + else: |
| 66 | + return 'No errors' |
| 67 | + except IOError: |
| 68 | + return 'File "{0}" does not exist'.format(self.result_file) |
0 commit comments