Example #1
0
    def __init__(self,
                 url,
                 key,
                 project=None,
                 component_conf={},
                 custom_fields=[],
                 reporter_field=None):
        """Initialise the client

        :param str url: the URL where the redmine is hosted
        :param str key: the authentication API REST key
        :param int or str project: the project identifier.
                                   It is None, then it takes the default one.
        :param dict component_conf: the component configuration to set
                                    the component based on the configuration file.
        :param list custom_fields: the custom fields that are mandatory to set
                                   when creating the issue.
        :param dict reporter_field: field to set reporter email
        """
        self.redmine = redmine.Redmine(url, key=key)
        self.project = project
        self.component_conf = component_conf
        self.custom_fields = custom_fields
        self.reporter_field = reporter_field

        # Use Bug by now, we can look for Crash Report tracker as well
        tracker_elems = filter(lambda t: t['name'] == 'Bug',
                               self.redmine.tracker.all())
        if len(tracker_elems) > 0:
            self.tracker_id = tracker_elems[0]['id']
        else:
            self.tracker_id = None
Example #2
0
    def __init__(self, host, key):
        self.connection = redmine.Redmine(host, key=key)

        # Prefetch redmine activities
        data = self.connection.enumeration.filter( \
                                resource="time_entry_activities")
        for activity in data:
            name = activity.name.lower()
            self.activities.append(name)
            self.activities_id[name] = activity.id
Example #3
0
    def run(self, ticket):
        version = self.dispatcher.call_sync('system.info.version')
        project_name = '-'.join(version.split('-')[:2]).lower()
        attachments = []
        debug_file_name = os.path.join(
            DEFAULT_DEBUG_DUMP_DIR,
            version + '_' + time.strftime('%Y%m%d%H%M%S') + '.tar.gz')

        try:
            rm_connection = redmine.Redmine(BUGTRACKER_ADDRESS,
                                            username=ticket['username'],
                                            password=unpassword(
                                                ticket['password']))
            rm_connection.auth()

            for attachment in ticket.get('attachments', []):
                attachment = os.path.normpath(attachment)
                attachments.append({
                    'path': attachment,
                    'filename': os.path.split(attachment)[-1]
                })
                if not os.path.exists(attachment):
                    raise TaskException(
                        errno.ENOENT,
                        'File {} does not exists.'.format(attachment))

            if ticket.get('debug'):
                self.run_subtask_sync('debug.save_to_file', debug_file_name)
                attachments.append({
                    'path':
                    debug_file_name,
                    'filename':
                    os.path.split(debug_file_name)[-1]
                })

            redmine_response = rm_connection.issue.create(
                project_id=project_name,
                subject=ticket['subject'],
                description=ticket['description'],
                category_id=ticket['category'],
                custom_fields=[{
                    'id': 2,
                    'value': VERSION_CODES['BETA2']
                }],
                is_private=ticket.get('debug', False),
                tracker_id=1 if ticket['type'] == 'bug' else 2,
                uploads=attachments)
        except redmine.exceptions.AuthError:
            raise TaskException(errno.EINVAL, 'Invalid username or password')

        finally:
            if ticket.get('debug') and os.path.exists(debug_file_name):
                os.remove(debug_file_name)

        return redmine_response.id
Example #4
0
    def main(this, argv):

        parser = this.get_base_parser()
        (options, args) = parser.parse_known_args(argv)

        config = this.parse_config(options)

        subcommand_parser = this.get_subcommand_parser()
        this.parser = subcommand_parser

        if options.help or not argv:
            subcommand_parser.print_help()
            return 0

        api_key = None
        if options.unauthenticated is False:
            api_key = os.getenv('REDCLI_API_KEY', None)
            if api_key is None:
                try:
                    api_key = config.get('credentials', 'api_key')

                except ConfigParser.Error as e:
                    print >>sys.stderr, "You need to specify your API key either via " \
                            "$REDCLI_API_KEY or in your configuration file"
                    return 1

        auth_url = options.auth_url
        if auth_url is None:
            try:
                auth_url = config.get('global', 'auth_url')

            except ConfigParser.Error as e:
                print >>sys.stderr, "You need to specify your authentication url either via " \
                        "--auth-url or in your configuration file"
                return 2

        args = subcommand_parser.parse_args(argv)

        # Merge args from command line and config file
        this.merge_config_args(args)

        # Does the user provides some callbacks for printing
        this.handle_user_exit(args)

        if args.func == this.do_help:
            this.do_help(args)
            return 0

        cli = redmine.Redmine(auth_url,
                              key=api_key,
                              debug=args.debug,
                              version=args.redmine_version)

        return args.func(cli, args)
