Beispiel #1
0
def main(command, options):
    """ Function called by bin/roundabout """

    config_file = options.config_file or roundabout.config.DEFAULT
    config = roundabout.config.Config(config_file)
    if command == "run":
        log.init_logger(config, stream=True)
    else:
        log.init_logger(config)

        daemon = roundabout.daemon.Daemon(
                    stdin="roundabout.log",
                    stdout="roundabout.log",
                    stderr="roundabout.log",
                    pidfile=config["default"].get("pidfile", "roundabout.pid"))

        if command == "start":
            daemon.start()
        elif command == "stop":
            daemon.stop()
            sys.exit(0)
        elif command == "restart":
            daemon.restart()

    try:
        run(config)
    except KeyboardInterrupt:
        pass
    except Exception, e:
        log.error("Unknown error: %s" % str(e))
        log.error(traceback.format_exc())
Beispiel #2
0
    def req(self, url, json_decode=False):
        """
        Connect to remote url, using the provided credentials. Return either
        the result or if json_decode=True, the JSONDecoded result.
        """
        username = self.config["ci"]["username"]
        password = self.config["ci"]["password"]
        b64string = base64.encodestring("%s:%s" % (username, password))[:-1]
        req = urllib2.Request(url)
        if "http_proxy" in self.config["ci"]:    
            req.set_proxy( self.config["ci"]["http_proxy"],
                           self.config["ci"]["http_proxy_type"] )
        req.add_header("Authorization", "Basic %s" % b64string)

        try:
            res = self.opener(req)
        except Exception as e:
            contents = e.read()
            log.error(contents) # http errors have content bodies... like servlet
                                # container stacktraces. I'm looking at you, 
                                # Jenkins... -grue
            raise e

        if json_decode:
            res = json.loads(res.read())

        return res
Beispiel #3
0
def do_post_merge_tasks(config, github):
    try:
        pull_requests = github.pull_requests
        pull_requests = [(u, p) for u, p in pull_requests.items() if p.looks_good_to_a_human(github.approvers)]
    except RuntimeError, e:
        log.error("Unexpected response from github:\n %s" % str(e))
        pull_requests = []
Beispiel #4
0
def _handle_callback(cfg, mode, opener=None):
    base = "https://github.com"
    username, password = cfg["github"]["auth"].values()

    with request.gh_request(username, password) as github:
        topics = ("/events/pull_request", "/events/issue_comment")

        for t in topics:
            topic = urlparse.urljoin(base, cfg["github"]["repo"] + t)
            post_data = {"hub.mode": mode, "hub.topic": topic, "hub.callback": cfg["github"]["callback_url"]}
            secret = cfg["github"].get("secret")
            if secret:
                post_data["hub.secret"] = secret

            try:
                github.post("https://api.github.com/hub", encode=False, **post_data)
            except request.urllib2.URLError, e:
                log.error("Error trying to register: %s" % e.read())
Beispiel #5
0
    def _callback(env, start_response):
        body = env["wsgi.input"].read(int(env.get("CONTENT_LENGTH", 0)))

        secret = cfg.get("secret")
        sig = env.get("HTTP_X_HUB_SIGNATURE")

        if (secret or sig) and not _check_signature(secret, body, sig):
            start_response("500 Error", [("Content-type", "text/plain")])
            log.error("Signature did not match local HMAC from secret" "(%s, %s)" % (sig, secret))

            return ["Signature did not match local HMAC"]

        body = urlparse.parse_qs(body)
        payload = json.loads(body.get("payload", "[{}]")[0])

        if models.handle_model(env["HTTP_X_GITHUB_EVENT"], payload):
            start_response("200 OK", [("Content-type", "text/plain")])
            return ["THANKS!"]

        start_response("500 Error", ["Content-type", "text/plain"])
        log.error("Error building the model")
        return ["Error!"]
Beispiel #6
0
 def __init__(self, exc):
     super(GitException, self).__init__(exc)
     log.error(str(exc))
Beispiel #7
0
def run(config):
    """ 
    Run roundabout forever or until you kill it.
    """

    while True:
        github = roundabout.github.client.Client(config)

        try:
            pull_requests = github.pull_requests
            pull_requests = [(u, p) for u, p
                                    in pull_requests.items()
                                    if p.lgtm(github.approvers)]
        except RuntimeError, e:
            log.error("Unexpected response from github:\n %s" % str(e))
            pull_requests = []

        if not pull_requests:
            log.info("No work to do, sleeping.")
            sleeptime = int(config["default"].get("poll_sleep", 30))
            time.sleep(sleeptime)
            continue

        for url, pull_request in pull_requests:
            log.info("processing %s" % url)

            repo = git_client.Git(remote_name=pull_request.remote_name,
                                  remote_url=pull_request.remote_url,
                                  remote_branch=pull_request.remote_branch,
                                  config=config)

            # Create a remote, fetch it, checkout the branch
            with repo as git:
                log.info("Cloning to %s" % repo.clonepath)

                # Ensure we're on the requested branch for the pull_request.

                base_branch = pull_request.base_branch
                git.branch(base_branch).checkout()
                try:
                    git.merge(git.remote_branch,
                              squash=config["git"].get("squash_merges"))
                except git_client.GitException, e:
                    pull_request.close(git_client.MERGE_FAIL_MSG % e)
                    continue

                if config["pylint"]:
                    py_res = pylint.Pylint(config["pylint"]["modules"],
                                           config=config, path=repo.clonepath)
                    if not py_res:
                        pull_request.close(
                            pylint.PYLINT_FAIL_MSG % (py_res.previous_score,
                                                      py_res.current_score))
                        continue

                # push up a test branch
                git.push(base_branch, remote_branch=git.local_branch_name)

                with ci.job.Job.spawn(git.local_branch_name, config) as job:
                    while not job.complete:
                        job.reload()

                    if job:
                        # Successful build, good coverage, and clean pylint.
                        git.push(base_branch)
                        pull_request.close(git_client.BUILD_SUCCESS_MSG)
                    else:
                        pull_request.close(git_client.BUILD_FAIL_MSG % job.url)