Ejemplo n.º 1
0
    def get_last_commit(self, repository_path):
        commit_number = None
        author = None
        committer = None

        command = "git show -s --pretty=format:'%H||%an||%ae||%ai||%cn||%ce||%ci||%s'"

        executer = ShellExecuter()
        result = executer.execute(command, repository_path)

        if result.exit_code != 0:
            raise ValueError("unable to determine last commit. Error: %s" % result.run_log)
        commit_number, author_name, author_email, author_date, committer_name, committer_email, committer_date, subject = result.run_log.split("||")

        author_date = self.convert_to_date(author_date)
        committer_date = self.convert_to_date(committer_date)

        return {
                   'commit_number': commit_number,
                   'author': "%s <%s>" % (author_name, author_email),
                   'author_date': author_date,
                   'committer': "%s <%s>" % (committer_name, committer_email),
                   'committer_date': committer_date,
                   'subject': subject
               }
Ejemplo n.º 2
0
    def does_project_need_update(self, project):
        executer = ShellExecuter(verbose=self.server.context.settings.Ion.as_bool("verbose"))
        project_name = self.fix_name(project.name)
        repository_path = join(self.base_dir, project_name)
        is_repo_created = self.is_repository_created(repository_path)
        if not is_repo_created:
            self.log("The repository at %s needs to be created." % repository_path)
            return True

        self.log("Verifying if the repository at %s needs to be updated" % repository_path)
        executer.execute("git remote update", repository_path)
        result = executer.execute("git rev-parse origin/%s %s" % (project.branch, project.branch), repository_path)
        commits = result.run_log.split()
        return len(commits) != 2 or commits[0]!=commits[1]
Ejemplo n.º 3
0
    def create_or_update(self, project):
        executer = ShellExecuter(verbose=self.server.context.settings.Ion.as_bool("verbose"))
        project_name = self.fix_name(project.name)
        repository_path = join(self.base_dir, project_name)
        is_repo_created = self.is_repository_created(repository_path)
        if not is_repo_created and exists(repository_path):
            raise ValueError("The specified directory(%s) is not empty and is not a git repository")
        if not is_repo_created:
            if not exists(self.base_dir):
                try:
                    os.mkdir(self.base_dir)
                except:
                    raise ValueError("Could not create folder %s" % self.base_dir)
                self.log("Directory successfully created.")

            self.log("Retrieving scm data for project %s in repository %s (creating new repository - clone)" % (project_name, project.scm_repository))
            result = executer.execute("git clone %s %s --recursive --branch %s" % (project.scm_repository, project_name, project.branch), self.base_dir)
            if result.exit_code == 0:
                self.log("SCM Data retrieved successfully")
            else:
                self.log("Error retrieving SCM Data: %s" % result.run_log)
            last_commit = self.get_last_commit(repository_path)
            return ScmResult(result.exit_code == 0 and ScmResult.Created or ScmResult.Failed, repository_path, last_commit, result.run_log)
        else:
            self.log("Retrieving scm data for project %s in repository %s (updating repository - pull)" % (project_name, project.scm_repository))
            result = executer.execute("git branch | grep %s" % project.branch, repository_path)
            if project.branch.lower() in result.run_log.lower():
                result = executer.execute("git checkout %s" % project.branch.lower(), repository_path)
            else:
                result = executer.execute("git checkout -b %s" % project.branch.lower(), repository_path)

            result = executer.execute("git reset --hard", repository_path)
            result = executer.execute("git clean -df", repository_path)
            result = executer.execute("git pull origin %s" % project.branch, repository_path)
            result = executer.execute("git submodule update --init --recursive", repository_path)
            
            if result.exit_code == 0:
                self.log("SCM Data retrieved successfully")
            else:
                self.log("Error retrieving SCM Data: %s" % result.run_log)

            self.log("Retrieving last commit data for project %s in repository %s" % (project_name, project.scm_repository))
            last_commit = self.get_last_commit(repository_path)
            self.log("Data retrieved.")
            return ScmResult(result.exit_code == 0 and ScmResult.Updated or ScmResult.Failed, repository_path, last_commit, result.run_log)
Ejemplo n.º 4
0
 def __init__(self, server):
     self.server = server
     self.base_path = server.build_dir
     self.executer = ShellExecuter(verbose=self.server.context.settings.Ion.as_bool("verbose"))
