Commit 97e6922b authored by Damien Lespiau's avatar Damien Lespiau
Browse files

api: Add a revision parameter to series-new-revision events



It has been commented that assuming series-new-revision needs to have
the actual revision number to be non ambiguous.

Otherwise, if always fetching the latest series, there's a race possible
between someone polling for events and someone else sending a new
revision.
Suggested-by: default avatarGabriel Ciubotaru <gabriel.ciubotaru@intel.com>
Signed-off-by: default avatarDamien Lespiau <damien.lespiau@intel.com>
parent ba58d79c
......@@ -3,3 +3,4 @@ python-dateutil==1.5
djangorestframework>=2.4.8,<3.0.0
drf-nested-routers
enum34
jsonfield
......@@ -150,27 +150,38 @@ Events
"name": "series-new-revision",
"event_time": "2015-10-20T19:49:49.494",
"series": 23,
"user": null
"user": null,
"parameters": {
"revision": 2
}
},
{
"name": "series-new-revision",
"event_time": "2015-10-20T19:49:43.895",
"series": 22,
"user": null
"user": null,
"parameters": {
"revision": 1
}
}
]
}
At the moment, only one event is listed:
Each event type has some ``parameters`` specific to that event. At the moment,
only one event is possible:
- **series-new-revision**: This event corresponds to patchwork receiving a
full new revision of a series, should it be the initial submission of
subsequent updates. The difference can be made by looking at the version of
the series.
- **series-new-revision**: This event corresponds to patchwork receiving a new
revision of a series, should it be the initial submission or subsequent
updates. The difference can be made by looking at the version of the series.
This event only appears when patchwork has received the full set of mails
belonging to the same series, so the series object is guaranteed to contain
all patches.
belonging to the same series, so the revision object is guaranteed to
contain all patches.
**revision**: The version of the new revision that has been created.
``series`` and ``revision`` can be used to retrieve the corresponding
patches.
Series
------
......@@ -447,10 +458,14 @@ API Revisions
**Revision 2**
- Add mbox entry points for both patches and seriesL
- Add mbox entry points for both patches and series:
- /patches/${id}/mbox/
- /series/${id}/revisions/${version}/mbox/
- Add a ``parameters`` field to events and include the revision number to the
``series-new-revision`` event.
**Revision 1**
- Add /projects/${linkname}/events/ entry point.
......
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models, migrations
import jsonfield.fields
class Migration(migrations.Migration):
dependencies = [
('patchwork', '0005_event_eventlog'),
]
operations = [
migrations.AddField(
model_name='eventlog',
name='parameters',
field=jsonfield.fields.JSONField(null=True),
),
]
......@@ -27,6 +27,7 @@ from django.contrib.sites.models import Site
from django.conf import settings
from django.utils.functional import cached_property
from patchwork.parser import hash_patch, extract_tags
import jsonfield
import re
import datetime, time
......@@ -554,6 +555,7 @@ class EventLog(models.Model):
event_time = models.DateTimeField(auto_now=True)
series = models.ForeignKey(Series)
user = models.ForeignKey(User, null=True)
parameters = jsonfield.JSONField(null=True)
class Meta:
ordering = ['-event_time']
......@@ -642,7 +644,8 @@ models.signals.pre_save.connect(_patch_change_callback, sender = Patch)
def _on_revision_complete(sender, revision, **kwargs):
new_revision = Event.objects.get(name='series-new-revision')
log = EventLog(event=new_revision, series=revision.series,
user=revision.series.submitter.user)
user=revision.series.submitter.user,
parameters={'revision': revision.version})
log.save()
series_revision_complete.connect(_on_revision_complete)
......@@ -17,7 +17,10 @@
# along with Patchwork; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
import json
from django.contrib.auth.models import User
from django.core.exceptions import ValidationError
from patchwork.models import Project, Series, SeriesRevision, Patch, Person, \
State, EventLog
from rest_framework import serializers
......@@ -75,6 +78,17 @@ class PatchworkModelSerializer(serializers.ModelSerializer):
return super(PatchworkModelSerializer, self). \
get_related_field(model_field, related_model, to_many)
# See https://github.com/tomchristie/django-rest-framework/issues/1880
class JSONField(serializers.WritableField):
def to_native(self, obj):
return obj
def from_native(self, value):
if value is not None and not isinstance(value, dict):
raise ValidationError("This field must be a JSON object")
return value
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
......@@ -134,9 +148,10 @@ class RevisionSerializer(PatchworkModelSerializer):
class EventLogSerializer(PatchworkModelSerializer):
name = serializers.CharField(source='event.name', read_only=True)
parameters = JSONField(read_only=True)
class Meta:
model = EventLog
fields = ('name', 'event_time', 'series', 'user')
fields = ('name', 'event_time', 'series', 'user', 'parameters')
expand_serializers = {
'series': SeriesSerializer,
'user': UserSerializer,
......
......@@ -18,6 +18,7 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
from django.test import Client
from rest_framework.test import APIClient
import patchwork.tests.test_series as test_series
from patchwork.models import Series, Patch
......@@ -49,6 +50,7 @@ class APITest(test_series.Series0010):
def setUp(self):
super(APITest, self).setUp()
self.api = APIClient()
self.series = Series.objects.all()[0]
self.patch = Patch.objects.all()[2]
......@@ -67,15 +69,21 @@ class APITest(test_series.Series0010):
content_hash.update(content)
self.assertEqual(content_hash.hexdigest(), md5sum)
def testEntryPointPresence(self):
for entry_point in entry_points:
r = self.client.get('/api/1.0' + entry_point % {
def get(self, url):
return self.api.get('/api/1.0' + url % {
'project_id': self.project.pk,
'project_linkname': self.project.linkname,
'series_id': self.series.pk,
'revision_version': 1,
'patch_id': self.patch.pk,
})
})
def get_json(self, url):
return self.get(url).data
def testEntryPointPresence(self):
for entry_point in entry_points:
r = self.get(entry_point)
self.assertEqual(r.status_code, 200)
def testSeriesMbox(self):
......@@ -87,3 +95,9 @@ class APITest(test_series.Series0010):
self.check_mbox("/api/1.0/patches/%s/mbox/" % self.patch.pk,
'3-4-drm-i915-Introduce-a-for_each_crtc-macro.patch',
'b951af09618c6360516f16ed97a30753')
def testSeriesNewRevisionEvent(self):
events = self.get_json('/projects/%(project_id)s/events/')
self.assertEqual(events['count'], 1)
event = events['results'][0]
self.assertEqual(event['parameters']['revision'], 1)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment