def test_update_project(self):
        repository = ProjectRepository()
        project = self.create_project(name=u"Test Project")

        elixir.session.flush()
        elixir.session.commit()

        update = repository.get(project_id=project.id)
        self.assertEqual(update.id, project.id)
        self.assertEqual(update.name, project.name)
        self.assertEqual(update.build_script, project.build_script)

        update.name = u"Some Other Project"
        update.build_script = u"make build"
        update.scm_repository = u"new_repo"

        repository.update(update, [], [])

        elixir.session.flush()
        elixir.session.commit()

        updated = repository.get(project_id=project.id)
        self.assertEqual(updated.id, project.id)
        self.assertEqual(updated.name, u"Some Other Project")
        self.assertEqual(updated.build_script, u"make build")
        self.assertEqual(updated.scm_repository, u"new_repo")
    def test_get_project(self):
        repository = ProjectRepository()
        project = repository.create(name=u"Test Project", build_script=u"make test", scm_repository="git_repo")

        retrieved = repository.get(project_id=project.id)
        self.assertEqual(retrieved.id, project.id)
        self.assertEqual(retrieved.name, project.name)
        self.assertEqual(retrieved.build_script, project.build_script)
        self.assertEqual(retrieved.scm_repository, project.scm_repository)
    def test_update_project(self):
        repository = ProjectRepository()
        project = repository.create(name=u"Test Project", build_script=u"make test", scm_repository="git_repo")

        update = repository.get(project_id=project.id)
        self.assertEqual(update.id, project.id)
        self.assertEqual(update.name, project.name)
        self.assertEqual(update.build_script, project.build_script)
        
        update.name = u"Some Other Project"
        update.build_script = u"make build"
        update.scm_repository = u"new_repo"
        
        repository.update(update)

        updated = repository.get(project_id=project.id)
        self.assertEqual(updated.id, project.id)
        self.assertEqual(updated.name, u"Some Other Project")
        self.assertEqual(updated.build_script, u"make build")
        self.assertEqual(updated.scm_repository, u"new_repo")
    def test_get_project(self):
        repository = ProjectRepository()
        project = self.create_project(name=u"Test Project")

        elixir.session.flush()
        elixir.session.commit()

        retrieved = repository.get(project_id=project.id)
        self.assertEqual(retrieved.id, project.id)
        self.assertEqual(retrieved.name, project.name)
        self.assertEqual(retrieved.build_script, project.build_script)
        self.assertEqual(retrieved.scm_repository, project.scm_repository)
Beispiel #5
0
class BuildService(object):
    Success = "SUCCESS"
    Failure = "FAILURE"
    
    def __init__(self, repository=None, scm=None, executer=None, base_path=join(root_path,'skink','build')):
        if not repository:
            self.repository = ProjectRepository()
        else:
            self.repository = repository
            
        if not scm:
            self.scm = GitRepository(base_path)
        else:
            self.scm = scm
            
        if not executer:
            self.executer = ShellExecuter()
        else:
            self.executer = executer
        
        self.base_path = base_path

    def build_project(self, project_id):
        log = ["Build started at %s" % datetime.now()]
        status = BuildService.Failure
        scm_status = ScmResult.Failed
        project = self.repository.get(project_id)
        build = Build(datetime.now(), status,  scm_status, "", project)
        
        scm_creation_result = self.scm.create_or_update(project)
        build.scm_status = scm_creation_result.status
        if scm_creation_result.status == ScmResult.Failed:
            log.append(scm_creation_result.log)
            status = BuildService.Failure
        else:
            log.append("Downloaded code from %s" % project.scm_repository)
            
            execute_result = self.executer.execute(project.build_script, scm_creation_result.repository_path)
            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
        
        build.status = status
        build.log = "\n".join(log)
        self.repository.update(project)
        
        return build
Beispiel #6
0
class ProjectController(object):
    def __init__(self):
        self.repository = ProjectRepository()

    @cherrypy.expose
    @template.output("create_project.html")
    def new(self):
        return template.render()

    @cherrypy.expose
    def create(self, name, build_script, scm_repository):
        project = self.repository.create(name=name, build_script=build_script, scm_repository=scm_repository)
        raise cherrypy.HTTPRedirect("/")

    @cherrypy.expose
    @template.output("project_details.html")
    def default(self, project_id):
        project = self.repository.get(project_id)
        return template.render(project=project)

    @cherrypy.expose
    def delete(self, project_id):
        self.repository.delete(project_id)
        raise cherrypy.HTTPRedirect("/")