Ejemplo n.º 5
0
class BuildService(Service):
    Unknown = "Unknown"
    Success = "Successful"
    Failure = "Failed"

    def __init__(self, server):
        self.server = server
        self.base_path = server.build_dir
        self.executer = ShellExecuter(verbose=self.server.context.settings.Ion.as_bool("verbose"))

    def start_execute(self, executer):
        ctx = self.server.context
        ctx.current_command = executer.command
        ctx.current_process = executer
        ctx.current_start_time = time.time()
        ctx.current_project = self.current_project
        ctx.current_log = None

    def execute_beat(self, executer):
        ctx = self.server.context
        ctx.current_command = executer.command
        ctx.current_log = executer.result.log

    def finish_execute(self, executer):
        ctx = self.server.context
        ctx.current_command = None
        ctx.current_start_time = None
        ctx.current_project = None
        ctx.current_log = None

    def build_project(self, project_id):
        ctx = self.server.context

        self.connect()

        try:
            store = self.store
            log = ["Build started at %s" % datetime.now()]

            status = BuildService.Failure
            scm_status = ScmResult.Failed
            project = store.query(Project).get(project_id)

            self.current_project = project

            self.server.publish('on_before_build', {"server":self.server, "project":project})

            ctx.projects_being_built.append(project_id)

            last_build_number = store.query(Build.number).filter(Build.project==project).order_by(desc(Build.id)).first()
            last_build_number = last_build_number and last_build_number[0] or 0

            build_date = datetime.now()
            build_scm_status = scm_status
            build_log = ""

            scm_service = GitService(self.server)

            scm_creation_result = scm_service.create_or_update(project)
            build_scm_status = scm_creation_result.status
            store.commit()

            if scm_creation_result.status == ScmResult.Failed:
                log.append(scm_creation_result.log)
                status = BuildService.Failure
            else:
                log.append("Downloaded code from %s (%s)" % (project.scm_repository, scm_creation_result.status))

                self.executer.start_execute = self.start_execute
                self.executer.finish_execute = self.finish_execute
                self.executer.execute_beat = self.execute_beat

                execute_result = self.executer.execute(project.build_script, 
                                                       scm_creation_result.repository_path, 
                                                       timeout=ctx.settings.Skink.as_int("build_timeout"))

                self.executer.start_execute = None
                self.executer.finish_execute = None
                self.executer.execute_beat = None

                log.append("Executed %s" % project.build_script)
                log.append("Exit Code: %s" % execute_result.exit_code)
                log.append("Run Log:")
                log.append(execute_result.run_log)

                status = execute_result.exit_code == 0 and BuildService.Success or BuildService.Failure

            log.append("Build finished at %s" % datetime.now())

            build = Build(last_build_number + 1,
                          build_date,
                          status,
                          build_scm_status,
                          "\n".join(log),
                          force_unicode(scm_creation_result.last_commit["commit_number"]),
                          force_unicode(scm_creation_result.last_commit["author"]),
                          force_unicode(scm_creation_result.last_commit["committer"]),
                          force_unicode(scm_creation_result.last_commit["subject"]),
                          scm_creation_result.last_commit["author_date"],
                          scm_creation_result.last_commit["committer_date"],
                          project)

            store.add(build)
            store.commit()

            ctx.projects_being_built.remove(project_id)

            if (build.status == BuildService.Success):
                self.server.publish('on_before_build_successful', {"server":self.server, "project":project, "build":build})

            if (build.status == BuildService.Success):
                self.server.publish('on_build_successful', {"server":self.server, "project":project, "build":build})
                self.process_pipelines_for(project)
            else:
                self.server.publish('on_build_failed', {"server":self.server, "project":project, "build":build})

            return build
        finally:
            self.disconnect()

    def process_pipelines_for(self, project):
        pipelines = self.store.query(Pipeline) \
                              .filter(PipelineItem.project_id == project.id) \
                              .filter(PipelineItem.pipeline_id == Pipeline.id) \
                              .all()
        for pipeline in pipelines:
            pipeline_items = pipeline.items

            for index, pipeline_item in enumerate(pipeline_items):
                if index == len(pipeline_items) - 1:
                    continue

                if pipeline_item.project_id == project.id:
                    self.log("Adding project %d to the queue because it's in the same pipeline as project %s" % (pipeline_items[index+1].project.id, pipeline_item.project.name))
                    self.server.context.build_queue.append(pipeline_items[index+1].project_id)