Example #5
0
 def _redmine_connect(self):
     #   Задаем формат даты, не проверям сертификат сервера на валидность, возвращаем redmine дескриптор
     self.logger.debug("issue._redmine_connect started")
     if not self.rd:
         server = self.parameters.get("server")
         key = self.parameters.get("key")
         self.rd = redmine.Redmine(server,
                                   key=key,
                                   date_format='%Y.%m.%d',
                                   requests={'verify': False})
         self.logger.debug("issue._redmine_connect: rd={0} created".format(
             self.rd))
     return self.rd
Example #6
0
    def __init__(self,
                 url,
                 key,
                 project=None,
                 component_conf={},
                 custom_fields=[],
                 reporter_field=None,
                 status={}):
        """Initialise the client

        :param str url: the URL where the redmine is hosted
        :param str key: the authentication API REST key
        :param int or str project: the project identifier.
                                   It is None, then it takes the default one.
        :param dict component_conf: the component configuration to set
                                    the component based on the configuration file.
        :param list custom_fields: the custom fields that are mandatory to set
                                   when creating the issue.
        :param dict reporter_field: field to set reporter email

        :param dict status: indicate which are valid closed status
                            identifiers and reopened status
                            identifiers for reopening closed issues
                            once a new duplicate is uploaded.
                            *closed* is a tuple with valid closed status ids
                            *reopened* is the status to go after reopening an issue
        """
        self.redmine = redmine.Redmine(url, key=key)
        self.project = project
        self.component_conf = component_conf
        self.custom_fields = custom_fields
        self.reporter_field = reporter_field

        # Use Bug by now, we can look for Crash Report tracker as well
        tracker_elems = filter(lambda t: t['name'] == 'Bug',
                               self.redmine.tracker.all())
        if len(tracker_elems) > 0:
            self.tracker_id = tracker_elems[0]['id']
        else:
            self.tracker_id = None

        self.status = None
        # Make sure closed and reopened are consistent
        if 'closed' in status and 'reopened' in status:
            self.status = status
            # Make sure an iterable is always used for closed status
            if not hasattr(self.status['closed'], '__contains__'):
                self.status['closed'] = (self.status['closed'], )
def main():
    config = get_config('redmine.yml')

    ## connect to redmine
    redmine_instance = redmine.Redmine(config['url'],
                                       username=config['username'],
                                       password=config['password'])

    user_id = redmine_instance.user.get('current').id
    all_statuses = redmine_instance.issue_status.all()
    all_projects = redmine_instance.project.all()

    filters = get_filters(config, all_statuses, all_projects)
    status_id_filter_str = filters['status_id_filter_str']
    filtered_projects = filters['filtered_projects']
    included_custom_fields = filters['included_custom_fields']

    statuses_by_importance = get_statuses_by_importance(config, all_statuses)
    critical_statuses = statuses_by_importance['critical_statuses']
    unimportant_statuses = statuses_by_importance['unimportant_statuses']

    # get sorted list of issues
    issues = sorted(redmine_instance.issue.filter(
        assigned_to_id=user_id, status_id=status_id_filter_str),
                    key=lambda issue: issue.priority['id'],
                    reverse=True)

    for issue in issues:
        project_id = issue.project['id']

        if project_id not in filtered_projects:
            if hasattr(issue, 'custom_fields'):
                # convert redmine.resources.CustomField object list to list of dicts
                issue_custom_fields = list()
                for custom_field in issue.custom_fields:
                    issue_custom_fields.append({
                        'name': custom_field['name'],
                        'value': custom_field['value']
                    })

                for custom_field in included_custom_fields:
                    if custom_field in issue_custom_fields:
                        notification = build_notification(
                            issue, statuses_by_importance)
                        send_notification(notification)
                        continue
