From 509ea078f2866d880676b724b6ce55ad73c35376 Mon Sep 17 00:00:00 2001 From: "sentry-junior[bot]" <264270552+sentry-junior[bot]@users.noreply.github.com> Date: Sat, 7 Nov 2026 01:12:09 +0000 Subject: [PATCH] docs(issues): Mark issue update body fields as optional The single and bulk issue update endpoints always run GroupValidator with partial=True, so a request only has to send the fields it changes. The validators still declared every field as required, so the OpenAPI schema listed all of them, and every statusDetails field, as required in the request body. Generated clients such as @sentry/api then type every field as required, so a body that only sets status or assignedTo fails to typecheck. Mark the fields required=False so the docs match what the endpoints accept. Validation is unchanged because partial=True already skipped the required check. Refs getsentry/toolkit#2073 Co-Authored-By: BYK <126780+BYK@users.noreply.github.com> --- .../helpers/group_index/validators/group.py | 32 +++++++++++++------ .../group_index/validators/status_details.py | 11 +++++-- 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/src/sentry/api/helpers/group_index/validators/group.py b/src/sentry/api/helpers/group_index/validators/group.py index d1a5a92aaa1c..556a678adede 100644 --- a/src/sentry/api/helpers/group_index/validators/group.py +++ b/src/sentry/api/helpers/group_index/validators/group.py @@ -13,38 +13,45 @@ class GroupValidator(serializers.Serializer[Group]): inbox = serializers.BooleanField( - help_text="If true, marks the issue as reviewed by the requestor." + required=False, help_text="If true, marks the issue as reviewed by the requestor." ) status = serializers.ChoiceField( + required=False, help_text="The new status for the issues.", choices=list(zip(STATUS_UPDATE_CHOICES.keys(), STATUS_UPDATE_CHOICES.keys())), ) statusDetails = StatusDetailsValidator( - help_text="Additional details about the resolution. Status detail updates that include release data are only allowed for issues within a single project." + required=False, + help_text="Additional details about the resolution. Status detail updates that include release data are only allowed for issues within a single project.", ) substatus = serializers.ChoiceField( + required=False, choices=list(zip(SUBSTATUS_UPDATE_CHOICES.keys(), SUBSTATUS_UPDATE_CHOICES.keys())), allow_null=True, help_text="The new substatus of the issue.", ) hasSeen = serializers.BooleanField( - help_text="If true, marks the issue as seen by the requestor." + required=False, help_text="If true, marks the issue as seen by the requestor." ) isBookmarked = serializers.BooleanField( - help_text="If true, bookmarks the issue for the requestor." + required=False, help_text="If true, bookmarks the issue for the requestor." ) - isPublic = serializers.BooleanField(help_text="If true, publishes the issue.") + isPublic = serializers.BooleanField(required=False, help_text="If true, publishes the issue.") isSubscribed = serializers.BooleanField( - help_text="If true, subscribes the requestor to the issue." + required=False, help_text="If true, subscribes the requestor to the issue." + ) + merge = serializers.BooleanField( + required=False, help_text="If true, merges the issues together." ) - merge = serializers.BooleanField(help_text="If true, merges the issues together.") discard = serializers.BooleanField( - help_text="If true, discards the issues instead of updating them." + required=False, help_text="If true, discards the issues instead of updating them." ) assignedTo = ActorField( - help_text="The user or team that should be assigned to the issues. Values take the form of ``, `user:`, ``, ``, or `team:`." + required=False, + help_text="The user or team that should be assigned to the issues. Values take the form of ``, `user:`, ``, ``, or `team:`.", ) priority = serializers.ChoiceField( + required=False, help_text="The priority that should be set for the issues", choices=list( zip( @@ -59,35 +66,42 @@ class GroupValidator(serializers.Serializer[Group]): #################################################### # These are already covered by the `statusDetails` serializer field. ignoreDuration = serializers.IntegerField( + required=False, min_value=0, help_text="Ignore the issue for this many minutes.", ) ignoreCount = serializers.IntegerField( + required=False, min_value=0, help_text="Ignore the issue until it is seen this many more times.", ) ignoreWindow = serializers.IntegerField( + required=False, min_value=0, max_value=7 * 24 * 60, help_text="Window in minutes over which `ignoreCount` is measured. Maximum is 7 days.", ) ignoreUserCount = serializers.IntegerField( + required=False, min_value=0, help_text="Ignore the issue until it affects this many more users.", ) ignoreUserWindow = serializers.IntegerField( + required=False, min_value=0, max_value=7 * 24 * 60, help_text="Window in minutes over which `ignoreUserCount` is measured. Maximum is 7 days.", ) # The `inboxDetails`` field is empty. inboxDetails = InboxDetailsValidator( + required=False, help_text="Details recorded when the issue is moved out of the inbox.", ) # The `snooze` field is deprecated. # TODO(dcramer): remove in 9.0 # for the moment, the CLI sends this for any issue update, so allow nulls snoozeDuration = serializers.IntegerField( + required=False, allow_null=True, min_value=0, help_text="Snooze the issue for this many minutes.", diff --git a/src/sentry/api/helpers/group_index/validators/status_details.py b/src/sentry/api/helpers/group_index/validators/status_details.py index c35e16ffed9e..e91ad7e427ac 100644 --- a/src/sentry/api/helpers/group_index/validators/status_details.py +++ b/src/sentry/api/helpers/group_index/validators/status_details.py @@ -21,34 +21,39 @@ class StatusDetailsResult(TypedDict): @extend_schema_serializer() class StatusDetailsValidator(serializers.Serializer[StatusDetailsResult]): inNextRelease = serializers.BooleanField( - help_text="If true, marks the issue as resolved in the next release." + required=False, help_text="If true, marks the issue as resolved in the next release." ) inRelease = serializers.CharField( + required=False, help_text=( "The version of the release that the issue should be resolved in." "If set to `latest`, the latest release will be used." - ) + ), ) inCommit = InCommitValidator( help_text="The commit data that the issue should use for resolution.", required=False ) ignoreDuration = serializers.IntegerField( - help_text="Ignore the issue until for this many minutes.", min_value=0 + required=False, help_text="Ignore the issue until for this many minutes.", min_value=0 ) ignoreCount = serializers.IntegerField( + required=False, help_text="Ignore the issue until it has occurred this many times in `ignoreWindow` minutes.", min_value=0, ) ignoreWindow = serializers.IntegerField( + required=False, help_text="Ignore the issue until it has occurred `ignoreCount` times in this many minutes. (Max: 1 week)", min_value=0, max_value=7 * 24 * 60, ) ignoreUserCount = serializers.IntegerField( + required=False, help_text="Ignore the issue until it has affected this many users in `ignoreUserWindow` minutes.", min_value=0, ) ignoreUserWindow = serializers.IntegerField( + required=False, help_text="Ignore the issue until it has affected `ignoreUserCount` users in this many minutes. (Max: 1 week)", min_value=0, max_value=7 * 24 * 60,