示例#1
0
def get_root():
    settings = get_config()
    review = settings['reviewboard']
    client = RBClient(review['server'])
    client.login(review['user'], review['password'])

    return client.get_root()
示例#2
0
    def setUp(self):
        super(SVNRepositoryInfoTests, self).setUp()

        self.spy_on(urlopen, call_fake=self._urlopen)

        self.api_client = RBClient('http://localhost:8080/')
        self.root_resource = self.api_client.get_root()
示例#3
0
    def setUp(self):
        super(SVNRepositoryInfoTests, self).setUp()

        def _urlopen(url, **kwargs):
            url = url.get_full_url()

            try:
                payload = self.payloads[url]
            except KeyError:
                return MockResponse(
                    404, {},
                    json.dumps({
                        'rsp': {
                            'stat': 'fail',
                            'err': {
                                'code': 100,
                                'msg': 'Object does not exist',
                            },
                        },
                    }))

            return MockResponse(200, {
                'Content-Type': payload['mimetype'],
            }, json.dumps(payload['rsp']))

        self.spy_on(urlopen, call_fake=_urlopen)

        self.api_client = RBClient('http://localhost:8080/')
        self.root_resource = self.api_client.get_root()
示例#4
0
    def setUp(self):
        super(RepositoryMatchTests, self).setUp()

        @self.spy_for(urlopen)
        def _urlopen(url, **kwargs):
            url = url.get_full_url()

            try:
                payload = self.payloads[url]
            except KeyError:
                print('Test requested unexpected URL "%s"' % url)

                return MockResponse(
                    404, {},
                    json.dumps({
                        'rsp': {
                            'stat': 'fail',
                            'err': {
                                'code': 100,
                                'msg': 'Object does not exist',
                            },
                        },
                    }))

            return MockResponse(200, {
                'Content-Type': payload['mimetype'],
            }, json.dumps(payload['rsp']))

        self.api_client = RBClient('http://localhost:8080/')
        self.root_resource = self.api_client.get_root()
示例#5
0
 def rb_client(self):
     options = {}
     if os.path.exists(".reviewboardrc"):
         with open(".reviewboardrc") as reviewboardrc:
             for line in reviewboardrc:
                 if line.startswith("#"):
                     continue
                 if len(line.strip()) == 0:
                     continue
                 k, v = line.strip().split("=")
                 k = k.strip()
                 v = eval(v.strip())
                 options[k] = v
     rbclient = RBClient(options.get('REVIEWBOARD_URL') or 'https://reviews.apache.org/', RetryingSyncTransport)
     if not rbclient.get_root().get_session()['authenticated']:
         username = self.opt.reviewboard_username[0] if self.opt.reviewboard_username and \
                                                        self.opt.reviewboard_username[0] else raw_input(
             "Enter review board Username: "******"Enter password for %s: " % username)
         rbclient.login(username, password)
     root = rbclient.get_root()
     root.repository = options.get('REPOSITORY') or None
     root.branch = options.get('BRANCH') or options.get('TRACKING_BRANCH')
     root.target_groups = None
     if options.has_key('TARGET_GROUPS'):
         root.target_groups = options['TARGET_GROUPS']
     return root
    def _get_client(self, username=None, password=None, anonymous=False):
        from rbtools.api.client import RBClient
        from rbtools.api.transport.sync import SyncTransport

        class NoCacheTransport(SyncTransport):
            """API transport with disabled caching."""
            def enable_cache(self):
                pass

        # TODO consider moving this to __init__.
        if not self.mr:
            raise Exception('Could not find MozReview cluster instance')

        if username is None or password is None:
            username = os.environ.get('BUGZILLA_USERNAME')
            password = os.environ.get('BUGZILLA_PASSWORD')

        # RBClient is persisting login cookies from call to call
        # in $HOME/.rbtools-cookies. We want to be able to easily switch
        # between users, so we clear that cookie between calls to the
        # server and reauthenticate every time.
        try:
            os.remove(os.path.join(os.environ.get('HOME'), '.rbtools-cookies'))
        except Exception:
            pass

        if anonymous:
            return RBClient(self.mr.reviewboard_url,
                            transport_cls=NoCacheTransport)

        return RBClient(self.mr.reviewboard_url, username=username,
                        password=password, transport_cls=NoCacheTransport)
def main(url, group_names, days_old=7, dry_run=False):
    """ do something """
    try:
        user = os.environ['RBUSER']
    except KeyError:
        raise SystemExit("please set RBUSER environment variable for reviewboard user")
    try:
        passwd = os.environ['RBPASS']
    except KeyError:
        raise SystemExit("please set RBPASS environment variable for reviewboard password")
    #client = RBClient(url, user, passwd)
    client = RBClient(url)
    root = client.get_root()
    if not root:
        raise SystemExit("Error - could not get RBClient root.")

    for g_name in group_names:
        o = get_group_id_by_name(root, g_name, dry_run=dry_run)
        if not o:
            raise SystemExit("ERROR: no group '%s' found." % g_name)
        logger.debug("Found group '%s' id=%d" % (g_name, o))

    reviews = get_reviews_for_groups(root, group_names, dry_run=dry_run)

    old_reviews = filter_reviews_older_than(root, reviews, days_old, dry_run=dry_run)
    logger.info("found %d reviews for target groups and last updated %d or more days ago" % (len(old_reviews), days_old))

    if len(old_reviews) < 1:
        logger.info("Found no reviews matching criteria, exiting")
        return False

    users = get_submitters_for_reviews(old_reviews)
    logger.debug("got user information for %d users" % len(users))
    recipients = []
    for u in users:
        recipients.append("{u.fullname} <{u.email}>".format(u=users[u]))

    table = generate_report_html_table(old_reviews, url)

    body = "<h1>ReviewBoard reminder</h1>\n"
    body += """<p>You're receiving this message because you have one or more pending code reviews on <a href="{url}">{url}</a>
targeted at the '{group_names}' group(s) that have not been updated in over {days_old} days and have not been submitted.
At your convenience, please evaluate these reviews and close/submit any that have been merged or discarded.
Thank You.</p>\n""".format(url=url, days_old=days_old, group_names=", ".join(group_names))
    body += table
    body += "\n<br />\n"
    host = node()
    user = getuser()
    body += """
<p><em>generated by <a href=\"https://github.com/jantman/misc-scripts/blob/master/reviewboard_reminder_mail.py">reviewboard_reminder_mail.py</a>
running on {host} as {user} at {ds}</em></p>
""".format(host=host, user=user, ds=datetime.datetime.now().isoformat())

    if dry_run:
        print("Message to send:\n##############################\n{msg}\n#################################\n".format(msg=body))
        print("Would send to:\n {to}".format(to=", ".join(recipients)))
    else:
        raise SystemExit("Oops - never actually implemented the mail sending...")

    return True
示例#8
0
def ReviewBoardClient(url, username=None, password=None, apikey=None):
    """Obtain a RBClient instance via a context manager.

    This exists as a context manager because of gross hacks necessary for
    dealing with cookies. ``RBClient`` is coded such that it assumes it is
    being used under a user account and storing cookies is always acceptable.
    There is no way to disable cookie file writing or to tell it to use a file
    object (such as BytesIO) as the cookies database.

    We work around this deficiency by creating a temporary file and using it as
    the cookies database for the lifetime of the context manager. When the
    context manager exits, the temporary cookies file is deleted.
    """
    fd, path = tempfile.mkstemp()
    os.close(fd)
    try:
        if username and apikey:
            rbc = RBClient(url, cookie_file=path,
                           transport_cls=NoCacheTransport)
            login_resource = rbc.get_path(
                'extensions/mozreview.extension.MozReviewExtension/'
                'bugzilla-api-key-logins/')
            login_resource.create(username=username, api_key=apikey)
        else:
            rbc = RBClient(url, username=username, password=password,
                           cookie_file=path, transport_cls=NoCacheTransport)

        yield rbc
    finally:
        try:
            os.unlink(path)
        except Exception:
            pass
示例#9
0
    def __init__(self, configuration, *args):
        '''
        Helper to build an RBTools api root
        used by MozReview below
        '''
        url, api_key, username = self.requires(configuration, 'url', 'api_key',
                                               'username')

        # Authenticate client
        client = RBClient(url, save_cookies=False, allow_caching=False)
        login_resource = client.get_path(
            'extensions/mozreview.extension.MozReviewExtension/'
            'bugzilla-api-key-logins/')
        login_resource.create(username=username, api_key=api_key)
        self.api = client.get_root()

        # Report issues from specific analyzers
        self.analyzers = list(
            filter(
                lambda a: a in (CLANG_TIDY, CLANG_FORMAT, MOZLINT),
                configuration.get('analyzers', [
                    CLANG_TIDY,
                ]),
            ))
        assert len(self.analyzers) > 0, \
            'No valid analyzers for mozreview'
        self.publish_success = configuration.get('publish_success', False)
        assert isinstance(self.publish_success, bool)

        logger.info('Mozreview report enabled',
                    url=url,
                    username=username,
                    analyzers=self.analyzers)
