def build_issue(self, issue):
        self.create_fields(issue['fields'].keys())
        yt_issue = youtrack.Issue()
        yt_issue.numberInProject = issue['key'][(issue['key'].find('-') + 1):]
        yt_issue['comments'] = []
        yt_issue['description'] = self.build_description(issue)
        for field, value in issue['fields'].items():
            if value is None:
                continue
            field_name, field_type = self.describe_field(field)
            if field_name is None:
                continue
            if field_name == 'comment':
                for comment in value['comments']:
                    yt_issue['comments'].append(self.build_comment(comment))
            if field_type is None:
                if _debug:
                    print 'DEBUG: unclassified field', field
                continue

            is_list = isinstance(value, list)
            values = []
            for v in (value if is_list else [value]):
                values.append(self.build_value(field_name, field_type, v))
            if len(values):
                if is_list:
                    yt_issue[field_name] = values
                else:
                    yt_issue[field_name] = values[0]
        if 'reporterName' not in yt_issue:
            yt_issue['reporterName'] = 'root'
        return yt_issue
Ejemplo n.º 2
0
 def _make_issue(self, redmine_issue, project_id):
     issue = youtrack.Issue()
     issue['comments'] = []
     try:
         if self._params.get('create_redmine_linkage', False):
             self._add_field_to_issue(project_id, issue, "redmine_id",
                                      int(redmine_issue.id))
         for name, value in redmine_issue.attributes.items():
             if name in ('project', 'attachments'):
                 continue
             if name == 'assigned_to' and value.name in self._groups:
                 continue
             if name == 'id':
                 value = str(self._get_yt_issue_number(redmine_issue))
             if name == 'custom_fields':
                 for field in value:
                     self._add_field_to_issue(project_id, issue, field.name,
                                              field.value)
             elif name == 'journals':
                 self._add_journals(issue, value)
             else:
                 if name == 'category':
                     value = self._to_yt_subsystem(value)
                 if name == 'fixed_version':
                     value = self._to_yt_version(value)
                 self._add_field_to_issue(project_id, issue, name, value)
     except Exception, e:
         print 'Failed to process issue:'
         print redmine_issue
         traceback.print_exc()
         raise e
Ejemplo n.º 3
0
 def getIssues(self, projectId, filter, after, max):
     #response, content = self._req('GET', '/project/issues/' + urlquote(projectId) + "?" +
     response, content = self._req('GET', '/issue/byproject/' + urlquote(projectId) + "?" +
                                          urllib.urlencode({'after': str(after),
                                                            'max': str(max),
                                                            'filter': filter}))
     xml = minidom.parseString(content)
     return [youtrack.Issue(e, self) for e in xml.documentElement.childNodes if e.nodeType == Node.ELEMENT_NODE]
Ejemplo n.º 4
0
 def getAllIssues(self, filter = '', after = 0, max = 999999, withFields = ()):
     urlJobby = [('with',field) for field in withFields] + \
                 [('after',str(after)),
                 ('max',str(max)),
                 ('filter',filter)]
     response, content = self._req('GET', '/issue' + "?" +
                                          urllib.urlencode(urlJobby))
     xml = minidom.parseString(content)
     return [youtrack.Issue(e, self) for e in xml.documentElement.childNodes if e.nodeType == Node.ELEMENT_NODE]
Ejemplo n.º 5
0
 def get_issues(self, project_id, _filter, after, _max, updated_after=None, wikify=None):
     # response, content = self._req('GET', '/project/issues/' + urlquote(projectId) + "?" +
     params = {'after': str(after),
               'max': str(_max),
               'filter': _filter}
     if updated_after is not None:
         params['updatedAfter'] = updated_after
     if wikify is not None:
         params['wikifyDescription'] = wikify
     response, content = self._req('GET', '/issue/byproject/' + urlquote(project_id) + "?" +
                                   urllib.parse.urlencode(params))
     xml = minidom.parseString(content)
     return [youtrack.Issue(e, self) for e in xml.documentElement.childNodes if e.nodeType == Node.ELEMENT_NODE]
