def redmine_issues_assigned(request): params = request.POST if params is None: raise PermissionDenied cache_key = 'redmine-issues-assigned-%u' % request.user.id assigned_issue_ids = cache.get(cache_key) if assigned_issue_ids is None: redmine_url = Settings.objects.all() if redmine_url is None or len(redmine_url) <= 0: raise PermissionDenied redmine_url = redmine_url[0].redmine_url redmine_api_key = UserSettings.objects.filter(user=request.user) if redmine_api_key is None or len(redmine_api_key) <= 0: raise PermissionDenied redmine_api_key = redmine_api_key[0].redmine_api_key redmine = Redmine(redmine_url, key=redmine_api_key) assigned_issue_ids = [i.id for i in redmine.issues(assigned_to_id=redmine.user.id)] cache_expires = Settings.objects.all() if cache_expires is None or len(cache_expires) <= 0: raise PermissionDenied cache_expires = cache_expires[0].cache_expires cache.set(cache_key, assigned_issue_ids, cache_expires) issues_cache = RedmineIssuesCache(request.user) output = {} for id_ in assigned_issue_ids: issue = issues_cache.get_issue(id_) if issue['valid']: output[id_] = issue return HttpResponse(json.dumps(output), content_type='application/json')
def get_redmine(self, sender): redmine = self._cache.get(sender) if redmine is None: redmine = Redmine(self.redmine_url) redmine.default_project_id = self.project_id user = User.get_user_by_jid(sender) if user: redmine.key = user.key self._cache[sender] = redmine return redmine
def check_auth(username, password): """This function is called to check if a username / password combination is valid. """ global redmine global current_user try: redmine = Redmine(REDMINE_SERVER_URL, username=username, password=password) current_user = redmine.auth() except AuthError: logger.error('Exception with Redmine authentificate. Username or password invalid.') return False return True
def download_all_files(username,password,redmine_url,issues,savepath): """username->(String) redmine username password->(String) redmine password redmine_url->(String) server address for redmine issues->(list (redmine.issue)) list of redmine issues to download files from savepath->(String) path to save the files to downloads all of the files in each issue provided to the given path""" redmine = Redmine(redmine_url,username=username,password=password) # connect to redmine for issue in issues: for f in issue.attachments: redmine.download(f['content_url'],savepath=savepath)
def syncToRedmine(): '''Gathers issues in XML format and push them to Redmine instance''' configProperties = fetchParametersFromFile() xml = generateXml(filterNotNumericIssues(fetchFromDatabase(configProperties['db'], getDate()))) if xml: try: myredmine = Redmine(configProperties['url'], configProperties['key']) except: print("Something wrong, check out credentials or connectivity") else: for issue in xml: xmlDocument = minidom.parseString(issue) myredmine.post("time_entries.xml", xmlDocument) print("Sync to %s [OK]" % configProperties['url']) else: print("Today no time entries to send... have you been lazy?")
def full_sync_redmine_redmine(self): for project in self.mapping_dict_project_name.items(): for issue in self.get_all_issues_main_task_manager(project=project[0]): self.save_from_redmine_to_redmine(issue, project[1]) for project in self.mapping_dict_project_name.items(): for issue in self.get_all_issues_main_task_manager(project=project[0]): if hasattr(issue, "parent"): redmine_main_tasks_manager = Redmine(self.main_task_manager.url, key=self.main_task_manager.api_key) user = redmine_main_tasks_manager.user.get(issue.author.id) new_issue = Redmine(self.sync_task_manager.url, key=self.sync_task_manager.api_key, impersonate=self.mapping("username", user.login)). \ issue.get(self.mapping_dict_issue_id[str(issue.id)]) new_issue.parent_issue_id = self.mapping_dict_issue_id[str(issue.parent.id)] new_issue.save()
def wrapper(*args, **kwargs): app_path = click.get_app_dir(APP_NAME, force_posix=True) path_config = os.path.join(app_path, 'config.ini') try: config = ConfigParser.RawConfigParser() config.read(path_config) username = config.get('user', 'username') password = config.get('user', 'password') redmine = Redmine('https://factory.ailove.ru/', username=username, password=password) redmine.auth() except (AuthError, ConfigParser.NoSectionError, ConfigParser.NoOptionError, OSError): raise click.ClickException(click.style('Error: Login/Password incorrect\n' 'Please use command: ailove login', fg='red')) return f(*args, **kwargs)
def syncToRedmine(time_entries, sync_date): '''Gathers issues in XML format and push them to Redmine instance''' # Synch starts xml_list = generateXml(time_entries, sync_date) print_('-> Connecting to Redmine...') try: redmine_url = configProperties.get('redmine', 'url') myredmine = Redmine(redmine_url, configProperties.get('redmine', 'key')) except: print("\nCannot connect to Redmine, check out credentials or connectivity") return else: print('[OK]') print_("-> Sending entries") for entry in xml_list: xmlDocument = minidom.parseString(entry) myredmine.post("time_entries.xml", xmlDocument) print_('.')
def main(config_file_name: str): dirpath = os.path.abspath(os.path.dirname(__file__)) conf = yaml.load(open(dirpath + '/' + config_file_name).read()) r = Redmine(conf['atom_url']) try: f = open(dirpath + '/' + conf['last_updated_at'], 'r') last_updated_at = f.read().strip() f.close() except IOError: last_updated_at = r.updated_at entries = r.get_new_entries(last_updated_at) s = Slack(conf['webhook_url'], conf['channel']) for entry in entries: s.post(entry['author_name'], entry['title'], entry['title_link'], entry['text']) # update last_updated_at f = open(dirpath + '/' + conf['last_updated_at'], 'w') f.write(r.updated_at) f.close()
def test_version_1_1(self): ''' Check to ensure expected settings for Redmine version 1.1. ''' redm = Redmine('null', version=1.1) assert redm.version is 1.1 assert redm.key_in_header is True assert redm.issues is not None assert redm.projects is not None assert redm.users is not None assert redm.news is not None assert not hasattr(redm, 'time_entry_activities') assert redm._project_memberships is False assert redm._wiki_pages is False
def test_version_2_2(self): ''' Check to ensure expected settings for Remdine version 2.2. ''' redm = Redmine('null', version=2.2) assert redm.version is 2.2 assert redm.key_in_header is True assert redm.issues is not None assert redm.projects is not None assert redm.users is not None assert redm.news is not None assert redm.time_entry_activities is not None assert redm.has_project_memberships is True assert redm.has_wiki_pages is True
def test_version_none(self): ''' Check to ensure expected settings for Redmine with unknown version ''' redm = Redmine('null') assert redm.version is None # TODO: assert redm.key_in_header is False assert redm.issues is not None assert redm.projects is not None assert redm.users is not None assert redm.news is not None assert redm.time_entry_activities is not None assert redm._project_memberships is True assert redm._wiki_pages is True
def login(username, password): err = False for cmd_name, required in REQUIRE_CMDS.items(): click.echo('Check command: {} ... '.format(cmd_name), nl=False) if not check_command_exists(cmd_name) and required: err = True click.secho('requires installation', fg='red') elif not check_command_exists(cmd_name) and not required: click.secho('desirable to install', fg='yellow') else: click.secho('OK', fg='green') if err: click.secho('Please install the required packages', fg='red') return try: redmine = Redmine(REDMINE_URL, username=username, password=password) redmine.auth() except AuthError: click.secho('Error: Login/Password incorrect', fg='red') return app_path = click.get_app_dir(APP_NAME, force_posix=True) if not os.path.exists(app_path): os.makedirs(app_path) config = ConfigParser.RawConfigParser() path_config = os.path.join(app_path, 'config.ini') config.add_section('user') config.set('user', 'username', username) config.set('user', 'password', password) with open(path_config, 'wb') as configfile: config.write(configfile)
def lookup_redmine_issue(app, tracker_config, issue_id): from redmine import Redmine if not tracker_config.url: raise ValueError('URL required') redmine = Redmine(tracker_config.url, key=app.config.issuetracker_redmine_key, username=app.config.issuetracker_redmine_username, password=app.config.issuetracker_redmine_password, requests=app.config.issuetracker_redmine_requests) if redmine: issue = redmine.issue.get(issue_id) return Issue(id=issue_id, title=issue.subject, closed=issue.status is "Closed", url=issue.url)
def _issue(self, to, subject, message): ''' Create/Update Redmine Issue ''' ret = { "result": True, "comment": [], } cache_dir = '/tmp/zabbix-events/' issue_update = False if not os.path.isdir(cache_dir): os.makedirs(cache_dir) self._get_eventinfo(message) event_file = cache_dir + os.sep + str(self.eventinfo['eventid']) if os.path.isfile(event_file): event_fd = open(event_file, 'r') for eachline in event_fd: if eachline.startswith('issueid:'): issueid = int(eachline.split()[-1]) issue_update = True break event_fd.close() # Process Issue redmine = Redmine(self.options['url'], key=self.options['key']) if not issue_update and self.eventinfo['status'] != 'OK': # Create Issue issue = redmine.issue.new() issue.project_id = self.options['project'] issue.subject = subject issue.description = message issue.priority_id = self.event_prioritys.get( self.eventinfo['severity'], 1) issue.status_id = self.event_status[self.eventinfo['status']] issue.assigned_to_id = int(to) issue.tracker_id = self.tracker_id try: issue.save() except Exception, e: ret['result'] = False ret['comment'].append(str(e)) return ret issueid = issue.id event_fd = open(event_file, 'a') event_fd.write('issueid: %s\n' % (issueid)) event_fd.close() ret['comment'].append('Issue create success!')
def getwi(request, wid): redmine = Redmine('http://git.ablesky.com', key=authKey) try: issue = redmine.issue.get(wid) except ResourceNotFoundError: return HttpResponse('') else: attachments = [] for item in issue.attachments: attachments.append(item.filename) print list(issue.project) issueitem = {'id': issue.id, 'type': issue.tracker.id, 'status': issue.status.id, 'subject': issue.subject, 'description': issue.description, 'PRI': issue.priority.id, 'assign_to': issue.assigned_to.id, 'uploads': attachments, 'cid': issue.project.id} return HttpResponse(json.dumps(issueitem))
def test_complete_example(self): redmine = Redmine(api=RedmineMock(issues_as_dict=get_example_issues())) result = render_issues(IssueStatus.ON_DEVELOP, redmine) expected = [ "> #### Backend", f"> • Bug [#12345]({URL}12345) (Bob Martin): Clean up code base *done by Martin Fowler*", f"> • Feature [#12346]({URL}12346) (Bob Martin): No one does this", "> #### Uncategorized", f"> • Bug [#12347]({URL}12347) (Bob Martin): Eat cake *done by Kent Beck*", "", ] for expected, actual in zip(expected, result.split("\n")): assert expected == actual
def ticket_forget(user, ticket_id): redmine = Redmine(settings.REDMINE_API_URL, key=settings.REDMINE_KEY, impersonate=user.login) try: issue = redmine.issue.get(ticket_id) except ResourceNotFoundError: return "Ticket no se encuentra" try: if issue.assigned_to.id == 0: return "El /ticket_{} ya esta suelto!".format(ticket_id) elif issue.assigned_to.id == user.id: redmine.issue.update(ticket_id, assigned_to_id=0) return "Acabas de soltar el /ticket_{}: {}".format(ticket_id, issue.subject) else: return "El /ticket_{} no es tuyo!".format(ticket_id) except ResourceAttrError: return "El /ticket_{} ya esta suelto!".format(ticket_id)
def __init__(self, issue_id, old_assignee_email, new_assignee_email, success_message, failure_message, old_status='new', new_status='resolved'): self.issue_id = issue_id self.old_status = old_status self.new_status = new_status self.old_assignee_email = old_assignee_email self.new_assignee_email = new_assignee_email self.success_message = success_message self.failure_message = failure_message self.redmine = Redmine(self.REDMINE_HOST, key=self.REDMINE_KEY)
def ticket_time_entry(user, ticket_id, mensaje, minutes): if isinstance(minutes, str): if minutes[-1] in "hH": hours = float(minutes[:-1]) elif minutes[-1] in "mM": hours = float(minutes[:-1])/60. else: hours = float(minutes)/60. else: hours = minutes/60. redmine = Redmine(settings.REDMINE_API_URL, key=settings.REDMINE_KEY, impersonate=user.login) redmine.time_entry.create(issue_id=ticket_id, hours=hours, activity_id=settings.DEFAULT_ACTIVITY, comments=mensaje) return "Anotado que has trabajado {minutes} minutos en el /ticket_{i}.\n" \ "Si quieres /suelta_{i} o /cierra_{i} o sigue trabajando".format( minutes=int(hours*60), i=ticket_id)
def main(): args = parse_arguments() redmine = Redmine() from_status = IssueStatus.from_string(args.from_status) to_status = IssueStatus.from_string(args.to_status) print("**Deployed**") print(render_issues(from_status, redmine)) print("**Rejected**") print(render_issues(IssueStatus.REJECTED, redmine)) if args.only_print: exit(0) move_issues(from_status, to_status, redmine) move_issues(IssueStatus.REJECTED, IssueStatus.REJECTED_LOGGED, redmine)
def create_redmine_issue(username, password, redmine_url, project_id, issue_subject, issue_description, assign_to): """Create and save a new issue on redmine username ->(String) authentication info for redmine password ->(String) authentication info for redmine project_id ->(String) name of project issue_subject ->(String) issue subject issue_description ->(String) description of issue assign_to ->(String) id of the person the task is assigned to Creates a new issue/ticket on redmine for the given information. """ redmine = Redmine(redmine_url, username=username, password=password) redmine.issue.create(project_id=project_id, subject=issue_subject, description=issue_subject, assigned_to_id=assign_to)
def make_processor(config): redmine = Redmine(config['redmine_url'], key=config['api_key']) def process(log_entry): if log_entry.is_uploaded: return activity_id = config['act_name2act_id'][log_entry.account_path[2]] redmine.time_entry.create( **{ 'issue_id': log_entry.account_path[1], 'activity_id': activity_id, 'spent_on': log_entry.date, 'hours': float(log_entry.hours), 'comments': log_entry.comment }) return process
def authenticate(self, username=None, password=None): user = None redmine_projects_identifier = [] try: redmine = Redmine(settings.REDMINE_SERVER_URL, username=username, password=password) redmine_user = redmine.user.get("current", include="memberships") for membership in redmine_user.memberships: redmine_projects_identifier.append( redmine.project.get(membership.project.id).identifier) if not self._check_redmine_project(redmine, redmine_projects_identifier): logger.error( 'Exeption with Redmine authentificate. User does not belong to specified groups.' ) return None try: django_redmine_user = RedmineUser.objects.get( redmine_user_id=redmine_user.id) if django_redmine_user.username != username: django_redmine_user.username = username django_redmine_user.save() user = django_redmine_user.user if self._refresh_user(redmine_user, user, username, redmine_projects_identifier): user.save() except RedmineUser.DoesNotExist: user, created = User.objects.get_or_create(username=username) self._refresh_user(redmine_user, user, username, redmine_projects_identifier) user.save() django_redmine_user = RedmineUser( user=user, username=username, redmine_user_id=redmine_user.id) django_redmine_user.save() except AuthError: logger.error( 'Exception with Redmine authentificate. Username or password invalid.' ) return None return user
def get_telegram_users(): "Fills dictionary from redmine with objects for each authorized user" redmine = Redmine(settings.REDMINE_API_URL, key=settings.REDMINE_KEY) # We search all users from redmine that have a telegram id and we build # a list of objects with useful data out = {} for user in redmine.user.all(): for cf in user.custom_fields: if cf.name == "telegram": chatid = int(cf.value or 0) if chatid > 0: out[chatid] = SimpleNamespace( name="{} {}".format(user.firstname, user.lastname), login=user.login, id=user.id, ) break return out
def __init__(self, *args, **kwargs): super(ArchiveModule, self).__init__(*args, **kwargs) config = self.controller.config if not config.has_section('redmine'): raise KeyError("No redmine section in configuration file.") for setting in ['host', 'api_key', 'default_project', 'infobot']: if not config.has_option('redmine', setting): raise KeyError( "Missing required redmine setting: {}".format(setting)) self.hostname = config.get('redmine', 'host') self.host = Redmine(self.hostname, key=config.get('redmine', 'api_key')) self.project = config.get('redmine', 'default_project') self.infobot = config.get('redmine', 'infobot') self.waiting = None self.target = None self.info = "" self.requester = () self.got_preamble = False
def updatewi(request): buglist = request.GET updatewi = {} redmine = Redmine('http://git.ablesky.com', key=authKey) results = [] for tid, wid in buglist.items(): try: issue = redmine.issue.get(wid) except ResourceNotFoundError: updatewi[wid] = "err" else: if issue.status.id != 1: updatewi[wid] = issue.status.id if issue.status.id == 5: results.append(case.models.result(testcase_id=tid, result='Pass', exec_date=datetime.datetime.now(), executor="Redmine更新", executorid="1", r_remark="#"+wid, isactived=1)) case.models.result.objects.bulk_create(results) return HttpResponse(json.dumps(updatewi))
def post(self): self.write('Hello') print('test1') data = json.loads(self.request.body) message = data["item"]['message']['message'] index1 = message.find("issues") + 7 index2 = message.rfind("/") if index2 < index1: index2 = len(message) s = int(message[index1:index2]) redmine = Redmine('http://redmine.vigroup.ru', key='eded47b9c0e8856b08fb184beb8a3c34c3aa0ab4') issue = redmine.issues.get(s) mes = 'Link: <a href="http://redmine.vigroup.ru/issues/' + str( issue.id ) + '">http://redmine.vigroup.ru/issues/' + str( issue.id ) + "</a><br>" "Name: " + issue.subject + '<br>Responsible: ' + issue.assigned_to.name pprint((data)) url = "https://api.hipchat.com/v2/room/2106789/notification?auth_token=8tea2EhoyH7hYKSQSdzGTD8YKgAiUByU8PmabZxV" header = { "Content-Type": "application/json", "Encoding": "utf8", "User-Agent": "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8 GTB7.1 (.NET CLR 3.5.30729)" } content = { "color": "green", "message": mes, "notify": 'true', "message_format": "html" } postHipChat = requests.request('POST', url, headers=header, timeout=30, data=json.dumps(content))
def export_to_redmine(request): if request.method == 'POST': redmine_settings = SettingsModel.on_site.get(pk__isnull=False) subject = request.POST.get('subject') desc = request.POST.get('description') try: redmine = Redmine(redmine_settings.redmine_tracker_url, username=redmine_settings.redmine_username, password=redmine_settings.redmine_password) path_files = request.POST.getlist('path_files[]')[0].split(',') name_files = request.POST.getlist('name_files[]')[0].split(',') uploads = [] if path_files[0] and name_files[0]: for x in xrange(len(path_files)): uploads.append({ 'path': path_files[x], 'filename': name_files[x] }) issue = redmine.issue.create( project_id=redmine_settings.redmine_project, subject=unicode(subject), description=unicode(desc), uploads=uploads) success = 'ok' messages = issue.id except: success = 'false' messages = '' for x in xrange(len(path_files)): if os.path.isfile(path_files[x]): os.remove(path_files[x]) else: success = 'false' messages = '' return { 'success': success, 'messages': messages, }
def create_redmine_issue(self): self.redmine = Redmine(self.REDMINE_HOST, key=self.REDMINE_KEY) self.project_data = {'name': 'test', 'identifier': 'test'} self.project = self.redmine.project.create(**self.project_data) self.user = self.redmine.user.all()[0] self.user_data = { 'login': '******', 'firstname': 'user2', 'lastname': 'user2', 'mail': '*****@*****.**', } self.user2 = self.redmine.user.create(**self.user_data) self.issue_data = { 'project_id': self.project.id, 'subject': 'Temp Issue', 'status_id': REDMINE_STATUS_MAPPING['resolved'], 'assigned_to_id': self.user.id } self.issue = self.redmine.issue.create(**self.issue_data) self.issue.status_id = REDMINE_STATUS_MAPPING[ 'resolved'] # in case you are wondering status_id doesn't work in create self.issue.save() self.redmine.project_membership.create(project_id=self.project.id, user_id=self.user.id, role_ids=[3, 4]) self.redmine.project_membership.create(project_id=self.project.id, user_id=self.user2.id, role_ids=[3, 4])
def main(): parser = argparse.ArgumentParser(usage='', add_help=False) parser.add_argument('--project') parser.add_argument('--user') parser.add_argument('--first-name') parser.add_argument('--last-name') parser.add_argument('--email') parser.add_argument('--redmine-url') parser.add_argument('--redmine-key-file') parser.add_argument('--help', action='store_true', default=False) args = vars(parser.parse_args()) if args['project'] is None or args['user'] is None or args[ 'first_name'] is None or args['last_name'] is None or args[ 'email'] is None or args['redmine_url'] is None or args[ 'redmine_key_file'] is None: exit('Invalid usage') try: redmine_key_file = open(args['redmine_key_file'], 'r') redmine_key = redmine_key_file.read().strip('\r\n') except IOError as e: exit('Error reading Redmine API key file \'%s\': %s' % (args['redmine_key_file'], e.strerror)) redmine = Redmine(args['redmine_url'], key=redmine_key, requests={'verify': False}) add_user(project_name=args['project'], username=args['user'], first_name=args['first_name'], last_name=args['last_name'], email=args['email'], redmine=redmine)
def assignedTo(self): redmine = Redmine('http://192.168.100.4/redmine/', key='fb77dd01d1c51f56596f5e3a36fcfc5f1f77d16f') users = redmine.user.all() profileDir = Path.Path().GetServerPath() + '/TeamConfig' MiliWork = {} if os.path.isdir(profileDir): for i in os.listdir(profileDir): name, ext = os.path.splitext(i) if ext == '.miliProfile': tmpAccount = MiliUser.MiliUser(userName=name) MiliWork[name] = tmpAccount['department'] self.pipelineTDs = {} for user in users: userLogin = user['_attributes']['login'] userID = user['_attributes']['id'] if userLogin in list( MiliWork.keys()) and MiliWork[userLogin] == 'PipelineTD': tmpMap = {'userID': userID, 'userLogin': userLogin} self.pipelineTDs[str(user).decode('utf-8')] = tmpMap #print userID,userLogin,user for item in list(self.pipelineTDs.keys()): self.assigned.addItem(item)
global configProperties configPath = os.path.join(os.path.split(os.path.abspath(sys.argv[0]))[0], "..", configFileName) config = ConfigParser.ConfigParser() # fetch parameters from a config file config.read(configPath) configProperties = config return configProperties if __name__ == "__main__": configProperties = fetchParametersFromFile() redmine_url = configProperties.get("redmine", "url") print ("-> Connecting to Redmine..."), sys.stdout.flush() try: redmine_url = configProperties.get("redmine", "url") myredmine = Redmine(redmine_url, configProperties.get("redmine", "key")) except: print ("\nCannot connect to Redmine, check out credentials or connectivity") sys.exit() print ("[OK]") print ("-> Sending request"), sys.stdout.flush() try: res = myredmine.get("/enumerations/time_entry_activities.xml") except urllib2.HTTPError, e: print if e.code == 404: print "[404] Error !" print "Make sure your version of Redmine is >= 2.2."
#!/usr/bin/env python import re import sys import traceback import redmine from tabulate import tabulate from response import Response import config if config.redmine_key: from redmine import Redmine, ResourceNotFoundError redmine = Redmine(config.redmine_url, key=config.redmine_key) else: redmine = None def link_redmine(mattermost_request): text = mattermost_request.text answer = "" text = ''.join(text).encode('latin1') ids = re.findall('#([0-9]+)', text) if (len(ids) < 1): return Response("no issue IDs found") answer = "" for issue in ids:
def SetRMParams(project): redmine = Redmine(redmine_server, requests={'verify': False}, \ key=redmine_key) return redmine
subcategory = "UNIX" elif "CentOS" in family: category = 56 subcategory = "UNIX" elif "Windows" in family: category = 55 subcategory = "Windows" else: category = 0 subcategory = " " return category, subcategory #Specify Redmine server params redmine = Redmine(redmine_server, requests={'verify': False}, key=redmine_key, version='2.5.1') def redmine_issue(priority, subject, body, category): ## Create an issue in Redmine to track the vulnerability # and return information regarding the created ticket new_issue = redmine.issue.create(project_id = redmine_project, \ priority_id = priority, subject = subject, description = body,\ tracker_id=19, category_id = category) redmine_issue_id = str(new_issue.id) redmine_url = redmine_server + "/issues/" + redmine_issue_id print("redmine ticket created") return redmine_url, redmine_issue_id
def __init__(self, url, user, password): self.redmine = Redmine(url, username=user, password=password)
def formatIssueLog(issue, directory, date, action): return "|".join([str(toTimestamp(date)), issue.author.login or issue.author.name or "Unknown", action, onlyPrintable(directory or '') + '/' + onlyPrintable(issue.subject or "No subject").replace('\\','_').replace('/', '_')]) def formatCreationLog(issue, directory, date): return formatIssueLog(issue, directory, date, 'A') def formatModifyLog(issue, directory, date): return formatIssueLog(issue, directory, date, 'M') def formatDeletionLog(issue, directory, date): return formatIssueLog(issue, directory, date, 'D') eventList = [] server = Redmine('http://dev.w42.ru', key = api_key) projects = server.projects(key = api_key) #['speek', 'qt-dev'] filter_date = time.strptime("2013-07-01", "%Y-%m-%d") issues_filter = ">=" + time.strftime("%Y-%m-%d", filter_date) for project in projects: projectName = project.name # project = server.projects[projectName] # Find Eric in the user data # Extend issues in project assigned to user by two weeks #assigned_to_id=user.id): #print "Созданы:", issues_filter, int(time.mktime(filter_date)) try: for issue in project.issues(status_id="*", created_on=issues_filter, sort="created_on", subproject_id='!*'):
first_activity_id = 1 last_activity_id = 50 if len(sys.argv) == 2: issue_id=int(sys.argv[1]) else: print "Usage : {} test_issue_id".format(sys.argv[0]) print print "The purpose of this tool is to guess Redmine activities IDs when used Redmine version is <= 2.2" print "(/enumerations/time_entry_activities.xml in Rest API is implemented in v2.2)" print "The script will attempt to add {n} time entries (from {first} to {last}) in Redmine #test_issue_id,".format(n=last_activity_id-first_activity_id+1, first=first_activity_id, last=last_activity_id) print "with for each entry the sent activity id on comment argument." print "This will make you then possible to go to that issue page and look on spend time to get activities IDs." sys.exit() configProperties = fetchParametersFromFile() print_('-> Connecting to Redmine...') try: redmine_url = configProperties.get('redmine', 'url') myredmine = Redmine(redmine_url, configProperties.get('redmine', 'key')) except: print("\nCannot connect to Redmine, check out credentials or connectivity") sys.exit() print('[OK]') for activity_id in range(first_activity_id, last_activity_id + 1): print_("{} ".format(activity_id)) xml = generateXml(issue_id, activity_id) myredmine.post("time_entries.xml", minidom.parseString(xml)) time.sleep(1)
Creates a new issue/ticket on redmine for the given information. """ redmine = Redmine(redmine_url,username=username,password=password) redmine.issue.create(project_id=project_id,subject=issue_subject,description=issue_subject,assigned_to_id=assign_to) if __name__ == "__main__": # Password and username input is for testing, I didn't want to leave my password up on github # Ideally when this is deployed, an external library will be imported with the settings. username = input("username:"******"password:"******"https://digitalscholarship.utsc.utoronto.ca/redmine" # Location of redmine redmine = Redmine(redmine_url,username=username,password=password) # connect to redmine redmine.auth() test_proj = redmine.project.get('test-project-kim3') # print(test_proj) create_redmine_issue(username,password,redmine_url,'test-project-kim2',"TEST SUBJECT", "TEST DESCRIPTION") projects = redmine.project.all() for proj in projects: print(proj.name) print(proj.identifier)
def _command(self, command='issues', command_url='issues.xml', **kwargs): force = kwargs.get('force', False) limit = kwargs.get('limit', 100) offset = kwargs.get('offset', 0) sort = kwargs.get('sort', 'id:desc') filter = kwargs.get('filter', None) project = kwargs.get('project', None) object_id = kwargs.get('object_id', None) me_only = kwargs.get('me_only', False) element_filter = kwargs.get('element', command) includes = kwargs.get('includes', None) params = [] if includes is not None: params += (('include', includes),) if offset is not None: params += (('offset', offset),) if sort is not None: params += (('sort', sort),) if limit is not None: params += (('limit', limit),) if project: params += (('project_id', self.aliases.get(project, project)),) if me_only: params += (('assigned_to_id', self.me),) params_key = '-'.join(['%s%s' % (p[0], p[1]) for p in params]) params_key += 'filter%s' % filter params_key += 'object_id%s' % object_id key = 'command%sparams%s' % (command, params_key) data = RedmineData(key, url=self.url, command=command) if not force: if data.load(): return (True, data) rm = Redmine(self.url, key=self.key) try: # As of Feb 2013 the pyredmine library has finally had a bunch of updates # - including cacheing! The response from RedMine.open is now a string rather # than a raw ElementTree instance so must convert now. issues = ET.fromstring(rm.open(command_url, parms=params)).findall(element_filter) except urllib2.HTTPError: return (False, 'There was an HTTP error - do you have permission to access?') issue_data = list() for issue in issues: issue_id = issue.find('id').text if command == 'projects': name = issue.find('identifier').text elif command == 'issue_statuses': name = issue.find('name').text else: name = issue.find('project').get('name') try: description = issue.find('description').text except AttributeError: description = 'N/A' try: subject = issue.find('subject').text except AttributeError: subject = 'N/A' history = list() if command == 'issues' and object_id: journals = issue.find('journals').findall('journal') for j in journals: history.append([ j.find('user').get('name'), j.find('created_on').text, j.find('notes').text, ]) if filter is None or (filter in subject.lower() or filter in name.lower()): issue_data.append((issue_id, name, subject.replace('\n', ''), description, history)) data.cache(issue_data) return (True, data)
from redmine import Redmine from redmine_settings import server from datetime import datetime import pytz server = Redmine(server['url'], username=server['username'], password=server['password']) COLUMN_STATE_MAP = { 'Reviewed': 'col_todo', 'New': 'col_todo', 'Closed': 'col_done', 'Feedback': 'col_done', 'Verify': 'col_done', 'Needs Release': 'col_done', 'In Progress': 'col_inprogress', 'Duplicate': 'col_done', 'Rejected': 'col_done', } WEEK_SECONDS = 60 * 60 * 24 * 7 CACHE = {} def issue(redmine_issue): then = redmine_issue.updated_on now = datetime.utcnow().replace(tzinfo=pytz.UTC)
from redmine import Redmine rd = Redmine("http://redmine.sislam.com.br", key="03988ba1a5d559b2525ed55db325ea4696c41ba4") tree = rd.get("projects.xml") for node in tree.iter('project'): print node.find("name").text print node.find("id").text
import os import sys # set the redmine url here REDMINE_URL="https://example.com/redmine" # Name of the group to allow Jenkins access JENKINS_ACCESS="jenkins_users" if __name__=="__main__": if len(sys.argv) >= 2: REDMINE_URL=sys.argv[1] username = os.environ['U'] password = os.environ['P'] print("Authenticating... %s@%s" % (username, REDMINE_URL)) instance = Redmine(REDMINE_URL, username=username, password=password) # This will fail if the authentication failed details = json.loads(instance.get("users/current.json?include=groups")) # Do the actual authorization logic for group in details['user']['groups']: if group['name'] == JENKINS_ACCESS: print("Authorization successful") exit(0) print("Authorization failed") exit(1)
def save_from_redmine_to_redmine(self, issue, project): redmine_main_tasks_manager = Redmine(self.main_task_manager.url, key=self.main_task_manager.api_key) user = redmine_main_tasks_manager.user.get(issue.author.id) logger.info("Issue {} is processed".format(issue.id)) new_issue = Redmine(self.sync_task_manager.url, key=self.sync_task_manager.api_key, impersonate=self.mapping("username", user.login)).issue.new() new_issue.project_id = project new_issue.subject = issue.subject new_issue.tracker_id = self.mapping("tracker_id", issue.tracker.id) new_issue.description = issue.description new_issue.status_id = self.mapping("status_id", issue.status.id) new_issue.priority_id = self.mapping("priority_id", issue.priority.id) if hasattr(issue, "assigned_to"): new_issue.assigned_to_id = self.mapping("user_id", issue.assigned_to.id) if hasattr(issue, "watchers"): # It's not working! watcher_user_ids = [] for watcher in issue.watchers: watcher_user_ids.append(self.mapping("user_id", watcher.id)) new_issue.watcher_user_ids = watcher_user_ids if hasattr(issue, "start_date"): new_issue.start_date = issue.start_date if hasattr(issue, "due_date"): new_issue.due_date = issue.due_date if hasattr(issue, "estimated_hours"): new_issue.estimated_hours = issue.estimated_hours new_issue.done_ratio = issue.done_ratio if issue.attachments: upload_list = [] for attachment in issue.attachments: redmine_main_tasks_manager.download(attachment.content_url, savepath='/tmp/', filename=attachment.filename) upload_list.append({'path': '/tmp/' + attachment.filename, 'filename': attachment.filename, 'description': attachment.description}) new_issue.uploads = upload_list new_issue.save() self.mapping_dict_issue_id[str(issue.id)] = new_issue.id self.save() time_entries = redmine_main_tasks_manager.time_entry.filter(issue_id=issue.id) if time_entries: for time_entry in time_entries: user = redmine_main_tasks_manager.user.get(time_entry.user.id) new_time_entry = Redmine(self.sync_task_manager.url, key=self.sync_task_manager.api_key, impersonate=self.mapping("username", user.login)).time_entry.new() new_time_entry.user_id = self.mapping("user_id", time_entry.user.id) if issue.id == time_entry.issue.id: # if we have related tasks then time entries are doubled and we need to check it new_time_entry.issue_id = new_issue.id new_time_entry.spent_on = time_entry.spent_on new_time_entry.hours = time_entry.hours new_time_entry.activity_id = time_entry.activity.id new_time_entry.comments = time_entry.comments new_time_entry.save() # adding notes to the task if issue.journals: for arg in issue.journals: if arg.notes: user = redmine_main_tasks_manager.user.get(arg.user.id) update_issue = Redmine(self.sync_task_manager.url, key=self.sync_task_manager.api_key, impersonate=self.mapping("username", user.login)).issue.get(new_issue.id) update_issue.notes = arg.notes update_issue.save()
def tag(product, version, options): try: temp_dir = tempfile.mkdtemp() print("Clone git@%s:%s/%s.git" % (options.repository, options.group, product)) cmd = "git clone git@%s:%s/%s.git" % ( options.repository, options.group, product, ) execute(cmd, cwd=temp_dir) print("Checkout develop") cwd = os.path.join(temp_dir, product) cmd = "git checkout develop" execute(cmd, cwd=cwd) print("Create local release branch") cmd = "git checkout -b release_%s" % (version) execute(cmd, cwd=cwd) print("Patching %s.version in %s to %s" % (product, options.properties, version)) replace( os.path.join(cwd, "%s" % (options.properties)), "%s.version=.*" % (product), "%s.version=%s" % (product, version), ) print("Commit changes") cmd = 'git commit -m "Udpate version" %s' % (options.properties) execute(cmd, cwd=cwd) # redmine issue after git commit if not options.noredmine: redmine_url = "http://" + options.redminerepository + "/redmine" home = expanduser("~") redmine_key = (open( home + "/.redmine_apikey_" + options.redminerepository, "r").read().replace("\n", "")) redmine = Redmine(redmine_url, key=redmine_key) project = get_project( redmine, options.redmineid if options.redmineid is not None else product) issueid = create_redmine_issue(redmine, project, version) else: issueid = "XXXXX" print("Merge release branch in master") cmd = "git checkout master" execute(cmd, cwd=cwd) cmd = 'git merge --no-ff -X theirs release_%s -m "Version %s\n\nFixID #%s"' % ( version, version, issueid, ) execute(cmd, cwd=cwd) print("Tag master") cmd = "git tag %s_%s" % (product, version) execute(cmd, cwd=cwd) do_push = False if options.noconfirm: do_push = True else: while True: try: do_push = strtobool( raw_input( "Do you really want to push the tag to origin ? (y/n) " )) except ValueError: pass else: break if do_push: cmd = "git push origin master --tags" execute(cmd, cwd=cwd) webbrowser.open("http://" + options.repository + "/redmine/projects/" + project.identifier + "/issues") print("Done") else: print("Operation cancelled") return 0 except Exception as e: print("Error :") print(str(e)) return -1 finally: shutil.rmtree(temp_dir)
def update_issue_redmine_redmine(self, issue_id, issue_status, project_id, reverse=False): main_tasks_manager = self.main_task_manager if not reverse else self.sync_task_manager sync_tasks_manager = self.sync_task_manager if not reverse else self.main_task_manager issue = Redmine(main_tasks_manager.url, key=main_tasks_manager.api_key). \ issue.get(issue_id) mapping = self.mapping if not reverse else self.reverse_mapping logger.info("Main tasks manager: {}".format(main_tasks_manager.name)) logger.info("Sync tasks manager: {}".format(sync_tasks_manager.name)) if issue_status == "edit": logger.info("Editing an existing task") old_issue_id = self.mapping_dict_issue_id[str(issue_id)] if not reverse else \ list(self.mapping_dict_issue_id.keys())[list(self.mapping_dict_issue_id.values()).index(str(issue_id))] old_issue = Redmine(sync_tasks_manager.url, key=sync_tasks_manager.api_key).issue.get(old_issue_id) updated_old_issue = old_issue.updated_on for arg in issue.journals: if arg.created_on > updated_old_issue: upload_list = [] # This variable is used when we need to update attachement list user = Redmine(sync_tasks_manager.url, key=sync_tasks_manager.api_key).user.get(arg.user.id) old_issue = Redmine(sync_tasks_manager.url, key=sync_tasks_manager.api_key, impersonate=mapping("username", user.login)).issue.get(old_issue.id) for detail in arg.details: if detail['property'] == "attachment": for attachment in issue.attachments: if detail['new_value'] == attachment.filename: Redmine(main_tasks_manager.url, key=main_tasks_manager.api_key). \ download(attachment.content_url, savepath='/tmp/', filename=attachment.filename) upload_list.append( {'path': '/tmp/' + attachment.filename, 'filename': attachment.filename, 'description': attachment.description}) if 'old_value' in detail and 'new_value' not in detail: for attachment in old_issue.attachemnts: if detail['old_value'] == attachment.filename: pass # It is not working because Redmine python api doesn't support it # Redmine(main_tasks_manager.url, key=sync_tasks_manager.api_key).attachment.delete(attachment.id) elif detail['name'] == "tracker_id": old_issue.tracker_id = mapping("tracker_id", detail['new_value']) elif detail['name'] == "subject": old_issue.subject = detail['new_value'] elif detail['name'] == "description": old_issue.description = detail['new_value'] elif detail['name'] == "status_id": old_issue.status_id = mapping("status_id", detail['new_value']) elif detail['name'] == "assigned_to_id": old_issue.assigned_to_id = mapping("user_id", detail['new_value']) elif detail['name'] == "estimated_hours": old_issue.estimated_hours = detail['new_value'] if len(upload_list): old_issue.uploads = upload_list old_issue.save() if hasattr(arg, "notes"): old_issue.notes = arg.notes old_issue.save() # TODO # adding parent id # addining new task after full sync # tests # remove old times entries for time_entry in Redmine(sync_tasks_manager.url, key=sync_tasks_manager.api_key).time_entry.filter( issue_id=old_issue.id): Redmine(sync_tasks_manager.url, key=sync_tasks_manager.api_key).time_entry.delete(time_entry.id) # We need to add all times entries again time_entries = Redmine(main_tasks_manager.url, key=main_tasks_manager.api_key).time_entry.filter( issue_id=issue.id) if time_entries: logger.info("In the time entries block") # import ipdb;ipdb.set_trace() for time_entry in time_entries: user = Redmine(main_tasks_manager.url, key=main_tasks_manager.api_key).user.get(time_entry.user.id) new_time_entry = Redmine(sync_tasks_manager.url, key=sync_tasks_manager.api_key, impersonate=mapping("username", user.login)).time_entry.new() new_time_entry.user_id = self.mapping("user_id", time_entry.user.id) if issue.id == time_entry.issue.id: # if we have related tasks then time entries are doubled and we need to check it new_time_entry.issue_id = old_issue.id new_time_entry.spent_on = time_entry.spent_on new_time_entry.hours = time_entry.hours new_time_entry.activity_id = time_entry.activity.id new_time_entry.comments = time_entry.comments new_time_entry.save() logger.info("Task was edited") elif issue_status == "new": logger.info("Create a new task") user = Redmine(main_tasks_manager.url, key=main_tasks_manager.api_key).user.get(issue.author.id) new_issue = Redmine(sync_tasks_manager.url, key=sync_tasks_manager.api_key, impersonate=mapping("username", user.login)).issue.new() logger.info("Project name {}".format(mapping("project_name", project_id))) new_issue.project_id = mapping("project_name", project_id) new_issue.subject = issue.subject new_issue.tracker_id = mapping("tracker_id", issue.tracker.id) new_issue.description = issue.description new_issue.status_id = mapping("status_id", issue.status.id) new_issue.priority_id = mapping("priority_id", issue.priority.id) if hasattr(issue, "assigned_to"): new_issue.assigned_to_id = mapping("user_id", issue.assigned_to.id) if hasattr(issue, "watchers"): # It's not working! watcher_user_ids = [] for watcher in issue.watchers: watcher_user_ids.append(mapping("user_id", watcher.id)) new_issue.watcher_user_ids = watcher_user_ids if hasattr(issue, "start_date"): new_issue.start_date = issue.start_date if hasattr(issue, "due_date"): new_issue.due_date = issue.due_date if hasattr(issue, "estimated_hours"): new_issue.estimated_hours = issue.estimated_hours new_issue.done_ratio = issue.done_ratio if issue.attachments: logger.info("Updated issue has attachments. Creating attachements") upload_list = [] for attachment in issue.attachments: Redmine(main_tasks_manager.url, key=main_tasks_manager.api_key).download(attachment.content_url, savepath='/tmp/', filename=attachment.filename) upload_list.append({'path': '/tmp/' + attachment.filename, 'filename': attachment.filename, 'description': attachment.description}) new_issue.uploads = upload_list new_issue.save() if reverse: self.mapping_dict_issue_id[str(new_issue.id)] = issue.id else: self.mapping_dict_issue_id[str(issue.id)] = new_issue.id self.save() time_entries = Redmine(main_tasks_manager.url, key=main_tasks_manager.api_key).time_entry.filter(issue_id=issue.id) if time_entries: logger.info("In the time entries block") for time_entry in time_entries: user = main_tasks_manager.user.get(time_entry.user.id) new_time_entry = Redmine(sync_tasks_manager.url, key=sync_tasks_manager.api_key, impersonate=mapping("username", user.login)).time_entry.new() new_time_entry.user_id = mapping("user_id", time_entry.user.id) if issue.id == time_entry.issue.id: # if we have related tasks then time entries are doubled and we need to check it new_time_entry.issue_id = new_issue.id new_time_entry.spent_on = time_entry.spent_on new_time_entry.hours = time_entry.hours new_time_entry.activity_id = time_entry.activity.id new_time_entry.comments = time_entry.comments new_time_entry.save() # adding notes to the task if issue.journals: for arg in issue.journals: if arg.notes: user = Redmine(main_tasks_manager.url, key=main_tasks_manager.api_key).user.get(arg.user.id) update_issue = Redmine(sync_tasks_manager.url, key=self.sync_tasks_manager.api_key, impersonate=mapping("username", user.login)).issue.get(new_issue.id) update_issue.notes = arg.notes update_issue.save() logger.info("New task was created.")