def process_review_requests(client, channel, nick, review_ids):
    """
    Processes a list of review request ids using a shared client
    """
    logger.info("Starting codereview of: {0}".format(review_ids))
    api = RBClient(settings.CODEREVIEW_REVIEWBOARD_API_URL,
                   username=settings.CODEREVIEW_REVIEWBOARD_API_USERNAME,
                   password=settings.CODEREVIEW_REVIEWBOARD_API_PASSWORD)

    try:
        api_root = api.get_root()
    except:
        logger.exception("Cannot access reviewboard")
        client.msg(
            channel,
            "I can't complete your review {0} because I can't access reviewboard".format(nick)
        )
        return

    errors = []

    for review_id in review_ids:
        try:
            do_review(client, channel, nick, api_root, review_id)
        except:
            logger.exception("Cannot codereview cr{0}".format(review_id))
            errors.append(review_id)

    if errors:
        cr_list = ', '.join(map(lambda id: 'cr{0}'.format(id), errors))
        client.msg(channel, 'Codereview complete {0}, but I was unable to review: {1}'.format(nick, cr_list))
    else:
        client.msg(channel, 'Codereview complete {0}'.format(nick))
示例#11
0
def get_api(server_url, **kwargs):
    """Returns an RBClient instance and the associated root resource.

    Hooks should use this method to gain access to the API, instead of
    instantiating their own client.

    Args:
        server_url (unicode):
            The server URL to retrieve.

        **kwargs (dict):
            Additional keyword arguments to pass to the
            :py:class:`~rbtools.api.client.RBClient` constructor. See
            :py:meth:`SyncTransport.__init__()
            <rbtools.api.transport.sync.SyncTransport.__init__>` for arguments
            that are accepted.

    Returns:
        tuple:
        This returns a 2-tuple of the :py:class:`~rbtools.api.client.RBClient`
        and :py:class:`<root resource> rbtools.api.resource.Resource`.
    """
    api_client = RBClient(server_url, **kwargs)

    try:
        api_root = api_client.get_root()
    except ServerInterfaceError as e:
        raise HookError('Could not reach the Review Board server at %s: %s' %
                        (server_url, e))
    except APIError as e:
        raise HookError('Unexpected API Error: %s' % e)

    return api_client, api_root
示例#12
0
文件: common.py 项目: clach04/rbtools
def get_api(server_url, **kwargs):
    """Returns an RBClient instance and the associated root resource.

    Hooks should use this method to gain access to the API, instead of
    instantiating their own client.

    Args:
        server_url (unicode):
            The server URL to retrieve.

        **kwargs (dict):
            Additional keyword arguments to pass to the
            :py:class:`~rbtools.api.client.RBClient` constructor. See
            :py:meth:`SyncTransport.__init__()
            <rbtools.api.transport.sync.SyncTransport.__init__>` for arguments
            that are accepted.

    Returns:
        tuple:
        This returns a 2-tuple of the :py:class:`~rbtools.api.client.RBClient`
        and :py:class:`<root resource> rbtools.api.resource.Resource`.
    """
    api_client = RBClient(server_url, **kwargs)

    try:
        api_root = api_client.get_root()
    except ServerInterfaceError as e:
        raise HookError('Could not reach the Review Board server at %s: %s'
                        % (server_url, e))
    except APIError as e:
        raise HookError('Unexpected API Error: %s' % e)

    return api_client, api_root
示例#13
0
    def download_reviews(self, dev_group):
        self.dev_group = dev_group

        root = RBClient(self.url, api_token=self.token).get_root()
        reviews = root.get_review_requests(to_groups=dev_group, status='pending', counts_only=True)
        reviews = root.get_review_requests(to_groups=dev_group, status='pending', max_results=reviews.count)
        self.reviews = [self.RawReviewInfo(r) for r in reviews]
    def ship_it(self, rrid, username, password):
        """Create and publish a ship-it review"""

        # TODO: this code is lifted from the reviewboard mach commands. If we
        #       need to make more reviewboard api calls in these tests, we
        #       should make a function in the base class to get a RBClient.
        class NoCacheTransport(SyncTransport):
            """API transport with disabled caching."""
            def enable_cache(self):
                pass

        # RBClient is persisting login cookies from call to call
        # in $HOME/.rbtools-cookies. We want to be able to easily switch
        # between users, so we clear that cookie between calls to the
        # server and reauthenticate every time.
        try:
            os.remove(os.path.join(os.environ.get('HOME'), '.rbtools-cookies'))
        except Exception:
            pass

        client = RBClient(self.rburl,
                          username=username,
                          password=password,
                          transport_cls=NoCacheTransport)
        root = client.get_root()

        reviews = root.get_reviews(review_request_id=rrid)
        reviews.create(public=True, ship_it=True)
    def ship_it(self, rrid, username, password):
        """Create and publish a ship-it review"""

        # TODO: this code is lifted from the reviewboard mach commands. If we
        #       need to make more reviewboard api calls in these tests, we
        #       should make a function in the base class to get a RBClient.
        class NoCacheTransport(SyncTransport):
            """API transport with disabled caching."""
            def enable_cache(self):
                pass

        # RBClient is persisting login cookies from call to call
        # in $HOME/.rbtools-cookies. We want to be able to easily switch
        # between users, so we clear that cookie between calls to the
        # server and reauthenticate every time.
        try:
            os.remove(os.path.join(os.environ.get('HOME'), '.rbtools-cookies'))
        except Exception:
            pass

        client = RBClient(self.rburl, username=username,
                          password=password, transport_cls=NoCacheTransport)
        root = client.get_root()

        reviews = root.get_reviews(review_request_id=rrid)
        reviews.create(public=True, ship_it=True)
def ReviewBoardClient(url, username=None, password=None, apikey=None):
    """Obtain a RBClient instance."""
    if username and apikey:
        rbc = RBClient(url, save_cookies=False, allow_caching=False)
        login_resource = rbc.get_path("extensions/mozreview.extension.MozReviewExtension/" "bugzilla-api-key-logins/")
        login_resource.create(username=username, api_key=apikey)
    else:
        rbc = RBClient(url, username=username, password=password, save_cookies=False, allow_caching=False)

    return rbc
示例#17
0
def main():
    '''
    Posts a review to the review with specified id indicating if the build
    passed or failed
    '''
    parser = argparse.ArgumentParser()
    parser.add_argument("--cfg", required=True, help="Configuration file")
    parser.add_argument("--reviewid",
                        required=True,
                        help="Review id to post to")
    parser.add_argument("--buildurl",
                        required=True,
                        help="The jenkins build url")
    parser.add_argument("--buildstate",
                        required=True,
                        choices=["SUCCESS", "UNSTABLE", "FAILURE"],
                        help="Indicates if build succeeded (1) or failed (0)")

    args = parser.parse_args()

    reviewid = args.reviewid
    buildurl = args.buildurl
    buildstate = args.buildstate

    config = ConfigParser.ConfigParser()

    try:
        config.read(args.cfg)

        client = RBClient(config.get('jrbb', 'reviewboard_server'),
                          username=config.get('jrbb', 'reviewboard_user'),
                          api_token=config.get('jrbb', 'reviewboard_apitoken'))
    except ConfigParser.NoSectionError:
        print "Configuration file " + args.cfg + " not found or missing items"
        exit(1)

    root = client.get_root()

    # Get the revision number of the latest diff from the review

    # pylint: disable=no-member
    reviewreq = root.get_review_request(review_request_id=reviewid)

    reviews = reviewreq.get_reviews()

    if buildstate == 'SUCCESS':
        msg = 'Successfully built changes. See ' + buildurl
    else:
        msg = 'Opps! I could not build these changes. See ' + buildurl

    reviews.create(body_bottom=msg, public=True)

    print "Posted to review " + reviewid + " build state=" + buildstate + \
          ". Build url=" + buildurl
示例#18
0
def build_api_root(url, username, api_key):
    '''
    Helper to build an RBTools api root
    used by BatchReview
    '''
    logger.info('Authenticate on Mozreview', url=url, username=username)
    client = RBClient(url, save_cookies=False, allow_caching=False)
    login_resource = client.get_path(
        'extensions/mozreview.extension.MozReviewExtension/'
        'bugzilla-api-key-logins/')
    login_resource.create(username=username, api_key=api_key)
    return client.get_root()
示例#19
0
 def __init__(self, url):
     self.client = RBClient(url)
     self.root = self.client.get_root()
     try:
         self._version = float(
             self.root.rsp['product']['version'].split()[0])
     except:
         self._version = 0.0
     self._templates = self.root.rsp['uri_templates']
     self._files = {}
     self._file_data = {}
     self._simplefile_data = {}
示例#20
0
文件: common.py 项目: MistShi/rbtools
def get_api(server_url, username, password):
    """Returns an RBClient instance and the associated root resource.

    Hooks should use this method to gain access to the API, instead of
    instantianting their own client.
    """
    api_client = RBClient(server_url, username=username, password=password)

    try:
        api_root = api_client.get_root()
    except ServerInterfaceError, e:
        raise HookError('Could not reach the Review Board server at %s: %s'
                        % (server_url, e))
示例#21
0
def get_api(server_url, username, password):
    """Returns an RBClient instance and the associated root resource.

    Hooks should use this method to gain access to the API, instead of
    instantianting their own client.
    """
    api_client = RBClient(server_url, username=username, password=password)

    try:
        api_root = api_client.get_root()
    except ServerInterfaceError, e:
        raise HookError('Could not reach the Review Board server at %s: %s' %
                        (server_url, e))
示例#22
0
    def run(self):
        while True:
            id = q.get()
            client = RBClient(reviewboard_url, api_token=api_token)
            root = client.get_root()
            review = root.get_review_request(review_request_id=id)
            comments = review.get_reviews(max_results=200)

            for i, c in enumerate(comments):
                if i == len(comments) - 1:
                    break
                if c.links.user.title == jenkins_uname and c.ship_it:
                    c.update(ship_it=False)
