def chroot_update(username, coprname, chrootname): form = forms.ChrootForm() copr = coprs_logic.CoprsLogic.get(flask.g.user, username, coprname).first() if not copr: return page_not_found( "Projec with name {0} does not exist.".format(coprname)) try: chroot = coprs_logic.MockChrootsLogic.get_from_name( chrootname, active_only=True).first() except ValueError as e: return page_not_found(str(e)) if form.validate_on_submit() and flask.g.user.can_build_in(copr): coprs_logic.CoprChrootsLogic.update_buildroot_pkgs( copr, chroot, form.buildroot_pkgs.data) flask.flash( "Buildroot {0} for project {1} was updated".format( chrootname, coprname)) db.session.commit() return flask.redirect(flask.url_for("coprs_ns.copr_edit", username=username, coprname=copr.name)) else: if form.validate_on_submit(): flask.flash("You are not allowed to modify chroots.") else: return chroot_edit(username, coprname, chrootname)
def chroot_edit(username, coprname, chrootname): copr = coprs_logic.CoprsLogic.get(flask.g.user, username, coprname).first() if not copr: return page_not_found( "Project with name {0} does not exist.".format(coprname)) try: chroot = coprs_logic.MockChrootsLogic.get_from_name( chrootname, active_only=True).first() except ValueError as e: return page_not_found(str(e)) if not chroot: return page_not_found( "Chroot name {0} does not exist.".format(chrootname)) form = forms.ChrootForm(buildroot_pkgs=copr.buildroot_pkgs(chroot)) # FIXME - test if chroot belongs to copr if flask.g.user.can_build_in(copr): return flask.render_template("coprs/detail/edit_chroot.html", form=form, copr=copr, chroot=chroot) else: return page_not_found( "You are not allowed to modify chroots in project {0}." .format(coprname))
def chroot_update(username, coprname, chrootname): form = forms.ChrootForm() copr = coprs_logic.CoprsLogic.get(flask.g.user, username, coprname).first() if not copr: return page_not_found( "Projec with name {0} does not exist.".format(coprname)) try: chroot = coprs_logic.MockChrootsLogic.get_from_name( chrootname, active_only=True).first() except ValueError as e: return page_not_found(str(e)) if form.validate_on_submit() and flask.g.user.can_build_in(copr): coprs_logic.CoprChrootsLogic.update_buildroot_pkgs( copr, chroot, form.buildroot_pkgs.data) flask.flash("Buildroot {0} for project {1} was updated".format( chrootname, coprname)) db.session.commit() return flask.redirect( flask.url_for("coprs_ns.copr_edit", username=username, coprname=copr.name)) else: if form.validate_on_submit(): flask.flash("You are not allowed to modify chroots.") else: return chroot_edit(username, coprname, chrootname)
def chroot_edit(username, coprname, chrootname): copr = coprs_logic.CoprsLogic.get(flask.g.user, username, coprname).first() if not copr: return page_not_found( "Project with name {0} does not exist.".format(coprname)) try: chroot = coprs_logic.MockChrootsLogic.get_from_name( chrootname, active_only=True).first() except ValueError as e: return page_not_found(str(e)) if not chroot: return page_not_found( "Chroot name {0} does not exist.".format(chrootname)) form = forms.ChrootForm(buildroot_pkgs=copr.buildroot_pkgs(chroot)) # FIXME - test if chroot belongs to copr if flask.g.user.can_build_in(copr): return flask.render_template("coprs/detail/edit_chroot.html", form=form, copr=copr, chroot=chroot) else: return page_not_found( "You are not allowed to modify chroots in project {0}.".format( coprname))
def generate_repo_file(username, coprname, name_release, repofile): """ Generate repo file for a given repo name. Reponame = username-coprname """ # This solution is used because flask splits off the last part after a # dash, therefore user-re-po resolves to user-re/po instead of user/re-po # FAS usernames may not contain dashes, so this construction is safe. reponame = "{0}-{1}".format(username, coprname) if repofile is not None and repofile != username + '-' + coprname + '-' + name_release + '.repo': return page_not_found( "Repository filename does not match expected: {0}" .format(repofile)) try: # query.one() is used since it fetches all builds, unlike # query.first(). copr = coprs_logic.CoprsLogic.get(flask.g.user, username, coprname, with_builds=True).one() except sqlalchemy.orm.exc.NoResultFound: return page_not_found( "Project {0}/{1} does not exist".format(username, coprname)) mock_chroot = coprs_logic.MockChrootsLogic.get_from_name(name_release, noarch=True).first() if not mock_chroot: return page_not_found("Chroot {0} does not exist".format(name_release)) url = "" for build in copr.builds: if build.results: url = build.results break if not url: return page_not_found( "Repository not initialized: No finished builds in {0}/{1}." .format(username, coprname)) repo_url = generate_repo_url(mock_chroot, url) pubkey_url = urlparse.urljoin(url, "pubkey.gpg") response = flask.make_response( flask.render_template("coprs/copr.repo", copr=copr, url=repo_url, pubkey_url=pubkey_url)) response.mimetype = "text/plain" response.headers["Content-Disposition"] = \ "filename={0}.repo".format(reponame) return response
def webhooks_hello(copr_id, uuid): # For the documentation of the data we receive see: # https://developer.github.com/v3/activity/events/types/#pushevent try: copr = ComplexLogic.get_copr_by_id_safe(copr_id) except ObjectNotFound: return page_not_found("Project does not exist") if copr.webhook_secret != uuid: return access_restricted("This webhook is not valid") try: request_json = flask.request.json clone_url = request_json["repository"]["clone_url"] except KeyError: return "Bad Request", 400 if "commits" in request_json: commits = request_json["commits"] else: commits = [] packages = PackagesLogic.get_for_webhook_rebuild(copr_id, uuid, clone_url, commits) for package in packages: BuildsLogic.rebuild_package(package) db.session.commit() return "OK", 200
def copr_delete(username, coprname): form = forms.CoprDeleteForm() copr = coprs_logic.CoprsLogic.get(flask.g.user, username, coprname).first() if form.validate_on_submit() and copr: builds_query = builds_logic.BuildsLogic.get_multiple( flask.g.user, copr=copr) try: for build in builds_query: builds_logic.BuildsLogic.delete_build(flask.g.user, build) coprs_logic.CoprsLogic.delete(flask.g.user, copr) except (exceptions.ActionInProgressException, exceptions.InsufficientRightsException) as e: db.session.rollback() flask.flash(str(e)) return flask.redirect(flask.url_for("coprs_ns.copr_detail", username=username, coprname=coprname)) else: db.session.commit() flask.flash("Project was deleted successfully.") return flask.redirect(flask.url_for("coprs_ns.coprs_by_owner", username=username)) else: if copr: return flask.render_template("coprs/detail/delete.html", form=form, copr=copr) else: return page_not_found("Project {0}/{1} does not exist" .format(username, coprname))
def copr_build_monitor(username, coprname): try: copr = coprs_logic.CoprsLogic.get( flask.g.user, username, coprname, with_mock_chroots=True).one() except sqlalchemy.orm.exc.NoResultFound: return page_not_found( "Copr with name {0} does not exist.".format(coprname)) form = forms.CoprLegalFlagForm() monitor = builds_logic.BuildsMonitorLogic.get_monitor_data(copr) md_chroots = monitor["chroots"] active_chroots = sorted( copr.active_chroots, key=lambda chroot: md_chroots.index(chroot.name) ) oses = [chroot.os for chroot in active_chroots] oses_grouped = [(len(list(group)), key) for key, group in groupby(oses)] archs = [chroot.arch for chroot in active_chroots] kwargs = dict(copr=copr, oses=oses_grouped, archs=archs, form=form) kwargs.update(monitor) kwargs["build"] = kwargs["latest_build"] del kwargs["latest_build"] return flask.render_template("coprs/detail/monitor.html", **kwargs)
def copr_permissions(username, coprname): query = coprs_logic.CoprsLogic.get(flask.g.user, username, coprname) copr = query.first() if not copr: return page_not_found( "Copr with name {0} does not exist.".format(coprname)) permissions = coprs_logic.CoprPermissionsLogic.get_for_copr( flask.g.user, copr).all() if flask.g.user: user_perm = flask.g.user.permissions_for_copr(copr) else: user_perm = None permissions_applier_form = None permissions_form = None # generate a proper form for displaying if flask.g.user: if flask.g.user.can_edit(copr): permissions_form = forms.PermissionsFormFactory.create_form_cls( permissions)() else: # https://github.com/ajford/flask-wtf/issues/58 permissions_applier_form = \ forms.PermissionsApplierFormFactory.create_form_cls( user_perm)(formdata=None) return flask.render_template( "coprs/detail/permissions.html", copr=copr, permissions_form=permissions_form, permissions_applier_form=permissions_applier_form, permissions=permissions, current_user_permissions=user_perm)
def coprs_by_user(username=None, page=1): user = users_logic.UsersLogic.get(username).first() if not user: return page_not_found("User {0} does not exist.".format(username)) pinned = [pin.copr for pin in PinnedCoprsLogic.get_by_user_id(user.id) ] if page == 1 else [] query = CoprsLogic.get_multiple_owned_by_username(username) query = CoprsLogic.filter_without_ids(query, [copr.id for copr in pinned]) query = CoprsLogic.filter_without_group_projects(query) query = CoprsLogic.set_query_order(query, desc=True) paginator = helpers.Paginator(query, query.count(), page) coprs = paginator.sliced_query # flask.g.user is none when no user is logged - showing builds from everyone users_builds = builds_logic.BuildsLogic.get_recent_tasks(flask.g.user, 4) data = builds_logic.BuildsLogic.get_small_graph_data('30min') return flask.render_template("coprs/show/user.html", user=user, coprs=coprs, pinned=pinned, paginator=paginator, tasks_info=ComplexLogic.get_queue_sizes(), users_builds=users_builds, graph=data)
def copr_permissions_applier_change(username, coprname): copr = coprs_logic.CoprsLogic.get(flask.g.user, username, coprname).first() permission = coprs_logic.CoprPermissionsLogic.get( flask.g.user, copr, flask.g.user).first() applier_permissions_form = \ forms.PermissionsApplierFormFactory.create_form_cls(permission)() if not copr: return page_not_found( "Project with name {0} does not exist.".format(coprname)) if copr.owner == flask.g.user: flask.flash("Owner cannot request permissions for his own project.") elif applier_permissions_form.validate_on_submit(): # we rely on these to be 0 or 1 from form. TODO: abstract from that if permission is not None: old_builder = permission.copr_builder old_admin = permission.copr_admin else: old_builder = 0 old_admin = 0 new_builder = applier_permissions_form.copr_builder.data new_admin = applier_permissions_form.copr_admin.data coprs_logic.CoprPermissionsLogic.update_permissions_by_applier( flask.g.user, copr, permission, new_builder, new_admin) db.session.commit() flask.flash( "Successfuly updated permissions for project '{0}'." .format(copr.name)) admin_mails = [copr.owner.mail] for perm in copr.copr_permissions: # this 2 means that his status (admin) is approved if perm.copr_admin == 2: admin_mails.append(perm.user.mail) # sending emails if flask.current_app.config.get("SEND_EMAILS", False): for mail in admin_mails: msg = MIMEText( "{6} is asking for these permissions:\n\n" "Builder: {0} -> {1}\nAdmin: {2} -> {3}\n\n" "Project: {4}\nOwner: {5}".format( helpers.PermissionEnum(old_builder), helpers.PermissionEnum(new_builder), helpers.PermissionEnum(old_admin), helpers.PermissionEnum(new_admin), copr.name, copr.owner.name, flask.g.user.name)) msg["Subject"] = "[Copr] {0}: {1} is asking permissons".format(copr.name, flask.g.user.name) msg["From"] = "root@{0}".format(platform.node()) msg["To"] = mail s = smtplib.SMTP("localhost") s.sendmail("root@{0}".format(platform.node()), mail, msg.as_string()) s.quit() return flask.redirect(flask.url_for("coprs_ns.copr_detail", username=copr.owner.name, coprname=copr.name))
def copr_repeat_build(username, coprname, build_id, page=1): build = builds_logic.BuildsLogic.get(build_id).first() copr = coprs_logic.CoprsLogic.get( flask.g.user, username=username, coprname=coprname).first() if not build: return page_not_found( "Build with id {0} does not exist.".format(build_id)) if not copr: return page_not_found( "Copr {0}/{1} does not exist.".format(username, coprname)) if not flask.g.user.can_build_in(build.copr): flask.flash("You are not allowed to repeat this build.") form = forms.BuildFormFactory.create_form_cls(copr.active_chroots)( pkgs=build.pkgs, enable_net=build.enable_net, ) # remove all checkboxes by default for ch in copr.active_chroots: field = getattr(form, ch.name) field.data = False chroot_to_build = request.args.get("chroot") app.logger.debug("got param chroot: {}".format(chroot_to_build)) if chroot_to_build: # set single checkbox if chroot query arg was provided if hasattr(form, chroot_to_build): getattr(form, chroot_to_build).data = True else: # set checkbox on the failed chroots chroots_to_select = set(ch.name for ch in build.get_chroots_by_status([ helpers.StatusEnum('failed'), helpers.StatusEnum('canceled'), ])) for ch in build.chroots: if ch.name in chroots_to_select: getattr(form, ch.name).data = True return flask.render_template("coprs/detail/add_build.html", copr=copr, form=form)
def copr_build_redirect(build_id): build = builds_logic.BuildsLogic.get_by_id(build_id) if not build: return page_not_found( "Build {0} does not exist.".format(str(build_id))) return flask.redirect(flask.url_for("coprs_ns.copr_build", username=build.copr.owner.name, coprname=build.copr.name, build_id=build_id))
def copr_new_build(username, coprname): copr = coprs_logic.CoprsLogic.get(flask.g.user, username, coprname).first() if not copr: return page_not_found( "Project {0}/{1} does not exist.".format(username, coprname)) form = forms.BuildFormFactory.create_form_cls(copr.active_chroots)() if form.validate_on_submit(): pkgs = form.pkgs.data.replace("\n", " ").split(" ") # validate (and skip bad) urls bad_urls = [] for pkg in pkgs: if not re.match("^.*\.src\.rpm$", pkg): bad_urls.append(pkg) flask.flash("Bad url: {0} (skipped)".format(pkg)) for bad_url in bad_urls: pkgs.remove(bad_url) if not pkgs: flask.flash("No builds submitted") else: # check which chroots we need chroots = [] for chroot in copr.active_chroots: if chroot.name in form.selected_chroots: chroots.append(chroot) # build each package as a separate build try: for pkg in pkgs: build = builds_logic.BuildsLogic.add( user=flask.g.user, pkgs=pkg, copr=copr, chroots=chroots, enable_net=form.enable_net.data) if flask.g.user.proven: build.memory_reqs = form.memory_reqs.data build.timeout = form.timeout.data except (ActionInProgressException, InsufficientRightsException) as e: flask.flash(str(e)) db.session.rollback() else: flask.flash("Build was added") db.session.commit() return flask.redirect(flask.url_for("coprs_ns.copr_builds", username=username, coprname=copr.name)) else: return copr_add_build(username=username, coprname=coprname, form=form)
def copr_add_build(username, coprname, form=None): copr = coprs_logic.CoprsLogic.get(flask.g.user, username, coprname).first() if not copr: return page_not_found( "Copr with name {0} does not exist.".format(coprname)) if not form: form = forms.BuildFormFactory.create_form_cls(copr.active_chroots)() return flask.render_template("coprs/detail/add_build.html", copr=copr, form=form)
def copr_build(username, coprname, build_id): build = builds_logic.BuildsLogic.get_by_id(build_id) copr = coprs_logic.CoprsLogic.get(flask.g.user, username, coprname).first() if not build: return page_not_found( "Build {0} does not exist.".format(str(build_id))) if not copr: # but the build does return flask.render_template( "coprs/detail/build-no-project.html", build=build, username=username, coprname=coprname) return flask.render_template("coprs/detail/build.html", build=build, copr=copr)
def copr_edit(username, coprname, form=None): query = coprs_logic.CoprsLogic.get(flask.g.user, username, coprname) copr = query.first() if not copr: return page_not_found( "Copr with name {0} does not exist.".format(coprname)) if not form: form = forms.CoprFormFactory.create_form_cls( copr.mock_chroots)(obj=copr) return flask.render_template("coprs/detail/edit.html", copr=copr, form=form)
def webhooks_gitlab_push(copr_id, uuid): # For the documentation of the data we receive see: # https://gitlab.com/help/user/project/integrations/webhooks#events try: copr = ComplexLogic.get_copr_by_id_safe(copr_id) except ObjectNotFound: return page_not_found("Project does not exist") if copr.webhook_secret != uuid: return access_restricted("This webhook is not valid") try: payload = flask.request.json clone_url = payload['project']['git_http_url'] commits = [] payload_commits = payload.get('commits', []) for payload_commit in payload_commits: commits.append({ 'added': payload_commit['added'], 'modified': payload_commit['modified'], 'removed': payload_commit['removed'], }) if payload['object_kind'] == 'tag_push': ref_type = 'tag' ref = os.path.basename(payload.get('ref', '')) else: ref_type = None ref = payload.get('ref', '') try: submitter = 'gitlab.com:{}'.format(str(payload["user_username"])) except KeyError: submitter = None except KeyError: return "Bad Request", 400 packages = PackagesLogic.get_for_webhook_rebuild(copr_id, uuid, clone_url, commits, ref_type, ref) committish = (ref if ref_type == 'tag' else payload.get('after', '')) for package in packages: BuildsLogic.rebuild_package(package, {'committish': committish}, submitted_by=submitter) db.session.commit() return "OK", 200
def copr_delete_build(username, coprname, build_id, page=1): build = builds_logic.BuildsLogic.get(build_id).first() if not build: return page_not_found( "Build with id {0} does not exist.".format(build_id)) try: builds_logic.BuildsLogic.delete_build(flask.g.user, build) except (InsufficientRightsException, ActionInProgressException) as e: flask.flash(str(e)) else: db.session.commit() flask.flash("Build was deleted") return flask.redirect(flask.url_for("coprs_ns.copr_builds", username=username, coprname=coprname, page=page))
def copr_detail(username, coprname): query = coprs_logic.CoprsLogic.get( flask.g.user, username, coprname, with_mock_chroots=True) form = forms.CoprLegalFlagForm() try: copr = query.one() except sqlalchemy.orm.exc.NoResultFound: return page_not_found( "Copr with name {0} does not exist.".format(coprname)) repo_dl_stat = CounterStatLogic.get_copr_repo_dl_stat(copr) repos_info = {} for chroot in copr.active_chroots: chroot_rpms_dl_stat_key = CHROOT_REPO_MD_DL_STAT_FMT.format( copr_user=copr.owner.name, copr_project_name=copr.name, copr_chroot=chroot.name, ) chroot_rpms_dl_stat = TimedStatEvents.get_count( rconnect=rcp.get_connection(), name=chroot_rpms_dl_stat_key, ) if chroot.name_release not in repos_info: repos_info[chroot.name_release] = { "name_release": chroot.name_release, "name_release_human": chroot.name_release_human, "arch_list": [chroot.arch], "repo_file": "{}-{}-{}.repo".format(copr.owner.name, copr.name, chroot.name_release), "dl_stat": repo_dl_stat[chroot.name_release], "rpm_dl_stat": { chroot.arch: chroot_rpms_dl_stat } } else: repos_info[chroot.name_release]["arch_list"].append(chroot.arch) repos_info[chroot.name_release]["rpm_dl_stat"][chroot.arch] = chroot_rpms_dl_stat repos_info_list = sorted(repos_info.values(), key=lambda rec: rec["name_release"]) return flask.render_template("coprs/detail/overview.html", copr=copr, form=form, repo_dl_stat=repo_dl_stat, repos_info_list=repos_info_list, )
def copr_builds(username, coprname, page=1): copr = coprs_logic.CoprsLogic.get(flask.g.user, username, coprname).first() if not copr: return page_not_found( "Copr with name {0} does not exist.".format(coprname)) builds_query = builds_logic.BuildsLogic.get_multiple( flask.g.user, copr=copr) paginator = helpers.Paginator( builds_query, copr.build_count, page, per_page_override=20) return flask.render_template("coprs/detail/builds.html", copr=copr, builds=paginator.sliced_query, paginator=paginator)
def webhooks_git_push(copr_id, uuid): if flask.request.headers["X-GitHub-Event"] == "ping": return "OK", 200 # For the documentation of the data we receive see: # https://developer.github.com/v3/activity/events/types/#pushevent try: copr = ComplexLogic.get_copr_by_id_safe(copr_id) except ObjectNotFound: return page_not_found("Project does not exist") if copr.webhook_secret != uuid: return access_restricted("This webhook is not valid") try: payload = flask.request.json clone_url = payload['repository']['clone_url'] commits = [] payload_commits = payload.get('commits', []) for payload_commit in payload_commits: commits.append({ 'added': payload_commit['added'], 'modified': payload_commit['modified'], 'removed': payload_commit['removed'], }) ref_type = payload.get('ref_type', '') ref = payload.get('ref', '') try: sender = payload['sender']['url'] except KeyError: sender = None except KeyError: return "Bad Request", 400 packages = PackagesLogic.get_for_webhook_rebuild(copr_id, uuid, clone_url, commits, ref_type, ref) committish = (ref if ref_type == 'tag' else payload.get('after', '')) for package in packages: BuildsLogic.rebuild_package(package, {'committish': committish}, submitted_by=sender) db.session.commit() return "OK", 200
def copr_cancel_build(username, coprname, build_id, page=1): # only the user who ran the build can cancel it build = builds_logic.BuildsLogic.get(build_id).first() if not build: return page_not_found( "Build with id {0} does not exist.".format(build_id)) try: builds_logic.BuildsLogic.cancel_build(flask.g.user, build) except InsufficientRightsException as e: flask.flash(str(e)) else: db.session.commit() flask.flash("Build was canceled") return flask.redirect(flask.url_for("coprs_ns.copr_builds", username=username, coprname=coprname, page=page))
def webhooks_bitbucket_push(copr_id, uuid): # For the documentation of the data we receive see: # https://confluence.atlassian.com/bitbucket/event-payloads-740262817.html try: copr = ComplexLogic.get_copr_by_id_safe(copr_id) except ObjectNotFound: return page_not_found("Project does not exist") if copr.webhook_secret != uuid: return access_restricted("This webhook is not valid") try: payload = flask.request.json api_url = payload['repository']['links']['self']['href'] clone_url = payload['repository']['links']['html']['href'] commits = [] ref_type = payload['push']['changes'][0]['new']['type'] ref = payload['push']['changes'][0]['new']['name'] try: actor = payload['actor']['links']['html']['href'] except KeyError: actor = None if ref_type == 'tag': committish = ref else: committish = payload['push']['changes'][0]['new']['target']['hash'] except KeyError: return "Bad Request", 400 packages = PackagesLogic.get_for_webhook_rebuild(copr_id, uuid, clone_url, commits, ref_type, ref) for package in packages: BuildsLogic.rebuild_package(package, {'committish': committish}, submitted_by=actor) db.session.commit() return "OK", 200
def coprs_by_user(username=None, page=1): user = users_logic.UsersLogic.get(username).first() if not user: return page_not_found("User {0} does not exist.".format(username)) query = CoprsLogic.get_multiple_owned_by_username(username) query = CoprsLogic.filter_without_group_projects(query) query = CoprsLogic.set_query_order(query, desc=True) paginator = helpers.Paginator(query, query.count(), page) coprs = paginator.sliced_query # flask.g.user is none when no user is logged - showing builds from everyone users_builds = builds_logic.BuildsLogic.get_recent_tasks(flask.g.user, 5) return flask.render_template("coprs/show/user.html", user=user, coprs=coprs, paginator=paginator, tasks_info=ComplexLogic.get_queues_size(), users_builds=users_builds)
def coprs_by_owner(username=None, page=1): user = users_logic.UsersLogic.get(username).first() if not user: return page_not_found( "User {0} does not exist.".format(username)) query = CoprsLogic.get_multiple_owned_by_username(username) query = CoprsLogic.filter_without_group_projects(query) query = CoprsLogic.set_query_order(query, desc=True) paginator = helpers.Paginator(query, query.count(), page) coprs = paginator.sliced_query # flask.g.user is none when no user is logged - showing builds from everyone users_builds = builds_logic.BuildsLogic.get_recent_tasks(flask.g.user, 5) return flask.render_template("coprs/show/user.html", user=user, coprs=coprs, paginator=paginator, tasks_info=ComplexLogic.get_queues_size(), users_builds=users_builds)
def webhooks_hello(copr_id, uuid): try: copr = ComplexLogic.get_copr_by_id_safe(copr_id) except ObjectNotFound: return page_not_found("Project does not exist") if copr.webhook_secret != uuid: return access_restricted("This webhook is not valid") try: request_json = flask.request.json clone_url = request_json["repository"]["clone_url"] except KeyError: return "Bad Request", 400 packages = PackagesLogic.get_for_webhook_rebuild(copr_id, uuid, clone_url) for package in packages: BuildsLogic.rebuild_package(package) db.session.commit() return "OK", 200
def handle_404(error): return page_not_found(error.message)
def handle_404(self, error): return page_not_found(self.message(error))