def post(self, repo: Repository): """ Create a new build. """ schema = BuildCreateSchema(strict=True, context={"repository": repo}) result = self.schema_from_request(schema, partial=True) if result.errors: return self.respond(result.errors, 403) data = result.data # TODO(dcramer): only if we create a source via a patch will we need the author # author_data = data.pop('author') # if author_data.get('email'): # author = Author.query.filter( # Author.repository_id == repo.id, Author.email == author_data['email'] # ).first() # else: # author = None # if not author: # author = Author(repository_id=repo.id, **author_data) # db.session.add(author) # db.session.flush() # TODO(dcramer): need to handle patch case yet source = (Source.query.options( joinedload("author"), joinedload("revision")).filter( Source.revision_sha == data.pop("ref"), Source.repository_id == repo.id).first()) build = Build(repository=repo, **data) # TODO(dcramer): we should convert source in the schema build.source = source # build.source_id = source.id build.author = source.author if not source.patch_id: if not build.label: build.label = source.revision.message.split("\n")[0] if not build.label: return self.error("missing build label") db.session.add(build) try: db.session.commit() except IntegrityError: db.session.rollback() return self.respond(status=422) result = build_schema.dump(build) assert not result.errors, "this should never happen" publish("builds", "build.create", result.data) return self.respond(result.data, 200)
def merge_builds(target: Build, build: Build) -> Build: # explicitly unset the default id as target should begin as an empty instance target.id = None # Store the original build so we can retrieve its ID or number later, or # show a list of all builds in the UI target.original.append(build) # These properties should theoretically always be the same within a build # group, so merging is not necessary. We assign here so the initial build # gets populated. target.source = build.source target.label = build.source.revision.message # Merge properties, if they already exist. In the first run, everything # will be empty, since every group is initialized with an empty build. # Afterwards, we always use the more extreme value (e.g. earlier start # date or worse result). target.stats = target.stats + build.stats if target.stats else build.stats target.status = ( Status(max(target.status.value, build.status.value)) if target.status else build.status ) target.result = ( Result(max(target.result.value, build.result.value)) if target.result else build.result ) target.date_started = ( min(target.date_started, build.date_started) if target.date_started and build.date_started else target.date_started or build.date_started ) target.date_finished = ( max(target.date_finished, build.date_finished) if target.date_finished and build.date_finished else target.date_finished or build.date_finished ) target.provider = ( "%s, %s" % (target.provider, build.provider) if target.provider else build.provider ) # NOTE: The build number is not merged, as it would not convey any meaning # in the context of a build group. In that fashion, build numbers should # not be used in the UI, until we create a better interface. # NOTE: We do not merge data here, as it is not really used in the UI # If there is an actual use for data, then it should be merged or appended return target
def post(self, repo: Repository): """ Create a new build. """ result = self.schema_from_request(build_create_schema, partial=True) if result.errors: return self.respond(result.errors, 403) data = result.data ref = data.pop('ref', None) if ref is None: return self.error('missing ref') try: revision = identify_revision(repo, ref) except UnknownRevision: current_app.logger.warn('invalid ref received', exc_info=True) return self.error('unable to find a revision matching ref') # TODO(dcramer): only if we create a source via a patch will we need the author # author_data = data.pop('author') # if author_data.get('email'): # author = Author.query.filter( # Author.repository_id == repo.id, Author.email == author_data['email'] # ).first() # else: # author = None # if not author: # author = Author(repository_id=repo.id, **author_data) # db.session.add(author) # db.session.flush() # TODO(dcramer): need to handle patch case yet source = Source.query.options(joinedload('author'), ).filter( Source.revision_sha == revision.sha, Source.repository_id == repo.id, ).first() build = Build(repository=repo, **data) # TODO(dcramer): we should convert source in the schema build.source = source # build.source_id = source.id build.author = source.author if not source.patch_id: if not build.label: build.label = source.revision.message.split('\n')[0] db.session.add(build) db.session.commit() return self.respond_with_schema(build_schema, build)
def build_instance(self, data, **kwargs): revision = self.context.get("resolved_revision") build = Build( repository=self.context.get("repository"), revision_sha=revision.sha if revision else None, **data ) if build.data is None: build.data = {} build.data["required_hook_ids"] = Hook.get_required_hook_ids( build.repository.id ) if revision: if not build.label: build.label = revision.message.split("\n")[0] if not build.authors and revision.authors: build.authors = revision.authors return build
def post(self, project: Project): """ Create a new build. """ result = self.schema_from_request(build_create_schema, partial=True) if result.errors: return self.respond(result.errors, 403) data = result.data revision_sha = data.pop('revision_sha') source = Source.query.filter( Source.revision_sha == revision_sha, Source.repository_id == project.repository_id, ).first() if not source: return self.error('invalid source') # TODO(dcramer): only if we create a source via a patch will we need the author # author_data = data.pop('author') # if author_data.get('email'): # author = Author.query.filter( # Author.repository_id == repo.id, Author.email == author_data['email'] # ).first() # else: # author = None # if not author: # author = Author(repository_id=repo.id, **author_data) # db.session.add(author) # db.session.flush() build = Build(**data) build.organization_id = project.organization_id build.project_id = project.id # TODO(dcramer): we should convert source in the schema build.source = source build.source_id = source.id if not source.patch_id: if not build.label: build.label = source.revision.message.split('\n')[0] assert build.source_id db.session.add(build) db.session.commit() return self.respond_with_schema(build_schema, build)