示例#23
0
    def get_root(self, server_url):
        """Returns the root resource of an RBClient."""
        cookie_file = self.get_cookie()

        self.rb_api = RBClient(server_url,
                               cookie_file=cookie_file,
                               username=self.options.username,
                               password=self.options.password,
                               auth_callback=self.credentials_prompt)
        root = None
        try:
            root = self.rb_api.get_root()
        except ServerInterfaceError, e:
            die("Could not reach the review board server at %s" % server_url)
示例#24
0
def main():
    '''
    Fetches the latest patch diff from the review given the review id passed
    as a parameter and writes it an output file.
    '''
    parser = argparse.ArgumentParser()
    parser.add_argument("--reviewid",
                        required=True,
                        help="review id to post to")
    parser.add_argument("--cfg", required=True, help="Configuration file")
    parser.add_argument("--out",
                        required=True,
                        help="Output file location (e.g. patch.diff)")
    args = parser.parse_args()
    reviewid = args.reviewid

    config = ConfigParser.ConfigParser()

    try:
        config.read(args.cfg)

        client = RBClient(config.get('jrbb', 'reviewboard_server'),
                          username=config.get('jrbb', 'reviewboard_user'),
                          api_token=config.get('jrbb', 'reviewboard_apitoken'))

    except ConfigParser.NoSectionError:
        print "Configuration file " + args.cfg + " not found or missing items"
        exit(1)

    root = client.get_root()

    # Get the revision number of the latest diff from the review

    # pylint: disable=no-member
    reviewrequest = root.get_review_request(review_request_id=reviewid)
    diffrevision = reviewrequest.get_latest_diff().revision
    print "Latest diff revision for review", reviewid, "is", diffrevision
    diff = root.get_diff(review_request_id=reviewid,
                         diff_revision=diffrevision)
    patch = diff.get_patch()

    print "Retrieved the following patch file"
    print "-------------------------------------------------------------------"
    print patch.data
    print "-------------------------------------------------------------------"

    outfile = open(args.out, "w")
    print >> outfile, patch.data
    outfile.close()
    print "Patch written to " + args.out
示例#25
0
def ProcessReviewRequest(payload, tool_settings):
    """Execute an automated review on a review request."""
    routing_key = ProcessReviewRequest.request.delivery_info['routing_key']
    route_parts = routing_key.partition('.')
    tool_ep = route_parts[0]
    logger.info("Request to execute review tool '%s' for %s" %
                (tool_ep, payload['url']))

    try:
        logger.info("Initializing RB API")
        api_client = RBClient(payload['url'],
                              cookie_file=COOKIE_FILE,
                              agent=AGENT,
                              session=payload['session'])
        api_root = api_client.get_root()
    except:
        logger.error("Could not contact RB server at '%s'" % payload['url'])
        return False

    logger.info("Loading requested tool '%s'" % tool_ep)
    tools = []
    for ep in pkg_resources.iter_entry_points(group='reviewbot.tools',
                                              name=tool_ep):
        tools.append(ep.load())

    if len(tools) > 1:
        _update_tool_execution(api_root,
                               payload['request'],
                               status=FAILED,
                               msg="Tool '%s' is ambiguous" % tool_ep)
        return False
    elif len(tools) == 0:
        _update_tool_execution(api_root,
                               payload['request'],
                               status=FAILED,
                               msg="Tool '%s' not found" % tool_ep)
        return False

    tool = tools[0]
    try:
        logger.info("Initializing review")
        review = Review(api_root, payload['request'],
                        payload['review_settings'])
    except Exception, e:
        _update_tool_execution(api_root,
                               payload['request'],
                               status=FAILED,
                               msg="Error initializing review: %s" % str(e))
        return False
示例#26
0
def get_open_reviews(args):
    # get open reviews to a specified user, group, etc.
    args['status'] = 'pending'
    args['max_results'] = MAX_RESULTS

    client = RBClient(RB_URL)
    root = client.get_root()
    if not root:
        print "Error - could not get RBClient root."
        return False

    req = root.get_review_requests(**args)
    print "\n\nGot %d pending/unsubmitted reviews" % req.total_results
    for review in req:
        print "%d - %s - %s" % (review.id, review.get_submitter().username, review.summary)
def shipit(use_merge):
  subprocess.check_call(["git", "fetch"])

  if use_merge:
    subprocess.check_call(["git", "merge", "origin/master"])
  else:
    subprocess.check_call(["git", "rebase", "origin/master"])

  # run spec
  try:
    if os.path.exists("scripts/test.sh"):
      subprocess.check_call(["scripts/test.sh"])
  except subprocess.CalledProcessError:
    exit(1)

  branch = current_branch()
  rid = get_branch_info("rid")

  if not rid:
    print "You don't have a review branch."
    exit(1)
  else:
    rid = int(rid)

  # git checkout master
  subprocess.check_call(["git", "checkout", "master"])

  # git pull origin master
  subprocess.check_call(["git", "pull", "origin", "master"])

  # git merge current_branch
  subprocess.check_call(["git", "merge", branch])

  # git push origin master
  subprocess.check_call(["git", "push", "origin", "master"])

  # git push origin :current_branch
  subprocess.check_call(["git", "push", "origin", ":" + branch])

  # git branch -D current_branch
  subprocess.check_call(["git", "branch", "-D", branch])

  # close reviewboard request
  from rbtools.api.client import RBClient
  client = RBClient('http://reviewboard.nodeswork.com')
  root = client.get_root()
  request = root.get_review_request(review_request_id=rid)
  request.update(status="submitted")
示例#28
0
    def setUp(self):
        super(SVNRepositoryInfoTests, self).setUp()

        def _urlopen(url, **kwargs):
            url = url.get_full_url()

            try:
                payload = self.payloads[url]
            except KeyError:
                return MockResponse(404, {}, json.dumps({
                    'rsp': {
                        'stat': 'fail',
                        'err': {
                            'code': 100,
                            'msg': 'Object does not exist',
                        },
                    },
                }))

            return MockResponse(
                200,
                {
                    'Content-Type': payload['mimetype'],
                },
                json.dumps(payload['rsp']))

        self.spy_on(urlopen, call_fake=_urlopen)

        self.api_client = RBClient('http://localhost:8080/')
        self.root_resource = self.api_client.get_root()
示例#29
0
def ReviewBoardClient(url, username=None, password=None, apikey=None):
    """Obtain a RBClient instance."""
    if username and apikey:
        rbc = RBClient(url, save_cookies=False, allow_caching=False)
        login_resource = rbc.get_path(
            'extensions/mozreview.extension.MozReviewExtension/'
            'bugzilla-api-key-logins/')
        login_resource.create(username=username, api_key=apikey)
    else:
        rbc = RBClient(url,
                       username=username,
                       password=password,
                       save_cookies=False,
                       allow_caching=False)

    return rbc
示例#30
0
def get_open_reviews(args):
    # get open reviews to a specified user, group, etc.
    args['status'] = 'pending'
    args['max_results'] = MAX_RESULTS

    client = RBClient(RB_URL)
    root = client.get_root()
    if not root:
        print "Error - could not get RBClient root."
        return False

    req = root.get_review_requests(**args)
    print "\n\nGot %d pending/unsubmitted reviews" % req.total_results
    for review in req:
        print "%d - %s - %s" % (review.id, review.get_submitter().username,
                                review.summary)
示例#31
0
def run(old_value, new_value, ref):
    diff = call_cmd("git diff %s..%s"%(old_value, new_value))
    info(diff)

    ci_range = "%s..%s"%(old_value, new_value)
    # get author name
    cmd = "git log --format=%cn -1 " + new_value
    author = call_cmd(cmd).strip()
    if author in AUTHOR_MAP:
        author = AUTHOR_MAP[author]
    reviewer = REVIEWER_MAP[author]

    # get summary desc
    cmd = "git log --format=%s " + ci_range
    logs = call_cmd(cmd)
    summary = logs.split(os.linesep)[0]
    cmd = "git log --pretty=fuller " + ci_range
    desc = call_cmd(cmd)
    summary = summary.replace("\"", "@")
    desc = desc.replace("\"", "@")

    repo_branch = ref.split("/")[-1]

    # 创建review_request
    client = RBClient(rbcfg["rbserver"], username=rbcfg["rbadmin"], password=rbcfg["rbadminpw"])
    root = client.get_root()
    request_data = {
            "repository" : rbcfg["rbrepo"],
            "submit_as" : author,
            }
    r = root.get_review_requests().create(**request_data)
    vl = root.get_diff_validation()
    basedir = "/"
    #info("------------------"+diff)
    vl.validate_diff(rbcfg["rbrepo"], diff, base_dir=basedir)
    r.get_diffs().upload_diff(diff, base_dir=basedir)
    draft = r.get_draft()
    update_data = {
            "branch" : repo_branch,
            "summary" : summary,
            "description" : desc,
            "target_people" : reviewer,
            "public" : True,
            }
            
    ret = draft.update(**update_data)
    info("repo:<%s> rev:<%s> rid:<%s>"%(rbcfg["rbserver"], ci_range, r.id))
