def main(argv): project_name = '' project_id = '' project_desc = '' project_usr = '******' project_pwd = 'Sarasa12' svn_cli = pysvn.Client() svn_working_path = '/tmp' youtrack_url = 'http://localhost:80' try: opts, args = getopt.getopt(argv,"hp:i:d:",["project_name=","project_id=", "project_desc="]) except getopt.GetoptError: print 'test.py -p <project_name> -i <project_id> -d <project_desc>' sys.exit(2) for opt, arg in opts: if opt == '-h': print 'test.py -p <project_name> -i <project_id> -d <project_desc>' sys.exit() elif opt in ("-p", "--project_name"): project_name = arg elif opt in ("-i", "--project_id"): project_id = arg elif opt in ("-d", "--project_desc"): project_desc = arg #yt = Connection('http://v-rot-mne-nogi.myjetbrains.com/youtrack', 'root', 'root') #, proxy_info = httplib2.ProxyInfo(socks.PROXY_TYPE_HTTP, 'localhost', 8888)) yt = Connection(youtrack_url, project_usr, project_pwd) #def createProjectDetailed(self, projectId, name, description, projectLeadLogin, startingNumber=1) print yt.createProjectDetailed(project_id, project_name, project_desc, project_usr, 1)
def jira2youtrack(source_url, source_login, source_password, target_url, target_login, target_password, project_id): print("source_url : " + source_url) print("source_login : "******"source_password : "******"target_url : " + target_url) print("target_login : "******"target_password : "******"project_id : " + project_id) source = JiraClient(source_url, source_login, source_password) target = Connection(target_url, target_login, target_password) # # target.createProjectDetailed(project_id, project_id, "", target_login) # # for i in range(0, 5500): # try: # jira_issues = source.get_issues(project_id, i * 10, (i + 1) * 10) # target.importIssues(project_id, project_id + " assignees", # [create_yt_issue_from_jira_issue(target, issue, project_id) for issue in # jira_issues]) # for issue in jira_issues: # process_labels(target, issue) # process_attachments(source, target, issue) # except BaseException, e: # print(str(e)) for i in range(0, 5500): jira_issues = source.get_issues(project_id, i * 50, (i + 1) * 50) links = [] for issue in jira_issues: process_links(target, issue, links) print(target.importLinks(links))
def jira2youtrack(source_url, source_login, source_password, target_url, target_login, target_password, projects, flags, field_mappings, value_mappings): print 'source_url : ' + source_url print 'source_login : '******'target_url : ' + target_url print 'target_login : '******'', target_login) except YouTrackException: pass while True: _end = start + chunk_size - 1 if end and _end > end: _end = end if start > _end: break print 'Processing issues: %s [%d .. %d]' % (project_id, start, _end) try: jira_issues = source.get_issues(project_id, start, _end) start += chunk_size if not (jira_issues or end): break # Filter out moved issues jira_issues = [issue for issue in jira_issues if issue['key'].startswith('%s-' % project_id)] if flags & FI_ISSUES: issues2import = [] for issue in jira_issues: issues2import.append( to_yt_issue(target, issue, project_id, field_mappings, value_mappings)) if not issues2import: continue target.importIssues( project_id, '%s assignees' % project_id, issues2import) except YouTrackException, e: print e continue for issue in jira_issues: if flags & FI_LINKS: process_links(target, issue, issue_links) if flags & FI_LABELS: process_labels(target, issue) if flags & FI_ATTACHMENTS: process_attachments(source, target, issue, flags & FI_REPLACE_ATTACHMENTS > 0) if flags & FI_WORK_LOG: process_worklog(source, target, issue)
def agilezen2youtrack(source_url, source_token, target_url, target_login, target_password, project_names_to_import): source = Client(source_url, source_token) target = Connection(target_url, target_login, target_password) last_page = False current_page = 1 try: target.createCustomFieldDetailed("State", "state[1]", False, True, True, {"attachBundlePolicy": "2"}) except YouTrackException, e: print str(e)
def submit(self): try: connection = Connection(settings.YOUTRACK_URL, settings.YOUTRACK_LOGIN, settings.YOUTRACK_PASSWORD) response, content = connection.createIssue(self.project, assignee=None, summary=u'Issue from feedback form', description=self.cleaned_data['description']) print response issue_id = response['location'].split('/')[-1] connection.executeCommand(issue_id, 'Customer email ' + self.cleaned_data['email']) return True except YouTrackException: return False
def add_tags(tag_file,target_url, target_login, target_password): """ Add tags from the tag file (run after known creation) :param tag_file: :return: """ target = Connection(target_url, target_login, target_password) with open(tag_file) as tag_o_file: reader = csv.reader(tag_o_file) for row in reader: issue = row[0] for t in row[1:]: print "executing tag for %s" %(issue) target.executeCommand(issue, "tag %s" % (t))
def process_commits(secret=None): if context_secret and secret != context_secret: abort(403) yt = Connection(yt_url, yt_login, yt_password) try: cmd_pattern = re.compile( r'#((?:%s)-\d+)(?:\s+(.+))?' % '|'.join(yt.getProjects().keys()), re.IGNORECASE | re.MULTILINE) except YouTrackException: app.logger.warning('Cannot get projects from YT') cmd_pattern = re.compile(r'#([A-z]+-\d+)(?:\s+(.+))?', re.MULTILINE) payload = json.loads(request.form.get('payload')) commits_url_template = get_commits_url_template(payload) for commit in payload['commits']: message = commit['message'].encode('utf-8') issue_refs = cmd_pattern.findall(message) if not issue_refs: continue commit_node = commit['node'] commit_url = commits_url_template % commit['raw_node'] timestamp = commit['utctimestamp'] author = commit['author'].encode('utf-8') match = re.search(r'<(.+?)>', commit['raw_author']) if not match: app.logger.error("Cannot get author's email address.") abort(400) users = yt.getUsers(params={'q': match.group(1)}) if not users: app.logger.error('Cannot find user with email ' + match.group(1)) abort(400) if len(users) != 1: app.logger.error('Not unique email address ' + match.group(1)) abort(400) comment = "Commit [%s %s] made by '''%s''' on ''%s''\n{quote}%s{quote}" \ % (commit_url, commit_node, author, timestamp, message) cmd_exec_result = True for issue_id, command in issue_refs: if command is None: command = '' try: app.logger.info("Adding commit %s to issue %s (command: %s)" % (commit_node, issue_id, command)) yt.executeCommand(issue_id, command, comment, run_as=users[0].login) except YouTrackException as e: cmd_exec_result = False app.logger.error('Failed to add commit %s to issue %s: %s' % (commit_node, issue_id, e.message)) if not cmd_exec_result: abort(500) return 'success'
def submit(self): try: connection = Connection(settings.YOUTRACK_URL, settings.YOUTRACK_LOGIN, settings.YOUTRACK_PASSWORD) response, content = connection.createIssue(self.project, assignee=None, summary=self.get_summary().encode('utf-8'), description=self.cleaned_data['description'].encode('utf-8')) issue_id = response['location'].split('/')[-1] commands = '' if self.subsystem is not None: commands += ' Subsystem %s' % self.subsystem commands += ' Customer email ' + self.cleaned_data['email'] connection.executeCommand(issue_id, commands) return True except YouTrackException: return False
def main(): target_url, target_login, target_password, issue_source = sys.argv[1:5] target = Connection(target_url, target_login, target_password) if os.path.exists(issue_source): #"treat as a file of issues to delete" issues = open(issue_source).readlines() else: issues = [] issues.append(issue_source) for issue in issues: if str(issue).strip() == "": continue print "deleting %s" % (issue,) try: result = target._req("DELETE", "/issue/%s" % (str(issue).strip(),)) print result except Exception as e: print e
def youtrack2youtrack(source_url, source_login, source_password, target_url, target_login, target_password, project_ids, query = ''): if not len(project_ids): print "You should sign at least one project to import" return source = Connection(source_url, source_login, source_password) target = Connection(target_url, target_login, target_password) #, proxy_info = httplib2.ProxyInfo(socks.PROXY_TYPE_HTTP, 'localhost', 8888) print "Import issue link types" for ilt in source.getIssueLinkTypes(): try: print target.createIssueLinkType(ilt) except youtrack.YouTrackException, e: print e.message
def jira2youtrack(source_url, source_login, source_password, target_url, target_login, target_password, project_id, issues_count, skip_count): print("source_url : " + source_url) print("source_login : "******"target_url : " + target_url) print("target_login : "******"project_id : " + project_id) print("issues_count : ", issues_count) print("skip_count : ", skip_count) first_chunk = skip_count / 10 last_chunk = issues_count / 10 if issues_count % 10: last_chunk += 1 source = JiraClient(source_url, source_login, source_password) target = Connection(target_url, target_login, target_password) try: target.createProjectDetailed(project_id, project_id, "", target_login) except YouTrackException: pass for i in range(first_chunk, last_chunk): start = i * 10 + 1 end = (i + 1) * 10 + 1 if start <= skip_count: start = skip_count + 1 if end > issues_count + 1: end = issues_count + 1 try: jira_issues = source.get_issues(project_id, start, end) target.importIssues(project_id, project_id + " assignees", [create_yt_issue_from_jira_issue(target, issue, project_id) for issue in jira_issues]) for issue in jira_issues: try: process_labels(target, issue) except YouTrackException, e: print e try: process_attachments(source, target, issue) except YouTrackException, e: print e try: process_worklog(source, target, issue) except YouTrackException, e: print e
def googlecode2youtrack(project_name, source_login, source_password, target_url, target_login, target_password, project_id): target = Connection(target_url, target_login, target_password) try: target.getProject(project_id) except YouTrackException: target.createProjectDetailed(project_id, project_name, "", target_login) for field_name, field_type in googleCode.FIELD_TYPES.items(): create_and_attach_custom_field(target, project_id, field_name, field_type) start = 1 max = 30 while True: source = gdata.projecthosting.client.ProjectHostingClient() source.client_login(source_login, source_password, source="youtrack", service="code") print "Get issues from " + str(start) + " to " + str(start + max) query = gdata.projecthosting.client.Query(start_index=start, max_results=max) issues = source.get_issues(project_name, query=query).entry start += max if len(issues) <= 0: break target.importIssues(project_id, project_name + " assignees", [to_yt_issue(target, project_id, issue, source.get_comments(project_name, issue_id(issue)).entry) for issue in issues]) for issue in issues: import_tags(target, project_id, issue) import_attachments(target, project_id, project_name, issue, target_login)
def zendesk2youtrack(source_url, source_login, source_password, target_url, target_login, target_password, project_id): target = Connection(target_url, target_login, target_password) source = ZendeskClient(source_url, source_login, source_password) importer = ZendeskYouTrackImporter( source, target, ZendeskYouTrackImportConfig(youtrackutils.zendesk.NAMES, {}, {})) importer.do_import({project_id: project_id})
def push_event_hook(): push_event = request.json app.logger.debug(push_event) user_name = push_event['user_name'] repo_name = push_event['repository']['name'] repo_url = push_event['repository']['url'] repo_homepage = push_event['repository']['homepage'] refspec = push_event['ref'] app.logger.debug('Received push event by %s in branch %s on repository %s', user_name, refspec, repo_url) for commit in push_event['commits']: app.logger.debug('Processing commit %s by %s (%s) in %s', commit['id'], commit['author']['name'], commit['author']['email'], commit['url']) commit_time = dateutil.parser.parse(commit['timestamp']) issues = re.findall(app.config['REGEX'], commit['message'], re.MULTILINE) if not issues: app.logger.debug( '''Didn't find any referenced issues in commit %s''', commit['id']) else: app.logger.debug('Found %d referenced issues in commit %s', len(issues), commit['id']) yt = Connection(app.config['YOUTRACK_URL'], app.config['YOUTRACK_USERNAME'], app.config['YOUTRACK_PASSWORD']) user_login = get_user_login(yt, commit['author']['email']) if user_login is None: app.logger.warn( "Couldn't find user with email address %s. Using default user.", commit['author']['email']) default_user = yt.getUser(app.config['DEFAULT_USER']) user_login = default_user['login'] for issue_id in issues: app.logger.debug('Processing reference to issue %s', issue_id) try: yt.getIssue(issue_id) comment_string = 'Commit [%(url)s %(id)s] on branch %(refspec)s in [%(repo_homepage)s %(repo_name)s] made by %(author)s on %(date)s\n{quote}%(message)s{quote}' % { 'url': commit['url'], 'id': commit['id'], 'author': commit['author']['name'], 'date': str(commit_time), 'message': commit['message'], 'repo_homepage': repo_homepage, 'repo_name': repo_name, 'refspec': refspec } app.logger.debug(comment_string) yt.executeCommand(issueId=issue_id, command='comment', comment=comment_string.encode('utf-8'), run_as=user_login.encode('utf-8')) except YouTrackException: app.logger.warn("Couldn't find issue %s", issue_id) return Response('Push event processed. Thanks!', mimetype='text/plain')
def __init__(self, server, username, password): self.logger = LoggerFactory.getLogger("com.xebialabs.yourtrack.Server") if server is None: sys.exit("No server provided.") if username is not None: youtrackUsername = username else: youtrackUsername = server['username'] if password is not None: youtrackPassword = password else: youtrackPassword = server['password'] if server['token'] is not None: # authentication request with permanent token self.youtrack = YouTrack(server['url'], token=server['token']) else: # authentication with username and password self.youtrack = YouTrack(server['url'], login=youtrackUsername, password=youtrackPassword)
def host_elegido(bot, update, user_data): bot.sendChatAction(chat_id=update.callback_query.from_user.id, action=ChatAction.TYPING) usuario = usuarios.getCollection().find_one( {'chat_id': update.callback_query.from_user.id}) logger.info('Elegir host Opción {}'.format(update.callback_query.data)) host = next(x for x in usuario['hosts'] if x['host'] == update.callback_query.data) user_data['host'] = host try: connection = Connection(user_data['host']['host'], user_data['host']['username'], user_data['host']['pass']) connections[usuario['chat_id']] = connection proyectos = connection.getProjects() except YouTrackException as e: logger.error(e) del user_data['host']['pass'] usuarios.getCollection().update( {'chat_id': update.callback_query.from_user.id}, {'$pull': { 'hosts': user_data['host'] }}) return CONFIRMAR keyboard = [] for proyecto in proyectos.keys(): keyboard.append( InlineKeyboardButton(proyectos[proyecto], callback_data=proyecto)) # Acomodo el teclado keyboard = [keyboard[i:i + 3] for i in range(0, len(keyboard), 3)] reply_markup = InlineKeyboardMarkup(keyboard, resize_keyboard=True, one_time_keyboard=True) update.callback_query.edit_message_text(text="Bien! Elegí un proyecto", reply_markup=reply_markup) return PROYECTO
def issue_elegido(bot, update, user_data): bot.sendChatAction(chat_id=update.callback_query.from_user.id, action=ChatAction.TYPING) user_data['issue'] = update.callback_query.data logger.info('Elegir Issue {} Opción {}'.format(user_data['proyecto'], user_data['issue'])) connection = Connection(user_data['host']['host'], user_data['host']['username'], user_data['host']['pass']) try: the_types = connection.getProjectTimeTrackingWorkTypes( user_data['proyecto']) except YouTrackException as e: logger.error('Error de Youtrack {}'.format(e)) reply_markup = InlineKeyboardMarkup([[ InlineKeyboardButton("Elegir otro proyecto", callback_data=user_data['host']['host']) ]], resize_keyboard=True, one_time_keyboard=True) del user_data['proyecto'] update.callback_query.edit_message_text( text="El proyecto no admite registro de horas, hablá con tu PM", reply_markup=reply_markup) return HOST user_data['types'] = the_types['types'] keyboard = [] for one_type in the_types['types']: keyboard.append([ InlineKeyboardButton(one_type['name'], callback_data=one_type['id']) ]) reply_markup = InlineKeyboardMarkup(keyboard, resize_keyboard=True, one_time_keyboard=True) update.callback_query.edit_message_text(text="Elegí el tipo", reply_markup=reply_markup) return RECIBIR
class Fish: def __init__(self): self.conn = YT(YT_PATH, LOGIN, PASSWORD) def get_issue_data(self, project_id, request_filter, divider): issues = self.conn.get_issues(project_id, request_filter, AFTER, MAX) total_reward = 0 for issue in issues: total_reward += int(issue.get('Estimation', 0)) finished_issues = self.conn.get_issues( project_id, request_filter + FILTER_FINISHED, AFTER, MAX) total_cost = 0 for issue in finished_issues: total_cost += int(issue.get( 'Spent time', 0)) if int(issue.get('Spent time', 0)) < int( issue.get('Estimation', 0)) else int( issue.get('Estimation', 0)) return list(map(lambda x: x // divider, [total_reward, total_cost]))
def main(args): """ Add / Update / Remove items from the specified bundle """ enum_dest = EnumValueDest cnx = Connection(args.youtrack, args.yusername, args.ypassword) enum_bundle = cnx.getEnumBundle(args.bundle) list_items = {} for i in enum_bundle.values: list_items[v.element_name] = v.description enum_src = EnumValueSrc(args) for name, desc_data in enum_src.get_src_values(): desc = build_desc(args.desc, desc_data) if name in list_items.keys(): if not (desc == list_items[name]): pass pass else: print("%s: %s" % (name, str(desc_data)))
def import_attachments_only(source_url, source_login, source_password, target_url, target_login, target_password, project_ids): if not project_ids: print 'No projects to import. Exit...' return start = 0 max = 20 source = Connection(source_url, source_login, source_password) target = Connection(target_url, target_login, target_password) user_importer = UserImporter(source, target, caching_users=True) for projectId in project_ids: while True: try: print 'Get issues from %d to %d' % (start, start + max) issues = source.getIssues(projectId, '', start, max) if len(issues) <= 0: break for issue in issues: print 'Process attachments for issue %s' % issue.id attachments = issue.getAttachments() users = set([]) for a in attachments: author = a.getAuthor() if author is not None: users.add(author) user_importer.importUsersRecursively(users) for a in attachments: print 'Transfer attachment of %s: %s' % (issue.id, a.name.encode('utf-8')) try: target.createAttachmentFromAttachment(issue.id, a) except BaseException, e: print 'Cannot import attachment [ %s ]' % a.name.encode('utf-8') print repr(e) except Exception, e: print 'Cannot process issues from %d to %d' % (start, start + max) traceback.print_exc() raise e start += max
def process_commits(secret=None): if context_secret and secret != context_secret: abort(403) yt = Connection(yt_url, yt_login, yt_password) try: cmd_pattern = re.compile( r'#((?:%s)-\d+)(?:\s+(.+))?' % '|'.join(yt.getProjects().keys()), re.IGNORECASE | re.MULTILINE) except YouTrackException: app.logger.warning('Cannot get projects from YT') cmd_pattern = re.compile(r'#([A-z]+-\d+)(?:\s+(.+))?', re.MULTILINE) payload = json.loads(request.form.get('payload')) commits_url_template = get_commits_url_template(payload) for commit in payload['commits']: message = commit['message'].encode('utf-8') issue_refs = cmd_pattern.findall(message) if not issue_refs: continue commit_node = commit['node'] commit_url = commits_url_template % commit['raw_node'] timestamp = commit['utctimestamp'] author = commit['author'].encode('utf-8') match = re.search(r'<(.+?)>', commit['raw_author']) if not match: app.logger.error("Cannot get author's email address.") abort(400) users = yt.getUsers(params={'q': match.group(1)}) if not users: app.logger.error('Cannot find user with email ' + match.group(1)) abort(400) if len(users) != 1: app.logger.error('Not unique email address ' + match.group(1)) abort(400) comment = "Commit [%s %s] made by '''%s''' on ''%s''\n{quote}%s{quote}" \ % (commit_url, commit_node, author, timestamp, message) cmd_exec_result = True for issue_id, command in issue_refs: if command is None: command = '' try: app.logger.info( "Adding commit %s to issue %s (command: %s)" % (commit_node, issue_id, command)) yt.executeCommand(issue_id, command, comment, run_as=users[0].login) except YouTrackException as e: cmd_exec_result = False app.logger.error( 'Failed to add commit %s to issue %s: %s' % (commit_node, issue_id, e.message)) if not cmd_exec_result: abort(500) return 'success'
def csv2youtrack(source_file, target_url, target_login, target_password, comments_file=None, attachments_file=None): target = Connection(target_url, target_login, target_password) source = Client(source_file) source_comments = None if comments_file: source_comments = Client(comments_file) source_attachments = None if attachments_file: source_attachments = Client(attachments_file) config = CsvYouTrackImportConfig(csvClient.FIELD_NAMES, csvClient.FIELD_TYPES) importer = CsvYouTrackImporter(source, target, config, source_comments, source_attachments) importer.import_csv()
def issue_actualizar_estado(bot, update, user_data): bot.sendChatAction(chat_id=update.callback_query.from_user.id, action=ChatAction.TYPING) if update.callback_query.data == 'issue_estado_cerrar': estado = 'Fixed' else: estado = 'In Progress' logger.info('Actualizar estado issue {} {}'.format(user_data['issue'], estado)) try: connection = Connection(user_data['host']['host'], user_data['host']['username'], user_data['host']['pass']) command = 'State ' + estado connection.executeCommand(user_data['issue'], command) update.callback_query.edit_message_text("Gracias amego!") except Exception as e: logger.error(e) update.callback_query.edit_message_text("No eh!") return ConversationHandler.END
def receive_hook(): payload = request.json user_name = payload['user_name'] repo_url = payload['repository']['url'] app.logger.debug('Received payload for a push by %s on repository %s', user_name, repo_url) for commit in payload['commits']: app.logger.debug('Processing commit %s by %s (%s) in %s', commit['id'], commit['author']['name'], commit['author']['email'], commit['url']) commit_time = dateutil.parser.parse(commit['timestamp']) refs = re.findall(app.config['REGEX'], commit['message'], re.MULTILINE) if not refs: app.logger.info('''Didn't find any referenced issues in commit %s''', commit['id']) else: app.logger.info('Found %d referenced issues in commit %s', len(refs), commit['id']) yt = Connection(app.config['YOUTRACK_URL'], app.config['YOUTRACK_USERNAME'], app.config['YOUTRACK_PASSWORD']) user = app.config['DEFAULT_USER'] users = yt.getUsers({ 'q': commit['author']['email'] }) if not users: app.logger.warn('''Couldn't find user with email address %s. Using default user.''', commit['author']['email']) elif len(users) > 1: app.logger.warn('''Found more than one user with email address %s. Using default user.''', commit['author']['email']) else: user = users[0]['login'] for ref in refs: app.logger.info('Processing reference to issue %s', ref) try: issue = yt.getIssue(ref) comment_string = 'Commit [%(url)s %(id)s] made by %(author)s on %(date)s\n{quote}%(message)s{quote}' % {'url': commit['url'], 'id': commit['id'], 'author': commit['author']['name'], 'date': str(commit_time), 'message': commit['message']} app.logger.debug(comment_string) yt.executeCommand(issueId=ref, command='comment', comment=comment_string, run_as=user) except YouTrackException: app.logger.warn('''Couldn't find issue %s''', ref) return Response('Payload processed. Thanks!', mimetype='text/plain')
def push_event_hook(room=None): push_event = request.json app.logger.debug(push_event) app.logger.debug("slack_room:%s" % room) # process mergerequest if 'object_kind' in push_event and push_event['object_kind'] == 'merge_request': obj = push_event['object_attributes'] user = push_event['user'] slack = Slacker(app.config['SLACK_TOKEN']) url = "%s/%s/%s/merge_requests/%d" % (app.config['GITLAB_HOME'], obj['target']['namespace'], obj['target']['name'], obj['iid']) print url event = "Pull Request(%s): %s - %s\n%s" % (obj['state'], url, obj['title'], obj['description']) slack.chat.post_message('#%s' % room, event, username=user['username'], icon_url=user['avatar_url']) return Response('Push event processed. Thanks!', mimetype='text/plain') user_name = push_event['user_name'] repo_name = push_event['repository']['name'] repo_url = push_event['repository']['url'] repo_homepage = push_event['repository']['homepage'] refspec = push_event['ref'] app.logger.debug('Received push event by %s in branch %s on repository %s', user_name, refspec, repo_url) for commit in push_event['commits']: app.logger.debug('Processing commit %s by %s (%s) in %s', commit['id'], commit['author']['name'], commit['author']['email'], commit['url']) commit_time = dateutil.parser.parse(commit['timestamp']) issues = re.findall(app.config['REGEX'], commit['message'], re.MULTILINE) if not issues: app.logger.debug('''Didn't find any referenced issues in commit %s''', commit['id']) else: app.logger.debug('Found %d referenced issues in commit %s', len(issues), commit['id']) yt = Connection(app.config['YOUTRACK_URL'], app.config['YOUTRACK_USERNAME'], app.config['YOUTRACK_PASSWORD']) user_login = get_user_login(yt, commit['author']['email']) if user_login is None: app.logger.warn("Couldn't find user with email address %s. Using default user.", commit['author']['email']) default_user = yt.getUser(app.config['DEFAULT_USER']) user_login = default_user['login'] for issue_id in issues: app.logger.debug('Processing reference to issue %s', issue_id) try: yt.getIssue(issue_id) comment_string = 'Commit [%(url)s %(id)s] on branch %(refspec)s in [%(repo_homepage)s %(repo_name)s] made by %(author)s on %(date)s\n{quote}%(message)s{quote}' % {'url': commit['url'], 'id': commit['id'], 'author': commit['author']['name'], 'date': str(commit_time), 'message': commit['message'], 'repo_homepage': repo_homepage, 'repo_name': repo_name, 'refspec': refspec} app.logger.debug(comment_string) yt.executeCommand(issueId=issue_id, command='comment', comment=comment_string.encode('utf-8'), run_as=user_login.encode('utf-8')) except YouTrackException: app.logger.warn("Couldn't find issue %s", issue_id) return Response('Push event processed. Thanks!', mimetype='text/plain')
def doMove(source_url, source_login, source_password, target_url, target_login, target_password, source_issue_id, target_project_id) : print "source_url : " + source_url print "source_login : "******"source_password : "******"target_url : " + target_url print "target_login : "******"target_password : "******"source_id : " + source_issue_id print "target_project : " + target_project_id # connecting try : target = Connection(target_url, target_login, target_password) print "Connected to target url [%s]" % target_url except Exception, ex: print "Failed to connect to target url [%s] with login/password [%s/%s]" % (target_url, target_login, target_password) raise ex
def googlecode2youtrack(project_name, source_login, source_password, target_url, target_login, target_password, project_id): target = Connection(target_url, target_login, target_password) try: target.getProject(project_id) except YouTrackException: target.createProjectDetailed(project_id, project_name, "", target_login) for field_name, field_type in googleCode.FIELD_TYPES.items(): create_and_attach_custom_field(target, project_id, field_name, field_type) start = 1 max = 30 while True: source = gdata.projecthosting.client.ProjectHostingClient() source.client_login(source_login, source_password, source="youtrack", service="code") print "Get issues from " + str(start) + " to " + str(start + max) query = gdata.projecthosting.client.Query(start_index=start, max_results=max) issues = source.get_issues(project_name, query=query).entry start += max if len(issues) <= 0: break target.importIssues(project_id, project_name + " assignees", [ to_yt_issue( target, project_id, issue, source.get_comments(project_name, issue_id(issue)).entry) for issue in issues ]) for issue in issues: import_tags(target, project_id, issue) import_attachments(target, project_id, project_name, issue, target_login)
def csv2youtrack(source_file, target_url, target_login, target_password): target = Connection(target_url, target_login, target_password) source = Client(source_file) import_custom_fields(source.get_header(), target) max = 100 while True: issues = source.get_issue_list(max) if not len(issues): break projects = get_projects(issues) for p in projects: try: target.getProject(p) except YouTrackException: target.createProjectDetailed(p, p, "", target_login) target.importIssues(p, p + " Assignees", [to_yt_issue(issue, target) for issue in issues if (get_project(issue) == p)])
def youtrack2youtrack(source_url, source_login, source_password, target_url, target_login, target_password, project_ids, query=''): if not len(project_ids): print "You should sign at least one project to import" return source = Connection(source_url, source_login, source_password) target = Connection( target_url, target_login, target_password ) #, proxy_info = httplib2.ProxyInfo(socks.PROXY_TYPE_HTTP, 'localhost', 8888) print "Import issue link types" for ilt in source.getIssueLinkTypes(): try: print target.createIssueLinkType(ilt) except youtrack.YouTrackException, e: print e.message
class YtClient(object): def __init__(self, server, username, password): self.logger = LoggerFactory.getLogger("com.xebialabs.yourtrack.Server") if server is None: sys.exit("No server provided.") if username is not None: youtrackUsername = username else: youtrackUsername = server['username'] if password is not None: youtrackPassword = password else: youtrackPassword = server['password'] if server['token'] is not None: # authentication request with permanent token self.youtrack = YouTrack(server['url'], token=server['token']) else: # authentication with username and password self.youtrack = YouTrack(server['url'], login=youtrackUsername, password=youtrackPassword) def getIssue(self, issueId): return self.youtrack.getIssue(issueId) def getAllIssues(self, query, withFields): self.logger.debug("getAllIssues") self.logger.debug("Query = %s" % query) self.logger.debug("Fields = %s" % withFields) return self.youtrack.getAllIssues(filter=query, withFields=withFields) def updateIssuesByQuery(self, query, fieldsToUpdate, comment): command = "" for key in fieldsToUpdate: command += key + " " + fieldsToUpdate[key] foundIssues = self.youtrack.getAllIssues(filter=query, withFields=[]) for issue in foundIssues: self.youtrack.executeCommand(issue['id'], command, comment) def getIssuesByQuery(self, query, fieldList=[]): self.logger.debug("getIssuesByQuery") return self.youtrack.getAllIssues(filter=query, withFields=[])
def push_event_hook(): push_event = request.json app.logger.debug(push_event) user_name = push_event['user_name'] repo_name = push_event['repository']['name'] repo_url = push_event['repository']['url'] repo_homepage = push_event['repository']['homepage'] refspec = push_event['ref'] app.logger.debug('Received push event by %s in branch %s on repository %s', user_name, refspec, repo_url) for commit in push_event['commits']: app.logger.debug('Processing commit %s by %s (%s) in %s', commit['id'], commit['author']['name'], commit['author']['email'], commit['url']) commit_time = dateutil.parser.parse(commit['timestamp']) issues = re.findall(app.config['REGEX'], commit['message'], re.MULTILINE) if not issues: app.logger.debug('''Didn't find any referenced issues in commit %s''', commit['id']) else: app.logger.debug('Found %d referenced issues in commit %s', len(issues), commit['id']) yt = Connection(app.config['YOUTRACK_URL'], app.config['YOUTRACK_USERNAME'], app.config['YOUTRACK_PASSWORD']) default_user = yt.getUser(app.config['DEFAULT_USER']) user_login = default_user['login'] users = yt.getUsers({ 'q': commit['author']['email'] }) if not users: app.logger.warn('''Couldn't find user with email address %s. Using default user.''', commit['author']['email']) elif len(users) > 1: app.logger.warn('''Found more than one user with email address %s. Using default user.''', commit['author']['email']) else: user_login = users[0]['login'] for issue_id in issues: app.logger.debug('Processing reference to issue %s', issue_id) try: issue = yt.getIssue(issue_id) comment_string = 'Commit [%(url)s %(id)s] on branch %(refspec)s in [%(repo_homepage)s %(repo_name)s] made by %(author)s on %(date)s\n{quote}%(message)s{quote}' % {'url': commit['url'], 'id': commit['id'], 'author': commit['author']['name'], 'date': str(commit_time), 'message': commit['message'], 'repo_homepage': repo_homepage, 'repo_name': repo_name, 'refspec': refspec} app.logger.debug(comment_string) yt.executeCommand(issueId=issue_id, command='comment', comment=comment_string.encode('utf-8'), run_as=user_login.encode('utf-8')) except YouTrackException: app.logger.warn('''Couldn't find issue %s''', ref) return Response('Push event processed. Thanks!', mimetype='text/plain')
def fb2youtrack(target_url, target_login, target_password, source_url, source_login, source_password, project_names, max_issue_id) : #encoding = 'utf-8' source = FBClient(source_url, source_login, source_password) target = Connection(target_url, target_login, target_password) accessible_projects = source.list_project_names() for p_name in project_names : if not(p_name in accessible_projects.keys()) : print 'Unknown project names. Exiting...' sys.exit() # for p_name in accessible_projects : # if (p_name.encode('utf-8') in project_names_str) : # project_names_str.remove(p_name.encode('utf-8')) # project_names.append(p_name) # # if (len(project_names_str) != 0) : # print 'Unknown project names!' print('Creating custom fields') # # for field_name in ['Category', 'Priority', 'Status']: # field_name = get_yt_name_from_fb__field_name(field_name) # create_custom_field(target, fbugz.CF_TYPES[field_name], field_name, False) fb_category_bundle_name = u'FB Categories' fb_priorities_bundle_name = u'FB Priorities' fb_statuses_bundle_name = u'FB Statuses' common_fields = { u'category' : fb_category_bundle_name, u'priority' : fb_priorities_bundle_name, u'status' : fb_statuses_bundle_name } field_name = u'category' create_bundle_with_values(target,fbugz.CF_TYPES[get_yt_name_from_fb_field_name(field_name)], common_fields[field_name], source.list_categories(), lambda bundle, value : bundle.createElement(to_yt_field_value(field_name, value))) field_name = u'priority' create_bundle_with_values(target, fbugz.CF_TYPES[get_yt_name_from_fb_field_name(field_name)], common_fields[field_name], [elem[0] + '-' + elem[1] for elem in source.list_priorities()], lambda bundle, value : bundle.createElement(to_yt_field_value(field_name, value))) field_name = u'status' statuses = [(to_yt_field_value(field_name, value), resolved) for (value, resolved) in source.list_statuses()] create_bundle_with_values(target, fbugz.CF_TYPES[get_yt_name_from_fb_field_name(field_name)], common_fields[field_name], statuses, lambda bundle, value : to_yt_status(bundle, value)) simple_fields = [u'original_title', u'version', u'computer', u'due', u'estimate'] for name in simple_fields: name = get_yt_name_from_fb_field_name(name) create_custom_field(target, fbugz.CF_TYPES[name], name, False) print 'Importing users' for name in ['Normal', 'Deleted', 'Community', 'Virtual'] : group = Group() group.name = name try : target.createGroup(group) print 'Group with name [ %s ] successfully created' % name except: print "Can't create group with name [ %s ] (maybe because it already exists)" % name users_to_import = [] max = 100 for user in source.get_users() : yt_user = _to_yt_user(user) print 'Importing user [ %s ]' % yt_user.login users_to_import.append(yt_user) if len(users_to_import) >= max: _do_import_users(target, users_to_import) users_to_import = [] _do_import_users(target, users_to_import) print 'Importing users finished' # to handle linked issues try : target.createIssueLinkTypeDetailed('parent-child', 'child of', 'parent of', True) except YouTrackException: print "Can't create issue link type [ parent-child ] (maybe because it already exists)" links_to_import = [] for project_name in project_names : value_sets = dict([]) project_id = accessible_projects[project_name] print 'Importing project [ %s ]' % project_name target.createProjectDetailed(project_id, project_name.encode('utf-8'), 'no description', 'root') print 'Creating custom fields in project [ %s ]' % project_name for cf_name in common_fields: bundle_name = common_fields[cf_name] cf_name = get_yt_name_from_fb_field_name(cf_name) target.deleteProjectCustomField(project_id, cf_name) target.createProjectCustomFieldDetailed(project_id, cf_name, 'No ' + cf_name.lower(), {'bundle' : bundle_name}) for cf_name in simple_fields: cf_name = get_yt_name_from_fb_field_name(cf_name) try: target.createProjectCustomFieldDetailed(project_id, cf_name, 'No ' + cf_name.lower()) except YouTrackException: print "Can't create custom field with name [%s]" % cf_name cf_name = get_yt_name_from_fb_field_name('fix_for') milestones = source.get_milestones(project_id) value_sets["fix_for"] = [] for milestone in milestones: value_sets["fix_for"].append(milestone.name) milestone.name = to_yt_field_value('fix_for', milestone.name) add_values_to_field(target, cf_name, project_id, milestones, lambda bundle, value: _to_yt_version(bundle, value)) cf_name = get_yt_name_from_fb_field_name('area') areas = source.get_areas(project_id) value_sets["area"] = [] for area in areas: value_sets["area"].append(area.name) area.name = to_yt_field_value('area', area.name) add_values_to_field(target, cf_name, project_id, areas, lambda bundle, value: _to_yt_subsystem(bundle, value)) print 'Importing issues for project [ %s ]' % project_name start = 0 issues_to_import = [] # create dictionary with child : parent pairs while start <= max_issue_id: fb_issues = source.get_issues(project_name, start, 30) for issue in fb_issues : add_values_to_field(target, get_yt_name_from_fb_field_name('area'), project_id, [issue.field_values['area']], lambda bundle, value: bundle.createElement(value)) issues_to_import.append(_to_yt_issue(issue, value_sets)) target.importIssues(project_id, project_name.encode('utf-8') + " assignees", issues_to_import) for issue in fb_issues : full_issue_id = '%s-%s' % (project_id, issue.ix_bug) for attach in issue.attachments : target.createAttachmentFromAttachment(full_issue_id, attach) for tag in issue.tags : target.executeCommand(full_issue_id, 'tag ' + tag) if issue.bug_parent is not None: parent_issue_id = '%s-%s' % (source.get_issue_project_id(issue.bug_parent), issue.bug_parent) link = Link() link.typeName = 'parent-child' link.source = full_issue_id link.target = parent_issue_id links_to_import.append(link) issues_to_import = [] start += 30 print 'Importing issues for project [ %s ] finished' % project_name print 'Importing issue links' print target.importLinks(links_to_import) print 'Importing issue links finished'
def post(self, request, format=None): serializer = self.get_serializer_class() log.debug(type(request.DATA)) if isinstance(request.DATA, QueryDict): data = request.DATA.dict() user = request.user elif isinstance(request.DATA, dict): data = request.DATA user = request.user else: data = request.DATA log.debug(data) try: if len(settings.REDMINE_ADDRESS): serializer = serializer(data=data) if serializer.is_valid(): obj = serializer.save() try: ret = request_redmine('issues', data=obj.to_json(), method='POST') except urllib2.HTTPError as ex: log.debug("HTTPError") return Response(data={ 'code': ex.code, 'message': ex.reason }, status=status.HTTP_400_BAD_REQUEST) except urllib2.URLError as ex: log.debug("URLError") return Response(data={'reason': ex.reason[1]}, status=status.HTTP_400_BAD_REQUEST) log.debug(ret) return Response(serializer.data, status=status.HTTP_201_CREATED) else: log.debug("Serializer is invalid") else: log.debug("No redmine address") except AttributeError: log.debug("Redmine address not set.") try: if len(settings.YOUTRACK_ADDRESS): log.debug("YouTrack address is set") conn = YTConnection(settings.YOUTRACK_ADDRESS, settings.YOUTRACK_USER, settings.YOUTRACK_PASSWORD) serializer = YouTrackIssueSerializer(data=data) if serializer.is_valid(): obj = serializer.save() description = obj.description ret = conn.createIssue(obj.project_id, assignee=None, summary=obj.subject, description=description, priority=obj.priority, type=obj.type, subsystem=obj.subsystem) log.debug(ret) ret_dict = obj.to_dict() try: del (ret_dict['project_id']) except KeyError: pass return Response(ret_dict, status=status.HTTP_201_CREATED) except AttributeError: log.debug("YouTrack address not set.") return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
# coding=UTF-8 from youtrack.connection import Connection, httplib2 from xml.etree.ElementTree import fromstring import random import urllib import httplib import urllib2 import socks httplib2.debuglevel=4 httplib.debuglevel=4 yt = Connection('http://teamsys.intellij.net', 'resttest', 'resttest')#, proxy_info = httplib2.ProxyInfo(socks.PROXY_TYPE_HTTP, 'localhost', 8888)) #yt = Connection('http://localhost:8080', 'root', 'root') #yt = Connection('http://v-rot-mne-nogi.myjetbrains.com/youtrack', 'root', 'root') #, proxy_info = httplib2.ProxyInfo(socks.PROXY_TYPE_HTTP, 'localhost', 8888)) print 'connected' # create subsystem #print yt.createSubsystemDetailed('ADM', 'ss' + str(random.random()), False, 'root') # get issue #i = yt.getIssue('SB-4950') #print i print yt.createIssue('SB', 'resttest', 'test', 'test', '1', 'Bug', 'Unknown', 'Open', '', '', '') #print i.getAttachments()
if not (target_cf.type == source_cf.type): print "In your target and source YT instances you have field with name [ %s ]" % cf_name.encode( 'utf-8') print "They have different types. Source field type [ %s ]. Target field type [ %s ]" %\ (source_cf.type, target_cf.type) print "exiting..." exit() else: if hasattr(source_cf, "defaultBundle"): create_bundle_from_bundle(source, target, source_cf.defaultBundle, source_cf.type, user_importer) target.createCustomField(source_cf) for projectId in project_ids: source = Connection(source_url, source_login, source_password) target = Connection( target_url, target_login, target_password ) #, proxy_info = httplib2.ProxyInfo(socks.PROXY_TYPE_HTTP, 'localhost', 8888) #reset connections to avoid disconnections user_importer.resetConnections(source, target) link_importer.resetConnections(target) # copy project, subsystems, versions project = source.getProject(projectId) link_importer.addAvailableIssuesFrom(projectId) project_custom_fields = source.getProjectCustomFields(projectId) # create bundles and additional values for pcf_ref in project_custom_fields: pcf = source.getProjectCustomField(projectId, pcf_ref.name)
def import_attachments_only(source_url, source_login, source_password, target_url, target_login, target_password, project_ids, params=None): if not project_ids: print 'No projects to import. Exit...' return if params is None: params = {} start = 0 max = 20 source = Connection(source_url, source_login, source_password) target = Connection(target_url, target_login, target_password) user_importer = UserImporter(source, target, caching_users=params.get('enable_user_caching', True)) for projectId in project_ids: while True: try: print 'Get issues from %d to %d' % (start, start + max) issues = source.getIssues(projectId, '', start, max) if len(issues) <= 0: break for issue in issues: print 'Process attachments for issue %s' % issue.id existing_attachments = dict() try: for a in target.getAttachments(issue.id): existing_attachments[a.name + '\n' + a.created] = a except youtrack.YouTrackException, e: if e.response.status == 404: print "Skip importing attachments because issue %s doesn't exist" % issue.id continue raise e attachments = [] users = set([]) for a in issue.getAttachments(): if a.name + '\n' + a.created in existing_attachments and not params.get('replace_attachments'): print "Skip attachment '%s' (created: %s) because it's already exists" \ % (a.name.encode('utf-8'), a.created) continue attachments.append(a) author = a.getAuthor() if author is not None: users.add(author) user_importer.importUsersRecursively(users) for a in attachments: print 'Transfer attachment of %s: %s' % (issue.id, a.name.encode('utf-8')) try: target.createAttachmentFromAttachment(issue.id, a) except BaseException, e: print 'Cannot import attachment [ %s ]' % a.name.encode('utf-8') print repr(e) continue if params.get('replace_attachments'): try: old_attachment = existing_attachments.get(a.name + '\n' + a.created) if old_attachment: print 'Deleting old attachment' target.deleteAttachment(issue.id, old_attachment.id) except BaseException, e: print "Cannot delete attachment '%s' from issue %s" % (a.name.encode('utf-8'), issue.id) print e
sys.path.append(parentdir) config = ConfigParser.ConfigParser() config.read('config.ini') LOGIN = config.get('CREDENTIALS', 'domain') + '\\' + config.get('CREDENTIALS', 'login') PASSWRD = base64.b64decode(config.get('CREDENTIALS', 'password')) YOUTRACK_URL = config.get('YOUTRACK', 'url') REDMINE_URL = config.get('REDMINE', 'url') REDMINE_API_KEY = config.get('REDMINE', 'api key') REDMINE_PROJECT = config.get('REDMINE', 'project') YOUTRACK_PROJECT = config.get('YOUTRACK', 'project') SEARCH_QUERY = config.get('YOUTRACK', 'search query').replace('\n', '') try: youtrack = Connection(YOUTRACK_URL, LOGIN, PASSWRD) except YouTrackException as yt_exc: print yt_exc sys.exit(0) redmine = Redmine(REDMINE_URL, key=REDMINE_API_KEY, requests={'verify': False}) print "Getting YouTrack issues..." issues_list = youtrack.getIssues('project: ' + YOUTRACK_PROJECT + ' ' + SEARCH_QUERY, 0, 5000) try: redmine_users = get_redmine_users() redmine_trackers = get_redmine_trackers() redmine_statuses = get_redmine_statuses() redmine_priorities = get_redmine_priorities() redmine_versions = get_redmine_project_versions()
import random import urllib #import httplib #import urllib2 #import socks import csv import re import time import datetime httplib2.debuglevel = 4 #httplib.debuglevel=4 # connection yt = Connection( 'https://youtrack.ugent.be', 'root', 'PRCyt,17*' ) #, proxy_info = httplib2.ProxyInfo(socks.PROXY_TYPE_HTTP, 'youtrack.ugent.be', 8080)) print('connected') # get CMB issues PRCissues = yt.get_all_issues("PRC-", 0, 500) #datetime.datetime.now()-datetime.datetime.fromtimestamp(int(issue['created'])<datetime.timedelta(minutes=40) #datetime.datetime.fromtimestamp(int(PRCissues[0]['created'])/1000).strftime('%Y-%m-%d %H:%M:%S.%f') # issue IDs per project # open PRC issue IDs PRCissuesIDs = [] Currentissuesindexes = list() counter = 0 for issue in PRCissues:
def mantis2youtrack(target_url, target_login, target_pass, mantis_db_name, mantis_db_host, mantis_db_port, mantis_db_login, mantis_db_pass, mantis_project_names): print "target_url : " + target_url print "target_login : "******"target_pass : "******"mantis_db_name : " + mantis_db_name print "mantis_db_host : " + mantis_db_host print "mantis_db_port : " + mantis_db_port print "mantis_db_login : "******"mantis_db_pass : "******"mantis_project_names : " + repr(mantis_project_names) #connacting to yt target = Connection(target_url, target_login, target_pass) #connacting to mantis client = MantisClient(mantis_db_host, int(mantis_db_port), mantis_db_login, mantis_db_pass, mantis_db_name, mantis.CHARSET) if not len(mantis_project_names): print "You should declarer at least one project to import" sys.exit() print "Creating custom fields definitions" create_yt_custom_field(target, u"priority") create_yt_custom_field(target, u"severity") create_yt_custom_field(target, u"category_id") create_yt_custom_field(target, u"version", "1") create_yt_custom_field(target, u"fixed_in_version", "1") create_yt_custom_field(target, u"build", "1") create_yt_custom_field(target, u"platform") create_yt_custom_field(target, u"os") create_yt_custom_field(target, u"os_build") create_yt_custom_field(target, u"due_date") create_yt_custom_field(target, u"Reproducibility") create_yt_custom_field(target, u"target_version", u'1') create_yt_custom_field(target, u"status") create_yt_custom_field(target, u"resolution") create_yt_custom_field(target, u'project_id', u'1') # adding some custom fields that are predefined in mantis project_ids = [] for name in mantis_project_names: project_ids.append(client.get_project_id_by_name(name)) custom_fields = client.get_mantis_custom_fields(project_ids) for cf_def in custom_fields: print "Processing custom field [ %s ]" % cf_def.name.encode('utf-8') process_mantis_custom_field(target, cf_def) print "Creating custom fields definitions finished" issue_tags = set([]) for name in mantis_project_names: project_id = str(client.get_project_id_by_name(name)) name = name.replace("/", " ") print "Creating project [ %s ] with name [ %s ]" % (project_id, name) try: target.getProject(project_id) except YouTrackException: target.createProjectDetailed(project_id, name, client.get_project_description(project_id), target_login) print "Importing components to project [ %s ]" % project_id add_values_to_fields(target, project_id, u"category_id", client.get_mantis_categories(project_id), lambda component, yt_bundle, value_mapping: to_yt_subsystem(component, yt_bundle, value_mapping)) print "Importing components to project [ %s ] finished" % project_id print "Importing versions to project [ %s ]" % project_id mantis_versions = client.get_mantis_versions(project_id) add_values_to_fields(target, project_id, u"version", mantis_versions, lambda version, yt_bundle, value_mapping: to_yt_version(version, yt_bundle, value_mapping)) add_values_to_fields(target, project_id, u"fixed_in_version", mantis_versions, lambda version, yt_bundle, value_mapping: to_yt_version(version, yt_bundle, value_mapping)) print "Importing versions to project [ %s ] finished" % project_id print "Attaching custom fields to project [ %s ]" % project_id cf_ids = client.get_custom_fields_attached_to_project(project_id) for cf in custom_fields: if cf.field_id in cf_ids: attach_field_to_project(target, project_id, cf.name) print "Attaching custom fields to project [ %s ] finished" % project_id print "Importing issues to project [ %s ]" % project_id max_count = 100 after = 0 go_on = True while go_on: go_on = False mantis_issues = client.get_mantis_issues(project_id, after, max_count) after += max_count if len(mantis_issues): go_on = True target.importIssues(project_id, name + " Assignees", [to_yt_issue(issue, project_id, target) for issue in mantis_issues]) # import attachments for issue in mantis_issues: issue_attachments = client.get_attachments(issue['id']) issue_id = "%s-%s" % (project_id, issue['id']) import_attachments(issue_attachments, issue_id, target) issue_tags |= set(client.get_issue_tags_by_id(issue['id'])) print "Importing issues to project [ %s ] finished" % project_id import_tags(client, target, project_ids, issue_tags) print "Importing issue links" go_on = True after = 0 max_count = 200 while go_on: go_on = False mantis_issue_links = client.get_issue_links(after, max_count) yt_issue_links = [] for link in mantis_issue_links: go_on = True print "Processing issue link for source issue [ %s ]" % str(link.source) yt_issue_links.append(to_yt_link(link)) after += max_count print target.importLinks(yt_issue_links) print "Importing issue links finished"
def setUp(self): #self.con = Connection('http://teamsys.intellij.net', 'resttest', 'resttest') self.con = Connection("http://localhost:8081", "root", "root")
class ConnectionTest(unittest.TestCase): def setUp(self): #self.con = Connection('http://teamsys.intellij.net', 'resttest', 'resttest') self.con = Connection("http://localhost:8081", "root", "root") def test_getProject(self): p = self.con.getProject('SB') self.assertEqual(p.id, 'SB') self.assertEqual(p.name, 'Sandbox') def test_getSubsystems(self): subsystems = self.con.getSubsystems('SB') default = [s for s in subsystems if s.isDefault][0] self.assertTrue(default is not None) def test_getIssue(self): i = self.con.getIssue('SB-1') self.assertEqual(i.id, 'SB-1') self.assertEqual(i.numberInProject, '1') self.assertEqual(i.projectShortName, 'SB') def test_createIssue(self): i = self.con.createIssue('SB', 'resttest', 'Test issue', 'Test description', '2', 'Bug', 'First', 'Open', '', '', '') self.assertEqual(i.projectShortName, 'SB') self.assertEqual(i.priority, '2') self.assertEqual(i.type, 'Bug') self.assertEqual(i.subsystem, 'First') def test_createIssueAttachment(self): i = self.con.createIssue('SB', 'resttest', 'For attachmkents test', 'Test description', '2', 'Bug', 'First', 'Open', '', '', '') fname = 'connection_test.py' content = open(fname) self.con.createAttachment(i.id, fname, content) self.assertEqual(fname, self.con.getAttachments(i.id)[0].name) def test_createAndDeleteSubsystem(self): name = 'Test Subsystem [' + str(random.random()) + "]" self.con.createSubsystemDetailed('SB', name, False, 'resttest') s = self.con.getSubsystem('SB', name) self.assertEqual(s.name, name) self.assertEqual(s.isDefault, 'false') #todo: uncomment when fix deployed to teamsys #self.assertEqual(s.defaultAssignee, 'resttest') self.con.deleteSubsystem('SB', name) def test_importIssues(self): issues = self.con.getIssues("A", "", 0, 10) for issue in issues: if hasattr(issue, "Assignee"): issue["assigneeName"] = issue["Assignee"] del issue.Assignee self.con.importIssues("B", "assignees", issues)
def setUp(self): self.con = Connection('http://localhost:8081', 'root', 'root')
print "target_url : " + target_url print "target_login : "******"target_password : "******"source_id : " + source_issue_id print "target_project : " + target_project_id # connecting try : target = Connection(target_url, target_login, target_password) print "Connected to target url [%s]" % target_url except Exception, ex: print "Failed to connect to target url [%s] with login/password [%s/%s]" % (target_url, target_login, target_password) raise ex try : source = Connection(source_url, source_login, source_password) print "Connected to source url [%s]" % source_url except Exception, ex : print "Failed to connect to source url [%s] with login/password [%s/%s]" % (source_url, source_login, source_password) raise ex try : target.getProject(target_project_id) except Exception, ex: print "Can't connect to target project [%s]" % target_project_id raise ex #twin issues try : source_issue = source.getIssue(source_issue_id) except Exception, ex :
def mantis2youtrack(target_url, target_login, target_pass, mantis_db_name, mantis_db_host, mantis_db_port, mantis_db_login, mantis_db_pass, mantis_project_names): print "target_url : " + target_url print "target_login : "******"target_pass : "******"mantis_db_name : " + mantis_db_name print "mantis_db_host : " + mantis_db_host print "mantis_db_port : " + mantis_db_port print "mantis_db_login : "******"mantis_db_pass : "******"mantis_project_names : " + repr(mantis_project_names) #connacting to yt target = Connection(target_url, target_login, target_pass) #connacting to mantis client = MantisClient(mantis_db_host, int(mantis_db_port), mantis_db_login, mantis_db_pass, mantis_db_name, mantis.CHARSET) if not len(mantis_project_names): print "You should declarer at least one project to import" sys.exit() print "Creating custom fields definitions" create_yt_custom_field(target, u"priority") create_yt_custom_field(target, u"severity") create_yt_custom_field(target, u"category_id") create_yt_custom_field(target, u"version", "1") create_yt_custom_field(target, u"fixed_in_version", "1") create_yt_custom_field(target, u"build", "1") create_yt_custom_field(target, u"platform") create_yt_custom_field(target, u"os") create_yt_custom_field(target, u"os_build") create_yt_custom_field(target, u"due_date") create_yt_custom_field(target, u"Reproducibility") create_yt_custom_field(target, u"target_version", u'1') create_yt_custom_field(target, u"status") create_yt_custom_field(target, u"resolution") create_yt_custom_field(target, u'project_id', u'1') # adding some custom fields that are predefined in mantis project_ids = [] for name in mantis_project_names: project_ids.append(client.get_project_id_by_name(name)) custom_fields = client.get_mantis_custom_fields(project_ids) for cf_def in custom_fields: print "Processing custom field [ %s ]" % cf_def.name.encode('utf-8') process_mantis_custom_field(target, cf_def) print "Creating custom fields definitions finished" issue_tags = set([]) for name in mantis_project_names: project_id = str(client.get_project_id_by_name(name)) name = name.replace("/", " ") print "Creating project [ %s ] with name [ %s ]" % (project_id, name) try: target.getProject(project_id) except YouTrackException: target.createProjectDetailed( project_id, name, client.get_project_description(project_id), target_login) print "Importing components to project [ %s ]" % project_id add_values_to_fields( target, project_id, u"category_id", client.get_mantis_categories(project_id), lambda component, yt_bundle, value_mapping: to_yt_subsystem( component, yt_bundle, value_mapping)) print "Importing components to project [ %s ] finished" % project_id print "Importing versions to project [ %s ]" % project_id mantis_versions = client.get_mantis_versions(project_id) add_values_to_fields( target, project_id, u"version", mantis_versions, lambda version, yt_bundle, value_mapping: to_yt_version( version, yt_bundle, value_mapping)) add_values_to_fields( target, project_id, u"fixed_in_version", mantis_versions, lambda version, yt_bundle, value_mapping: to_yt_version( version, yt_bundle, value_mapping)) print "Importing versions to project [ %s ] finished" % project_id print "Attaching custom fields to project [ %s ]" % project_id cf_ids = client.get_custom_fields_attached_to_project(project_id) for cf in custom_fields: if cf.field_id in cf_ids: attach_field_to_project(target, project_id, cf.name) print "Attaching custom fields to project [ %s ] finished" % project_id print "Importing issues to project [ %s ]" % project_id max_count = 100 after = 0 go_on = True while go_on: go_on = False mantis_issues = client.get_mantis_issues(project_id, after, max_count) after += max_count if len(mantis_issues): go_on = True target.importIssues(project_id, name + " Assignees", [ to_yt_issue(issue, project_id, target) for issue in mantis_issues ]) # import attachments for issue in mantis_issues: issue_attachments = client.get_attachments(issue['id']) issue_id = "%s-%s" % (project_id, issue['id']) import_attachments(issue_attachments, issue_id, target) issue_tags |= set(client.get_issue_tags_by_id(issue['id'])) print "Importing issues to project [ %s ] finished" % project_id import_tags(client, target, project_ids, issue_tags) print "Importing issue links" go_on = True after = 0 max_count = 200 while go_on: go_on = False mantis_issue_links = client.get_issue_links(after, max_count) yt_issue_links = [] for link in mantis_issue_links: go_on = True print "Processing issue link for source issue [ %s ]" % str( link.source) yt_issue_links.append(to_yt_link(link)) after += max_count print target.importLinks(yt_issue_links) print "Importing issue links finished"
def bugzilla2youtrack(target_url, target_login, target_pass, bz_db, bz_host, bz_port, bz_login, bz_pass, bz_product_names, issues_filter): # connecting to bz client = Client(bz_host, int(bz_port), bz_login, bz_pass, db_name=bz_db) if not len(bz_product_names): answer = raw_input("All projects will be imported. Are you sure? [y/n]") if answer.capitalize() != "Y": sys.exit() bz_product_names = client.get_product_names() print "bz_product_names : " + repr(bz_product_names) # connecting to yt target = Connection(target_url, target_login, target_pass) print "Creating issue link types" link_types = client.get_issue_link_types() for link in link_types: print "Processing link type [ %s ]" % link.name try: target.createIssueLinkType(to_yt_issue_link_type(link)) except YouTrackException: print "Can't create link type [ %s ] (maybe because it already exists)" % link.name print "Creating issue link types finished" print "Creating custom fields" custom_fields = client.get_custom_fields() for cf in custom_fields: create_yt_custom_field(cf, target) print "Creating custom fields finished" for key in bugzilla.FIELD_TYPES: if key not in youtrack.EXISTING_FIELDS: create_custom_field(target, bugzilla.FIELD_TYPES[key], key, True, bundle_policy="1") bz_product_ids = [] for name in bz_product_names: product_id = str(client.get_product_id_by_name(name)) bz_product_ids.append(product_id) print "Creating project [ %s ] with name [ %s ]" % (product_id, name) try: target.getProject(str(product_id)) except YouTrackException: target.createProjectDetailed(str(product_id), name, client.get_project_description(product_id), target_login) print "Importing components for project [ %s ]" % product_id process_components(client.get_components(product_id), product_id, target) print "Importing components finished for project [ %s ]" % product_id print "Importing versions for project [ %s ]" % product_id process_versions(client.get_versions(product_id), product_id, target) print "Importing versions finished for project [ %s ] finished" % product_id print "Importing issues to project [ %s ]" % product_id max_count = 100 count = 0 from_id = 0 bz_issues_count = client.get_issues_count(product_id) while count < bz_issues_count: batch = client.get_issues(product_id, from_id, from_id + max_count) batch = [bz_issue for bz_issue in batch if (issues_filter(bz_issue))] count += len(batch) from_id += max_count target.importIssues(product_id, product_id + " assignees", [to_yt_issue(bz_issue, product_id, target) for bz_issue in batch]) # todo convert to good tags import for issue in batch: tags = issue["keywords"] | issue["flags"] for t in tags: print "Processing tag [ %s ]" % t.encode('utf8') target.executeCommand(str(product_id) + "-" + str(issue[get_number_in_project_field_name()]), "tag " + t.encode('utf8')) for issue in batch: for attach in issue["attachments"]: print "Processing attachment [ %s ]" % (attach.name.encode('utf8')) content = StringIO(attach.content) target.createAttachment(str(product_id) + "-" + str(issue[get_number_in_project_field_name()]), attach.name, content, attach.reporter , created=str(int(attach.created) * 1000)) print "Importing issues to project [ %s ] finished" % product_id # todo add pagination to links print "Importing issue links" cf_links = client.get_issue_links() duplicate_links = client.get_duplicate_links() if len(duplicate_links): try: target.createIssueLinkTypeDetailed("Duplicate", "duplicates", "is duplicated by", True) except YouTrackException: print "Can't create link type [ Duplicate ] (maybe because it already exists)" depend_links = client.get_dependencies_link() if len(depend_links): try: target.createIssueLinkTypeDetailed("Depend", "depends on", "is required for", True) except YouTrackException: print "Can't create link type [ Depend ] (maybe because it already exists)" links = cf_links | duplicate_links | depend_links links_to_import = list([]) for link in links: print "Processing link %s for issue%s" % (link.name, link.source) if (str(link.target_product_id) in bz_product_ids) and (str(link.source_product_id) in bz_product_ids): links_to_import.append(to_yt_issue_link(link)) print target.importLinks(links_to_import) print "Importing issue links finished"
def import_attachments_only(source_url, source_login, source_password, target_url, target_login, target_password, project_ids, source_token=None, target_token=None, params=None): if not project_ids: print('No projects to import. Exit...') return if params is None: params = {} start = 0 max = 20 source = Connection(source_url, source_login, source_password) if (source_token is None) else Connection(source_url, token=source_token) target = Connection(target_url, target_login, target_password) if (target_token is None) else Connection(target_url, token=target_token) user_importer = UserImporter(source, target, caching_users=params.get('enable_user_caching', True)) for projectId in project_ids: while True: try: print('Get issues from %d to %d' % (start, start + max)) issues = source.getIssues(projectId, '', start, max) if len(issues) <= 0: break for issue in issues: print('Process attachments for issue %s' % issue.id) existing_attachments = dict() try: for a in target.getAttachments(issue.id): existing_attachments[a.name + '\n' + a.created] = a except youtrack.YouTrackException as e: if e.response.status == 404: print("Skip importing attachments because issue %s doesn't exist" % issue.id) continue raise e attachments = [] users = set([]) for a in issue.getAttachments(): if a.name + '\n' + a.created in existing_attachments and not params.get('replace_attachments'): print("Skip attachment '%s' (created: %s) because it's already exists" % (utf8encode(a.name), utf8encode(a.created))) continue attachments.append(a) author = a.getAuthor() if author is not None: users.add(author) user_importer.importUsersRecursively(users) for a in attachments: print('Transfer attachment of %s: %s' % (utf8encode(issue.id), utf8encode(a.name))) try: target.createAttachmentFromAttachment(issue.id, a) except BaseException as e: print('Cannot import attachment [ %s ]' % utf8encode(a.name)) print(repr(e)) continue if params.get('replace_attachments'): try: old_attachment = existing_attachments.get(a.name + '\n' + a.created) if old_attachment: print('Deleting old attachment') target.deleteAttachment(issue.id, old_attachment.id) except BaseException as e: print("Cannot delete attachment '%s' from issue %s" % ( utf8encode(a.name), utf8encode(issue.id))) print(e) except Exception as e: print('Cannot process issues from %d to %d' % (start, start + max)) traceback.print_exc() raise e start += max
target_cf = target.getCustomField(cf_name) if not(target_cf.type == source_cf.type): print "In your target and source YT instances you have field with name [ %s ]" % cf_name.encode('utf-8') print "They have different types. Source field type [ %s ]. Target field type [ %s ]" %\ (source_cf.type, target_cf.type) print "exiting..." exit() else: if hasattr(source_cf, "defaultBundle"): create_bundle_from_bundle(source, target, source_cf.defaultBundle, source_cf.type, user_importer) target.createCustomField(source_cf) failed_commands = [] for projectId in project_ids: source = Connection(source_url, source_login, source_password) target = Connection(target_url, target_login, target_password) #, proxy_info = httplib2.ProxyInfo(socks.PROXY_TYPE_HTTP, 'localhost', 8888) #reset connections to avoid disconnections user_importer.resetConnections(source, target) link_importer.resetConnections(target) # copy project, subsystems, versions project = source.getProject(projectId) link_importer.addAvailableIssuesFrom(projectId) project_custom_fields = source.getProjectCustomFields(projectId) # create bundles and additional values for pcf_ref in project_custom_fields: pcf = source.getProjectCustomField(projectId, pcf_ref.name) if hasattr(pcf, "bundle"):
def bugzilla2youtrack(target_url, target_login, target_pass, bz_db, bz_host, bz_port, bz_login, bz_pass, bz_product_names, issues_filter): # connecting to bz client = Client(bz_host, int(bz_port), bz_login, bz_pass, db_name=bz_db) if not len(bz_product_names): answer = raw_input("All projects will be imported. Are you sure? [y/n]") if answer.capitalize() != "Y": sys.exit() bz_product_names = client.get_product_names() print("bz_product_names : " + repr(bz_product_names)) # connecting to yt target = Connection(target_url, target_login, target_pass) print("Creating issue link types") link_types = client.get_issue_link_types() for link in link_types: print("Processing link type [ %s ]" % link.name) try: target.createIssueLinkType(to_yt_issue_link_type(link)) except YouTrackException: print("Can't create link type [ %s ] (maybe because it already exists)" % link.name) print("Creating issue link types finished") print("Creating custom fields") custom_fields = client.get_custom_fields() for cf in custom_fields: create_yt_custom_field(cf, target) print("Creating custom fields finished") for key in youtrackutils.bugzilla.FIELD_TYPES: if key not in youtrack.EXISTING_FIELDS: create_custom_field(target, youtrackutils.bugzilla.FIELD_TYPES[key], key, True, bundle_policy="1") bz_product_ids = [] for name in bz_product_names: product_id = str(client.get_product_id_by_name(name)) bz_product_ids.append(product_id) print("Creating project [ %s ] with name [ %s ]" % (product_id, name)) try: target.getProject(str(product_id)) except YouTrackException: target.createProjectDetailed(str(product_id), name, client.get_project_description(product_id), target_login) print("Importing components for project [ %s ]" % product_id) process_components(client.get_components(product_id), product_id, target) print("Importing components finished for project [ %s ]" % product_id) print("Importing versions for project [ %s ]" % product_id) process_versions(client.get_versions(product_id), product_id, target) print("Importing versions finished for project [ %s ] finished" % product_id) print("Importing issues to project [ %s ]" % product_id) max_count = 100 count = 0 from_id = 0 bz_issues_count = client.get_issues_count(product_id) while count < bz_issues_count: batch = client.get_issues(product_id, from_id, from_id + max_count) batch = [bz_issue for bz_issue in batch if (issues_filter(bz_issue))] count += len(batch) from_id += max_count target.importIssues(product_id, product_id + " assignees", [to_yt_issue(bz_issue, product_id, target) for bz_issue in batch]) # todo convert to good tags import for issue in batch: tags = issue["keywords"] | issue["flags"] for t in tags: print("Processing tag [ %s ]" % t.encode('utf8')) target.executeCommand(str(product_id) + "-" + str(issue[get_number_in_project_field_name()]), "tag " + t.encode('utf8')) for issue in batch: for attach in issue["attachments"]: print("Processing attachment [ %s ]" % (attach.name.encode('utf8'))) content = StringIO(attach.content) target.createAttachment(str(product_id) + "-" + str(issue[get_number_in_project_field_name()]), attach.name, content, attach.reporter.login , created=str(int(attach.created) * 1000)) print("Importing issues to project [ %s ] finished" % product_id) # todo add pagination to links print("Importing issue links") cf_links = client.get_issue_links() duplicate_links = client.get_duplicate_links() if len(duplicate_links): try: target.createIssueLinkTypeDetailed("Duplicate", "duplicates", "is duplicated by", True) except YouTrackException: print("Can't create link type [ Duplicate ] (maybe because it already exists)") depend_links = client.get_dependencies_link() if len(depend_links): try: target.createIssueLinkTypeDetailed("Depend", "depends on", "is required for", True) except YouTrackException: print("Can't create link type [ Depend ] (maybe because it already exists)") links = cf_links | duplicate_links | depend_links links_to_import = list([]) for link in links: print("Processing link %s for issue%s" % (link.name, link.source)) if (str(link.target_product_id) in bz_product_ids) and (str(link.source_product_id) in bz_product_ids): links_to_import.append(to_yt_issue_link(link)) print(target.importLinks(links_to_import)) print("Importing issue links finished")
from youtrack.connection import Connection youtrack_url = 'http://youtrack.dev.kbinform.ru/' youtrack_login = '******' youtrack_password = '******' youtrack = Connection(youtrack_url, youtrack_login, youtrack_password) project_list = [ 'ezmp_product', ] for _ in range(30): for p in project_list: issues = youtrack.get_issues(p, '', '', '') for i in issues: youtrack.delete_issue(i._data['id'])
def trac2youtrack(target_url, target_login, target_password, project_ID, project_name, env_path): # creating connection to trac to import issues to client = Client(env_path) # creating connection to youtrack to import issues in target = Connection(target_url, target_login, target_password) #create project print "Creating project[%s]" % project_name try : target.getProject(project_ID) except youtrack.YouTrackException: target.createProjectDetailed(project_ID, project_name, client.get_project_description(), target_login) #importing users trac_users = client.get_users() print "Importing users" yt_users = list([]) # converting trac users to yt users registered_users = set([]) for user in trac_users : print "Processing user [ %s ]" % user.name registered_users.add(user.name) yt_users.append(to_youtrack_user(user)) # adding users to yt project target.importUsers(yt_users) print "Importing users finished" print "Creating project custom fields" create_yt_custom_field(target, project_ID, "Priority", client.get_issue_priorities()) create_yt_custom_field(target, project_ID, "Type", client.get_issue_types()) trac_resolution_to_yt_state = lambda track_field, yt_bundle : to_youtrack_state(track_field, yt_bundle) create_yt_bundle_custom_field(target, project_ID, "Resolution", client.get_issue_resolutions(), trac_resolution_to_yt_state) trac_versions = client.get_versions() trac_version_to_yt_version = lambda trac_field, yt_bundle : to_youtrack_version(trac_field, yt_bundle) create_yt_bundle_custom_field(target, project_ID, "Version", trac_versions, trac_version_to_yt_version) #create_yt_bundle_custom_field(target, project_ID, "Affected versions", trac_versions, trac_version_to_yt_version) trac_components = client.get_components() for cmp in trac_components : if cmp.owner not in registered_users : cmp.owner, registered_users = process_non_authorised_user(target, registered_users, cmp.owner) trac_component_to_yt_subsystem = lambda trac_field, yt_bundle : to_youtrack_subsystem(trac_field, yt_bundle) create_yt_bundle_custom_field(target, project_ID, "Component", trac_components, trac_component_to_yt_subsystem) create_yt_custom_field(target, project_ID, "Severity", client.get_severities()) trac_custom_fields = client.get_custom_fields_declared() check_box_fields = dict([]) for elem in trac_custom_fields: print "Processing custom field [ %s ]" % elem.name type_name = None if elem.type == "checkbox": if len(elem.label) > 0: opt = elem.label else: opt = elem.name options = list([opt]) check_box_fields[elem.name] = opt else: options = elem.options values = None if len(options): values = options field_name = elem.name if field_name in tracLib.FIELD_NAMES.keys() : field_name = tracLib.FIELD_NAMES[field_name] field_type = tracLib.CUSTOM_FIELD_TYPES[elem.type] if field_name in tracLib.FIELD_TYPES.keys(): field_type = tracLib.FIELD_TYPES[field_name] process_custom_field(target, project_ID, field_type, field_name, trac_values_to_youtrack_values(field_name, values)) print "Creating project custom fields finished" print "Importing issues" trac_issues = client.get_issues() yt_issues = list([]) counter = 0 max = 100 for issue in trac_issues: print "Processing issue [ %s ]" % (str(issue.id)) counter += 1 if not (issue.reporter in registered_users): yt_user, registered_users = process_non_authorised_user(target, registered_users, issue.reporter) if yt_user is None : issue.reporter = "guest" else: issue.reporter = yt_user if not (issue.owner in registered_users): yt_user, registered_users = process_non_authorised_user(target, registered_users, issue.owner) if yt_user is None : issue.owner = "" else: issue.owner = yt_user legal_cc = set([]) for cc in issue.cc: if cc in registered_users: legal_cc.add(cc) issue.cc = legal_cc yt_issues.append(to_youtrack_issue(issue, check_box_fields)) if counter == max: counter = 0 print target.importIssues(project_ID, project_name + ' Assignees', yt_issues) yt_issues = list([]) print target.importIssues(project_ID, project_name + ' Assignees', yt_issues) print 'Importing issues finished' #importing tags print "Importing keywords" for issue in trac_issues: print "Importing tags from issue [ %s ]" % (str(issue.id)) tags = issue.keywords for t in tags: target.executeCommand(str(project_ID) + "-" + str(issue.id), "tag " + t.encode('utf-8')) print "Importing keywords finished" print "Importing attachments" for issue in trac_issues: print "Processing issue [ %s ]" % (str(issue.id)) issue_attach = issue.attachment for attach in issue_attach: print "Processing attachment [ %s ]" % attach.filename.encode('utf-8') if not (attach.author_name in registered_users): yt_user, registered_users = process_non_authorised_user(target, registered_users, attach.author_name) if yt_user is None : attach.author_name = "guest" else: attach.author_name = yt_user content = open(urllib.quote(attach.filename.encode('utf-8'))) target.createAttachment(str(project_ID) + "-" + str(issue.id), attach.name, content, attach.author_name, created=attach.time) print "Importing attachments finished" print "Importing workitems" tt_enabled = False for issue in trac_issues: if issue.workitems: if not tt_enabled: tt_settings = target.getProjectTimeTrackingSettings(str(project_ID)) if not tt_settings.Enabled: print "Enabling TimeTracking for the prject" target.setProjectTimeTrackingSettings(str(project_ID), enabled=True) tt_enabled = True print "Processing issue [ %s ]" % (str(issue.id)) workitems = [to_youtrack_workitem(w) for w in issue.workitems] target.importWorkItems(str(project_ID) + "-" + str(issue.id), workitems) print "Importing workitems finished"
def fb2youtrack(target_url, target_login, target_password, source_url, source_login, source_password, project_names, max_issue_id): #encoding = 'utf-8' source = FBClient(source_url, source_login, source_password) target = Connection(target_url, target_login, target_password) accessible_projects = source.list_project_names() for p_name in project_names: if not (p_name in accessible_projects.keys()): print 'Unknown project names. Exiting...' sys.exit() # for p_name in accessible_projects : # if (p_name.encode('utf-8') in project_names_str) : # project_names_str.remove(p_name.encode('utf-8')) # project_names.append(p_name) # # if (len(project_names_str) != 0) : # print 'Unknown project names!' print('Creating custom fields') # # for field_name in ['Category', 'Priority', 'Status']: # field_name = get_yt_name_from_fb__field_name(field_name) # create_custom_field(target, fbugz.CF_TYPES[field_name], field_name, False) fb_category_bundle_name = u'FB Categories' fb_priorities_bundle_name = u'FB Priorities' fb_statuses_bundle_name = u'FB Statuses' common_fields = { u'category': fb_category_bundle_name, u'priority': fb_priorities_bundle_name, u'status': fb_statuses_bundle_name } field_name = u'category' create_bundle_with_values( target, fbugz.CF_TYPES[get_yt_name_from_fb_field_name(field_name)], common_fields[field_name], source.list_categories(), lambda bundle, value: bundle.createElement( to_yt_field_value(field_name, value))) field_name = u'priority' create_bundle_with_values( target, fbugz.CF_TYPES[get_yt_name_from_fb_field_name(field_name)], common_fields[field_name], [elem[0] + '-' + elem[1] for elem in source.list_priorities()], lambda bundle, value: bundle.createElement( to_yt_field_value(field_name, value))) field_name = u'status' statuses = [(to_yt_field_value(field_name, value), resolved) for (value, resolved) in source.list_statuses()] create_bundle_with_values( target, fbugz.CF_TYPES[get_yt_name_from_fb_field_name(field_name)], common_fields[field_name], statuses, lambda bundle, value: to_yt_status(bundle, value)) simple_fields = [ u'original_title', u'version', u'computer', u'due', u'estimate' ] for name in simple_fields: name = get_yt_name_from_fb_field_name(name) create_custom_field(target, fbugz.CF_TYPES[name], name, False) print 'Importing users' for name in ['Normal', 'Deleted', 'Community', 'Virtual']: group = Group() group.name = name try: target.createGroup(group) print 'Group with name [ %s ] successfully created' % name except: print "Can't create group with name [ %s ] (maybe because it already exists)" % name users_to_import = [] max = 100 for user in source.get_users(): yt_user = _to_yt_user(user) print 'Importing user [ %s ]' % yt_user.login users_to_import.append(yt_user) if len(users_to_import) >= max: _do_import_users(target, users_to_import) users_to_import = [] _do_import_users(target, users_to_import) print 'Importing users finished' # to handle linked issues try: target.createIssueLinkTypeDetailed('parent-child', 'child of', 'parent of', True) except YouTrackException: print "Can't create issue link type [ parent-child ] (maybe because it already exists)" links_to_import = [] for project_name in project_names: value_sets = dict([]) project_id = accessible_projects[project_name] print 'Importing project [ %s ]' % project_name target.createProjectDetailed(project_id, project_name.encode('utf-8'), 'no description', 'root') print 'Creating custom fields in project [ %s ]' % project_name for cf_name in common_fields: bundle_name = common_fields[cf_name] cf_name = get_yt_name_from_fb_field_name(cf_name) target.deleteProjectCustomField(project_id, cf_name) target.createProjectCustomFieldDetailed(project_id, cf_name, 'No ' + cf_name.lower(), {'bundle': bundle_name}) for cf_name in simple_fields: cf_name = get_yt_name_from_fb_field_name(cf_name) try: target.createProjectCustomFieldDetailed( project_id, cf_name, 'No ' + cf_name.lower()) except YouTrackException: print "Can't create custom field with name [%s]" % cf_name cf_name = get_yt_name_from_fb_field_name('fix_for') milestones = source.get_milestones(project_id) value_sets["fix_for"] = [] for milestone in milestones: value_sets["fix_for"].append(milestone.name) milestone.name = to_yt_field_value('fix_for', milestone.name) add_values_to_field( target, cf_name, project_id, milestones, lambda bundle, value: _to_yt_version(bundle, value)) cf_name = get_yt_name_from_fb_field_name('area') areas = source.get_areas(project_id) value_sets["area"] = [] for area in areas: value_sets["area"].append(area.name) area.name = to_yt_field_value('area', area.name) add_values_to_field( target, cf_name, project_id, areas, lambda bundle, value: _to_yt_subsystem(bundle, value)) print 'Importing issues for project [ %s ]' % project_name start = 0 issues_to_import = [] # create dictionary with child : parent pairs while start <= max_issue_id: fb_issues = source.get_issues(project_name, start, 30) for issue in fb_issues: add_values_to_field( target, get_yt_name_from_fb_field_name('area'), project_id, [issue.field_values['area']], lambda bundle, value: bundle.createElement(value)) issues_to_import.append(_to_yt_issue(issue, value_sets)) target.importIssues(project_id, project_name.encode('utf-8') + " assignees", issues_to_import) for issue in fb_issues: full_issue_id = '%s-%s' % (project_id, issue.ix_bug) for attach in issue.attachments: target.createAttachmentFromAttachment( full_issue_id, attach) for tag in issue.tags: target.executeCommand(full_issue_id, 'tag ' + tag) if issue.bug_parent is not None: parent_issue_id = '%s-%s' % (source.get_issue_project_id( issue.bug_parent), issue.bug_parent) link = Link() link.typeName = 'parent-child' link.source = full_issue_id link.target = parent_issue_id links_to_import.append(link) issues_to_import = [] start += 30 print 'Importing issues for project [ %s ] finished' % project_name print 'Importing issue links' print target.importLinks(links_to_import) print 'Importing issue links finished'
issue[field_name] = get_value_presentation(field_type, value) # process custom fields for custom_field in jira_issue.customFieldValues: field_name = get_yt_field_name(custom_field.customFieldId) field_value = custom_field.values field_type = get_yt_field_type(field_name) if (field_name is not None) and (field_type is not None): pass return issue source = JiraSoapClient("jira url", "jira login", "jira pass") target = Connection('http://localhost:8081', 'root', 'root') project_ids = {'ACS' : 100, 'ASL' : 100, 'BLZ' : 100, 'CGM' : 100, 'DURANGO' : 100, 'FCM' : 100, 'FLEXDMV' : 100, 'FLEXDOCS' : 100, 'FLEXENT' : 100, 'SDK' : 100, 'FLEXPMD' : 100, 'FXU' : 100 }
def youtrack2youtrack(source_url, source_login, source_password, target_url, target_login, target_password, project_ids, query='', source_token=None, target_token=None, params=None): if not len(project_ids): print("You should sign at least one project to import") return if params is None: params = {} source = Connection(source_url, source_login, source_password) if (source_token is None) else Connection(source_url, token=source_token) target = Connection(target_url, target_login, target_password) if (target_token is None) else Connection(target_url, token=target_token) # , proxy_info = httplib2.ProxyInfo(socks.PROXY_TYPE_HTTP, 'localhost', 8888) print("Import issue link types") for ilt in source.getIssueLinkTypes(): try: print(target.createIssueLinkType(ilt)) except youtrack.YouTrackException as e: print(e.message) user_importer = UserImporter(source, target, caching_users=params.get('enable_user_caching', True)) link_importer = LinkImporter(target) # create all projects with minimum info and project lead set created_projects = [] for project_id in project_ids: created = create_project_stub(source, target, project_id, user_importer) created_projects.append(created) # save created project ids to create correct group roles afterwards user_importer.addCreatedProjects([project.id for project in created_projects]) # import project leads with group they are included and roles assigned to these groups user_importer.importUsersRecursively([target.getUser(project.lead) for project in created_projects]) # afterwards in a script any user import imply recursive import cf_names_to_import = set([]) # names of cf prototypes that should be imported for project_id in project_ids: cf_names_to_import.update([pcf.name.capitalize() for pcf in source.getProjectCustomFields(project_id)]) target_cf_names = [pcf.name.capitalize() for pcf in target.getCustomFields()] period_cf_names = [] for cf_name in cf_names_to_import: source_cf = source.getCustomField(cf_name) if source_cf.type.lower() == 'period': period_cf_names.append(source_cf.name.lower()) print("Processing custom field '%s'" % utf8encode(cf_name)) if cf_name in target_cf_names: target_cf = target.getCustomField(cf_name) if not (target_cf.type == source_cf.type): print("In your target and source YT instances you have field with name [ %s ]" % utf8encode(cf_name)) print("They have different types. Source field type [ %s ]. Target field type [ %s ]" % (source_cf.type, target_cf.type)) print("exiting...") exit() else: if hasattr(source_cf, "defaultBundle"): create_bundle_from_bundle(source, target, source_cf.defaultBundle, source_cf.type, user_importer) target.createCustomField(source_cf) failed_commands = [] for projectId in project_ids: source = Connection(source_url, source_login, source_password) if (source_token is None) else Connection( source_url, token=source_token) target = Connection(target_url, target_login, target_password) if (target_token is None) else Connection( target_url, token=target_token) # , proxy_info = httplib2.ProxyInfo(socks.PROXY_TYPE_HTTP, 'localhost', 8888) # reset connections to avoid disconnections user_importer.resetConnections(source, target) link_importer.resetConnections(target) # copy project, subsystems, versions project = source.getProject(projectId) link_importer.addAvailableIssuesFrom(projectId) project_custom_fields = source.getProjectCustomFields(projectId) # create bundles and additional values for pcf_ref in project_custom_fields: pcf = source.getProjectCustomField(projectId, pcf_ref.name) if hasattr(pcf, "bundle"): try: create_bundle_from_bundle(source, target, pcf.bundle, source.getCustomField(pcf.name).type, user_importer) except youtrack.YouTrackException as e: if e.response.status != 409: raise e else: print(e) target_project_fields = [pcf.name.lower() for pcf in target.getProjectCustomFields(projectId)] for field in project_custom_fields: if field.name.lower() in target_project_fields: if hasattr(field, 'bundle'): if field.bundle != target.getProjectCustomField(projectId, field.name).bundle: target.deleteProjectCustomField(projectId, field.name) create_project_custom_field(target, field, projectId) else: try: create_project_custom_field(target, field, projectId) except youtrack.YouTrackException as e: if e.response.status != 409: raise e else: print(e) # copy issues start = 0 max = 20 sync_workitems = enable_time_tracking(source, target, projectId) tt_settings = target.getProjectTimeTrackingSettings(projectId) print("Import issues") last_created_issue_number = 0 while True: try: print("Get issues from " + str(start) + " to " + str(start + max)) issues = source.getIssues(projectId, query, start, max) if len(issues) <= 0: break if convert_period_values and period_cf_names: for issue in issues: for pname in period_cf_names: for fname in issue.__dict__: if fname.lower() != pname: continue issue[fname] = period_to_minutes(issue[fname]) users = set([]) for issue in issues: print("Collect users for issue [%s]" % issue.id) users.add(issue.getReporter()) if issue.hasAssignee(): if isinstance(issue.Assignee, (list, tuple)): users.update(issue.getAssignee()) else: users.add(issue.getAssignee()) # TODO: http://youtrack.jetbrains.net/issue/JT-6100 users.add(issue.getUpdater()) if issue.hasVoters(): users.update(issue.getVoters()) for comment in issue.getComments(): users.add(comment.getAuthor()) print("Collect links for issue [%s]" % issue.id) link_importer.collectLinks(issue.getLinks(True)) # links.extend(issue.getLinks(True)) # fix problem with comment.text for comment in issue.getComments(): if not hasattr(comment, "text") or (len(comment.text.strip()) == 0): setattr(comment, 'text', 'no text') user_importer.importUsersRecursively(users) print("Create issues [" + str(len(issues)) + "]") if params.get('create_new_issues'): create_issues(target, issues, last_created_issue_number) else: print(target.importIssues(projectId, project.name + ' Assignees', issues)) link_importer.addAvailableIssues(issues) for issue in issues: try: target_issue = target.getIssue(issue.id) except youtrack.YouTrackException as e: print("Cannot get target issue") print(e) continue if params.get('sync_tags') and issue.tags: try: for tag in issue.tags: tag = re.sub(r'[,&<>]', '_', tag) try: target.executeCommand(issue.id, 'tag ' + tag, disable_notifications=True) except youtrack.YouTrackException: tag = re.sub(r'[\s-]', '_', tag) target.executeCommand(issue.id, 'tag ' + tag, disable_notifications=True) except youtrack.YouTrackException as e: print("Cannot sync tags for issue " + issue.id) print(e) if params.get('add_new_comments'): target_comments = dict() max_id = 0 for c in target_issue.getComments(): target_comments[c.created] = c if max_id < c.created: max_id = c.created for c in issue.getComments(): if c.created > max_id or c.created not in target_comments: group = None if hasattr(c, 'permittedGroup'): group = c.permittedGroup try: target.executeCommand(issue.id, 'comment', c.text, group, c.author, disable_notifications=True) except youtrack.YouTrackException as e: print('Cannot add comment to issue') print(e) if params.get('sync_custom_fields'): skip_fields = [] if tt_settings and tt_settings.Enabled and tt_settings.TimeSpentField: skip_fields.append(tt_settings.TimeSpentField) skip_fields = [name.lower() for name in skip_fields] for pcf in [pcf for pcf in project_custom_fields if pcf.name.lower() not in skip_fields]: target_cf_value = None if pcf.name in target_issue: target_cf_value = target_issue[pcf.name] if isinstance(target_cf_value, (list, tuple)): target_cf_value = set(target_cf_value) elif target_cf_value == target.getProjectCustomField(projectId, pcf.name).emptyText: target_cf_value = None source_cf_value = None if pcf.name in issue: source_cf_value = issue[pcf.name] if isinstance(source_cf_value, (list, tuple)): source_cf_value = set(source_cf_value) elif source_cf_value == source.getProjectCustomField(projectId, pcf.name).emptyText: source_cf_value = None if source_cf_value == target_cf_value: continue if isinstance(source_cf_value, set) or isinstance(target_cf_value, set): if source_cf_value is None: source_cf_value = set([]) elif not isinstance(source_cf_value, set): source_cf_value = set([source_cf_value]) if target_cf_value is None: target_cf_value = set([]) elif not isinstance(target_cf_value, set): target_cf_value = set([target_cf_value]) for v in target_cf_value: if v not in source_cf_value: target.executeCommand(issue.id, 'remove %s %s' % (pcf.name, v), disable_notifications=True) for v in source_cf_value: if v not in target_cf_value: target.executeCommand(issue.id, 'add %s %s' % (pcf.name, v), disable_notifications=True) else: if source_cf_value is None: source_cf_value = target.getProjectCustomField(projectId, pcf.name).emptyText if pcf.type.lower() == 'date': m = re.match(r'(\d{10})(?:\d{3})?', str(source_cf_value)) if m: source_cf_value = datetime.datetime.fromtimestamp( int(m.group(1))).strftime('%Y-%m-%d') elif pcf.type.lower() == 'period': source_cf_value = '%sm' % source_cf_value command = '%s %s' % (pcf.name, source_cf_value) try: target.executeCommand(issue.id, command, disable_notifications=True) except youtrack.YouTrackException as e: if e.response.status == 412 and e.response.reason.find('Precondition Failed') > -1: print('WARN: Some workflow blocks following command: %s' % command) failed_commands.append((issue.id, command)) if sync_workitems: workitems = source.getWorkItems(issue.id) if workitems: existing_workitems = dict() target_workitems = target.getWorkItems(issue.id) if target_workitems: for w in target_workitems: _id = '%s\n%s\n%s' % (w.date, w.authorLogin, w.duration) if hasattr(w, 'description'): _id += '\n%s' % w.description existing_workitems[_id] = w new_workitems = [] for w in workitems: _id = '%s\n%s\n%s' % (w.date, w.authorLogin, w.duration) if hasattr(w, 'description'): _id += '\n%s' % w.description if _id not in existing_workitems: new_workitems.append(w) if new_workitems: print("Process workitems for issue [ " + issue.id + "]") try: user_importer.importUsersRecursively( [source.getUser(w.authorLogin) for w in new_workitems]) target.importWorkItems(issue.id, new_workitems) except youtrack.YouTrackException as e: if e.response.status == 404: print("WARN: Target YouTrack doesn't support workitems importing.") print("WARN: Workitems won't be imported.") sync_workitems = False else: print("ERROR: Skipping workitems because of error:" + str(e)) print("Process attachments for issue [%s]" % issue.id) existing_attachments = dict() try: for a in target.getAttachments(issue.id): existing_attachments[a.name + '\n' + a.created] = a except youtrack.YouTrackException as e: if e.response.status == 404: print("Skip importing attachments because issue %s doesn't exist" % issue.id) continue raise e attachments = [] users = set([]) for a in issue.getAttachments(): if a.name + '\n' + a.created in existing_attachments and not params.get('replace_attachments'): a.name = utf8encode(a.name) try: print("Skip attachment '%s' (created: %s) because it's already exists" % (utf8encode(a.name), utf8encode(a.created))) except Exception: pass continue attachments.append(a) author = a.getAuthor() if author is not None: users.add(author) user_importer.importUsersRecursively(users) for a in attachments: print("Transfer attachment of " + utf8encode(issue.id) + ": " + utf8encode(a.name)) # TODO: add authorLogin to workaround http://youtrack.jetbrains.net/issue/JT-6082 # a.authorLogin = target_login try: target.createAttachmentFromAttachment(issue.id, a) except BaseException as e: print("Cant import attachment [ %s ]" % utf8encode(a.name)) print(repr(e)) continue if params.get('replace_attachments'): try: old_attachment = existing_attachments.get(a.name + '\n' + a.created) if old_attachment: print('Deleting old attachment') target.deleteAttachment(issue.id, old_attachment.id) except BaseException as e: print("Cannot delete attachment '%s' from issue %s" % ( utf8encode(a.name), utf8encode(issue.id))) print(e) except Exception as e: print('Cant process issues from ' + str(start) + ' to ' + str(start + max)) traceback.print_exc() raise e start += max print("Import issue links") link_importer.importCollectedLinks() print("Trying to execute failed commands once again") for issue_id, command in failed_commands: try: print('Executing command on issue %s: %s' % (issue_id, command)) target.executeCommand(issue_id, command, disable_notifications=True) except youtrack.YouTrackException as e: print('Failed to execute command for issue #%s: %s' % (issue_id, command)) print(e)
if cf_name in target_cf_names: target_cf = target.getCustomField(cf_name) if not(target_cf.type == source_cf.type): print "In your target and source YT instances you have field with name [ %s ]" % cf_name.encode('utf-8') print "They have different types. Source field type [ %s ]. Target field type [ %s ]" %\ (source_cf.type, target_cf.type) print "exiting..." exit() else: if hasattr(source_cf, "defaultBundle"): create_bundle_from_bundle(source, target, source_cf.defaultBundle, source_cf.type, user_importer) target.createCustomField(source_cf) for projectId in project_ids: source = Connection(source_url, source_login, source_password) target = Connection(target_url, target_login, target_password) #, proxy_info = httplib2.ProxyInfo(socks.PROXY_TYPE_HTTP, 'localhost', 8888) #reset connections to avoid disconnections user_importer.resetConnections(source, target) link_importer.resetConnections(target) # copy project, subsystems, versions project = source.getProject(projectId) link_importer.addAvailableIssuesFrom(projectId) project_custom_fields = source.getProjectCustomFields(projectId) # create bundles and additional values for pcf_ref in project_custom_fields: pcf = source.getProjectCustomField(projectId, pcf_ref.name) if hasattr(pcf, "bundle"):
def fb2youtrack(params): # Connection to FogBugz source = FBClient(params['fb_url'], params['fb_login'], params['fb_password']) # Connecting to YouTrack token = params.get('token') if not token and 'token_file' in params: try: with open(params['token_file'], 'r') as f: token = f.read().strip() except (OSError, IOError) as e: print("Cannot load token from file: " + str(e)) sys.exit(1) if token: target = Connection(params['yt_url'], token=token) elif 'yt_login' in params: target = Connection(params['yt_url'], params.get('yt_login'), params.get('yt_password')) else: print("You have to provide token or login/password to import data") sys.exit(1) if not params.get('project_lead_login'): project_lead = params.get('yt_login') if not project_lead: for login in ('root', 'admin', 'administrator', 'guest'): try: project_lead = target.getUser(login).login break except youtrack.YouTrackException: continue params['project_lead_login'] = project_lead max_issue_id = params['fb_max_issue_id'] project_names = youtrackutils.fbugz.PROJECTS_TO_IMPORT accessible_projects = source.list_project_names() for p_name in project_names: if not (p_name in accessible_projects.keys()): print('Unknown project names. Exiting...') sys.exit() # for p_name in accessible_projects : # if (p_name.encode('utf-8') in project_names_str) : # project_names_str.remove(p_name.encode('utf-8')) # project_names.append(p_name) # # if (len(project_names_str) != 0) : # print 'Unknown project names!' print('Creating custom fields') # # for field_name in ['Category', 'Priority', 'Status']: # field_name = get_yt_name_from_fb__field_name(field_name) # create_custom_field(target, fbugz.CF_TYPES[field_name], field_name, False) fb_category_bundle_name = u'FB Categories' fb_priorities_bundle_name = u'FB Priorities' fb_statuses_bundle_name = u'FB Statuses' common_fields = { u'category' : fb_category_bundle_name, u'priority' : fb_priorities_bundle_name, u'status' : fb_statuses_bundle_name } field_name = u'category' create_bundle_with_values( target, youtrackutils.fbugz.CF_TYPES[get_yt_field_name(field_name)], common_fields[field_name], source.list_categories(), lambda bundle, value: bundle.createElement(to_yt_field_value(field_name, value))) field_name = u'priority' create_bundle_with_values(target, youtrackutils.fbugz.CF_TYPES[get_yt_field_name(field_name)], common_fields[field_name], [elem[0] + '-' + elem[1] for elem in source.list_priorities()], lambda bundle, value : bundle.createElement(to_yt_field_value(field_name, value))) field_name = u'status' statuses = [(to_yt_field_value(field_name, value), resolved) for (value, resolved) in source.list_statuses()] create_bundle_with_values(target, youtrackutils.fbugz.CF_TYPES[get_yt_field_name(field_name)], common_fields[field_name], statuses, lambda bundle, value : to_yt_status(bundle, value)) simple_fields = [u'original_title', u'version', u'computer', u'due', u'estimate'] for name in simple_fields: name = get_yt_field_name(name) create_custom_field(target, youtrackutils.fbugz.CF_TYPES[name], name, False) print('Importing users') for name in ['Normal', 'Deleted', 'Community', 'Virtual'] : group = Group() group.name = name try : target.createGroup(group) print('Group with name [ %s ] successfully created' % name) except: print("Can't create group with name [ %s ] (maybe because it already exists)" % name) users_to_import = [] max = 100 for user in source.get_users() : yt_user = _to_yt_user(user) print('Importing user [ %s ]' % yt_user.login) users_to_import.append(yt_user) if len(users_to_import) >= max: _do_import_users(target, users_to_import) users_to_import = [] _do_import_users(target, users_to_import) print('Importing users finished') # to handle linked issues try : target.createIssueLinkTypeDetailed('parent-child', 'child of', 'parent of', True) except YouTrackException: print("Can't create issue link type [ parent-child ] (maybe because it already exists)") links_to_import = [] for project_name in project_names: value_sets = dict([]) project_id = accessible_projects[project_name] print('Importing project [ %s ]' % project_name) target.createProjectDetailed(project_id, project_name.encode('utf-8'), '', params['project_lead_login']) print('Creating custom fields in project [ %s ]' % project_name) for cf_name in common_fields: bundle_name = common_fields[cf_name] cf_name = get_yt_field_name(cf_name) target.deleteProjectCustomField(project_id, cf_name) target.createProjectCustomFieldDetailed(project_id, cf_name, 'No ' + cf_name.lower(), {'bundle' : bundle_name}) for cf_name in simple_fields: cf_name = get_yt_field_name(cf_name) try: target.createProjectCustomFieldDetailed(project_id, cf_name, 'No ' + cf_name.lower()) except YouTrackException: print("Can't create custom field with name [%s]" % cf_name) cf_name = get_yt_field_name('fix_for') milestones = source.get_milestones(project_id) value_sets["fix_for"] = [] for milestone in milestones: value_sets["fix_for"].append(milestone.name) milestone.name = to_yt_field_value('fix_for', milestone.name) add_values_to_field(target, cf_name, project_id, milestones, lambda bundle, value: _to_yt_version(bundle, value)) cf_name = get_yt_field_name('area') areas = source.get_areas(project_id) value_sets["area"] = [] for area in areas: value_sets["area"].append(area.name) area.name = to_yt_field_value('area', area.name) add_values_to_field(target, cf_name, project_id, areas, lambda bundle, value: _to_yt_subsystem(bundle, value)) print('Importing issues for project [ %s ]' % project_name) start = 0 issues_to_import = [] # create dictionary with child : parent pairs while start <= max_issue_id: fb_issues = source.get_issues(project_name, start, 30) for issue in fb_issues : add_values_to_field(target, get_yt_field_name('area'), project_id, [issue.field_values['area']], lambda bundle, value: bundle.createElement(value)) issues_to_import.append(_to_yt_issue(issue, value_sets)) target.importIssues(project_id, project_name.encode('utf-8') + " assignees", issues_to_import) for issue in fb_issues : full_issue_id = '%s-%s' % (project_id, issue.ix_bug) for attach in issue.attachments : target.createAttachmentFromAttachment(full_issue_id, attach) for tag in issue.tags : target.executeCommand(full_issue_id, 'tag ' + tag) if issue.bug_parent is not None: parent_issue_id = '%s-%s' % (source.get_issue_project_id(issue.bug_parent), issue.bug_parent) link = Link() link.typeName = 'parent-child' link.source = full_issue_id link.target = parent_issue_id links_to_import.append(link) issues_to_import = [] start += 30 print('Importing issues for project [ %s ] finished' % project_name) print('Importing issue links') print(target.importLinks(links_to_import)) print('Importing issue links finished')
from youtrack.connection import Connection target = Connection("some url", "root", "root") for user in target.getUsers(): yt_user = target.getUser(user.login) try: if (str(yt_user.email).find("jetbrains") > 0): print yt_user.email elif (str(yt_user.email).find("intellij") > 0): print yt_user.email except: print "exception"
def redmine2youtrack(target_url, target_login, target_password, project_ID, project_name, url, api_key, from_project_ID): # creating connection to redmine to import issues to client = Client(url=url, api_key=api_key) # creating connection to youtrack to import issues in target = Connection(target_url, target_login, target_password) #create project print "Creating project[%s]" % project_name try : target.getProject(project_ID) except youtrack.YouTrackException: target.createProjectDetailed(project_ID, project_name, client.get_project_description(), target_login) #importing users redmine_users = client.get_users() print "Importing users" yt_users = list([]) # converting redmine users to yt users registered_users = set([]) for user in redmine_users : print "Processing user [ %s ]" % user.login registered_users.add(user.id) yt_users.append(to_youtrack_user(user)) # adding users to yt project target.importUsers(yt_users) print "Importing users finished" print "Creating project custom fields" create_yt_custom_field(target, project_ID, "Priority", client.get_issue_priorities()) create_yt_custom_field(target, project_ID, "Type", client.get_issue_types()) redmine_resolution_to_yt_state = lambda track_field, yt_bundle : to_youtrack_state(track_field, yt_bundle) create_yt_bundle_custom_field(target, project_ID, "Resolution", client.get_issue_resolutions(), redmine_resolution_to_yt_state) redmine_versions = client.get_versions(project_id=from_project_ID) redmine_version_to_yt_version = lambda redmine_field, yt_bundle : to_youtrack_version(redmine_field, yt_bundle) create_yt_bundle_custom_field(target, project_ID, "Version", redmine_versions, redmine_version_to_yt_version) #create_yt_bundle_custom_field(target, project_ID, "Affected versions", redmine_versions, redmine_version_to_yt_version) redmine_components = client.get_components(project_id=from_project_ID) redmine_component_to_yt_subsystem = lambda redmine_field, yt_bundle : to_youtrack_subsystem(redmine_field, yt_bundle) create_yt_bundle_custom_field(target, project_ID, "Component", redmine_components, redmine_component_to_yt_subsystem) redmine_custom_fields = client.get_custom_fields_declared() check_box_fields = dict([]) for elem in redmine_custom_fields: print "Processing custom field [ %s ]" % elem.name type_name = None if elem.type == "checkbox": if len(elem.label) > 0: opt = elem.label else: opt = elem.name options = list([opt]) check_box_fields[elem.name] = opt else: options = elem.options values = None if len(options): values = options field_name = elem.name if field_name in redmine.FIELD_NAMES.keys() : field_name = redmine.FIELD_NAMES[field_name] field_type = redmine.CUSTOM_FIELD_TYPES[elem.type] if field_name in redmine.FIELD_TYPES.keys(): field_type = redmine.FIELD_TYPES[field_name] process_custom_field(target, project_ID, field_type, field_name, redmine_values_to_youtrack_values(field_name, values)) print "Creating project custom fields finished" print "Importing issues" redmine_issues = client.get_all_issues(options={'project_id': from_project_ID}) yt_issues = list([]) counter = 0 max = 100 for issue in redmine_issues: print "Processing issue [ %s ]" % (str(issue.id)) counter += 1 if not issue.author is None and not (issue.author.id in registered_users): issue.author = None if hasattr(issue, 'assigned_to') and not issue.assigned_to is None and not (issue.assigned_to.id in registered_users): issue.assigned_to = None #legal_cc = set([]) #for cc in issue.cc: # if cc in registered_users: # legal_cc.add(cc) #issue.cc = legal_cc yt_issues.append(to_youtrack_issue(issue, check_box_fields)) if counter == max: counter = 0 print target.importIssues(project_ID, project_name + ' Assignees', yt_issues) yt_issues = list([]) print target.importIssues(project_ID, project_name + ' Assignees', yt_issues) print 'Importing issues finished' #importing tags #print "Importing keywords" #for issue in redmine_issues: # print "Importing tags from issue [ %s ]" % (str(issue.id)) # tags = issue.keywords # for t in tags: # target.executeCommand(str(project_ID) + "-" + str(issue.id), "tag " + t.encode('utf-8')) #print "Importing keywords finished" print "Importing attachments" for issue in redmine_issues: print "Processing issue [ %s ]" % (str(issue.id)) issue_attach = issue.attachment for attach in issue_attach: print "Processing attachment [ %s ]" % attach.filename.encode('utf-8') if not (attach.author_name.id in registered_users): attach.author_name = "guest" content = open(urllib.quote(attach.filename.encode('utf-8'))) target.createAttachment(str(project_ID) + "-" + str(issue.id), attach.filename, content, attach.author_name, created=attach.time) print "Importing attachments finished"