#70 Add the pagure_distgit 3rd party extension for pagure
Merged 6 years ago by pingou. Opened 6 years ago by pingou.

file modified
+4
@@ -4,5 +4,9 @@ 

  include dist_git_auth_tests.py

  include pagure_poc.py

  recursive-include template *

+ recursive-include pagure_distgit *

  recursive-include scripts *

  recursive-include static *

+ 

+ recursive-exclude . *.pyc

+ recursive-exclude pagure_distgit *.pyc

file added
+40
@@ -0,0 +1,40 @@ 

+ #!/usr/bin/env python

+ 

+ from __future__ import print_function, unicode_literals

+ 

+ import argparse

+ import os

+ 

+ from sqlalchemy import create_engine

+ 

+ 

+ parser = argparse.ArgumentParser(

+     description="Create/Update the Pagure database"

+ )

+ parser.add_argument(

+     "--config",

+     "-c",

+     dest="config",

+     help="Configuration file to use for pagure.",

+ )

+ 

+ args = parser.parse_args()

+ 

+ if args.config:

+     config = args.config

+     if not config.startswith("/"):

+         here = os.path.join(os.path.dirname(os.path.abspath(__file__)))

+         config = os.path.join(here, config)

+     print(config)

+     os.environ["PAGURE_CONFIG"] = config

+ 

+ import pagure.config

+ from pagure_distgit.model import BASE, PagureAnitya

+ 

+ db_url = pagure.config.config.get("DB_URL")

+ if db_url.startswith("postgres"):

+     engine = create_engine(db_url, echo=True, client_encoding="utf8")

+ else:

+     engine = create_engine(db_url, echo=True)

+ 

+ BASE.metadata.create_all(engine, tables=[PagureAnitya.__table__])

empty or binary file added
@@ -0,0 +1,29 @@ 

+ # -*- coding: utf-8 -*-

+ 

+ """

+  (c) 2019 - Copyright Red Hat Inc

+ 

+  Authors:

+    Pierre-Yves Chibon <pingou@pingoured.fr>

+ 

+ """

+ 

+ from __future__ import unicode_literals, print_function

+ 

+ import wtforms

+ 

+ import pagure.forms

+ 

+ 

+ class AnityaForm(pagure.forms.PagureForm):

+     """ Form to configure taiga for a project. """

+ 

+     anitya_status = wtforms.SelectField(

+         "Monitoring status of the package in anitya",

+         [wtforms.validators.DataRequired()],

+         choices=[

+             ("monitoring", "monitoring"),

+             ("no-monitoring", "no-monitoring"),

+             ("monitoring-with-scratch", "monitoring-with-scratch"),

+         ],

+     )

@@ -0,0 +1,59 @@ 

+ # -*- coding: utf-8 -*-

+ 

+ """

+  (c) 2019 - Copyright Red Hat Inc

+ 

+  Authors:

+    Pierre-Yves Chibon <pingou@pingoured.fr>

+ 

+ """

+ 

+ from __future__ import unicode_literals, print_function

+ 

+ import logging

+ import sqlalchemy as sa

+ 

+ from sqlalchemy.orm import backref

+ from sqlalchemy.orm import relation

+ 

+ from pagure.lib.model_base import BASE

+ from pagure.lib.model import Project

+ 

+ 

+ _log = logging.getLogger(__name__)

+ 

+ 

+ # DB Model

+ 

+ 

+ class PagureAnitya(BASE):

+     """ Stores information about the monitoring of a project in anitya.

+ 

+     Table -- pagure_anitya

+     """

+ 

+     __tablename__ = "pagure_anitya"

+ 

+     id = sa.Column(sa.Integer, primary_key=True)

+     project_id = sa.Column(

+         sa.Integer,

+         sa.ForeignKey("projects.id", onupdate="CASCADE", ondelete="CASCADE"),

+         nullable=False,

+         unique=True,

+         index=True,

+     )

+ 

+     anitya_status = sa.Column(

+         sa.String(255), nullable=False, unique=False, default="no-monitoring"

+     )

+ 

+     project = relation(

+         "Project",

+         remote_side=[Project.id],

+         backref=backref(

+             "anitya",

+             cascade="delete, delete-orphan",

+             single_parent=True,

+             uselist=False,

+         ),

+     )

@@ -0,0 +1,87 @@ 

+ # -*- coding: utf-8 -*-

+ 