示例#32
0
 def get_rb_client(self):
     if not self.rb_client:
         options = {}
         with open(".reviewboardrc") as reviewboardrc:
             for line in reviewboardrc:
                 if line.startswith("#"):
                     continue
                 if len(line.strip()) == 0:
                     continue
                 k, v = line.strip().split("=")
                 k = k.strip()
                 v = eval(v.strip())
                 options[k] = v
         rbclient = RBClient(options['REVIEWBOARD_URL'])
         self.repository = options['REPOSITORY']
         self.branch = options.get('BRANCH') or options.get('TRACKING_BRANCH')
         self.target_groups = None
         if options.has_key('TARGET_GROUPS'):
             self.target_groups = options['TARGET_GROUPS']
         if rbclient.get_root().get_session()['authenticated']:
             return rbclient.get_root()
         username = self.opt.reviewboard_username or raw_input("Enter review board Username: "******"Enter password: ")
         rbclient.login(username, password)
         self.rb_client = rbclient.get_root()
     return self.rb_client
示例#33
0
文件: tasks.py 项目: djl197/ReviewBot
def ProcessReviewRequest(payload, tool_settings):
    """Execute an automated review on a review request."""
    routing_key = ProcessReviewRequest.request.delivery_info['routing_key']
    route_parts = routing_key.partition('.')
    tool_ep = route_parts[0]
    logger.info(
        "Request to execute review tool '%s' for %s" % (
            tool_ep, payload['url']))

    try:
        logger.info("Initializing RB API")
        api_client = RBClient(
            payload['url'],
            cookie_file=COOKIE_FILE,
            agent=AGENT,
            session=payload['session'])
        api_root = api_client.get_root()
    except:
        logger.error("Could not contact RB server at '%s'" % payload['url'])
        return False

    logger.info("Loading requested tool '%s'" % tool_ep)
    tools = []
    for ep in pkg_resources.iter_entry_points(group='reviewbot.tools',
                                              name=tool_ep):
        tools.append(ep.load())

    if len(tools) > 1:
        _update_tool_execution(api_root, payload['request'], status=FAILED,
                               msg="Tool '%s' is ambiguous" % tool_ep)
        return False
    elif len(tools) == 0:
        _update_tool_execution(api_root, payload['request'], status=FAILED,
                               msg="Tool '%s' not found" % tool_ep)
        return False

    tool = tools[0]
    try:
        logger.info("Initializing review")
        review = Review(api_root, payload['request'],
                        payload['review_settings'])
    except Exception, e:
        _update_tool_execution(api_root, payload['request'], status=FAILED,
                               msg="Error initializing review: %s" % str(e))
        return False
def get_open_reviews(args):
    """
    get open reviews to a specified user, group, etc.
    """
    args['status'] = 'pending'
    if 'max_results' not in args:
        args['max_results'] = 100

    client = RBClient(RB_URL)
    root = client.get_root()
    if not root:
        print "Error - could not get RBClient root."
        return False

    req = root.get_review_requests(**args)
    ret = {'total': req.total_results, 'reviews': []}
    for review in req:
        ret['reviews'].append("(%s) %s <%s/r/%d/>" % (review.get_submitter().username, review.summary, RB_URL, review.id))
    return ret
示例#35
0
文件: tasks.py 项目: djl197/ReviewBot
def update_tools_list(panel, payload):
    """Update the RB server with installed tools.

    This will detect the installed analysis tool plugins
    and inform Review Board of them.
    """
    logging.info("Request to refresh installed tools from '%s'" %
                 payload['url'])

    logging.info("Iterating Tools")
    tools = []

    for ep in pkg_resources.iter_entry_points(group='reviewbot.tools'):
        entry_point = ep.name
        tool_class = ep.load()
        tool = tool_class()
        logging.info("Tool: %s" % entry_point)

        if tool.check_dependencies():
            tools.append({
                'name': tool_class.name,
                'entry_point': entry_point,
                'version': tool_class.version,
                'description': tool_class.description,
                'tool_options': json.dumps(tool_class.options),
            })
        else:
            logging.warning("%s dependency check failed." % ep.name)

    logging.info("Done iterating Tools")
    tools = json.dumps(tools)
    hostname = panel.hostname

    try:
        api_client = RBClient(
            payload['url'],
            cookie_file=COOKIE_FILE,
            agent=AGENT,
            session=payload['session'])
        api_root = api_client.get_root()
    except Exception, e:
        logging.error("Could not reach RB server: %s" % str(e))
        return {'error': 'Could not reach RB server.'}
示例#36
0
def update_tools_list(panel, payload):
    """Update the RB server with installed tools.

    This will detect the installed analysis tool plugins
    and inform Review Board of them.
    """
    logging.info("Request to refresh installed tools from '%s'" %
                 payload['url'])

    logging.info("Iterating Tools")
    tools = []

    for ep in pkg_resources.iter_entry_points(group='reviewbot.tools'):
        entry_point = ep.name
        tool_class = ep.load()
        tool = tool_class()
        logging.info("Tool: %s" % entry_point)

        if tool.check_dependencies():
            tools.append({
                'name': tool_class.name,
                'entry_point': entry_point,
                'version': tool_class.version,
                'description': tool_class.description,
                'tool_options': json.dumps(tool_class.options),
            })
        else:
            logging.warning("%s dependency check failed." % ep.name)

    logging.info("Done iterating Tools")
    tools = json.dumps(tools)
    hostname = panel.hostname

    try:
        api_client = RBClient(
            payload['url'],
            cookie_file=COOKIE_FILE,
            agent=AGENT,
            session=payload['session'])
        api_root = api_client.get_root()
    except Exception, e:
        logging.error("Could not reach RB server: %s" % str(e))
        return {'error': 'Could not reach RB server.'}
示例#37
0
    def _make_api_client(self, server_url):
        """Return an RBClient object for the server.

        The RBClient will be instantiated with the proper arguments
        for talking to the provided Review Board server url.
        """
        return RBClient(server_url,
                        username=self.options.username,
                        password=self.options.password,
                        auth_callback=self.credentials_prompt)
示例#38
0
 def get_rb_client(self):
     options = {}
     with open(".reviewboardrc") as reviewboardrc:
         for line in reviewboardrc:
             k, v = line.split("=")
             k = k.strip()
             v = eval(v.strip())
             options[k] = v
     rbclient = RBClient(options['REVIEWBOARD_URL'])
     self.repository = options['REPOSITORY']
     self.branch = options['BRANCH']
     self.target_groups = None
     if options.has_key('TARGET_GROUPS'):
         self.target_groups = options['TARGET_GROUPS']
     if rbclient.get_root().get_session()['authenticated']:
         return rbclient
     username = raw_input("Enter review board Username: "******"Enter password: ")
     rbclient.login(username, password)
     return rbclient
示例#39
0
def get_open_reviews(args):
    """
    get open reviews to a specified user, group, etc.
    """
    args['status'] = 'pending'
    if 'max_results' not in args:
        args['max_results'] = 100

    client = RBClient(RB_URL)
    root = client.get_root()
    if not root:
        print "Error - could not get RBClient root."
        return False

    req = root.get_review_requests(**args)
    ret = {'total': req.total_results, 'reviews': []}
    for review in req:
        ret['reviews'].append("(%s) %s <%s/r/%d/>" %
                              (review.get_submitter().username, review.summary,
                               RB_URL, review.id))
    return ret
示例#40
0
 def rb_client(self):
     options = {}
     if os.path.exists(".reviewboardrc"):
         with open(".reviewboardrc") as reviewboardrc:
             for line in reviewboardrc:
                 if line.startswith("#"):
                     continue
                 if len(line.strip()) == 0:
                     continue
                 k, v = line.strip().split("=")
                 k = k.strip()
                 v = eval(v.strip())
                 options[k] = v
     rbclient = RBClient(
         options.get('REVIEWBOARD_URL') or 'https://reviews.apache.org/',
         RetryingSyncTransport)
     if not rbclient.get_root().get_session()['authenticated']:
         username = self.opt.reviewboard_username[0] if self.opt.reviewboard_username and \
                                                        self.opt.reviewboard_username[0] else raw_input(
             "Enter review board Username: "******"Enter password for %s: " % username)
         rbclient.login(username, password)
     root = rbclient.get_root()
     root.repository = options.get('REPOSITORY') or None
     root.branch = options.get('BRANCH') or options.get('TRACKING_BRANCH')
     root.target_groups = None
     if options.has_key('TARGET_GROUPS'):
         root.target_groups = options['TARGET_GROUPS']
     return root
示例#41
0
def fetch_repositories(url, user=None, token=None):
    """Fetch repositories from Review Board.

    Args:
        url (unicode):
            The configured url for the connection.

        user (unicode):
            The configured user for the connection.

        token (unicode):
            The configured API token for the user.
    """
    logging.info('Fetching repositories from Review Board: %s', url)
    # TODO: merge with COOKIE_FILE/AGENT in tasks.py
    root = RBClient(url, username=user, api_token=token,
                    cookie_file='reviewbot-cookies.txt',
                    agent='ReviewBot').get_root()

    for tool_type in ('Mercurial', 'Git'):
        repos = root.get_repositories(tool=tool_type, only_links='',
                                      only_fields='path,mirror_path,name')

        for repo in repos.all_items:
            repo_source = None

            for path in (repo.path, repo.mirror_path):
                if (os.path.exists(path) or path.startswith('http') or
                    path.startswith('git')):
                    repo_source = path
                    break

            if repo_source:
                init_repository(repo.name, tool_type.lower(), repo_source)
            else:
                logging.warn('Cannot find usable path for repository: %s',
                             repo.name)
