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)
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)
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)
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()
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()
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)
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)
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()