def test_when_current_release_version_is_set_incorrect_inputs_fallback_to_older_model( self): """ Test that ensures in a project that follows semver and where current_release_version is set, wrong release input (non semver) comparison does not break the method, but rather fallsback to the older model of comparison """ old_random_release = self.create_release(date_added=timezone.now() - timedelta(minutes=45), version="doggo") GroupResolution.objects.create( release=old_random_release, current_release_version=old_random_release.version, group=self.group, type=GroupResolution.Type.in_next_release, ) for release in [ self.old_release, self.new_release, self.old_semver_release, self.new_semver_release, ]: assert not GroupResolution.has_resolution(self.group, release)
def test_no_release_with_resolution(self): GroupResolution.objects.create( release=self.new_release, group=self.group, type=GroupResolution.Type.in_release, ) assert GroupResolution.has_resolution(self.group, None)
def test_in_release_with_current_release(self): GroupResolution.objects.create( release=self.old_release, group=self.group, type=GroupResolution.Type.in_release, ) assert not GroupResolution.has_resolution(self.group, self.old_release)
def test_in_release_with_old_release(self): GroupResolution.objects.create( release=self.new_release, group=self.group, type=GroupResolution.Type.in_release, ) assert GroupResolution.has_resolution(self.group, self.old_release)
def test_when_current_release_version_is_set_with_old_release(self): for grp_res_type in [ GroupResolution.Type.in_release, GroupResolution.Type.in_next_release ]: grp_resolution = GroupResolution.objects.create( release=self.new_release, current_release_version=self.new_release.version, group=self.group, type=grp_res_type, ) assert GroupResolution.has_resolution(self.group, self.old_release) grp_resolution.delete()
def test_for_semver_when_current_release_version_is_set_with_new_semver_release( self): # Behaviour should be the same in both `in_release` and `in_next_release` because if # `current_release_version` is set then comparison will be > current_release_version # should not have a resolution for grp_res_type in [ GroupResolution.Type.in_release, GroupResolution.Type.in_next_release ]: grp_resolution = GroupResolution.objects.create( release=self.old_semver_release, current_release_version=self.old_semver_release.version, group=self.group, type=grp_res_type, ) assert not GroupResolution.has_resolution(self.group, self.new_semver_release) grp_resolution.delete()
def test_when_current_release_version_is_set_but_does_not_exist_fallback_to_older_model( self): """ Test that ensures in a project that does not follows semver, and current_release_version is set but no corresponding Release instance exists for that release version then comparison does not break the method, but rather fallsback to the older model """ GroupResolution.objects.create( release=self.old_release, current_release_version="kittie 12", group=self.group, type=GroupResolution.Type.in_next_release, ) for release in [ self.new_release, self.old_semver_release, self.new_semver_release ]: assert not GroupResolution.has_resolution(self.group, release)
def _handle_regression(self, group, event, release): if not group.is_resolved(): return # we only mark it as a regression if the event's release is newer than # the release which we originally marked this as resolved elif GroupResolution.has_resolution(group, release): return if not plugin_is_regression(group, event): return # we now think its a regression, rely on the database to validate that # no one beat us to this date = max(event.datetime, group.last_seen) is_regression = bool( Group.objects.filter( id=group.id, # ensure we cant update things if the status has been set to # ignored status__in=[GroupStatus.RESOLVED, GroupStatus.UNRESOLVED], ).exclude( # add to the regression window to account for races here active_at__gte=date - timedelta(seconds=5), ).update( active_at=date, # explicitly set last_seen here as ``is_resolved()`` looks # at the value last_seen=date, status=GroupStatus.UNRESOLVED ) ) group.active_at = date group.status = GroupStatus.UNRESOLVED if is_regression and release: # resolutions are only valid if the state of the group is still # resolved -- if it were to change the resolution should get removed try: resolution = GroupResolution.objects.get( group=group, ) except GroupResolution.DoesNotExist: affected = False else: cursor = connection.cursor() # delete() API does not return affected rows cursor.execute("DELETE FROM sentry_groupresolution WHERE id = %s", [resolution.id]) affected = cursor.rowcount > 0 if affected: # if we had to remove the GroupResolution (i.e. we beat the # the queue to handling this) then we need to also record # the corresponding event try: activity = Activity.objects.filter( group=group, type=Activity.SET_RESOLVED_IN_RELEASE, ident=resolution.id, ).order_by('-datetime')[0] except IndexError: # XXX: handle missing data, as its not overly important pass else: activity.update(data={ 'version': release.version, }) if is_regression: activity = Activity.objects.create( project=group.project, group=group, type=Activity.SET_REGRESSION, data={ 'version': release.version if release else '', } ) activity.send_notification() return is_regression
def _handle_regression(group, event, release): if not group.is_resolved(): return # we only mark it as a regression if the event's release is newer than # the release which we originally marked this as resolved elif GroupResolution.has_resolution(group, release): return elif has_pending_commit_resolution(group): return if not plugin_is_regression(group, event): return # we now think its a regression, rely on the database to validate that # no one beat us to this date = max(event.datetime, group.last_seen) is_regression = bool( Group.objects.filter( id=group.id, # ensure we cant update things if the status has been set to # ignored status__in=[GroupStatus.RESOLVED, GroupStatus.UNRESOLVED], ).exclude( # add to the regression window to account for races here active_at__gte=date - timedelta(seconds=5)). update( active_at=date, # explicitly set last_seen here as ``is_resolved()`` looks # at the value last_seen=date, status=GroupStatus.UNRESOLVED, )) group.active_at = date group.status = GroupStatus.UNRESOLVED if is_regression and release: # resolutions are only valid if the state of the group is still # resolved -- if it were to change the resolution should get removed try: resolution = GroupResolution.objects.get(group=group) except GroupResolution.DoesNotExist: affected = False else: cursor = connection.cursor() # delete() API does not return affected rows cursor.execute("DELETE FROM sentry_groupresolution WHERE id = %s", [resolution.id]) affected = cursor.rowcount > 0 if affected: # if we had to remove the GroupResolution (i.e. we beat the # the queue to handling this) then we need to also record # the corresponding event try: activity = Activity.objects.filter( group=group, type=Activity.SET_RESOLVED_IN_RELEASE, ident=resolution.id).order_by("-datetime")[0] except IndexError: # XXX: handle missing data, as its not overly important pass else: activity.update(data={"version": release.version}) if is_regression: activity = Activity.objects.create( project_id=group.project_id, group=group, type=Activity.SET_REGRESSION, data={"version": release.version if release else ""}, ) activity.send_notification() kick_off_status_syncs.apply_async(kwargs={ "project_id": group.project_id, "group_id": group.id }) return is_regression
def test_no_release_with_no_resolution(self): assert not GroupResolution.has_resolution(self.group, None)
def test_in_next_release_with_old_release(self): GroupResolution.objects.create( release=self.new_release, group=self.group, type=GroupResolution.Type.in_next_release ) assert GroupResolution.has_resolution(self.group, self.old_release)
def test_for_semver_in_release_with_new_release(self): GroupResolution.objects.create(release=self.old_semver_release, group=self.group, type=GroupResolution.Type.in_release) assert not GroupResolution.has_resolution(self.group, self.new_semver_release)