示例#42
0
def get_open_reviews(args):
    """
    get open reviews to a specified user, group, etc.
    """
    args['status'] = 'pending'
    if 'max_results' not in args:
        args['max_results'] = 100

    client = RBClient(REVIEWBOARD_URL)

    # If we have a username and password, login
    if REVIEWBOARD_USERNAME and REVIEWBOARD_PASSWORD:
        client.login(REVIEWBOARD_USERNAME, REVIEWBOARD_PASSWORD)

    root = client.get_root()

    if not root:
        logger.error(u'Could not get RBClient root')
        return None

    try:
        req = root.get_review_requests(**args)
    except APIError:
        logger.exception(u'Error querying API')
        return None

    ret = {'total': req.total_results, 'reviews': []}
    review_fmt = u"[{user}] {summary} ({url}/r/{id})"

    for review in req:
        ret['reviews'].append(review_fmt.format(user=review.get_submitter().username,
                                                summary=review.summary,
                                                url=REVIEWBOARD_URL,
                                                id=review.id))

    return ret
示例#43
0
def process_review_requests(client, channel, nick, review_ids):
    """
    Processes a list of review request ids using a shared client
    """
    logger.info("Starting codereview of: {0}".format(review_ids))
    api = RBClient(settings.CODEREVIEW_REVIEWBOARD_API_URL,
                   username=settings.CODEREVIEW_REVIEWBOARD_API_USERNAME,
                   password=settings.CODEREVIEW_REVIEWBOARD_API_PASSWORD)

    try:
        api_root = api.get_root()
    except:
        logger.exception("Cannot access reviewboard")
        client.msg(
            channel,
            "I can't complete your review {0} because I can't access reviewboard"
            .format(nick))
        return

    errors = []

    for review_id in review_ids:
        try:
            do_review(client, channel, nick, api_root, review_id)
        except:
            logger.exception("Cannot codereview cr{0}".format(review_id))
            errors.append(review_id)

    if errors:
        cr_list = ', '.join(map(lambda id: 'cr{0}'.format(id), errors))
        client.msg(
            channel,
            'Codereview complete {0}, but I was unable to review: {1}'.format(
                nick, cr_list))
    else:
        client.msg(channel, 'Codereview complete {0}'.format(nick))
示例#44
0
    def _make_api_client(self, server_url):
        """Return an RBClient object for the server.

        The RBClient will be instantiated with the proper arguments
        for talking to the provided Review Board server url.
        """
        return RBClient(server_url,
                        username=self.options.username,
                        password=self.options.password,
                        api_token=self.options.api_token,
                        auth_callback=self.credentials_prompt,
                        otp_token_callback=self.otp_token_prompt,
                        disable_proxy=not self.options.enable_proxy,
                        verify_ssl=not self.options.disable_ssl_verification,
                        allow_caching=not self.options.disable_cache,
                        cache_location=self.options.cache_location,
                        in_memory_cache=self.options.in_memory_cache,
                        save_cookies=self.options.save_cookies,
                        ext_auth_cookies=self.options.ext_auth_cookies)
def run():
    look_args = " -r %s %s"%(rev, repo)

    # 是否为感兴趣的分支
    cmd = "svnlook dirs-changed %s"%look_args
    changed_dir = call_cmd(cmd).split(os.linesep)[0].strip() # 取第一行即可
    repo_branch = _process_branch(changed_dir)
    if not repo_branch:
        exit()

    # 是否有代码文件
    interested = False
    cmd = "svnlook changed %s"%look_args
    files = call_cmd(cmd)
    for f in files.split(os.linesep):
        if f.strip().endswith(rbcfg["filter_suffixs"]):
            interested = True
            break
    if not interested:
        exit()
    
    # 提取rbt post信息
    cmd = "svnlook author %s"%look_args
    author = call_cmd(cmd).strip()
    if author in AUTHOR_MAP:
        author = AUTHOR_MAP[author]
    reviewer = REVIEWER_MAP[author]

    cmd = "svnlook log %s"%look_args
    log = call_cmd(cmd)
    summary = desc = log.strip().replace(os.linesep, "&").replace("\"", "@")
    summary = "rev:%s-[%s]"%(rev, summary)

    cmd = "svnlook diff %s"%look_args
    diff = call_cmd(cmd)
    diff = _process_diff(diff)
    #info("\n"+diff)

    # 创建review_request
    client = RBClient(rbcfg["rbserver"], username=rbcfg["rbadmin"], password=rbcfg["rbadminpw"])
    root = client.get_root()
    request_data = {
            "repository" : rbcfg["rbrepo"],
            #"commit_id" : rev,
            "submit_as" : author,
            }
    r = root.get_review_requests().create(**request_data)
    vl = root.get_diff_validation()
    basedir = "/"
    #info("------------------"+diff)
    vl.validate_diff(rbcfg["rbrepo"], diff, base_dir=basedir)
    r.get_diffs().upload_diff(diff, base_dir=basedir)
    draft = r.get_draft()
    update_data = {
            "branch" : repo_branch,
            "summary" : summary,
            "description" : desc,
            "target_people" : reviewer,
            "public" : True,
            }
            
    ret = draft.update(**update_data)
    info("repo:<%s> rev:<%s> rid:<%s>"%(rbcfg["rbserver"], rev, r.id))
示例#46
0
def get_api_root(user, password):
    client = RBClient('http://localhost/', username=user, password=password)
    root = client.get_root()
    return root
示例#47
0
 def create_using_reviewboard_url(cls, reviewboard_url, **rb_client_kwargs):
     rb_client = RBClient(reviewboard_url, **rb_client_kwargs)
     return cls(rb_client)
示例#48
0
def update_tools_list(panel, payload):
    """Update the list of installed tools.

    This will detect the installed analysis tool plugins
    and inform Review Board of them.

    Args:
        panel (celery.worker.control.Panel):
            The worker control panel.

        payload (dict):
            The payload as assembled by the extension.

    Returns:
        bool:
        Whether the task completed successfully.
    """
    logger.info('Request to refresh installed tools from "%s"',
                payload['url'])

    logger.info('Iterating Tools')
    tools = []

    for ep in pkg_resources.iter_entry_points(group='reviewbot.tools'):
        entry_point = ep.name
        tool_class = ep.load()
        tool = tool_class()
        logger.info('Tool: %s' % entry_point)

        if tool.check_dependencies():
            tools.append({
                'name': tool_class.name,
                'entry_point': entry_point,
                'version': tool_class.version,
                'description': tool_class.description,
                'tool_options': json.dumps(tool_class.options),
                'timeout': tool_class.timeout,
                'working_directory_required':
                    tool_class.working_directory_required,
            })
        else:
            logger.warning('%s dependency check failed.', ep.name)

    logger.info('Done iterating Tools')
    hostname = panel.hostname

    try:
        api_client = RBClient(
            payload['url'],
            cookie_file=COOKIE_FILE,
            agent=AGENT,
            session=payload['session'])
        api_root = api_client.get_root()
    except Exception as e:
        logger.exception('Could not reach RB server: %s', e)

        return {
            'status': 'error',
            'error': 'Could not reach Review Board server: %s' % e,
        }

    try:
        api_tools = _get_extension_resource(api_root).get_tools()
        api_tools.create(hostname=hostname, tools=json.dumps(tools))
    except Exception as e:
        logger.exception('Problem POSTing tools: %s', e)

        return {
            'status': 'error',
            'error': 'Problem uploading tools: %s' % e,
        }

    return {
        'status': 'ok',
        'tools': tools,
    }