Example #8
0
def fetch_redmine_data(redmine_url, redmine_project, redmine_version,
                       redmine_user, redmine_password, redmine_key):
    """Return a dict of redmine data resources

    :param redmine_url: Redmine access http/s url
    :param redmine_project: Name of the Redmine project to use
    :param redmine_version: Version to search for in the Redmine project
    :param redmine_user: Login name for the a valid Redmine user
    :param redmine_password: Password for ``redmine_user``
    :param redmine_key: User's auth token (alternative to
                        ``redmine_user`` and ``redmine_password``)

    :returns: Context dict populated with the following data:
      - redmine_api: Object for redmine at *redmine_url*
      - redmine_project: Object for *redmine_project* at *redmine_url*
      - redmine_version: Object for *redmine_version* at *redmine_project*
      - redmine_issues: List of objects for open issues in *redmine_project*
        at *redmine_version*
    """
    api = redmine.Redmine(redmine_url, username=redmine_user,
                          password=redmine_password, key=redmine_key)

    project = get_project_by_name(api, redmine_project)
    if project is None:
        error(u'redmine: Project "{}" not found'.format(redmine_project))

    version = get_version_by_name(project, redmine_version)
    if version is None:
        error(u'redmine: Project "{}" has no version "{}"'
              .format(redmine_project, redmine_version))

    issues = api.issue.filter(
        project_id=project.id,
        fixed_version_id=version.id,
        status_id='closed'
    )

    return dict(
        redmine_api=api,
        redmine_issues=issues,
        redmine_project=project,
        redmine_version=version
    )
Example #9
0
    def __init__(self, url, user, password, project_name, verify=True):
        """
        Initializes the Redmine reader and connects to the REST service

        :param url: Redmine url, e.g. https://redmine.com/
        :param user:User to access redmine with, e.g. admin
        :param password:Password to access redmine with, e.g. paSSw0rd
        :param project_name:Name of the project, this can be read from the URL, e.g. https://redmine.com/projects/{project}
        :param verify:Flag indicating whether to accept non-verified SSL certificates
        """

        requests_config = {'verify': verify}

        self.redmine = redmine.Redmine(url,
                                       username=user,
                                       password=password,
                                       requests=requests_config)

        self.entry_meta = {}
        self.issue_meta = {}

        # Open project
        self.project = self.redmine.project.get(project_name)
Example #10
0
import csv
import redmine
from django.shortcuts import render, redirect, HttpResponse, render_to_response, RequestContext
from django.views.generic.edit import View
import django.forms as forms
from django.core.context_processors import csrf
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator

import redmine
from . import settings as s

REDMINE_OBJECT = redmine.Redmine(s.REDMINE_SETTINGS['server'],
                                 username=s.REDMINE_SETTINGS['username'],
                                 password=s.REDMINE_SETTINGS['password'])

try:
    OUTPUT_CSV = s.OUTPUT_CSV
except:
    OUTPUT_CSV = 'rm_report.csv'

# Create your views here.


class ExportForm(forms.Form):
    def __init__(self, *args, rm=REDMINE_OBJECT, **kwargs):
        super(ExportForm, self).__init__(*args, **kwargs)
        projects = rm.project.all()
        self.fields['project'].choices = [(p.identifier, p.name)
                                          for p in projects]
