Exemplo n.º 1
0
    def restart(self, user: User, idx: int) -> None:
        from piper_core.model.jobs.job import Job
        from piper_core.model.stages.stage import Stage

        try:
            build: Build = Build.get(Build.id == idx)
        except DoesNotExist:
            raise FacadeNotFound

        if user.role is not UserRole.MASTER:
            try:
                ProjectUser.get((ProjectUser.user == user)
                                & (ProjectUser.project == build.project))
            except DoesNotExist:
                raise FacadeUnauthorized

        if build.status not in Status.final_statuses():
            raise FacadeInvalidAction

        build.restart()
        first = Stage.select().where(Stage.build == build).order_by(
            Stage.order.asc()).first()
        jobs = Job.select().where(Job.stage == first)
        for job in jobs:
            job.status = Status.READY
            job.save()
            self.queue.push(job)
Exemplo n.º 2
0
    def cancel(self, user: User, idx: int) -> None:
        from piper_core.model.jobs.job import Job
        try:
            stage: Stage = Stage.get(Stage.id == idx)
        except DoesNotExist:
            raise FacadeNotFound

        if user.role is not UserRole.MASTER:
            try:
                ProjectUser.get((ProjectUser.user == user)
                                & (ProjectUser.project == stage.build.project))
            except DoesNotExist:
                raise FacadeUnauthorized

        if stage.status not in Status.cancelable_statuses():
            raise FacadeInvalidAction

        stage.cancel()
        next_stage: Stage = Stage.get((Stage.build == stage.build)
                                      & (Stage.order == stage.order + 1))
        if not next_stage or next_stage.status is not Status.READY:
            return

        jobs = Job.select().where(Job.stage == next_stage)
        for job in jobs:
            self.queue.push(job)
Exemplo n.º 3
0
    def parse_webhook(self, data):
        from piper_core.model.stages.stage import Stage
        from piper_core.model.jobs.job import Job
        from piper_core.model.jobs.environment import Environment

        commit = self.github.parse_webhook(data)
        yml = self.github.fetch_piper_yml(commit)

        project = Project.get(
            Project.origin == commit.branch.repository.origin)
        build = Build(project=project,
                      branch=commit.branch.name,
                      commit=commit.sha)
        self.create_build(yml, build)

        jobs = Job.select().join(Stage).where(Stage.build == build)
        for job in jobs:
            Environment.create(name='PIPER', value=True, job=job)
            Environment.create(name='PIPER_BRANCH',
                               value=commit.branch.name,
                               job=job)
            Environment.create(name='PIPER_COMMIT', value=commit.sha, job=job)
            Environment.create(name='PIPER_COMMIT_MESSAGE',
                               value=commit.message,
                               job=job)
            Environment.create(name='PIPER_JOB_ID', value=job.id, job=job)
            Environment.create(name='PIPER_BUILD_ID', value=build.id, job=job)
            Environment.create(name='PIPER_STAGE',
                               value=job.stage.name,
                               job=job)

        first = Stage.select().where(Stage.build == build).order_by(
            Stage.order.asc()).first()

        jobs = Job.select().where(Job.stage == first)
        for job in jobs:
            job.status = Status.READY
            job.save()
            self.queue.push(job)
Exemplo n.º 4
0
    def cancel(self):
        from piper_core.model.jobs.job import Job

        with database_proxy.transaction():
            jobs = Job.select().where((Job.stage == self) & (
                Job.status.in_(Status.cancelable_statuses())))
            for job in jobs:
                job.status = Status.CANCELED
                job.save()

            self.status = Stage.get(Stage.id == self.id).status
            self._set_build_status()
            self.build.save()
Exemplo n.º 5
0
    def restart(self):
        from piper_core.model.jobs.job import Job

        with database_proxy.transaction():
            jobs = Job.select().where((Job.stage == self) & (
                Job.status.in_(Status.final_statuses())))

            for job in jobs:
                job.status = Status.READY
                job.secret = uuid.uuid4().hex
                job.save()

            self.status = Stage.get(Stage.id == self.id).status
            self._set_build_status()
            self.build.save()