示例#49
0
def RunTool(server_url='',
            session='',
            username='',
            review_request_id=-1,
            diff_revision=-1,
            status_update_id=-1,
            review_settings={},
            tool_options={},
            repository_name='',
            base_commit_id='',
            *args, **kwargs):
    """Execute an automated review on a review request.

    Args:
        server_url (unicode):
            The URL of the Review Board server.

        session (unicode):
            The encoded session identifier.

        username (unicode):
            The name of the user who owns the ``session``.

        review_request_id (int):
            The ID of the review request being reviewed (ID for use in the
            API, which is the "display_id" field).

        diff_revision (int):
            The ID of the diff revision being reviewed.

        status_update_id (int):
            The ID of the status update for this invocation of the tool.

        review_settings (dict):
            Settings for how the review should be created.

        tool_options (dict):
            The tool-specific settings.

        repository_name (unicode):
            The name of the repository to clone to run the tool, if the tool
            requires full working directory access.

        base_commit_id (unicode):
            The ID of the commit that the patch should be applied to.

        args (tuple):
            Any additional positional arguments (perhaps used by a newer
            version of the Review Bot extension).

        kwargs (dict):
            Any additional keyword arguments (perhaps used by a newer version
            of the Review Bot extension).

    Returns:
        bool:
        Whether the task completed successfully.
    """
    try:
        routing_key = RunTool.request.delivery_info['routing_key']
        route_parts = routing_key.partition('.')
        tool_name = route_parts[0]

        log_detail = ('(server=%s, review_request_id=%s, diff_revision=%s)'
                      % (server_url, review_request_id, diff_revision))

        logger.info('Running tool "%s" %s', tool_name, log_detail)

        try:
            logger.info('Initializing RB API %s', log_detail)
            api_client = RBClient(server_url,
                                  cookie_file=COOKIE_FILE,
                                  agent=AGENT,
                                  session=session)
            api_root = api_client.get_root()
        except Exception as e:
            logger.error('Could not contact Review Board server: %s %s',
                         e, log_detail)
            return False

        logger.info('Loading requested tool "%s" %s', tool_name, log_detail)
        tools = [
            entrypoint.load()
            for entrypoint in pkg_resources.iter_entry_points(
                group='reviewbot.tools', name=tool_name)
        ]

        if len(tools) == 0:
            logger.error('Tool "%s" not found %s', tool_name, log_detail)
            return False
        elif len(tools) > 1:
            logger.error('Tool "%s" is ambiguous (found %s) %s',
                         tool_name, ', '.join(tool.name for tool in tools),
                         log_detail)
            return False
        else:
            tool = tools[0]

        repository = None

        try:
            logger.info('Creating status update %s', log_detail)
            status_update = api_root.get_status_update(
                review_request_id=review_request_id,
                status_update_id=status_update_id)
        except Exception as e:
            logger.exception('Unable to create status update: %s %s',
                             e, log_detail)
            return False

        if tool.working_directory_required:
            if not base_commit_id:
                logger.error('Working directory is required but the diffset '
                             'has no base_commit_id %s', log_detail)
                status_update.update(
                    state=ERROR,
                    description='Diff does not include parent commit '
                                'information.')
                return False

            try:
                repository = repositories[repository_name]
            except KeyError:
                logger.error('Unable to find configured repository "%s" %s',
                             repository_name, log_detail)
                return False

        try:
            logger.info('Initializing review %s', log_detail)
            review = Review(api_root, review_request_id, diff_revision,
                            review_settings)
            status_update.update(description='running...')
        except Exception as e:
            logger.exception('Failed to initialize review: %s %s', e, log_detail)
            status_update.update(state=ERROR, description='internal error.')
            return False

        try:
            logger.info('Initializing tool "%s %s" %s',
                        tool.name, tool.version, log_detail)
            t = tool()
        except Exception as e:
            logger.exception('Error initializing tool "%s": %s %s',
                             tool.name, e, log_detail)
            status_update.update(state=ERROR, description='internal error.')
            return False

        try:
            logger.info('Executing tool "%s" %s', tool.name, log_detail)
            t.execute(review, settings=tool_options, repository=repository,
                      base_commit_id=base_commit_id)
            logger.info('Tool "%s" completed successfully %s',
                        tool.name, log_detail)
        except Exception as e:
            logger.exception('Error executing tool "%s": %s %s',
                             tool.name, e, log_detail)
            status_update.update(state=ERROR, description='internal error.')
            return False

        if t.output:
            file_attachments = \
                api_root.get_user_file_attachments(username=username)
            attachment = \
                file_attachments.upload_attachment('tool-output', t.output)

            status_update.update(url=attachment.absolute_url,
                                 url_text='Tool console output')

        try:
            if not review.has_comments:
                status_update.update(state=DONE_SUCCESS,
                                     description='passed.')
            else:
                logger.info('Publishing review %s', log_detail)
                review_id = review.publish().id

                status_update.update(state=DONE_FAILURE,
                                     description='failed.',
                                     review_id=review_id)
        except Exception as e:
            logger.exception('Error when publishing review: %s %s', e, log_detail)
            status_update.update(state=ERROR, description='internal error.')
            return False

        logger.info('Review completed successfully %s', log_detail)
        return True
    finally:
        cleanup_tempfiles()
示例#50
0
class SVNRepositoryInfoTests(SpyAgency, SCMClientTests):
    """Unit tests for rbtools.clients.svn.SVNRepositoryInfo."""

    payloads = {
        'http://localhost:8080/api/': {
            'mimetype': 'application/vnd.reviewboard.org.root+json',
            'rsp': {
                'uri_templates': {},
                'links': {
                    'self': {
                        'href': 'http://localhost:8080/api/',
                        'method': 'GET',
                    },
                    'repositories': {
                        'href': 'http://localhost:8080/api/repositories/',
                        'method': 'GET',
                    },
                },
                'stat': 'ok',
            },
        },
        'http://localhost:8080/api/repositories/?tool=Subversion': {
            'mimetype': 'application/vnd.reviewboard.org.repositories+json',
            'rsp': {
                'repositories': [
                    {
                        # This one doesn't have a mirror_path, to emulate
                        # Review Board 1.6.
                        'id': 1,
                        'name': 'SVN Repo 1',
                        'path': 'https://svn1.example.com/',
                        'links': {
                            'info': {
                                'href': ('https://localhost:8080/api/'
                                         'repositories/1/info/'),
                                'method':
                                'GET',
                            },
                        },
                    },
                    {
                        'id': 2,
                        'name': 'SVN Repo 2',
                        'path': 'https://svn2.example.com/',
                        'mirror_path': 'svn+ssh://svn2.example.com/',
                        'links': {
                            'info': {
                                'href': ('https://localhost:8080/api/'
                                         'repositories/2/info/'),
                                'method':
                                'GET',
                            },
                        },
                    },
                ],
                'links': {
                    'next': {
                        'href': ('http://localhost:8080/api/repositories/'
                                 '?tool=Subversion&page=2'),
                        'method':
                        'GET',
                    },
                },
                'total_results':
                3,
                'stat':
                'ok',
            },
        },
        'http://localhost:8080/api/repositories/?tool=Subversion&page=2': {
            'mimetype': 'application/vnd.reviewboard.org.repositories+json',
            'rsp': {
                'repositories': [
                    {
                        'id': 3,
                        'name': 'SVN Repo 3',
                        'path': 'https://svn3.example.com/',
                        'mirror_path': 'svn+ssh://svn3.example.com/',
                        'links': {
                            'info': {
                                'href': ('https://localhost:8080/api/'
                                         'repositories/3/info/'),
                                'method':
                                'GET',
                            },
                        },
                    },
                ],
                'total_results':
                3,
                'stat':
                'ok',
            },
        },
        'https://localhost:8080/api/repositories/1/info/': {
            'mimetype': 'application/vnd.reviewboard.org.repository-info+json',
            'rsp': {
                'info': {
                    'uuid': 'UUID-1',
                    'url': 'https://svn1.example.com/',
                    'root_url': 'https://svn1.example.com/',
                },
                'stat': 'ok',
            },
        },
        'https://localhost:8080/api/repositories/2/info/': {
            'mimetype': 'application/vnd.reviewboard.org.repository-info+json',
            'rsp': {
                'info': {
                    'uuid': 'UUID-2',
                    'url': 'https://svn2.example.com/',
                    'root_url': 'https://svn2.example.com/',
                },
                'stat': 'ok',
            },
        },
        'https://localhost:8080/api/repositories/3/info/': {
            'mimetype': 'application/vnd.reviewboard.org.repository-info+json',
            'rsp': {
                'info': {
                    'uuid': 'UUID-3',
                    'url': 'https://svn3.example.com/',
                    'root_url': 'https://svn3.example.com/',
                },
                'stat': 'ok',
            },
        },
    }

    def setUp(self):
        super(SVNRepositoryInfoTests, self).setUp()

        def _urlopen(url, **kwargs):
            url = url.get_full_url()

            try:
                payload = self.payloads[url]
            except KeyError:
                return MockResponse(
                    404, {},
                    json.dumps({
                        'rsp': {
                            'stat': 'fail',
                            'err': {
                                'code': 100,
                                'msg': 'Object does not exist',
                            },
                        },
                    }))

            return MockResponse(200, {
                'Content-Type': payload['mimetype'],
            }, json.dumps(payload['rsp']))

        self.spy_on(urlopen, call_fake=_urlopen)

        self.api_client = RBClient('http://localhost:8080/')
        self.root_resource = self.api_client.get_root()

    def test_find_server_repository_info_with_path_match(self):
        """Testing SVNRepositoryInfo.find_server_repository_info with
        path matching
        """
        info = SVNRepositoryInfo('https://svn1.example.com/', '/', '')

        repo_info = info.find_server_repository_info(self.root_resource)
        self.assertEqual(repo_info, info)
        self.assertEqual(repo_info.repository_id, 1)

    def test_find_server_repository_info_with_mirror_path_match(self):
        """Testing SVNRepositoryInfo.find_server_repository_info with
        mirror_path matching
        """
        info = SVNRepositoryInfo('svn+ssh://svn2.example.com/', '/', '')

        repo_info = info.find_server_repository_info(self.root_resource)
        self.assertEqual(repo_info, info)
        self.assertEqual(repo_info.repository_id, 2)

    def test_find_server_repository_info_with_uuid_match(self):
        """Testing SVNRepositoryInfo.find_server_repository_info with
        UUID matching
        """
        info = SVNRepositoryInfo('svn+ssh://blargle/', '/', 'UUID-3')

        repo_info = info.find_server_repository_info(self.root_resource)
        self.assertNotEqual(repo_info, info)
        self.assertEqual(repo_info.repository_id, 3)

    def test_relative_paths(self):
        """Testing SVNRepositoryInfo._get_relative_path"""
        info = SVNRepositoryInfo('http://svn.example.com/svn/', '/', '')
        self.assertEqual(info._get_relative_path('/foo', '/bar'), None)
        self.assertEqual(info._get_relative_path('/', '/trunk/myproject'),
                         None)
        self.assertEqual(info._get_relative_path('/trunk/myproject', '/'),
                         '/trunk/myproject')
        self.assertEqual(info._get_relative_path('/trunk/myproject', ''),
                         '/trunk/myproject')
        self.assertEqual(info._get_relative_path('/trunk/myproject', '/trunk'),
                         '/myproject')
        self.assertEqual(
            info._get_relative_path('/trunk/myproject', '/trunk/myproject'),
            '/')