def main():
    # We get a redmine connection
    rm = redmine.Redmine(redmine_url, key=redmine_key)

    if os.path.exists(".rev_prev"):
        rev_prev = int(open(".rev_prev", 'r').read())
    else:
        logging.critical("Not having the .rev_prev file is very BAD !!!")
        sys.exit(1)

    # We list all SVN logs since last time
    logs = pysvn.Client().log(
        svn_url,
        revision_start=pysvn.Revision(pysvn.opt_revision_kind.number, rev_prev),
        revision_end=pysvn.Revision(pysvn.opt_revision_kind.head),
        limit=rev_limit
    )

    last_rev = None

    for log in logs:
        author = log["author"]
        revision = log.revision.number
        date = time.ctime(log.date)
        message = log.message
        logging.info("* {revision} - {date} - {author} : {message}".format(revision=revision,
                                                                           date=date,
                                                                           author=author,
                                                                           message=message.replace("\n", ".").replace("\r", ".")))

        if not last_rev or revision > last_rev:
            last_rev = revision

        changes_by_issue = handle_log(message, author, revision, date)
        if changes_by_issue:
            logging.debug("Changes: %s", json.dumps(changes_by_issue))
            for issue_id, changes in changes_by_issue.iteritems():
                logging.info("Considering update of issue %s ...", issue_id)
                try:
                    issue = rm.issue.get(issue_id)
                    if not issue:
                        logging.warning("Issue %s doesn't exist !!!", issue_id)
                        break
                    else:
                        msg = "SVN r{rev},".format(rev=revision)
                        for jl in issue.journals:
                            logging.debug("    Note: "+jl.notes.replace("\n", ".").replace("\r", "."))
                            if msg in jl.notes:
                                logging.warning("There's already a reference to our notes !")
                                changes = None
                                break
                    if not test_only and changes:
                        logging.info("Updating issue %s ...", issue_id)
                        try:
                            rm.issue.update(issue_id, **changes)
                        except redmine.ValidationError:
                            if "status_id" in changes.keys():
                                logging.info("Removing status change for issue %s", issue_id)
                                del changes["status_id"]
                                rm.issue.update(issue_id, **changes)
                            else:
                                logging.exception("Our issue wasn't validated %s", issue_id)
                except Exception:
                    logging.exception("Problem handling issue %s", issue_id)

    if last_rev:
        open(".rev_prev.tmp", 'w').write(str(last_rev))
        os.rename(".rev_prev.tmp", ".rev_prev")
Example #12
0
if bConsole:
    print 'Are your sure above information is correct?'
    print 'Press y to continue, q to quit.'
    while 1:
        c = getkey()
        if c == 'y' or c == 'Y':
            break
        elif c == 'q' or c == 'Q':
            sys.exit(1)
'''
 Redmine Connection
'''

if bAPIKey:
    print "Auth by 'API access key'" + IESUX
    demo = redmine.Redmine('http://rd1-1/redmine', key=APIKEY)
else:
    print "Auth by 'username/password'" + IESUX
    demo = redmine.Redmine('http://rd1-1/redmine',
                           username=USER,
                           password=PASS)
'''
 Created project under "OBM projects >> OBM 2012 Project"
'''

# Get the parent Project, e.g. OBM projects: http://rd1-1/redmine/projects/obm-projects
obm_prj = demo.getProject(SubProjectOf)