def to_youtrack_issue(project_ID, trac_issue, check_box_fields):
    issue = youtrack.Issue()

    issue.numberInProject = str(trac_issue.id)
    issue.summary = trac_issue.summary
    issue.description = trac_issue.description
    if trac_issue.time > 0:
        issue.created = str(trac_issue.time)
    if trac_issue.changetime > 0:
        issue.updated = str(trac_issue.changetime)
        # anonymous in trac == guest in util
    if trac_issue.reporter is None:
        issue.reporterName = "guest"
    else:
        issue.reporterName = trac_issue.reporter
    # watchers
    issue.watcherName = set([])
    for cc in trac_issue.cc:
        issue.watcherName.add(cc)
    # adding custom fields to issue
    custom_fields = trac_issue.custom_fields
    for cf in custom_fields.keys():
        if cf in check_box_fields:
            if custom_fields[cf] != "0":
                issue[cf] = check_box_fields[cf]
        else:
            value = custom_fields[cf]
            if cf in youtrackutils.tracLib.FIELD_NAMES.keys():
                cf = youtrackutils.tracLib.FIELD_NAMES[cf]
            if cf in youtrackutils.tracLib.FIELD_VALUES.keys():
                cf_values_mapping = youtrackutils.tracLib.FIELD_VALUES[cf]
                if value in cf_values_mapping:
                    value = cf_values_mapping[value]
            if (value is not None) and (value.strip() != ""):
                issue[cf] = value

    # handle special case of status:closed / resolution:fixed
    if (custom_fields["Status"] is not None) and (custom_fields["Status"] == "closed"):
        if (custom_fields["Resolution"] is not None) and (custom_fields["Resolution"] == "fixed"):
            issue["State"] = "Verified"

    unsorted_comments = []
    for comment in trac_issue.comments:
        unsorted_comments.append(to_youtrack_comment(project_ID, comment))
    issue.comments = sorted(unsorted_comments, key=lambda it: it.created)
    return issue
Ejemplo n.º 7
0
    def _make_issue(self, redmine_issue, project_id):
        issue = youtrack.Issue()
        issue['comments'] = []
        print(("--- ISSUE #{0}".format(redmine_issue.id)))
        if self._params.get('use_markdown'):
            issue['markdown'] = "true"
        try:
            if not hasattr(redmine_issue, 'author'):
                redmine_issue.author = 2  # set to Anonymous
            if self._params.get('create_redmine_linkage', False):
                self._add_field_to_issue(project_id, issue, "redmine_id",
                                         int(redmine_issue.id))
            checklist_value = None
            for name, value in list(redmine_issue.attributes.items()):
                if name in ('project', 'attachments', 'tags'):
                    continue
                if name == 'assigned_to' and value.name in self._groups:
                    continue
                if name == 'id':
                    value = str(self._get_yt_issue_number(redmine_issue))
                if name == 'checklist':
                    checklist_value = str(value)
                    continue
                if name == 'custom_fields':
                    for field in value:
                        self._add_field_to_issue(project_id, issue, field.name,
                                                 getattr(field, 'value', None))
                elif name == 'journals':
                    self._add_journals(issue, value)
                else:
                    if name == 'category':
                        value = self._to_yt_subsystem(value)
                    self._add_field_to_issue(project_id, issue, name, value)
            if checklist_value:
                issue['description'] = issue[
                    'description'] + "\n\n#### Checklist\n" + checklist_value

        except Exception as e:
            print('Failed to process issue:')
            print(redmine_issue)
            traceback.print_exc()
            raise e
        return issue
