def safe_delete(self): """Deletes a release if possible or raises a `UnsafeReleaseDeletion` exception. """ from sentry.models import Group, ReleaseFile from sentry.snuba.sessions import check_has_health_data # we don't want to remove the first_release metadata on the Group, and # while people might want to kill a release (maybe to remove files), # removing the release is prevented if Group.objects.filter(first_release=self).exists(): raise UnsafeReleaseDeletion(ERR_RELEASE_REFERENCED) # We do not allow releases with health data to be deleted because # the upserting from snuba data would create the release again. # We would need to be able to delete this data from snuba which we # can't do yet. project_ids = list(self.projects.values_list("id").all()) if check_has_health_data([(p[0], self.version) for p in project_ids]): raise UnsafeReleaseDeletion(ERR_RELEASE_HEALTH_DATA) # TODO(dcramer): this needs to happen in the queue as it could be a long # and expensive operation file_list = ReleaseFile.objects.filter( release=self).select_related("file") for releasefile in file_list: releasefile.file.delete() releasefile.delete() self.delete()
def get_session_stats(self, project_ids): segments, interval = STATS_PERIOD_CHOICES[self.stats_period] now = timezone.now() current_interval_start = now - (segments * interval) previous_interval_start = now - (2 * segments * interval) project_health_data_dict = releasehealth.get_current_and_previous_crash_free_rates( project_ids=project_ids, current_start=current_interval_start, current_end=now, previous_start=previous_interval_start, previous_end=current_interval_start, rollup=int(interval.total_seconds()), ) # list that contains ids of projects that has both `currentCrashFreeRate` and # `previousCrashFreeRate` set to None and so we are not sure if they have health data or # not and so we add those ids to this list to check later check_has_health_data_ids = [] for project_id in project_ids: current_crash_free_rate = project_health_data_dict[project_id][ "currentCrashFreeRate"] previous_crash_free_rate = project_health_data_dict[project_id][ "previousCrashFreeRate"] if [current_crash_free_rate, previous_crash_free_rate ] != [None, None]: project_health_data_dict[project_id]["hasHealthData"] = True else: project_health_data_dict[project_id]["hasHealthData"] = False check_has_health_data_ids.append(project_id) # For project ids we are not sure if they have health data in the last 90 days we # call -> check_has_data with those ids and then update our `project_health_data_dict` # accordingly if check_has_health_data_ids: projects_with_health_data = check_has_health_data( check_has_health_data_ids) for project_id in projects_with_health_data: project_health_data_dict[project_id]["hasHealthData"] = True return project_health_data_dict
def get_attrs(self, item_list, user, **kwargs): project = kwargs.get("project") # Some code paths pass an environment object, other pass a list of # environment names. environment = kwargs.get("environment") environments = kwargs.get("environments") if not environments: if environment: environments = [environment.name] else: environments = None with_health_data = kwargs.get("with_health_data", False) health_stat = kwargs.get("health_stat", None) health_stats_period = kwargs.get("health_stats_period") summary_stats_period = kwargs.get("summary_stats_period") no_snuba = kwargs.get("no_snuba") if with_health_data and no_snuba: raise TypeError("health data requires snuba") if environments is None: first_seen, last_seen, issue_counts_by_release = self.__get_release_data_no_environment( project, item_list) else: ( first_seen, last_seen, issue_counts_by_release, ) = self.__get_release_data_with_environments( project, item_list, environments) owners = { d["id"]: d for d in serialize({i.owner for i in item_list if i.owner_id}, user) } release_metadata_attrs = self._get_commit_metadata(item_list, user) deploy_metadata_attrs = self._get_deploy_metadata(item_list, user) release_projects = defaultdict(list) project_releases = ReleaseProject.objects.filter( release__in=item_list).values( "new_groups", "release_id", "release__version", "project__slug", "project__name", "project__id", "project__platform", ) platforms = ProjectPlatform.objects.filter( project_id__in={x["project__id"] for x in project_releases}).values_list( "project_id", "platform") platforms_by_project = defaultdict(list) for project_id, platform in platforms: platforms_by_project[project_id].append(platform) if with_health_data: health_data = get_release_health_data_overview( [(pr["project__id"], pr["release__version"]) for pr in project_releases], health_stats_period=health_stats_period, summary_stats_period=summary_stats_period, environments=environments, stat=health_stat, ) has_health_data = None else: health_data = None if no_snuba: has_health_data = {} else: has_health_data = check_has_health_data([ (pr["project__id"], pr["release__version"]) for pr in project_releases ]) for pr in project_releases: pr_rv = { "id": pr["project__id"], "slug": pr["project__slug"], "name": pr["project__name"], "new_groups": pr["new_groups"], "platform": pr["project__platform"], "platforms": platforms_by_project.get(pr["project__id"]) or [], } if health_data is not None: pr_rv["health_data"] = health_data.get( (pr["project__id"], pr["release__version"])) pr_rv["has_health_data"] = (pr_rv["health_data"] or {}).get("has_health_data", False) else: pr_rv["has_health_data"] = ( pr["project__id"], pr["release__version"], ) in has_health_data release_projects[pr["release_id"]].append(pr_rv) result = {} for item in item_list: single_release_projects = release_projects.get(item.id, []) if item._for_project_id is not None: single_release_projects = [ x for x in single_release_projects if x["id"] == item._for_project_id ] release_new_groups = (issue_counts_by_release.get(item.id) or {}).get(item._for_project_id) or 0 else: release_new_groups = sum((issue_counts_by_release.get(item.id) or {}).values()) p = { "owner": owners[str(item.owner_id)] if item.owner_id else None, "new_groups": release_new_groups, "projects": single_release_projects, "first_seen": first_seen.get(item.version), "last_seen": last_seen.get(item.version), } p.update(release_metadata_attrs[item]) p.update(deploy_metadata_attrs[item]) result[item] = p return result
def test_check_has_health_data(self): data = check_has_health_data([(self.project.id, self.session_release), (self.project.id, "dummy-release")]) assert data == {(self.project.id, self.session_release)}