diff --git a/package.json b/package.json index 0f3c93b2e57..21aa53ae565 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "react-tabs": "6.0.2", "reactstrap": "8.10.1", "redoc": "2.1.5", - "redux": "4.0.5", + "redux": "4.2.1", "redux-debounce": "1.0.1", "redux-mock-store": "1.5.5", "redux-thunk": "2.3.0", diff --git a/tests/webapp/api/test_performance_alertsummary_api.py b/tests/webapp/api/test_performance_alertsummary_api.py index 46c6e00fd24..1dd29dfebb3 100644 --- a/tests/webapp/api/test_performance_alertsummary_api.py +++ b/tests/webapp/api/test_performance_alertsummary_api.py @@ -88,6 +88,7 @@ def test_alert_summaries_get( "related_alerts", "repository", "push_id", + "original_revision", "status", "revision", "push_timestamp", @@ -167,6 +168,7 @@ def test_alert_summaries_get_onhold( "related_alerts", "repository", "push_id", + "original_revision", "status", "revision", "push_timestamp", @@ -238,6 +240,37 @@ def test_alert_summaries_put( assert PerformanceAlertSummary.objects.get(id=1).assignee == test_user +def test_performance_alert_summary_change_revision( + client, test_perf_alert_summary, test_sheriff, test_push +): + client.force_authenticate(user=test_sheriff) + + # verify we can set revision + assert PerformanceAlertSummary.objects.get(id=1).push.revision != test_push.revision + resp = client.put( + reverse("performance-alert-summaries-list") + "1/", + {"revision": test_push.revision}, + ) + assert resp.status_code == 200 + assert PerformanceAlertSummary.objects.get(id=1).push.revision == test_push.revision + + # verify we can set non-existing revision + resp = client.put( + reverse("performance-alert-summaries-list") + "1/", + {"revision": "no-push-revision"}, + ) + assert resp.status_code == 400 + + # revert revision + original_revision = PerformanceAlertSummary.objects.get(id=1).original_push.revision + resp = client.put( + reverse("performance-alert-summaries-list") + "1/", + {"revision": original_revision}, + ) + assert resp.status_code == 200 + assert PerformanceAlertSummary.objects.get(id=1).push.revision == original_revision + + def test_auth_for_alert_summary_post( client, test_repository, diff --git a/treeherder/webapp/api/performance_serializers.py b/treeherder/webapp/api/performance_serializers.py index 2b1a3b24c97..3b13036f0e0 100644 --- a/treeherder/webapp/api/performance_serializers.py +++ b/treeherder/webapp/api/performance_serializers.py @@ -17,6 +17,7 @@ PerformanceFramework, PerformanceSignature, PerformanceTag, + Push, ) from treeherder.webapp.api.utils import to_timestamp, FIVE_DAYS @@ -104,9 +105,11 @@ class PerformanceSignatureSerializer(serializers.ModelSerializer): option_collection_hash = serializers.SlugRelatedField( read_only=True, slug_field="option_collection_hash", source="option_collection" ) + machine_platform = serializers.SlugRelatedField( read_only=True, slug_field="platform", source="platform" ) + tags = WordsField(read_only=True, allow_blank=True) extra_options = WordsField(read_only=True, allow_blank=True) measurement_unit = serializers.CharField(read_only=True) @@ -272,7 +275,8 @@ class PerformanceAlertSummarySerializer(serializers.ModelSerializer): ) repository = serializers.SlugRelatedField(read_only=True, slug_field="name") framework = serializers.SlugRelatedField(read_only=True, slug_field="id") - revision = serializers.SlugRelatedField(read_only=True, slug_field="revision", source="push") + revision = serializers.SlugRelatedField(read_only=False, slug_field="revision", source="push", required=False, queryset=Push.objects.all()) + original_revision = serializers.SlugRelatedField(read_only=True, slug_field="revision", source="original_push") push_timestamp = TimestampField(source="push", read_only=True) prev_push_revision = serializers.SlugRelatedField( read_only=True, slug_field="revision", source="prev_push" @@ -308,6 +312,7 @@ class Meta: "id", "push_id", "prev_push_id", + "original_revision", "created", "first_triaged", "triage_due_date", diff --git a/yarn.lock b/yarn.lock index 7686dcd22d3..e5f8fa53fe6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1489,34 +1489,13 @@ resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== -"@babel/runtime@^7.1.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7": - version "7.16.3" - resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.3.tgz" - integrity sha512-WBwekcqacdY2e9AF/Q7WLFUWmdJGJTkbjqTjoMDgXkVZ3ZRUvOPsLb5KdwISoQVsbP+DQzVZW4Zhci0DvpbNTQ== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/runtime@^7.17.8": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.15.tgz#38f46494ccf6cf020bd4eed7124b425e83e523b8" - integrity sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA== - dependencies: - regenerator-runtime "^0.14.0" - -"@babel/runtime@^7.4.5": +"@babel/runtime@^7.1.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.17.8", "@babel/runtime@^7.4.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": version "7.24.7" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.7.tgz#f4f0d5530e8dbdf59b3451b9b3e594b6ba082e12" integrity sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw== dependencies: regenerator-runtime "^0.14.0" -"@babel/runtime@^7.9.2": - version "7.18.9" - resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.18.9.tgz" - integrity sha512-lkqXDcvlFT5rvEjiu6+QYO+1GXrEHRo2LOtS7E4GtX5ESIZOgepqsZBVIj6Pv+a6zqsya9VCgiK1KAK4BvJDAw== - dependencies: - regenerator-runtime "^0.13.4" - "@babel/template@^7.16.0", "@babel/template@^7.18.10", "@babel/template@^7.18.6", "@babel/template@^7.3.3": version "7.18.10" resolved "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz" @@ -10061,13 +10040,12 @@ redux-thunk@2.3.0: resolved "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.3.0.tgz" integrity sha512-km6dclyFnmcvxhAcrQV2AkZmPQjzPDjgVlQtR0EQjxZPyJ0BnMf3in1ryuR8A2qU0HldVRfxYXbFSKlI3N7Slw== -redux@4.0.5: - version "4.0.5" - resolved "https://registry.npmjs.org/redux/-/redux-4.0.5.tgz" - integrity sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w== +redux@4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/redux/-/redux-4.2.1.tgz#c08f4306826c49b5e9dc901dee0452ea8fce6197" + integrity sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w== dependencies: - loose-envify "^1.4.0" - symbol-observable "^1.2.0" + "@babel/runtime" "^7.9.2" reflect.ownkeys@^0.2.0: version "0.2.0" @@ -10096,11 +10074,6 @@ regenerator-runtime@^0.11.0: resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz" integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== -regenerator-runtime@^0.13.4: - version "0.13.9" - resolved "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz" - integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== - regenerator-runtime@^0.14.0: version "0.14.0" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz#5e19d68eb12d486f797e15a3c6a918f7cec5eb45" @@ -11066,11 +11039,6 @@ swagger2openapi@^7.0.8: yaml "^1.10.0" yargs "^17.0.1" -symbol-observable@^1.2.0: - version "1.2.0" - resolved "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz" - integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ== - symbol-tree@^3.2.4: version "3.2.4" resolved "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz"