On Mon, Jan 29, 2018 at 11:36:36PM +1100, Daniel Axtens wrote:
> Hi Don,
> 
> >> I suppose to put a finer point on it - what is your usecase here? What
> >> are you trying to achieve, and can we help you do that in a way that
> >> requires smaller changes to Patchwork, and is less fragile? (For example
> >> this is going to break if someone mis-spells the keyword you're looking
> >> for in the subject_match.)
> >
> > So here is our use case.  Internally at Red Hat we use one mailing list to
> > post all of our kernel patches.  However, being a distro company, patches
> > can be applied to either RHEL-6,7,X.  For the last 15 years we have always
> > used the method:
> >
> > [RHEL-7 PATCH] instead of [PATCH].
> 
> Ah yes. I work for Canonical (although I do Patchwork in a private
> capacity only) and our kernel team does something very similar.
> 
> > The project inside the []s has been what we filter through our regex.  Is it
> > prone to human typos?  Yes.  Most folks have stuck this in the .git/config
> > subjectprefix option.  That limited the typos. It isn't perfect.
> >
> > We have been using a hacked up PatchWork1 for the last 7 or so years.  This
> > is one of those features we need (or something to solve our problem) if we
> > want to migrate to a PatchWork2 instance.
> >
> > I hope that adds a little bit of context on our thinking.  Thoughts?
> 
> That's a compelling use-case and I'm happy to look at supporting it. I
> will review the patch more closely in the coming days.

Thanks for your understanding and support!

Again, we know the solution has its 'human' limitations. :-) We just never
came up with a better idea. So any ideas there are welcomed too! :-)

Cheers,
Don

