From 2c142a43833e4463a305c9b5315b8e30d43c6dc6 Mon Sep 17 00:00:00 2001 From: Arkadiusz Hiler Date: Mon, 17 Feb 2020 14:29:55 +0200 Subject: [PATCH] series/revision: Add skip testing button Add a button that marks the latest revision of a series as "skip testing". Only the author of the series and maintainers of the project can perform this action. The `skip_testing` state is exposed through the JSON API: /api/1.0/series/{int}/revisions/{int}/ The attached CI/testing infrastructure is responsible for checking this flag. The UI shows which revisions were skipped and who has triggered it. Closes #27 Signed-off-by: Arkadiusz Hiler --- .../0033_seriesrevision_skip_testing.py | 18 +++++++ .../0034_seriesrevision_skip_requester.py | 21 +++++++++ patchwork/models.py | 7 +++ patchwork/permissions.py | 3 ++ patchwork/serializers.py | 3 +- patchwork/templates/patchwork/series.html | 47 +++++++++++++++++++ patchwork/views/api.py | 13 +++++ patchwork/views/series.py | 3 ++ 8 files changed, 114 insertions(+), 1 deletion(-) create mode 100644 patchwork/migrations/0033_seriesrevision_skip_testing.py create mode 100644 patchwork/migrations/0034_seriesrevision_skip_requester.py diff --git a/patchwork/migrations/0033_seriesrevision_skip_testing.py b/patchwork/migrations/0033_seriesrevision_skip_testing.py new file mode 100644 index 0000000..630e559 --- /dev/null +++ b/patchwork/migrations/0033_seriesrevision_skip_testing.py @@ -0,0 +1,18 @@ +# Generated by Django 2.2.10 on 2020-02-17 22:46 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('patchwork', '0032_seriesrevision_completed'), + ] + + operations = [ + migrations.AddField( + model_name='seriesrevision', + name='skip_testing', + field=models.BooleanField(default=False), + ), + ] diff --git a/patchwork/migrations/0034_seriesrevision_skip_requester.py b/patchwork/migrations/0034_seriesrevision_skip_requester.py new file mode 100644 index 0000000..a5c6ccb --- /dev/null +++ b/patchwork/migrations/0034_seriesrevision_skip_requester.py @@ -0,0 +1,21 @@ +# Generated by Django 2.2.10 on 2020-02-17 23:09 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('patchwork', '0033_seriesrevision_skip_testing'), + ] + + operations = [ + migrations.AddField( + model_name='seriesrevision', + name='skip_requester', + field=models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/patchwork/models.py b/patchwork/models.py index c5fd88b..3f67073 100644 --- a/patchwork/models.py +++ b/patchwork/models.py @@ -631,6 +631,11 @@ class SeriesRevision(models.Model): state_summary = jsonfield.JSONField(null=True) test_state = models.SmallIntegerField(choices=TestState.STATE_CHOICES, null=True, blank=True) + + skip_testing = models.BooleanField(default=False) + skip_requester = models.ForeignKey(User, null=True, default=None, + on_delete=models.SET_NULL) + is_rerun = models.BooleanField(default=False) completed = models.DateTimeField(null=True, default=None) @@ -693,6 +698,8 @@ class SeriesRevision(models.Model): new.raw_cover_letter_headers = self.raw_cover_letter_headers new.version = self.version + 1 new.test_state = None + new.skip_testing = False + new.skip_requester = None new.save() return new diff --git a/patchwork/permissions.py b/patchwork/permissions.py index 18f3c32..1c8de2b 100644 --- a/patchwork/permissions.py +++ b/patchwork/permissions.py @@ -50,3 +50,6 @@ class Can: series.submitter.user == self.user) return False + + def skip_testing(self, obj): + return self.retest(obj) diff --git a/patchwork/serializers.py b/patchwork/serializers.py index eef8396..96bbb54 100644 --- a/patchwork/serializers.py +++ b/patchwork/serializers.py @@ -191,7 +191,8 @@ class RevisionSerializer(PatchworkModelSerializer): class Meta: model = SeriesRevision - fields = ('version', 'cover_letter', 'raw_cover_letter', 'patches') + fields = ('version', 'cover_letter', 'raw_cover_letter', 'patches', + 'skip_testing') read_only_fields = ('version', 'cover_letter') expand_serializers = { 'patches': PatchSerializer, diff --git a/patchwork/templates/patchwork/series.html b/patchwork/templates/patchwork/series.html index a1291e6..86bcfa9 100644 --- a/patchwork/templates/patchwork/series.html +++ b/patchwork/templates/patchwork/series.html @@ -60,6 +60,37 @@ $(document).ready(function() { pw.post_data(url, undefined, on_post_success, on_post_failure); }); + + $("#skip-latest").click(function(e) { + e.preventDefault(); + var button = $(this); + + button.prop('disabled', true); + + button.removeClass("btn-info"); + button.addClass("btn-warning"); + button.text("requesting retest"); + + var on_post_success = function() { + button.removeClass("btn-warning"); + button.addClass("btn-success"); + button.text("revision skipped"); + }; + + var on_post_failure = function() { + button.removeClass("btn-warning"); + button.addClass("btn-failure"); + button.text("failed!"); + }; + + var series = button.data('series'); + var revision = button.data('revision'); + var url = '/series/' + series + '/revisions/' + revision + '/skiptesting/'; + + pw.post_data(url, undefined, on_post_success, on_post_failure); + }); + + {% else %} var retest_container = $("#retest-latest-container"); retest_container.fadeTo(0, 0.2); // immediate "transition" @@ -135,6 +166,16 @@ $(document).ready(function() { data-series="{{ series.id }}" data-revision="{{ series.last_revision.version }}"> test revision {{ series.last_revision.version }} again + {% if series.last_revision.skip_testing %} + + {% else %} + + {% endif %} {% else %}