Beispiel #7
0
class BuildService(object):
    Success = u"SUCCESS"
    Failure = u"FAILURE"

    def __init__(self, repository=None, pipeline_repository=None, scm=None, executer=None, base_path=join(root_path, SkinkContext.current().build_path)):
        self.repository = repository
        if not repository:
            self.repository = ProjectRepository()

        self.pipeline_repository = pipeline_repository
        if not pipeline_repository:
            self.pipeline_repository = PipelineRepository()

        self.scm = scm
        if not scm:
            self.scm = GitRepository(base_path)

        self.executer = executer
        if not executer:
            self.executer = ShellExecuter()    

        self.base_path = base_path

    def build_project(self, project_id):
        ctx = SkinkContext.current()
        
        log = ["Build started at %s" % datetime.now()]

        status = BuildService.Failure
        scm_status = ScmResult.Failed
        project = self.repository.get(project_id)
        PluginEvents.on_before_build(project)
        ctx.projects_being_built.append(project_id)
        last_build_number = project.get_last_build_number()

        build = Build()
        build.date = datetime.now()
        build.status = status
        build.scm_status = scm_status
        build.log = ""
        build.project = project
        
        scm_creation_result = self.scm.create_or_update(project)
        build.scm_status = scm_creation_result.status
        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))
            
            execute_result = self.executer.execute(project.build_script, 
                                                   scm_creation_result.repository_path, 
                                                   timeout=ctx.build_timeout)

            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

        for command in project.tabs:
            build_tab = BuildTab(name=command.name, command=command.command, content_type=command.content_type, build=build)
            result = self.executer.execute(command.command, scm_creation_result.repository_path)
            build_tab.log = result.run_log

        for file_locator in project.file_locators:
            file_locator_path = join(self.base_path, project.name, file_locator.locator)
            print "Finding files for locator %s" % file_locator_path
            files = glob.glob(file_locator_path)
            print "%d files found" % len(files)
            for f in files:
                print "Adding file %s" % f
                filename = split(f)[-1]
                stream = open(f, 'rb')
                content = stream.read()
                stream.close()
                build_file = BuildFile(name=filename, original_path=f, content=content, build=build)

        build.number = last_build_number + 1
        build.status = status
        build.log = "\n".join(log)
        build.commit_number = force_unicode(scm_creation_result.last_commit["commit_number"])
        build.commit_author = force_unicode(scm_creation_result.last_commit["author"])
        build.commit_committer = force_unicode(scm_creation_result.last_commit["committer"])
        build.commit_author_date = scm_creation_result.last_commit["author_date"]
        build.commit_committer_date = scm_creation_result.last_commit["committer_date"]
        build.commit_text = force_unicode(scm_creation_result.last_commit["subject"])

        self.repository.update(project, project.tabs, [locator.locator for locator in project.file_locators])
        
        ctx.projects_being_built.remove(project_id)

        if (build.status == BuildService.Success):
            PluginEvents.on_build_successful(project, build)
            self.process_pipelines_for(project)
        else:
            PluginEvents.on_build_failed(project, build)
        
        return build

    def delete_scm_repository(self, project):
        self.scm.remove_repository(project)
        
    def process_pipelines_for(self, project):
        pipelines = self.pipeline_repository.get_all_pipelines_for(project)
        for pipeline in pipelines:
            for i in range(len(pipeline.items)):
                if i < len(pipeline.items) - 1:
                    if pipeline.items[i].project.id == project.id:
                        print "Adding project %d to the queue because it's in the same pipeline as project %s" % (pipeline.items[i+1].project.id, pipeline.items[i].project.name)
                        SkinkContext.current().build_queue.append(pipeline.items[i+1].project.id)
