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())
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
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 = []
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())
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!"]
def __init__(self, exc): super(GitException, self).__init__(exc) log.error(str(exc))
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)