示例#51
0
class SVNRepositoryInfoTests(SpyAgency, SCMClientTests):
    """Unit tests for rbtools.clients.svn.SVNRepositoryInfo."""

    payloads = {
        'http://localhost:8080/api/': {
            'mimetype': 'application/vnd.reviewboard.org.root+json',
            'rsp': {
                'uri_templates': {},
                'links': {
                    'self': {
                        'href': 'http://localhost:8080/api/',
                        'method': 'GET',
                    },
                    'repositories': {
                        'href': 'http://localhost:8080/api/repositories/',
                        'method': 'GET',
                    },
                },
                'stat': 'ok',
            },
        },
        'http://localhost:8080/api/repositories/?tool=Subversion': {
            'mimetype': 'application/vnd.reviewboard.org.repositories+json',
            'rsp': {
                'repositories': [
                    {
                        # This one doesn't have a mirror_path, to emulate
                        # Review Board 1.6.
                        'id': 1,
                        'name': 'SVN Repo 1',
                        'path': 'https://svn1.example.com/',
                        'links': {
                            'info': {
                                'href': ('https://localhost:8080/api/'
                                         'repositories/1/info/'),
                                'method': 'GET',
                            },
                        },
                    },
                    {
                        'id': 2,
                        'name': 'SVN Repo 2',
                        'path': 'https://svn2.example.com/',
                        'mirror_path': 'svn+ssh://svn2.example.com/',
                        'links': {
                            'info': {
                                'href': ('https://localhost:8080/api/'
                                         'repositories/2/info/'),
                                'method': 'GET',
                            },
                        },
                    },
                ],
                'links': {
                    'next': {
                        'href': ('http://localhost:8080/api/repositories/'
                                 '?tool=Subversion&page=2'),
                        'method': 'GET',
                    },
                },
                'total_results': 3,
                'stat': 'ok',
            },
        },
        'http://localhost:8080/api/repositories/?tool=Subversion&page=2': {
            'mimetype': 'application/vnd.reviewboard.org.repositories+json',
            'rsp': {
                'repositories': [
                    {
                        'id': 3,
                        'name': 'SVN Repo 3',
                        'path': 'https://svn3.example.com/',
                        'mirror_path': 'svn+ssh://svn3.example.com/',
                        'links': {
                            'info': {
                                'href': ('https://localhost:8080/api/'
                                         'repositories/3/info/'),
                                'method': 'GET',
                            },
                        },
                    },
                ],
                'total_results': 3,
                'stat': 'ok',
            },
        },
        'https://localhost:8080/api/repositories/1/info/': {
            'mimetype': 'application/vnd.reviewboard.org.repository-info+json',
            'rsp': {
                'info': {
                    'uuid': 'UUID-1',
                    'url': 'https://svn1.example.com/',
                    'root_url': 'https://svn1.example.com/',
                },
                'stat': 'ok',
            },
        },
        'https://localhost:8080/api/repositories/2/info/': {
            'mimetype': 'application/vnd.reviewboard.org.repository-info+json',
            'rsp': {
                'info': {
                    'uuid': 'UUID-2',
                    'url': 'https://svn2.example.com/',
                    'root_url': 'https://svn2.example.com/',
                },
                'stat': 'ok',
            },
        },
        'https://localhost:8080/api/repositories/3/info/': {
            'mimetype': 'application/vnd.reviewboard.org.repository-info+json',
            'rsp': {
                'info': {
                    'uuid': 'UUID-3',
                    'url': 'https://svn3.example.com/',
                    'root_url': 'https://svn3.example.com/',
                },
                'stat': 'ok',
            },
        },
    }

    def setUp(self):
        super(SVNRepositoryInfoTests, self).setUp()

        def _urlopen(url, **kwargs):
            url = url.get_full_url()

            try:
                payload = self.payloads[url]
            except KeyError:
                return MockResponse(404, {}, json.dumps({
                    'rsp': {
                        'stat': 'fail',
                        'err': {
                            'code': 100,
                            'msg': 'Object does not exist',
                        },
                    },
                }))

            return MockResponse(
                200,
                {
                    'Content-Type': payload['mimetype'],
                },
                json.dumps(payload['rsp']))

        self.spy_on(urlopen, call_fake=_urlopen)

        self.api_client = RBClient('http://localhost:8080/')
        self.root_resource = self.api_client.get_root()

    def test_find_server_repository_info_with_path_match(self):
        """Testing SVNRepositoryInfo.find_server_repository_info with
        path matching
        """
        info = SVNRepositoryInfo('https://svn1.example.com/', '/', '')

        repo_info = info.find_server_repository_info(self.root_resource)
        self.assertEqual(repo_info, info)
        self.assertEqual(repo_info.repository_id, 1)

    def test_find_server_repository_info_with_mirror_path_match(self):
        """Testing SVNRepositoryInfo.find_server_repository_info with
        mirror_path matching
        """
        info = SVNRepositoryInfo('svn+ssh://svn2.example.com/', '/', '')

        repo_info = info.find_server_repository_info(self.root_resource)
        self.assertEqual(repo_info, info)
        self.assertEqual(repo_info.repository_id, 2)

    def test_find_server_repository_info_with_uuid_match(self):
        """Testing SVNRepositoryInfo.find_server_repository_info with
        UUID matching
        """
        info = SVNRepositoryInfo('svn+ssh://blargle/', '/', 'UUID-3')

        repo_info = info.find_server_repository_info(self.root_resource)
        self.assertNotEqual(repo_info, info)
        self.assertEqual(repo_info.repository_id, 3)

    def test_relative_paths(self):
        """Testing SVNRepositoryInfo._get_relative_path"""
        info = SVNRepositoryInfo('http://svn.example.com/svn/', '/', '')
        self.assertEqual(info._get_relative_path('/foo', '/bar'), None)
        self.assertEqual(info._get_relative_path('/', '/trunk/myproject'),
                         None)
        self.assertEqual(info._get_relative_path('/trunk/myproject', '/'),
                         '/trunk/myproject')
        self.assertEqual(
            info._get_relative_path('/trunk/myproject', ''),
            '/trunk/myproject')
        self.assertEqual(
            info._get_relative_path('/trunk/myproject', '/trunk'),
            '/myproject')
        self.assertEqual(
            info._get_relative_path('/trunk/myproject', '/trunk/myproject'),
            '/')
示例#52
0
文件: common.py 项目: vbutrim/anytask
class AnyRB(object):
    def __init__(self, event):
        self.client = RBClient(settings.RB_API_URL, username=settings.RB_API_USERNAME, password=settings.RB_API_PASSWORD)
        self.event = event

    def upload_review(self):
        if len(self.event.file_set.all()) == 0:
            return None

        files_diff = []
        empty = True
        import magic
        for f in self.event.file_set.all():
            mime_type = magic.from_buffer(f.file.read(1024), mime=True)
            if mime_type[:4] != 'text':
                continue

            empty = False
            file_content = []
            for line in f.file:
                try:
                    file_content.append(line.decode('utf-8'))
                except:
                    file_content.append(line.decode('cp1251'))

            from difflib import unified_diff
            fname = f.filename()
            from_name = u'a/{0}'.format(fname)
            to_name = u'b/{0}'.format(fname)

            diff = [(u'diff --git {0} {1}'.format(from_name, to_name))]
            from_name = u'/dev/null'

            diff_content = unified_diff('',
                                        file_content,
                                        fromfile=from_name,
                                        tofile=to_name.encode('utf-8'))
            for line in diff_content:
                line = line.strip()
                if isinstance(line, str):
                    diff.append(line.decode('utf-8'))
                else:
                    diff.append(line)

            files_diff.append(u'\n'.join(diff))

        files_diff = u'\n'.join(files_diff)

        if empty:
            return None

        review_request = self.get_review_request()
        if review_request is None:
            review_request = self.create_review_request()
        if review_request is None:
            return review_request

        review_request.get_diffs().upload_diff(files_diff.encode('utf-8'))

        draft = review_request.get_or_create_draft()
        issue = self.event.issue
        summary = u'[{0}][{1}] {2}'.format(issue.student.get_full_name(),
                                           issue.task.course.get_user_group(issue.student),
                                           issue.task.title)

        description_template = u'Задача: "{0}", ' + \
                               u'курс: [{1}](http://{2}{3})\n' + \
                               u'Студент: [{4}](http://{2}{5})\n' + \
                               u'[Обсуждение задачи](http://{2}{6})'
        description = description_template.format(
                        issue.task.title,
                        issue.task.course,
                        Site.objects.get_current().domain,
                        issue.task.course.get_absolute_url(),
                        issue.student.get_full_name(),
                        issue.student.get_absolute_url(),
                        issue.get_absolute_url()
                      )

        draft = draft.update(summary=summary,
                             description=description,
                             description_text_type='markdown',
                             target=settings.RB_API_USERNAME, public=True,
                             )
        return review_request.id

    # def get_or_create_review_request(self):
    #     root = self.client.get_root()

    #     review_request = None
    #     try:
    #         review_id = self.event.issue.get_byname('review_id')
    #         review_request = root.get_review_request(review_request_id=review_id)
    #     except (AttributeError, ValueError):
    #         course_id = self.event.issue.task.course.id
    #         repository_name = str(self.event.issue.id)
    #         os.symlink(settings.RB_SYMLINK_DIR,os.path.join(settings.RB_SYMLINK_DIR, repository_name))
    #         repository = root.get_repositories().create(
    #                  name=repository_name,
    #                  path=settings.RB_SYMLINK_DIR+repository_name+'/.git',
    #                  tool='Git',
    #                  public=False)
    #         root.get_repository(repository_id=repository.id).update(grant_type='add',
    #                                                   grant_entity='user',
    #                                                   grant_name=self.event.author)
    #         root.get_repository(repository_id=repository.id).update(grant_type='add',
    #                                                   grant_entity='group',
    #                                                   grant_name='teachers')
    #         root.get_repository(repository_id=repository.id).update(grant_type='add',
    #                                                   grant_entity='group',
    #                                                   grant_name='teachers_{0}'.format(course_id))


    #         review_request = root.get_review_requests().create(repository=repository.id)
    #     self.event.issue.set_byname('review_id', review_request.id, self.event.author)
    #     return review_request

    def get_review_request(self):
        root = self.client.get_root()

        review_request = None
        try:
            review_id = self.event.issue.get_byname('review_id')
        except (AttributeError, ValueError):
            logger.info("Issue '%s' has not review_id.", self.event.issue.id)
            return None
        try:
            review_request = root.get_review_request(review_request_id=review_id)
            return review_request
        except Exception as e:
            logger.info("Issue '%s' has not RB review_request. Exception: '%s'.", self.event.issue.id, e)
            return None

    def create_review_request(self):
        root = self.client.get_root()

        review_request = None
        course_id = self.event.issue.task.course.id
        repository_name = str(self.event.issue.id)
        repository_path = os.path.join(settings.RB_SYMLINK_DIR, repository_name)
        os.symlink(settings.RB_SYMLINK_DIR,repository_path)

        try:
            repository = root.get_repositories().create(
                     name=repository_name,
                     path=os.path.join(repository_path,'.git'),
                     tool='Git',
                     public=False)
            root.get_repository(repository_id=repository.id).update(grant_type='add',
                                                      grant_entity='user',
                                                      grant_name=self.event.issue.student)
            root.get_repository(repository_id=repository.id).update(grant_type='add',
                                                      grant_entity='group',
                                                      grant_name='teachers_{0}'.format(course_id))

            review_request = root.get_review_requests().create(repository=repository.id)
            self.event.issue.set_byname('review_id', review_request.id, self.event.author)
        except Exception as e:
            logger.exception("Exception while creating review_request. Exception: '%s'. Issue: '%s'", e, self.event.issue.id)
            return None

        return review_request