def to_youtrack_issue(trac_issue, check_box_fields):
    issue = youtrack.Issue()

    issue.numberInProject = str(trac_issue.id)
    issue.summary = trac_issue.summary
    issue.description = trac_issue.description
    if trac_issue.time > 0:
        issue.created = str(trac_issue.time)
    if trac_issue.changetime > 0:
        issue.updated = str(trac_issue.changetime)
        # anonymous in trac == guest in youtrack
    if trac_issue.reporter is None:
        issue.reporterName = "guest"
    else:
        issue.reporterName = trac_issue.reporter
    #watchers
    issue.watcherName = set([])
    for cc in trac_issue.cc:
        issue.watcherName.add(cc)
    #adding custom fields to issue
    custom_fields = trac_issue.custom_fields
    for cf in custom_fields.keys():
        if cf in check_box_fields:
            if custom_fields[cf] != "0":
                issue[cf] = check_box_fields[cf]
        else:
            value = custom_fields[cf]
            if cf in tracLib.FIELD_NAMES.keys():
                cf = tracLib.FIELD_NAMES[cf]
            if cf in tracLib.FIELD_VALUES.keys():
                cf_values_mapping = tracLib.FIELD_VALUES[cf]
                if value in cf_values_mapping:
                    value = cf_values_mapping[value]
            if (value is not None) and (value.strip() != ""):
                issue[cf] = value
    issue.comments = []
    for comment in trac_issue.comments:
        issue.comments.append(to_youtrack_comment(comment))
    return issue
Ejemplo n.º 9
0
 def getIssue(self, id):
     return youtrack.Issue(self._get("/issue/" + id), self)
Ejemplo n.º 10
0
 def get_issue(self, _id):
     return youtrack.Issue(self._get("/issue/" + _id), self)