Beispiel #8
0
class ProjectController(BaseController):
    def __init__(self):
        self.repository = ProjectRepository()
        self.build_service = BuildService()

    @authenticated()
    @template.output("create_project.html")
    def new(self):
        return template.render(authenticated=self.authenticated(), project=None)

    @authenticated()
    @template.output("create_project.html")
    def edit(self, project_id):
        project = self.repository.get(project_id)
        return template.render(authenticated=self.authenticated(), project=project)

    def __process_tabs_for(self, data):
        tabs = None
        if data.has_key("additional_tab_name"):
            tab_names = [name for name in data["additional_tab_name"] if name != u""]
            tab_commands = [command for command in data["additional_tab_command"] if command != u""]
            tab_content_types = [
                content_type for content_type in data["additional_tab_content_type"] if content_type != u""
            ][1:]

            if len(tab_names) > len(tab_commands) or len(tab_names) > len(tab_content_types):
                raise ValueError("The number of tabs, commands and content types MUST be the same.")

            tabs = []
            for tab_index in range(len(tab_names)):
                tab = ProjectTab(
                    name=tab_names[tab_index],
                    command=tab_commands[tab_index],
                    content_type=tab_content_types[tab_index],
                )
                tabs.append(tab)
        return tabs

    def __process_file_locators_for(self, data):
        locators = None
        if data.has_key("additional_file_locator"):
            locators = [locator for locator in data["additional_file_locator"] if locator != u""]
        return locators

    @authenticated()
    def create(self, name, build_script, scm_repository, monitor_changes=None, **data):
        project = self.repository.create(
            name=name,
            build_script=build_script,
            scm_repository=scm_repository,
            monitor_changes=not monitor_changes is None,
            tabs=self.__process_tabs_for(data),
            file_locators=self.__process_file_locators_for(data),
        )
        PluginEvents.on_project_created(project)
        raise cherrypy.HTTPRedirect("/")

    @authenticated()
    def update(self, project_id, name, build_script, scm_repository, monitor_changes=None, **data):
        project = self.repository.get(project_id)
        project.name = name
        project.build_script = build_script
        project.scm_repository = scm_repository
        project.monitor_changes = not monitor_changes is None
        self.repository.update(
            project, self.__process_tabs_for(data), file_locators=self.__process_file_locators_for(data)
        )
        PluginEvents.on_project_updated(project)
        raise cherrypy.HTTPRedirect("/")

    @authenticated()
    def delete(self, project_id):
        project = self.repository.get(project_id)
        self.repository.delete(project_id)
        self.build_service.delete_scm_repository(project)
        PluginEvents.on_project_deleted(project)
        raise cherrypy.HTTPRedirect("/")

    @authenticated()
    def build(self, project_id):
        print "Adding project %s to the queue" % project_id
        SkinkContext.current().build_queue.append(project_id)
        raise cherrypy.HTTPRedirect("/project/%s" % project_id)

    @template.output("current_build.html")
    def current_build_report(self, **data):
        return template.render(authenticated=self.authenticated())

    def current_status(self, **data):
        ctx = SkinkContext.current()
        result = {}
        result["project"] = ctx.current_project and ctx.current_project.name or ""
        result["project_id"] = ctx.current_project and ctx.current_project.id or ""
        result["command"] = ctx.current_command
        result["log"] = ctx.current_log and u"<br />".join(unicode(ctx.current_log).splitlines()[-30:]) or ""

        return demjson.encode(result)

    def build_status(self, **data):
        ctx = SkinkContext.current()
        projects = self.repository.get_all()
        projects_being_built = [int(project_id) for project_id in ctx.projects_being_built]
        result = {}
        for project in projects:
            if project.id in projects_being_built:
                result[project.id] = (project.name, "BUILDING")
            else:
                result[project.id] = (
                    project.name,
                    (project.last_builds is not None and len(project.last_builds) > 0) and "BUILT" or "UNKNOWN",
                )

        return "\n".join(["%s=%s@@%s" % (k, v[0], v[1]) for k, v in result.items()])

    @template.output("project_details.html")
    def details(self, project_id):
        return self.render_details(project_id)

    @template.output("project_details.html")
    def build_details(self, project_id, build_id):
        return self.render_details(project_id, build_id)

    def build_tab_details(self, build_tab_id):
        return self.repository.get_build_tab_by_id(build_tab_id=build_tab_id).log

    def build_file_details(self, build_file_id):
        build_file = self.repository.get_build_file_by_id(build_file_id=build_file_id)
        response.headers["Content-Type"] = "application/x-download"
        response.headers["Content-Disposition"] = 'attachment; filename="%s"' % build_file.name
        response.headers["Accept-Ranges"] = "bytes"
        response.headers["Content-Length"] = len(build_file.content)
        response.body = build_file.content
        return response.body

    def get_all_status(self, **data):
        projects = self.repository.get_all()
        serialized_projects = []
        for project in projects:
            serialized_projects.append(project.to_dict())
        values = {}
        values["projects"] = serialized_projects

        cherrypy.response.headers["Content-Type"] = "application/json"
        return demjson.encode(values)

    def render_details(self, project_id, build_id=None):
        project = self.repository.get(project_id)
        if not build_id:
            build = project.last_builds and project.last_builds[0] or None
        else:
            build = project.get_build_by_id(int(build_id))
        build_log = ""
        if build and build.log:
            build_log = highlight(build.log, BashLexer(), HtmlFormatter())
        return template.render(
            authenticated=self.authenticated(), project=project, current_build=build, build_log=build_log
        )