Exemplo n.º 6
0
    def save(self, force_insert=False, only=None):
        from piper_core.model.jobs.job import Job

        if Stage.status not in self.dirty_fields:
            return super().save(force_insert, only)

        with database_proxy.transaction():
            if self.status is Status.RUNNING:
                stages = Stage.select().where(
                    (Stage.order > self.order) & (Stage.build == self.build)
                    & Stage.status.not_in(Status.final_statuses()))
                for stage in stages:
                    stage.status = Status.PENDING
                    Job.update(status=Status.PENDING).where(
                        Job.stage == stage).execute()
                    stage.save()

            if self.status in [
                    Status.CANCELED, Status.SKIPPED, Status.SUCCESS
            ]:
                try:
                    stage = Stage.get(
                        (Stage.order == self.order + 1)
                        & (Stage.build == self.build)
                        & Stage.status.not_in(Status.final_statuses()))
                    stage.status = Status.READY
                    Job.update(status=Status.READY).where(
                        Job.stage == stage).execute()
                    stage.save()
                except DoesNotExist:
                    pass

            if self.status in [Status.FAILED, Status.ERROR]:
                stages = Stage.select().where(
                    (Stage.order > self.order) & (Stage.build == self.build)
                    & Stage.status.not_in(Status.final_statuses()))
                for stage in stages:
                    Job.update(status=Status.FAILED).where(
                        Job.stage == stage).execute()
                    stage.status = Status.FAILED
                    stage.save()

            self._set_build_status()
            self.build.save()
            return super().save(force_insert, only)
Exemplo n.º 7
0
    def restart(self, user: User, idx: int) -> None:
        from piper_core.model.jobs.job import Job

        try:
            stage = Stage.get(Stage.id == idx)
        except DoesNotExist:
            raise FacadeNotFound

        if user.role is not UserRole.MASTER:
            try:
                ProjectUser.get((ProjectUser.user == user)
                                & (ProjectUser.project == stage.build.project))
            except DoesNotExist:
                raise FacadeUnauthorized

        if stage.status not in Status.final_statuses():
            raise FacadeInvalidAction

        stage.restart()
        jobs: List[Job] = Job.select().where((Job.stage == stage)
                                             & (Job.status == Status.READY))

        for job in jobs:
            self.queue.push(job)
Exemplo n.º 8
0
    def create_build(self, yml: Dict[Any, Any], build: Build):
        from piper_core.model.stages.stage import Stage
        from piper_core.model.jobs.job import Job
        from piper_core.model.jobs.environment import Environment
        from piper_core.model.jobs.command import Command, CommandType

        hook_schema = self.schema['components']['schemas']['piper-yml']
        try:
            Draft4Validator(schema=hook_schema).validate(yml)
        except ValidationError as e:
            raise Exception(e.message)

        stages = dict()
        for idx, s in enumerate(yml['stages']):
            stage = Stage()
            stage.name = s
            stage.order = idx
            stage.build = build
            stages[s] = stage

        jobs = list()
        environments = list()
        commands = list()
        for job_name, job_def in yml['jobs'].items():
            if job_def['stage'] not in stages:
                raise Exception

            job = Job()
            job.stage = stages[job_def['stage']]
            jobs.append(job)

            if 'when' in job_def:
                job.only = job_def['when']

            if 'runner' in job_def:
                # FIXME check if group exists
                job.group = job_def['runner']

            job.image = job_def['image']

            if 'env' in job_def:
                for env_name, env_value in job_def['env'].items():
                    env = Environment()
                    env.name = env_name
                    env.value = env_value
                    env.job = job
                    environments.append(env)

            for idx, command_cmd in enumerate(job_def['commands']):
                command = Command()
                command.order = idx
                command.cmd = command_cmd
                command.job = job
                command.type = CommandType.NORMAL
                commands.append(command)

            if 'after_failure' in job_def:
                for idx, command_cmd in enumerate(job_def['after_failure']):
                    command = Command()
                    command.order = idx
                    command.cmd = command_cmd
                    command.job = job
                    command.type = CommandType.AFTER_FAILURE
                    commands.append(command)

        with database_proxy.atomic():
            build.save()
            for _, stage in stages.items():
                stage.save()

            for job in jobs:
                job.save()

            for env in environments:
                env.save()

            for command in commands:
                command.save()