def migrate_tasks_to_issues(a_conn, yt_conn, a_work, yt_proj, yt_login):
    """ Asana Tasks can be in multiple Projects, yet YouTrack Issues can be in only one Subsystem.  Thus, we will
     use the 1st Project in the Asana list to use as the YouTrack Subsystem """

    # We must filter tasks by project, tag, or assignee + workspace, so we'll use the last option and migrate tasks
    # one user at a time
    numberInProject = 0
    for a_id, a_user in _a_users.iteritems():
        a_tasks = [
            i for i in a_conn.tasks.find_all(params={
                'workspace': a_work['id'],
                'assignee': a_id
            })
        ]
        if len(a_tasks) == 0:
            continue
        msg = "Fetching details for {} Asana Tasks assigned to {} in Workspace {}"
        print msg.format(len(a_tasks), a_user['email'], a_work['name'])
        a_tasks = get_task_details(a_conn, a_tasks)
        # print "Asana task details: {}".format(a_tasks)

        # Add to map
        merge_into_map(a_tasks, 'name', _task_map)
        global _a_tasks
        for i in a_tasks:
            _a_tasks[i['id']] = i.copy()

        print "Fetching existing YouTrack tasks"
        # Checking existing issues in YouTrack
        yt_filter = "Assignee: {}".format(
            _user_map[a_user['email']]['yt'].login)
        yt_issues = [
            i for i in yt_conn.getIssues(yt_proj.id, yt_filter, 0, 1000)
        ]
        # yt_issues = [yt_conn.getIssue(i.id) for i in yt_conn.getIssues(yt_proj.id, yt_filter, 0, 1000)]
        merge_into_map(yt_issues, 'summary', _task_map)
        merge_into_map(yt_issues, 'AsanaID', _asana_id_map)
        global _yt_issues
        for i in yt_issues:
            _yt_issues[i.numberInProject] = i
            numberInProject = max(numberInProject, int(i.numberInProject))
        numberInProject += 1

        # print "Task details: {}".format(yt_issues)
        # Now add Issues from all Tasks
        new_issues = []
        print 'Fetching Asana stories for each task...'
        for a in a_tasks:
            # Skip adding tasks where task name matches issue summary
            if 'yt' in _task_map[a['name']] or str(a['id']) in _asana_id_map:
                print "Skipping task import : {}".format(
                    a['name'].encode('utf-8'))
                continue

            # Look at Asana Story to find out who the YouTrack Issue reporterName should be
            a_stories = get_task_stories(a_conn, a)
            a_stories = get_story_details(a_conn, a_stories)

            # Save for later
            _a_tasks[a['id']]['stories'] = a_stories
            # Establish our comments and who created this Task
            comments = []
            reporter_name = None
            for s in a_stories:
                if s['type'] == 'comment':
                    comment = yt.Comment()
                    comment.author = a_id_to_yt_login(s['created_by']['id'])
                    # _user_map[_a_users[s['created_by']['id']]['email']]['yt'].login
                    comment.text = s['text']
                    comment.created = a_to_yt_time(s['created_at'])
                    comments.append(comment)
                elif s['type'] == 'system' and reporter_name is None and s[
                        'text'][:9] in ['assigned ', 'added to ', 'added sub']:
                    # TODO if subtask, link to other YT Issue
                    reporter_name = a_id_to_yt_login(s['created_by']['id'])

            # Build a list for bulk importing later
            """[{'numberInProject':'1', 'summary':'some problem', 'description':'some description', 'priority':'1',
                                    'fixedVersion':['1.0', '2.0'],
                                    'comment':[{'author':'yamaxim', 'text':'comment text', 'created':'1267030230127'}]},
                                   {'numberInProject':'2', 'summary':'some problem', 'description':'some description', 'priority':'1'}]"""

            if reporter_name is None:
                if a.get('asignee', None) is not None:
                    reporter_name = a_id_to_yt_login(a['assignee']['id'])
                else:
                    reporter_name = yt_login

            new_issue = yt.Issue()
            new_issue.comments = comments
            new_issue.reporterName = reporter_name
            new_issue['AsanaID'] = str(a['id'])
            new_issue.numberInProject = str(numberInProject)
            new_issue.summary = a.get('name', '')
            new_issue.description = a.get('notes', '')
            new_issue.state = 'Fixed' if a.get('completed',
                                               False) is True else 'Submitted'
            new_issue.assignee = a_id_to_yt_login(a['assignee']['id'])
            if a['due_on'] is not None:
                new_issue['Due Date'] = a_to_yt_date(a['due_on'])
            # new_issue = dict(numberInProject=str(a['id']), summary=a.get('name', ''), description=a.get('notes', ''),
            #                  state='Fixed' if a.get('completed', False) is True else 'Submitted')
            if 'created_at' in a:
                # created = datetime.strptime(a['created_at'], '%Y-%m-%dT%H:%M:%S.%fZ')
                # created = "{}{}".format(created.strftime('%s'), created.strftime('%f'))[:-3]
                new_issue.created = a_to_yt_time(a['created_at'])
            if 'modified_at' in a:
                # updated = datetime.strptime(a['modified_at'], '%Y-%m-%dT%H:%M:%S.%fZ')
                # updated = "{}{}".format(updated.strftime('%s'), updated.strftime('%f'))[:-3]
                # new_issue.updated = updated
                new_issue.updated = a_to_yt_time(a['modified_at'])
            if a.get('completed_at', None) is not None:
                # resolved = datetime.strptime(a['completed_at'], '%Y-%m-%dT%H:%M:%S.%fZ')
                # resolved = "{}{}".format(resolved.strftime('%s'), resolved.strftime('%f'))[:-3]
                # new_issue.resolved = resolved
                new_issue.resolved = a_to_yt_time(a['completed_at'])
            if 'projects' in a and len(a['projects']) > 0:
                new_issue['subsystem'] = a['projects'][0]['name']

            new_issues.append(new_issue)
            numberInProject += 1
        print 'Creating new YouTrack Issues for {} (Asana IDs: {})'.format(
            a_user['email'], [n.AsanaID for n in new_issues])
        print yt_conn.importIssues(yt_proj.id, None, new_issues, test=False)