示例#53
0
#!/usr/bin/python

import sys
import re
import rbtools
from rbtools.api.client import RBClient



if __name__ == '__main__':
    review_id = sys.argv[1]
    root = RBClient('http://rb.hotel.com').get_root()
    r1 = root.get_review_request(review_request_id=review_id)
    summary = r1['summary'] 
    bugs_closed_str = ",".join(list(r1['bugs_closed']))
    bugs_closed_str = "[%s]"%(bugs_closed_str)

    #summary=re.sub( bugs_closed_str, '', summary)
    summary=summary.replace( bugs_closed_str, '')

    diffs = r1.get_diffs()
    changed_files = diffs[-1].get_files()
    changed_files_str = ""
    for file in changed_files:
	file_name = file['source_file']
	#'/branches/sh-i53-bugs/front_end/modules/bulk/bulk_en.properties'
	#assumption is the file pattern is like this
	nth = [ m.start() for m in re.finditer(r"/",file_name)]
	file_name_pat = file_name[nth[2]+1:]
	changed_files_str += file_name_pat + " "
示例#54
0
文件: common.py 项目: vbutrim/anytask
 def __init__(self, event):
     self.client = RBClient(settings.RB_API_URL, username=settings.RB_API_USERNAME, password=settings.RB_API_PASSWORD)
     self.event = event
示例#55
0
def main(url, group_names, days_old=7, dry_run=False):
    """ do something """
    try:
        user = os.environ['RBUSER']
    except KeyError:
        raise SystemExit(
            "please set RBUSER environment variable for reviewboard user")
    try:
        passwd = os.environ['RBPASS']
    except KeyError:
        raise SystemExit(
            "please set RBPASS environment variable for reviewboard password")
    #client = RBClient(url, user, passwd)
    client = RBClient(url)
    root = client.get_root()
    if not root:
        raise SystemExit("Error - could not get RBClient root.")

    for g_name in group_names:
        o = get_group_id_by_name(root, g_name, dry_run=dry_run)
        if not o:
            raise SystemExit("ERROR: no group '%s' found." % g_name)
        logger.debug("Found group '%s' id=%d" % (g_name, o))

    reviews = get_reviews_for_groups(root, group_names, dry_run=dry_run)

    old_reviews = filter_reviews_older_than(root,
                                            reviews,
                                            days_old,
                                            dry_run=dry_run)
    logger.info(
        "found %d reviews for target groups and last updated %d or more days ago"
        % (len(old_reviews), days_old))

    if len(old_reviews) < 1:
        logger.info("Found no reviews matching criteria, exiting")
        return False

    users = get_submitters_for_reviews(old_reviews)
    logger.debug("got user information for %d users" % len(users))
    recipients = []
    for u in users:
        recipients.append("{u.fullname} <{u.email}>".format(u=users[u]))

    table = generate_report_html_table(old_reviews, url)

    body = "<h1>ReviewBoard reminder</h1>\n"
    body += """<p>You're receiving this message because you have one or more pending code reviews on <a href="{url}">{url}</a>
targeted at the '{group_names}' group(s) that have not been updated in over {days_old} days and have not been submitted.
At your convenience, please evaluate these reviews and close/submit any that have been merged or discarded.
Thank You.</p>\n""".format(url=url,
                           days_old=days_old,
                           group_names=", ".join(group_names))
    body += table
    body += "\n<br />\n"
    host = node()
    user = getuser()
    body += """
<p><em>generated by <a href=\"https://github.com/jantman/misc-scripts/blob/master/reviewboard_reminder_mail.py">reviewboard_reminder_mail.py</a>
running on {host} as {user} at {ds}</em></p>
""".format(host=host, user=user, ds=datetime.datetime.now().isoformat())

    if dry_run:
        print(
            "Message to send:\n##############################\n{msg}\n#################################\n"
            .format(msg=body))
        print("Would send to:\n {to}".format(to=", ".join(recipients)))
    else:
        raise SystemExit(
            "Oops - never actually implemented the mail sending...")

    return True
示例#56
0
    def __init__(self, config_path=None, reviewboard_url=None,
                 reviewboard_user=None, reviewboard_password=None,
                 pulse_host=None, pulse_port=None, pulse_userid=None,
                 pulse_password=None, exchange=None, queue=None,
                 routing_key=None, pulse_timeout=None, pulse_ssl=False,
                 repo_root=None, logger=None):

        if logger is None:
            self.logger = logging.getLogger('mozreviewbot')
        else:
            self.logger = logger

        # We use options passed into __init__ preferentially. If any of these
        # are not specified, we next check the configuration file, if any.
        # Finally, we use environment variables.
        if config_path and not os.path.isfile(config_path):
            # ConfigParser doesn't seem to throw if it is unable to find the
            # config file so we'll explicitly check that it exists.
            self.logger.error('could not locate config file: %s' % (
                config_path))
            config_path = None
        if config_path:
            try:
                config = ConfigParser()
                config.read(config_path)
                reviewboard_url = (reviewboard_url
                                   or config.get('reviewboard', 'url'))
                reviewboard_user = (reviewboard_user
                                    or config.get('reviewboard', 'user'))
                reviewboard_password = (reviewboard_password
                                        or config.get('reviewboard',
                                                      'password'))
                pulse_host = pulse_host or config.get('pulse', 'host')
                pulse_port = pulse_port or config.get('pulse', 'port')
                pulse_userid = pulse_userid or config.get('pulse', 'userid')
                pulse_password = pulse_password or config.get('pulse',
                                                              'password')
                exchange = exchange or config.get('pulse', 'exchange')
                queue = queue or config.get('pulse', 'queue')
                routing_key = routing_key or config.get('pulse',
                                                        'routing_key')
                pulse_timeout = pulse_timeout or config.get('pulse',
                                                            'timeout')
                if pulse_ssl is None:
                    pulse_ssl = config.get('pulse', 'ssl')
            except NoSectionError as e:
                self.logger.error('configuration file missing section: %s' %
                                  e.section)
            try:
                repo_root = repo_root or config.get('hg', 'repo_root')
            except (NoOptionError, NoSectionError):
                # Subclasses do not need to define repo root if they do not
                # plan on using the hg functionality.
                pass

            # keep config around in case any subclasses would like to extract
            # options from it.
            self.config = config
        else:
            self.config = None

        reviewboard_url = reviewboard_url or os.environ.get('REVIEWBOARD_URL')
        pulse_host = pulse_host or os.environ.get('PULSE_HOST')
        pulse_port = pulse_port or os.environ.get('PULSE_PORT')

        self.rbclient = RBClient(reviewboard_url, username=reviewboard_user,
                                 password=reviewboard_password)
        self.api_root = self.rbclient.get_root()

        self.conn = Connection(hostname=pulse_host, port=pulse_port,
                               userid=pulse_userid, password=pulse_password,
                               ssl=pulse_ssl)

        self.exchange = Exchange(exchange, type='topic', durable=True)
        self.queue = Queue(name=queue, exchange=self.exchange, durable=True,
                           routing_key=routing_key, exclusive=False,
                           auto_delete=False)

        self.pulse_timeout = float(pulse_timeout)
        self.repo_root = repo_root

        self.hg = None
        for DIR in os.environ['PATH'].split(os.pathsep):
            p = os.path.join(DIR, 'hg')
            if os.path.exists(p):
                self.hg = p