From: DJ Delorie <d...@delorie.com> This patch stitches in "comment created" events for patches and cover letter into the event queue.
Signed-off-by: DJ Delorie <d...@redhat.com> Signed-off-by: Stephen Finucane <step...@that.guru> Closes: #424 [stephenfin: Extend to cover letters also. Fix some formatting issues. Add a release note] --- docs/api/schemas/latest/patchwork.yaml | 71 +++++++++++++++ docs/api/schemas/patchwork.j2 | 77 +++++++++++++++++ docs/api/schemas/v1.0/patchwork.yaml | 59 +++++++++++++ docs/api/schemas/v1.1/patchwork.yaml | 64 ++++++++++++++ docs/api/schemas/v1.2/patchwork.yaml | 69 +++++++++++++++ docs/api/schemas/v1.3/patchwork.yaml | 71 +++++++++++++++ patchwork/api/embedded.py | 36 ++++++++ patchwork/api/event.py | 86 +++++++++++++++---- .../migrations/0046_patch_comment_events.py | 56 ++++++++++++ patchwork/models.py | 16 ++++ patchwork/signals.py | 30 +++++++ patchwork/tests/test_signals.py | 36 +++++++- .../comment-events-2bc9b754cad1fb32.yaml | 6 ++ 13 files changed, 657 insertions(+), 20 deletions(-) create mode 100644 patchwork/migrations/0046_patch_comment_events.py create mode 100644 releasenotes/notes/comment-events-2bc9b754cad1fb32.yaml diff --git docs/api/schemas/latest/patchwork.yaml docs/api/schemas/latest/patchwork.yaml index 43edfb04..06be99d3 100644 --- docs/api/schemas/latest/patchwork.yaml +++ docs/api/schemas/latest/patchwork.yaml @@ -420,6 +420,8 @@ paths: - check-created - series-created - series-completed + - cover-comment-created + - patch-comment-created - in: query name: series description: An ID of a series to filter events by. @@ -459,6 +461,8 @@ paths: - $ref: '#/components/schemas/EventCheckCreated' - $ref: '#/components/schemas/EventSeriesCreated' - $ref: '#/components/schemas/EventSeriesCompleted' + - $ref: '#/components/schemas/EventCoverCommentCreated' + - $ref: '#/components/schemas/EventPatchCommentCreated' discriminator: propertyName: category mapping: @@ -471,6 +475,8 @@ paths: check-created: '#/components/schemas/EventCheckCreated' series-created: '#/components/schemas/EventSeriesCreated' series-completed: '#/components/schemas/EventSeriesCompleted' + cover-comment-created: '#/components/schemas/EventCoverCommentCreated' + patch-comment-created: '#/components/schemas/EventPatchCommentCreated' tags: - events /api/patches/: @@ -1919,6 +1925,34 @@ components: properties: series: $ref: '#/components/schemas/SeriesEmbedded' + EventCoverCommentCreated: + allOf: + - $ref: '#/components/schemas/EventBase' + - type: object + properties: + category: + enum: + - cover-comment-created + payload: + properties: + cover: + $ref: '#/components/schemas/CoverEmbedded' + comment: + $ref: '#/components/schemas/CommentEmbedded' + EventPatchCommentCreated: + allOf: + - $ref: '#/components/schemas/EventBase' + - type: object + properties: + category: + enum: + - patch-comment-created + payload: + properties: + patch: + $ref: '#/components/schemas/PatchEmbedded' + comment: + $ref: '#/components/schemas/CommentEmbedded' PatchList: required: - state @@ -2394,6 +2428,43 @@ components: maxLength: 255 minLength: 1 readOnly: true + CommentEmbedded: + type: object + properties: + id: + title: ID + type: integer + readOnly: true + url: + title: URL + type: string + format: uri + readOnly: true + web_url: + title: Web URL + type: string + format: uri + readOnly: true + msgid: + title: Message ID + type: string + readOnly: true + minLength: 1 + list_archive_url: + title: List archive URL + type: string + readOnly: true + nullable: true + date: + title: Date + type: string + format: iso8601 + readOnly: true + name: + title: Name + type: string + readOnly: true + minLength: 1 CoverEmbedded: type: object properties: diff --git docs/api/schemas/patchwork.j2 docs/api/schemas/patchwork.j2 index df72c1ac..f8c6d214 100644 --- docs/api/schemas/patchwork.j2 +++ docs/api/schemas/patchwork.j2 @@ -431,6 +431,10 @@ paths: - check-created - series-created - series-completed +{% if version >= (1, 3) %} + - cover-comment-created + - patch-comment-created +{% endif %} - in: query name: series description: An ID of a series to filter events by. @@ -470,6 +474,8 @@ paths: - $ref: '#/components/schemas/EventCheckCreated' - $ref: '#/components/schemas/EventSeriesCreated' - $ref: '#/components/schemas/EventSeriesCompleted' + - $ref: '#/components/schemas/EventCoverCommentCreated' + - $ref: '#/components/schemas/EventPatchCommentCreated' discriminator: propertyName: category mapping: @@ -482,6 +488,8 @@ paths: check-created: '#/components/schemas/EventCheckCreated' series-created: '#/components/schemas/EventSeriesCreated' series-completed: '#/components/schemas/EventSeriesCompleted' + cover-comment-created: '#/components/schemas/EventCoverCommentCreated' + patch-comment-created: '#/components/schemas/EventPatchCommentCreated' tags: - events /api/{{ version_url }}patches/: @@ -1989,6 +1997,34 @@ components: properties: series: $ref: '#/components/schemas/SeriesEmbedded' + EventCoverCommentCreated: + allOf: + - $ref: '#/components/schemas/EventBase' + - type: object + properties: + category: + enum: + - cover-comment-created + payload: + properties: + cover: + $ref: '#/components/schemas/CoverEmbedded' + comment: + $ref: '#/components/schemas/CommentEmbedded' + EventPatchCommentCreated: + allOf: + - $ref: '#/components/schemas/EventBase' + - type: object + properties: + category: + enum: + - patch-comment-created + payload: + properties: + patch: + $ref: '#/components/schemas/PatchEmbedded' + comment: + $ref: '#/components/schemas/CommentEmbedded' PatchList: required: - state @@ -2482,6 +2518,47 @@ components: maxLength: 255 minLength: 1 readOnly: true + CommentEmbedded: + type: object + properties: + id: + title: ID + type: integer + readOnly: true + url: + title: URL + type: string + format: uri + readOnly: true +{% if version >= (1, 1) %} + web_url: + title: Web URL + type: string + format: uri + readOnly: true +{% endif %} + msgid: + title: Message ID + type: string + readOnly: true + minLength: 1 +{% if version >= (1, 2) %} + list_archive_url: + title: List archive URL + type: string + readOnly: true + nullable: true +{% endif %} + date: + title: Date + type: string + format: iso8601 + readOnly: true + name: + title: Name + type: string + readOnly: true + minLength: 1 CoverEmbedded: type: object properties: diff --git docs/api/schemas/v1.0/patchwork.yaml docs/api/schemas/v1.0/patchwork.yaml index e2f1362f..53571b60 100644 --- docs/api/schemas/v1.0/patchwork.yaml +++ docs/api/schemas/v1.0/patchwork.yaml @@ -285,6 +285,8 @@ paths: - $ref: '#/components/schemas/EventCheckCreated' - $ref: '#/components/schemas/EventSeriesCreated' - $ref: '#/components/schemas/EventSeriesCompleted' + - $ref: '#/components/schemas/EventCoverCommentCreated' + - $ref: '#/components/schemas/EventPatchCommentCreated' discriminator: propertyName: category mapping: @@ -297,6 +299,8 @@ paths: check-created: '#/components/schemas/EventCheckCreated' series-created: '#/components/schemas/EventSeriesCreated' series-completed: '#/components/schemas/EventSeriesCompleted' + cover-comment-created: '#/components/schemas/EventCoverCommentCreated' + patch-comment-created: '#/components/schemas/EventPatchCommentCreated' tags: - events /api/1.0/patches/: @@ -1562,6 +1566,34 @@ components: properties: series: $ref: '#/components/schemas/SeriesEmbedded' + EventCoverCommentCreated: + allOf: + - $ref: '#/components/schemas/EventBase' + - type: object + properties: + category: + enum: + - cover-comment-created + payload: + properties: + cover: + $ref: '#/components/schemas/CoverEmbedded' + comment: + $ref: '#/components/schemas/CommentEmbedded' + EventPatchCommentCreated: + allOf: + - $ref: '#/components/schemas/EventBase' + - type: object + properties: + category: + enum: + - patch-comment-created + payload: + properties: + patch: + $ref: '#/components/schemas/PatchEmbedded' + comment: + $ref: '#/components/schemas/CommentEmbedded' PatchList: required: - state @@ -1951,6 +1983,33 @@ components: maxLength: 255 minLength: 1 readOnly: true + CommentEmbedded: + type: object + properties: + id: + title: ID + type: integer + readOnly: true + url: + title: URL + type: string + format: uri + readOnly: true + msgid: + title: Message ID + type: string + readOnly: true + minLength: 1 + date: + title: Date + type: string + format: iso8601 + readOnly: true + name: + title: Name + type: string + readOnly: true + minLength: 1 CoverEmbedded: type: object properties: diff --git docs/api/schemas/v1.1/patchwork.yaml docs/api/schemas/v1.1/patchwork.yaml index cdf8ef29..f83b5e01 100644 --- docs/api/schemas/v1.1/patchwork.yaml +++ docs/api/schemas/v1.1/patchwork.yaml @@ -285,6 +285,8 @@ paths: - $ref: '#/components/schemas/EventCheckCreated' - $ref: '#/components/schemas/EventSeriesCreated' - $ref: '#/components/schemas/EventSeriesCompleted' + - $ref: '#/components/schemas/EventCoverCommentCreated' + - $ref: '#/components/schemas/EventPatchCommentCreated' discriminator: propertyName: category mapping: @@ -297,6 +299,8 @@ paths: check-created: '#/components/schemas/EventCheckCreated' series-created: '#/components/schemas/EventSeriesCreated' series-completed: '#/components/schemas/EventSeriesCompleted' + cover-comment-created: '#/components/schemas/EventCoverCommentCreated' + patch-comment-created: '#/components/schemas/EventPatchCommentCreated' tags: - events /api/1.1/patches/: @@ -1587,6 +1591,34 @@ components: properties: series: $ref: '#/components/schemas/SeriesEmbedded' + EventCoverCommentCreated: + allOf: + - $ref: '#/components/schemas/EventBase' + - type: object + properties: + category: + enum: + - cover-comment-created + payload: + properties: + cover: + $ref: '#/components/schemas/CoverEmbedded' + comment: + $ref: '#/components/schemas/CommentEmbedded' + EventPatchCommentCreated: + allOf: + - $ref: '#/components/schemas/EventBase' + - type: object + properties: + category: + enum: + - patch-comment-created + payload: + properties: + patch: + $ref: '#/components/schemas/PatchEmbedded' + comment: + $ref: '#/components/schemas/CommentEmbedded' PatchList: required: - state @@ -2002,6 +2034,38 @@ components: maxLength: 255 minLength: 1 readOnly: true + CommentEmbedded: + type: object + properties: + id: + title: ID + type: integer + readOnly: true + url: + title: URL + type: string + format: uri + readOnly: true + web_url: + title: Web URL + type: string + format: uri + readOnly: true + msgid: + title: Message ID + type: string + readOnly: true + minLength: 1 + date: + title: Date + type: string + format: iso8601 + readOnly: true + name: + title: Name + type: string + readOnly: true + minLength: 1 CoverEmbedded: type: object properties: diff --git docs/api/schemas/v1.2/patchwork.yaml docs/api/schemas/v1.2/patchwork.yaml index 2a37d81b..e8cee0e5 100644 --- docs/api/schemas/v1.2/patchwork.yaml +++ docs/api/schemas/v1.2/patchwork.yaml @@ -393,6 +393,8 @@ paths: - $ref: '#/components/schemas/EventCheckCreated' - $ref: '#/components/schemas/EventSeriesCreated' - $ref: '#/components/schemas/EventSeriesCompleted' + - $ref: '#/components/schemas/EventCoverCommentCreated' + - $ref: '#/components/schemas/EventPatchCommentCreated' discriminator: propertyName: category mapping: @@ -405,6 +407,8 @@ paths: check-created: '#/components/schemas/EventCheckCreated' series-created: '#/components/schemas/EventSeriesCreated' series-completed: '#/components/schemas/EventSeriesCompleted' + cover-comment-created: '#/components/schemas/EventCoverCommentCreated' + patch-comment-created: '#/components/schemas/EventPatchCommentCreated' tags: - events /api/1.2/patches/: @@ -1770,6 +1774,34 @@ components: properties: series: $ref: '#/components/schemas/SeriesEmbedded' + EventCoverCommentCreated: + allOf: + - $ref: '#/components/schemas/EventBase' + - type: object + properties: + category: + enum: + - cover-comment-created + payload: + properties: + cover: + $ref: '#/components/schemas/CoverEmbedded' + comment: + $ref: '#/components/schemas/CommentEmbedded' + EventPatchCommentCreated: + allOf: + - $ref: '#/components/schemas/EventBase' + - type: object + properties: + category: + enum: + - patch-comment-created + payload: + properties: + patch: + $ref: '#/components/schemas/PatchEmbedded' + comment: + $ref: '#/components/schemas/CommentEmbedded' PatchList: required: - state @@ -2245,6 +2277,43 @@ components: maxLength: 255 minLength: 1 readOnly: true + CommentEmbedded: + type: object + properties: + id: + title: ID + type: integer + readOnly: true + url: + title: URL + type: string + format: uri + readOnly: true + web_url: + title: Web URL + type: string + format: uri + readOnly: true + msgid: + title: Message ID + type: string + readOnly: true + minLength: 1 + list_archive_url: + title: List archive URL + type: string + readOnly: true + nullable: true + date: + title: Date + type: string + format: iso8601 + readOnly: true + name: + title: Name + type: string + readOnly: true + minLength: 1 CoverEmbedded: type: object properties: diff --git docs/api/schemas/v1.3/patchwork.yaml docs/api/schemas/v1.3/patchwork.yaml index 88c4e355..8b3b1154 100644 --- docs/api/schemas/v1.3/patchwork.yaml +++ docs/api/schemas/v1.3/patchwork.yaml @@ -420,6 +420,8 @@ paths: - check-created - series-created - series-completed + - cover-comment-created + - patch-comment-created - in: query name: series description: An ID of a series to filter events by. @@ -459,6 +461,8 @@ paths: - $ref: '#/components/schemas/EventCheckCreated' - $ref: '#/components/schemas/EventSeriesCreated' - $ref: '#/components/schemas/EventSeriesCompleted' + - $ref: '#/components/schemas/EventCoverCommentCreated' + - $ref: '#/components/schemas/EventPatchCommentCreated' discriminator: propertyName: category mapping: @@ -471,6 +475,8 @@ paths: check-created: '#/components/schemas/EventCheckCreated' series-created: '#/components/schemas/EventSeriesCreated' series-completed: '#/components/schemas/EventSeriesCompleted' + cover-comment-created: '#/components/schemas/EventCoverCommentCreated' + patch-comment-created: '#/components/schemas/EventPatchCommentCreated' tags: - events /api/1.3/patches/: @@ -1919,6 +1925,34 @@ components: properties: series: $ref: '#/components/schemas/SeriesEmbedded' + EventCoverCommentCreated: + allOf: + - $ref: '#/components/schemas/EventBase' + - type: object + properties: + category: + enum: + - cover-comment-created + payload: + properties: + cover: + $ref: '#/components/schemas/CoverEmbedded' + comment: + $ref: '#/components/schemas/CommentEmbedded' + EventPatchCommentCreated: + allOf: + - $ref: '#/components/schemas/EventBase' + - type: object + properties: + category: + enum: + - patch-comment-created + payload: + properties: + patch: + $ref: '#/components/schemas/PatchEmbedded' + comment: + $ref: '#/components/schemas/CommentEmbedded' PatchList: required: - state @@ -2394,6 +2428,43 @@ components: maxLength: 255 minLength: 1 readOnly: true + CommentEmbedded: + type: object + properties: + id: + title: ID + type: integer + readOnly: true + url: + title: URL + type: string + format: uri + readOnly: true + web_url: + title: Web URL + type: string + format: uri + readOnly: true + msgid: + title: Message ID + type: string + readOnly: true + minLength: 1 + list_archive_url: + title: List archive URL + type: string + readOnly: true + nullable: true + date: + title: Date + type: string + format: iso8601 + readOnly: true + name: + title: Name + type: string + readOnly: true + minLength: 1 CoverEmbedded: type: object properties: diff --git patchwork/api/embedded.py patchwork/api/embedded.py index 78316979..4ba80f4a 100644 --- patchwork/api/embedded.py +++ patchwork/api/embedded.py @@ -120,6 +120,24 @@ class CoverSerializer(SerializedRelatedField): } +class CoverCommentSerializer(SerializedRelatedField): + + class _Serializer(MboxMixin, WebURLMixin, BaseHyperlinkedModelSerializer): + + class Meta: + model = models.CoverComment + fields = ('id', 'url', 'web_url', 'msgid', 'list_archive_url', + 'date', 'name') + read_only_fields = fields + versioned_fields = { + '1.1': ('web_url', 'mbox', ), + '1.2': ('list_archive_url',), + } + extra_kwargs = { + 'url': {'view_name': 'api-cover-comment-detail'}, + } + + class PatchSerializer(SerializedRelatedField): class _Serializer(MboxMixin, WebURLMixin, BaseHyperlinkedModelSerializer): @@ -138,6 +156,24 @@ class PatchSerializer(SerializedRelatedField): } +class PatchCommentSerializer(SerializedRelatedField): + + class _Serializer(MboxMixin, WebURLMixin, BaseHyperlinkedModelSerializer): + + class Meta: + model = models.PatchComment + fields = ('id', 'url', 'web_url', 'msgid', 'list_archive_url', + 'date', 'name') + read_only_fields = fields + versioned_fields = { + '1.1': ('web_url', 'mbox', ), + '1.2': ('list_archive_url',), + } + extra_kwargs = { + 'url': {'view_name': 'api-patch-comment-detail'}, + } + + class PersonSerializer(SerializedRelatedField): class _Serializer(BaseHyperlinkedModelSerializer): diff --git patchwork/api/event.py patchwork/api/event.py index 71f95937..c1b09ab9 100644 --- patchwork/api/event.py +++ patchwork/api/event.py @@ -12,7 +12,9 @@ from rest_framework.serializers import SlugRelatedField from patchwork.api.embedded import CheckSerializer from patchwork.api.embedded import CoverSerializer +from patchwork.api.embedded import CoverCommentSerializer from patchwork.api.embedded import PatchSerializer +from patchwork.api.embedded import PatchCommentSerializer from patchwork.api.embedded import ProjectSerializer from patchwork.api.embedded import SeriesSerializer from patchwork.api.embedded import UserSerializer @@ -35,20 +37,41 @@ class EventSerializer(ModelSerializer): created_check = CheckSerializer() previous_relation = SerializerMethodField() current_relation = SerializerMethodField() + cover_comment = CoverCommentSerializer() + patch_comment = PatchCommentSerializer() + # Mapping of event type to fields to include in the response _category_map = { Event.CATEGORY_COVER_CREATED: ['cover'], Event.CATEGORY_PATCH_CREATED: ['patch'], Event.CATEGORY_PATCH_COMPLETED: ['patch', 'series'], - Event.CATEGORY_PATCH_STATE_CHANGED: ['patch', 'previous_state', - 'current_state'], - Event.CATEGORY_PATCH_DELEGATED: ['patch', 'previous_delegate', - 'current_delegate'], - Event.CATEGORY_PATCH_RELATION_CHANGED: ['patch', 'previous_relation', - 'current_relation'], + Event.CATEGORY_PATCH_STATE_CHANGED: [ + 'patch', + 'previous_state', + 'current_state', + ], + Event.CATEGORY_PATCH_DELEGATED: [ + 'patch', + 'previous_delegate', + 'current_delegate', + ], + Event.CATEGORY_PATCH_RELATION_CHANGED: [ + 'patch', + 'previous_relation', + 'current_relation', + ], Event.CATEGORY_CHECK_CREATED: ['patch', 'created_check'], Event.CATEGORY_SERIES_CREATED: ['series'], Event.CATEGORY_SERIES_COMPLETED: ['series'], + Event.CATEGORY_COVER_COMMENT_CREATED: ['cover', 'cover_comment'], + Event.CATEGORY_PATCH_COMMENT_CREATED: ['patch', 'patch_comment'], + } + + # Mapping of database column names to REST API representations + _field_name_map = { + 'created_check': 'check', + 'cover_comment': 'comment', + 'patch_comment': 'comment', } def get_previous_relation(self, instance): @@ -61,13 +84,19 @@ class EventSerializer(ModelSerializer): data = super(EventSerializer, self).to_representation(instance) payload = OrderedDict() kept_fields = self._category_map[instance.category] + [ - 'id', 'category', 'project', 'date', 'actor'] + 'id', + 'category', + 'project', + 'date', + 'actor', + ] for field in [x for x in data]: if field not in kept_fields: del data[field] elif field in self._category_map[instance.category]: - field_name = 'check' if field == 'created_check' else field + # remap fields if necessary + field_name = self._field_name_map.get(field, field) payload[field_name] = data.pop(field) data['payload'] = payload @@ -77,14 +106,27 @@ class EventSerializer(ModelSerializer): class Meta: model = Event fields = ( - 'id', 'category', 'project', 'date', 'actor', 'patch', - 'series', 'cover', 'previous_state', 'current_state', - 'previous_delegate', 'current_delegate', 'created_check', - 'previous_relation', 'current_relation', + 'id', + 'category', + 'project', + 'date', + 'actor', + 'patch', + 'series', + 'cover', + 'previous_state', + 'current_state', + 'previous_delegate', + 'current_delegate', + 'created_check', + 'previous_relation', + 'current_relation', + 'cover_comment', + 'patch_comment', ) read_only_fields = fields versioned_fields = { - '1.2': ('actor', ), + '1.2': ('actor',), } @@ -98,8 +140,16 @@ class EventList(ListAPIView): ordering = '-date' def get_queryset(self): - return Event.objects.all()\ - .prefetch_related('project', 'patch__project', 'series__project', - 'cover', 'previous_state', 'current_state', - 'previous_delegate', 'current_delegate', - 'created_check') + return Event.objects.all().prefetch_related( + 'project', + 'patch__project', + 'series__project', + 'cover', + 'previous_state', + 'current_state', + 'previous_delegate', + 'current_delegate', + 'created_check', + 'cover_comment', + 'patch_comment', + ) diff --git patchwork/migrations/0046_patch_comment_events.py patchwork/migrations/0046_patch_comment_events.py new file mode 100644 index 00000000..db198bd4 --- /dev/null +++ patchwork/migrations/0046_patch_comment_events.py @@ -0,0 +1,56 @@ +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('patchwork', '0045_addressed_fields'), + ] + + operations = [ + migrations.AddField( + model_name='event', + name='cover_comment', + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='+', + to='patchwork.covercomment', + ), + ), + migrations.AddField( + model_name='event', + name='patch_comment', + field=models.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name='+', + to='patchwork.patchcomment', + ), + ), + migrations.AlterField( + model_name='event', + name='category', + field=models.CharField( + choices=[ + ('cover-created', 'Cover Letter Created'), + ('patch-created', 'Patch Created'), + ('patch-completed', 'Patch Completed'), + ('patch-state-changed', 'Patch State Changed'), + ('patch-delegated', 'Patch Delegate Changed'), + ('patch-relation-changed', 'Patch Relation Changed'), + ('check-created', 'Check Created'), + ('series-created', 'Series Created'), + ('series-completed', 'Series Completed'), + ('cover-comment-created', 'Cover Comment Created'), + ('patch-comment-created', 'Patch Comment Created'), + ], + db_index=True, + help_text='The category of the event.', + max_length=25, + ), + ), + ] diff --git patchwork/models.py patchwork/models.py index 6304b34d..e4a910ed 100644 --- patchwork/models.py +++ patchwork/models.py @@ -1028,6 +1028,8 @@ class Event(models.Model): CATEGORY_CHECK_CREATED = 'check-created' CATEGORY_SERIES_CREATED = 'series-created' CATEGORY_SERIES_COMPLETED = 'series-completed' + CATEGORY_COVER_COMMENT_CREATED = 'cover-comment-created' + CATEGORY_PATCH_COMMENT_CREATED = 'patch-comment-created' CATEGORY_CHOICES = ( (CATEGORY_COVER_CREATED, 'Cover Letter Created'), (CATEGORY_PATCH_CREATED, 'Patch Created'), @@ -1038,6 +1040,8 @@ class Event(models.Model): (CATEGORY_CHECK_CREATED, 'Check Created'), (CATEGORY_SERIES_CREATED, 'Series Created'), (CATEGORY_SERIES_COMPLETED, 'Series Completed'), + (CATEGORY_COVER_COMMENT_CREATED, 'Cover Comment Created'), + (CATEGORY_PATCH_COMMENT_CREATED, 'Patch Comment Created'), ) # parents @@ -1113,6 +1117,18 @@ class Event(models.Model): Check, related_name='+', null=True, blank=True, on_delete=models.CASCADE) + # fields for 'cover-comment-created' events + + cover_comment = models.ForeignKey( + CoverComment, related_name='+', null=True, blank=True, + on_delete=models.CASCADE) + + # fields for 'patch-comment-created' events + + patch_comment = models.ForeignKey( + PatchComment, related_name='+', null=True, blank=True, + on_delete=models.CASCADE) + # TODO(stephenfin): Validate that the correct fields are being set by way # of a 'clean' method diff --git patchwork/signals.py patchwork/signals.py index dc08129c..d1aac8cf 100644 --- patchwork/signals.py +++ patchwork/signals.py @@ -11,9 +11,11 @@ from django.dispatch import receiver from patchwork.models import Check from patchwork.models import Cover +from patchwork.models import CoverComment from patchwork.models import Event from patchwork.models import Patch from patchwork.models import PatchChangeNotification +from patchwork.models import PatchComment from patchwork.models import Series @@ -267,3 +269,31 @@ def create_series_completed_event(sender, instance, raw, **kwargs): # the instance yet so we duplicate that logic here but with an offset if (instance.series.received_total + 1) >= instance.series.total: create_event(instance.series) + + +@receiver(post_save, sender=CoverComment) +def create_cover_comment_created_event(sender, instance, raw, **kwargs): + + def create_event(comment): + return Event.objects.create( + category=Event.CATEGORY_COVER_COMMENT_CREATED, + project=comment.cover.project, + cover=comment.cover, + cover_comment=comment, + ) + + create_event(instance) + + +@receiver(post_save, sender=PatchComment) +def create_patch_comment_created_event(sender, instance, raw, **kwargs): + + def create_event(comment): + return Event.objects.create( + category=Event.CATEGORY_PATCH_COMMENT_CREATED, + project=comment.patch.project, + patch=comment.patch, + patch_comment=comment, + ) + + create_event(instance) diff --git patchwork/tests/test_signals.py patchwork/tests/test_signals.py index 090b6dc0..5d5d8e3b 100644 --- patchwork/tests/test_signals.py +++ patchwork/tests/test_signals.py @@ -8,8 +8,12 @@ from django.test import TestCase from patchwork.models import Event from patchwork.tests import utils -BASE_FIELDS = ['previous_state', 'current_state', 'previous_delegate', - 'current_delegate'] +BASE_FIELDS = [ + 'previous_state', + 'current_state', + 'previous_delegate', + 'current_delegate', +] def _get_events(**filters): @@ -277,3 +281,31 @@ class SeriesChangedTest(_BaseTestCase): events = _get_events(series=series) self.assertIn(Event.CATEGORY_SERIES_COMPLETED, [x.category for x in events]) + + +class CoverCommentCreatedTest(_BaseTestCase): + + def test_cover_comment_created(self): + """Validate 'cover-comment-created' events.""" + comment = utils.create_cover_comment() + events = _get_events(cover_comment=comment) + self.assertEqual(events.count(), 1) + self.assertEqual( + events[0].category, Event.CATEGORY_COVER_COMMENT_CREATED, + ) + self.assertEqual(events[0].project, comment.cover.project) + self.assertEventFields(events[0]) + + +class PatchCommentCreatedTest(_BaseTestCase): + + def test_patch_comment_created(self): + """Validate 'patch-comment-created' events.""" + comment = utils.create_patch_comment() + events = _get_events(patch_comment=comment) + self.assertEqual(events.count(), 1) + self.assertEqual( + events[0].category, Event.CATEGORY_PATCH_COMMENT_CREATED, + ) + self.assertEqual(events[0].project, comment.patch.project) + self.assertEventFields(events[0]) diff --git releasenotes/notes/comment-events-2bc9b754cad1fb32.yaml releasenotes/notes/comment-events-2bc9b754cad1fb32.yaml new file mode 100644 index 00000000..a0895d44 --- /dev/null +++ releasenotes/notes/comment-events-2bc9b754cad1fb32.yaml @@ -0,0 +1,6 @@ +--- +features: + - | + Two new event types have been added: ``cover-comment-created`` and + ``patch-comment-created``. As their names would suggest, these track the + creation of new cover letter and patch comments respectively. -- 2.35.1 _______________________________________________ Patchwork mailing list Patchwork@lists.ozlabs.org https://lists.ozlabs.org/listinfo/patchwork