try:
    parent_prj = obm_prj.newSubProject(
        name=PRJ_MODELNAME,
Example #13
0
import pytz
import redmine
import re
import datetime
import inflect
from refreshbooks import api as refreshbooks

my_redmine_user_id = 22
noop = False

timezone = pytz.timezone("Australia/Brisbane")
inflector = inflect.engine()

redmine_url = os.environ["REDMINE_URL"]
redmine_key = os.environ["REDMINE_KEY"]
redmine_client = redmine.Redmine(redmine_url, key=redmine_key, version=1.4)

freshbooks_host = os.environ["FRESHBOOKS_HOST"]
freshbooks_key = os.environ["FRESHBOOKS_KEY"]
freshbooks_client = refreshbooks.TokenClient(freshbooks_host, freshbooks_key)

redmine_id_regex = re.compile("^Redmine ID: (\d+)$", re.MULTILINE)

project_lookup = dict()
task_lookup = dict()
time_entry_lookup = dict()


def freshbooks_items(item_name, **kwargs):
    '''Iterates over collection of items from `item_name` from all pages.'''
    collection = inflector.plural(item_name)
Example #14
0
def get_redmine_client(config):
    return redmine.Redmine(config['redmine-base-address'],
                           key=config['api-key'])
Example #15
0
    notice.show()
    return


# config
config_filename = 'redmine.yml'
config = yaml.load(
    open(path.join(path.dirname(path.abspath(__file__)), config_filename)))

redmine_url = config['url']
redmine_username = config['username']
redmine_password = config['password']

redmine_ieca = redmine.Redmine(redmine_url,
                               username=redmine_username,
                               password=redmine_password)

user_id = redmine_ieca.user.get('current').id
statuses = redmine_ieca.issue_status.all()
projects = redmine_ieca.project.all()

# fiter by status
status_filter = config['status_filter']
filtered_statuses = [
    status['id'] for status in statuses if status['name'] in status_filter
]
status_id_filter_str = '!' + '|'.join(
    str(status_id) for status_id in filtered_statuses)

# filter by project
Example #16
0
 def connect_redmine(self, configuration):
     self.project_name = configuration["redmine_projectname"]
     self.configuration = configuration
     self.redmine = redmine.Redmine(configuration["redmine_url"],
                                    key=configuration["redmine_api_key"],
                                    raise_attr_exception=False)
def sync_hours_for_date(password, date_str):
    in_date = strptime(date_str, '%d/%m/%Y')
    doy = in_date.tm_yday

    print "Syncing %d/%d/%d (%s)" % (in_date.tm_mday, in_date.tm_mon,
                                     in_date.tm_year, doy)

    h = Harvest(HARVEST_URL_ROOT, HARVEST_USER_EMAIL, password)
    rm = redmine.Redmine(REDMINE_URL_ROOT, key=REDMINE_API_KEY)
    rm_date = date(*in_date[:3])
    rm_users = rm.users
    rm_user = rm_users[6]
    day = h.get_day(doy, 2016)
    activities = rm.time_entry_activities
    development = None
    meeting = None
    proj_man = None
    for activity in activities:
        if activity.name == 'Development':
            development = activity
        elif activity.name == 'Meeting':
            meeting = activity
        if activity.name == 'Project Management':
            proj_man = activity

    if development is None or meeting is None or proj_man is None:
        raise ValueError('Cant find all activity types')

    at_map = {
        'Coding': development,
        'Meeting': meeting,
        'Project Management': proj_man
    }

    for day_entry in day['day_entries']:
        if day_entry['client'] != CLIENT_NAME:
            continue
        activity = at_map.get(day_entry['task'])
        if not activity:
            print "Can't map activity '%s'" % day_entry['task']
            continue
        if day_entry['notes'] is not None and 'logged' in day_entry[
                'notes'].lower():
            continue
        elif day_entry['notes'] is None:
            day_entry['notes'] = ''

        if activity == development or day_entry['notes'].startswith('#'):
            if day_entry['notes'].startswith('#'):
                try:
                    ticket_id = int(day_entry['notes'][1:])
                except (TypeError, ValueError):
                    print "Can't parse ID on %s" % day_entry['notes']
                    continue
            entry_notes = ''
        else:
            print "Not logging {}".format(day_entry['notes'])
            continue

        issue = rm.issues[ticket_id]
        try:
            te = rm.time_entries.new(issue=issue,
                                     activity=activity,
                                     spent_on=rm_date.strftime('%Y-%m-%d'),
                                     user=rm_user,
                                     hours=day_entry['hours'],
                                     comments=entry_notes)
        except Exception as e:
            print e.read()
            return
        if day_entry['notes'] == '':
            day_entry['notes'] = 'Logged'
        else:
            day_entry['notes'] += ' Logged'

        try:
            h.update(day_entry['id'], day_entry)
        except Exception as e:
            print "Failed to save time for %d. Delete manually" % ticket_id
            return
        print "Logged %02f hours for #%d" % (day_entry['hours'], ticket_id)