Ejemplo n.º 1
0
 def start(self):
     """ detach from the parent, decouple everything, and rebind """
     log.info("Starting roundabout...")
     _fork(1) and _decouple()
     _fork(2) and self.__rebind()
     self.__write_pid_file(os.getpid())
     log.info("Done")
Ejemplo n.º 2
0
 def reload(self):
     """Sleep for configured time, the descendent class should then reload 
     the data for the job.
     """
     sleeptime = int(self.config["ci"].get("job_reload_sleep", 30))
     log.info("Job not complete, sleeping for %s seconds..." % sleeptime)
     time.sleep(sleeptime)
Ejemplo n.º 3
0
    def merge(self, branch, squash=None, message=None):
        """ Merge the passed in branch with HEAD """

        log.info("merging %s into %s" % (branch, self.repo.active_branch.name))
        merge_cmd = ('git', 'merge', branch)
        try:
            if squash:
                squash_cmd = tuple(list(merge_cmd) + ['--squash'])
                self.repo.git.execute(squash_cmd)

                if not message:
                    try:
                        with open(self.clonepath + "/.git/SQUASH_MSG") as msg:
                            message = msg.read()
                    except IOError:
                        message = "Squash merge %s into %s" % (branch,
                            self.repo.active_branch.name)

                commit_cmd = ['git', 'commit', '-m']
                commit_cmd.append(message)
                return self.repo.git.execute(tuple(commit_cmd))
            else:
                return self.repo.git.execute(merge_cmd)
        except git.exc.GitCommandError, e:
            # If there's a merge failure reset and raise.
            self.repo.head.reset(working_tree=True)
            raise GitException(e)
Ejemplo n.º 4
0
    def comment(self, message):
        """
        Add a comment to the specified issue.

        Returns a dict representation of the comment.
        """
        log.info("commenting on %s: %s" % (self.number,  message))
        return self.client.github.issues.comment(
                    self.client.config["github"]["repo"], self.number, message)
Ejemplo n.º 5
0
    def spawn(cls, branch, config, opener=None):
        """
        Create and return a paramaterized Job based on the CI config.
        """

        ci_class = get_ci_class(config["ci"]["class"])
        log.info("Starting %s job" % config["ci"]["class"])

        return ci_class.spawn(branch, config, opener)
Ejemplo n.º 6
0
    def close(self, message):
        """
        Add a comment to this pull request and close it.

        Returns the closed Issue.
        """

        self.comment(message)
        log.info("Closing %s" % self.html_url)
        return self.client.github.issues.close(
                self.client.config["github"]["repo"], self.number)
Ejemplo n.º 7
0
    def spawn(cls, branch, config, opener=None):
        """
        Create and return a paramaterized build of the current job
        """

        _job = cls(config, opener=opener)
        log.info("Building: %s for %s" % (_job.config["ci"]["job"], branch))

        if _job.req(_job.build_endpoint % (_job.config["ci"]["base_url"], _job.config["ci"]["job"], branch)):
            build_id = _job.properties["nextBuildNumber"]
            while True:
                # Keep trying until we return something.
                try:
                    _job.build = [b for b in _job.builds if build_id == b.number][0]
                    log.info("Build URL: %s" % _job.url)
                    return _job
                except IndexError:
                    time.sleep(1)
Ejemplo n.º 8
0
 def stop(self):
     """ Read the pidfile for the process ID of the daemon and kill it """
     try:
         log.info("Stopping roundabout...")
         with open(self.pidfile, 'r') as fd:
             pid = fd.read()
             try:
                 os.kill(int(pid), signal.SIGTERM)
                 log.info("Done...")
             except ValueError:
                 log.info("Couldn't stop roundabout...")
                 return None
     except (IOError, OSError):
         log.info("Couldn't stop roundabout...")
         return None
Ejemplo n.º 9
0
def update_config(config_file):
    """ Update the configuration from yaml to json """

    if not config_file:
        raise RuntimeError("You didn't specify a configuration file")

    try:
        bak_file = config_file + '-bak'
        log.info("moving %s to %s" % (config_file, bak_file))

        os.rename(config_file, bak_file)
        with open(bak_file) as bak:
            log.info("Opening %s" % bak_file)
            with open(config_file, "w") as out:
                log.info("Writing %s" % config_file)
                json.dump(yaml.load(bak), out, indent=4)
    except yaml.YAMLError:
        log.info("Couldn't read a yaml file, so nothing needed to be done")
Ejemplo n.º 10
0
    finally:
        sys.exit(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 = []

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

    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)
Ejemplo n.º 11
0
 def push(self, branch, remote='origin', remote_branch=None):
     """ Push the branch up to the remote """
     if remote_branch:
         branch = "%s:%s" % (branch, remote_branch)
     log.info("pushing %s to %s" % (branch, remote))
     return self.repo.remote(remote).push(branch)
Ejemplo n.º 12
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)