> 
> Regards,
> Daniel
> 
> > Cheers,
> > Don
> >
> >> 
> >> Regards,
> >> Daniel
> >> 
> >> >
> >> > Signed-off-by: Veronika Kabatova <vkaba...@redhat.com>
> >> > ---
> >> >  docs/api.yaml                                      |  3 +++
> >> >  docs/deployment/management.rst                     |  4 +--
> >> >  patchwork/api/project.py                           |  5 ++--
> >> >  .../0021_add_subject_match_to_project.py           | 29 
> >> > ++++++++++++++++++++++
> >> >  patchwork/models.py                                |  9 ++++++-
> >> >  patchwork/parser.py                                | 19 +++++++++++++-
> >> >  .../notes/list-filtering-4643d98b4064367a.yaml     | 10 ++++++++
> >> >  7 files changed, 73 insertions(+), 6 deletions(-)
> >> >  create mode 100644 
> >> > patchwork/migrations/0021_add_subject_match_to_project.py
> >> >  create mode 100644 
> >> > releasenotes/notes/list-filtering-4643d98b4064367a.yaml
> >> >
> >> > diff --git a/docs/api.yaml b/docs/api.yaml
> >> > index 3e79f0b..3373226 100644
> >> > --- a/docs/api.yaml
> >> > +++ b/docs/api.yaml
> >> > @@ -374,6 +374,9 @@ definitions:
> >> >        list_id:
> >> >          type: string
> >> >          description: Mailing list identifier for project.
> >> > +      subject_match:
> >> > +        type: string
> >> > +        description: Regex used for email filtering.
> >> >        list_email:
> >> >          type: string
> >> >          description: Mailing list email address for project.
> >> > diff --git a/docs/deployment/management.rst 
> >> > b/docs/deployment/management.rst
> >> > index c50b7b6..870d7ee 100644
> >> > --- a/docs/deployment/management.rst
> >> > +++ b/docs/deployment/management.rst
> >> > @@ -63,7 +63,7 @@ due to, for example, an outage.
> >> >  .. option:: --list-id <list-id>
> >> >  
> >> >     mailing list ID. If not supplied, this will be extracted from the 
> >> > mail
> >> > -   headers.
> >> > +   headers. Don't use this option if you require filtering based on 
> >> > subjects.
> >> >  
> >> >  .. option:: infile
> >> >  
> >> > @@ -88,7 +88,7 @@ the :ref:`deployment installation guide 
> >> > <deployment-parsemail>`.
> >> >  .. option:: --list-id <list-id>
> >> >  
> >> >     mailing list ID. If not supplied, this will be extracted from the 
> >> > mail
> >> > -   headers.
> >> > +   headers. Don't use this option if you require filtering based on 
> >> > subjects.
> >> >  
> >> >  .. option:: infile
> >> >  
> >> > diff --git a/patchwork/api/project.py b/patchwork/api/project.py
> >> > index 446c473..597f605 100644
> >> > --- a/patchwork/api/project.py
> >> > +++ b/patchwork/api/project.py
> >> > @@ -39,8 +39,9 @@ class ProjectSerializer(HyperlinkedModelSerializer):
> >> >      class Meta:
> >> >          model = Project
> >> >          fields = ('id', 'url', 'name', 'link_name', 'list_id', 
> >> > 'list_email',
> >> > -                  'web_url', 'scm_url', 'webscm_url', 'maintainers')
> >> > -        read_only_fields = ('name', 'maintainers')
> >> > +                  'web_url', 'scm_url', 'webscm_url', 'maintainers',
> >> > +                  'subject_match')
> >> > +        read_only_fields = ('name', 'maintainers', 'subject_match')
> >> >          extra_kwargs = {
> >> >              'url': {'view_name': 'api-project-detail'},
> >> >          }
> >> > diff --git a/patchwork/migrations/0021_add_subject_match_to_project.py 
> >> > b/patchwork/migrations/0021_add_subject_match_to_project.py
> >> > new file mode 100644
> >> > index 0000000..6066266
> >> > --- /dev/null
> >> > +++ b/patchwork/migrations/0021_add_subject_match_to_project.py
> >> > @@ -0,0 +1,29 @@
> >> > +# -*- coding: utf-8 -*-
> >> > +# Generated by Django 1.10.8 on 2018-01-19 18:16
> >> > +from __future__ import unicode_literals
> >> > +
> >> > +from django.db import migrations, models
> >> > +
> >> > +
> >> > +class Migration(migrations.Migration):
> >> > +
> >> > +    dependencies = [
> >> > +        ('patchwork', '0020_tag_show_column'),
> >> > +    ]
> >> > +
> >> > +    operations = [
> >> > +        migrations.AddField(
> >> > +            model_name='project',
> >> > +            name='subject_match',
> >> > +            field=models.CharField(blank=True, default=b'', 
> >> > help_text=b'Regex to match the subject against if only part of emails 
> >> > sent to the list belongs to this project. Will be used with IGNORECASE 
> >> > and MULTILINE flags. If rules for more projects match the first one 
> >> > returned from DB is chosen.', max_length=64),
> >> > +        ),
> >> > +        migrations.AlterField(
> >> > +            model_name='project',
> >> > +            name='listid',
> >> > +            field=models.CharField(max_length=255),
> >> > +        ),
> >> > +        migrations.AlterUniqueTogether(
> >> > +            name='project',
> >> > +            unique_together=set([('listid', 'subject_match')]),
> >> > +        ),
> >> > +    ]
> >> > diff --git a/patchwork/models.py b/patchwork/models.py
> >> > index 11886f1..907707f 100644
> >> > --- a/patchwork/models.py
> >> > +++ b/patchwork/models.py
> >> > @@ -71,8 +71,14 @@ class Project(models.Model):
> >> >  
> >> >      linkname = models.CharField(max_length=255, unique=True)
> >> >      name = models.CharField(max_length=255, unique=True)
> >> > -    listid = models.CharField(max_length=255, unique=True)
> >> > +    listid = models.CharField(max_length=255)
> >> >      listemail = models.CharField(max_length=200)
> >> > +    subject_match = models.CharField(
> >> > +        max_length=64, blank=True, default='', help_text='Regex to 
> >> > match the '
> >> > +        'subject against if only part of emails sent to the list 
> >> > belongs to '
> >> > +        'this project. Will be used with IGNORECASE and MULTILINE 
> >> > flags. If '
> >> > +        'rules for more projects match the first one returned from DB 
> >> > is '
> >> > +        'chosen.')
> >> >  
> >> >      # url metadata
> >> >  
> >> > @@ -100,6 +106,7 @@ class Project(models.Model):
> >> >          return self.name
> >> >  
> >> >      class Meta:
> >> > +        unique_together = (('listid', 'subject_match'),)
> >> >          ordering = ['linkname']
> >> >  
> >> >  
> >> > diff --git a/patchwork/parser.py b/patchwork/parser.py
> >> > index ac7dc5f..015f709 100644
> >> > --- a/patchwork/parser.py
> >> > +++ b/patchwork/parser.py
> >> > @@ -157,9 +157,25 @@ def find_project_by_id(list_id):
> >> >          project = Project.objects.get(listid=list_id)
> >> >      except Project.DoesNotExist:
> >> >          logger.debug("'%s' if not a valid project list-id", list_id)
> >> > +    except Project.MultipleObjectsReturned:
> >> > +        logger.debug("Multiple projects with list-id '%s' found", 
> >> > list_id)
> >> >      return project
> >> >  
> >> >  
> >> > +def find_project_by_id_and_subject(list_id, subject):
> >> > +    """Find a `project` object based on `list_id` and subject prefix 
> >> > match."""
> >> > +    projects = Project.objects.filter(listid=list_id)
> >> > +    for project in projects:
> >> > +        if (not project.subject_match or
> >> > +                re.search(project.subject_match, subject,
> >> > +                          re.MULTILINE | re.IGNORECASE)):
> >> > +            return project
> >> > +
> >> > +    logger.debug("No project to match email with list-id '%s', subject 
> >> > '%s' "
> >> > +                 "found", list_id, subject)
> >> > +    return None
> >> > +
> >> > +
> >> >  def find_project_by_header(mail):
> >> >      project = None
> >> >      listid_res = [re.compile(r'.*<([^>]+)>.*', re.S),
> >> > @@ -181,7 +197,8 @@ def find_project_by_header(mail):
> >> >  
> >> >              listid = match.group(1)
> >> >  
> >> > -            project = find_project_by_id(listid)
> >> > +            project = find_project_by_id_and_subject(listid,
> >> > +                                                     
> >> > mail.get('Subject'))
> >> >              if project:
> >> >                  break
> >> >  
> >> > diff --git a/releasenotes/notes/list-filtering-4643d98b4064367a.yaml 
> >> > b/releasenotes/notes/list-filtering-4643d98b4064367a.yaml
> >> > new file mode 100644
> >> > index 0000000..21c1680
> >> > --- /dev/null
> >> > +++ b/releasenotes/notes/list-filtering-4643d98b4064367a.yaml
> >> > @@ -0,0 +1,10 @@
> >> > +---
> >> > +features:
> >> > +  - |
> >> > +    Allow list filtering into multiple projects (and email dropping) 
> >> > based on
> >> > +    subject prefixes. Disabled by default, enable by specifying a 
> >> > regular
> >> > +    expression which needs to be matched in the subject on a 
> >> > per-project basis
> >> > +    (field `subject_match`).
> >> > +api:
> >> > +  - |
> >> > +    Expose `subject_match` in REST API.
> >> > -- 
> >> > 2.13.6
> >> >
> >> > _______________________________________________
> >> > Patchwork mailing list
> >> > Patchwork@lists.ozlabs.org
> >> > https://lists.ozlabs.org/listinfo/patchwork
> >> _______________________________________________
> >> Patchwork mailing list
> >> Patchwork@lists.ozlabs.org
> >> https://lists.ozlabs.org/listinfo/patchwork
_______________________________________________
Patchwork mailing list
Patchwork@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/patchwork

Reply via email to