+ """

+  (c) 2019 - Copyright Red Hat Inc

+ 

+  Authors:

+    Pierre-Yves Chibon <pingou@pingoured.fr>

+ 

+ """

+ 

+ from __future__ import unicode_literals, print_function

+ import logging

+ 

+ import flask

+ from sqlalchemy.exc import SQLAlchemyError

+ 

+ import pagure.utils

+ from pagure.api import api_method, APIERROR, api_login_required

+ from pagure.api.utils import _get_repo, _check_token

+ 

+ import pagure_distgit.forms

+ from pagure_distgit import model

+ 

+ 

+ _log = logging.getLogger(__name__)

+ 

+ DISTGIT_NS = flask.Blueprint(

+     "distgit_ns", __name__, url_prefix="/_dg", template_folder="templates"

+ )

+ 

+ 

+ @DISTGIT_NS.route("/anitya/<namespace>/<repo>", methods=["GET"])

+ def anitya_get_endpoint(namespace, repo):

+     """ Returns the current status of the monitoring in anitya of this package.

+     """

+     repo = flask.g.repo

+     output = {"monitoring": "no-monitoring"}

+     if repo.anitya:

+         output = {"monitoring": repo.anitya.anitya_status}

+     return flask.jsonify(output)

+ 

+ 

+ @DISTGIT_NS.route("/anitya/<namespace>/<repo>", methods=["PATCH"])

+ @api_login_required(acls=["modify_project"])

+ @api_method

+ def anitya_patch_endpoint(namespace, repo):

+     """ Updates the current status of the monitoring in anitya of this package.

+     """

+ 

+     repo = _get_repo(repo, namespace=namespace)

+     _check_token(repo, project_token=False)

+ 

+     is_site_admin = pagure.utils.is_admin()

+     admins = [u.username for u in repo.get_project_users("admin")]

+     # Only allow the main admin, the admins of the project, and Pagure site

+     # admins to modify projects' monitoring, even if the user has the right

+     # ACLs on their token

+     if (

+         flask.g.fas_user.username not in admins

+         and flask.g.fas_user.username != repo.user.username

+         and not is_site_admin

+     ):

+         raise pagure.exceptions.APIError(

+             401, error_code=APIERROR.EMODIFYPROJECTNOTALLOWED

+         )

+ 

+     form = pagure_distgit.forms.AnityaForm(csrf_enabled=False)

+     if form.validate_on_submit():

+         try:

+             if repo.anitya:

+                 repo.anitya.anitya_status = form.anitya_status.data

+             else:

+                 repo = model.PagureAnitya(

+                     project_id=repo.id, anitya_status=form.anitya_status.data

+                 )

+             flask.g.session.add(repo)

+             flask.g.session.commit()

+         except SQLAlchemyError as err:  # pragma: no cover

+             flask.g.session.rollback()

+             _log.exception(err)

+             raise pagure.exceptions.APIError(400, error_code=APIERROR.EDBERROR)

+     else:

+         raise pagure.exceptions.APIError(

+             400, error_code=APIERROR.EINVALIDREQ, errors=form.errors

+         )

+ 

+     return anitya_get_endpoint(namespace, repo.name)

file modified
+1 -1
@@ -25,7 +25,7 @@ 

      install_requires=install_requires,

      tests_require=tests_require,

      test_suite='nose.collector',

-     packages=[],

+     packages=['pagure_distgit'],

      py_modules=['dist_git_auth'],

      include_package_data=True,

      zip_safe=False,

This 3rd party extension has a dedicated database model expending
pagure's database model to store information about monitoring status of
a project.
It also has two new endpoints, one to retrieve the current monitoring
status of a project, the second to update it.
These two endpoints are then leveraged in the srcfpo theme of pagure to
display the current monitoring status of the package and update it.

Signed-off-by: Pierre-Yves Chibon pingou@pingoured.fr

Knowing that we might want to add more stuff in this plugin later, should we have more generic name ? like PagureDistgit ? or do you think it is better to create new tables every time ?

Same here for the tablename

Should this be moved to its own module ?

I'm kinda thinking it may be better to have a new table every time, otherwise it'll create too much empty columns which aren't great from a DB point of view.

Do we want a default value here ?

Do you want the "POST" method here ?

Nope indeed, thanks for catching this :)

rebased onto 5db59c4f5fc9f95077fc6763977df12ee0cd9b2f

6 years ago

rebased onto b3b0444

6 years ago

Pull-Request has been merged by pingou

6 years ago