Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions static/app/routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1108,12 +1108,16 @@ function buildRoutes() {
/>
<Route
path="commits/"
componentPromise={() => import('app/views/releases/detail/commits')}
componentPromise={() =>
import('app/views/releases/detail/commitsAndFiles/commits')
}
component={SafeLazyLoad}
/>
<Route
path="files-changed/"
componentPromise={() => import('app/views/releases/detail/filesChanged')}
componentPromise={() =>
import('app/views/releases/detail/commitsAndFiles/filesChanged')
}
component={SafeLazyLoad}
/>
<Redirect from="new-events/" to="/organizations/:orgId/releases/:release/" />
Expand Down
18 changes: 17 additions & 1 deletion static/app/utils/sessions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,17 @@ import {
SIXTY_DAYS,
THIRTY_DAYS,
} from 'app/components/charts/utils';
import {IconCheckmark, IconFire, IconWarning} from 'app/icons';
import {SessionApiResponse, SessionField, SessionStatus} from 'app/types';
import {SeriesDataUnit} from 'app/types/echarts';
import {defined, percent} from 'app/utils';
import {Theme} from 'app/utils/theme';
import {IconSize, Theme} from 'app/utils/theme';
import {getCrashFreePercent, getSessionStatusPercent} from 'app/views/releases/utils';
import {sessionTerm} from 'app/views/releases/utils/sessionTerm';

const CRASH_FREE_DANGER_THRESHOLD = 98;
const CRASH_FREE_WARNING_THRESHOLD = 99.5;

export function getCount(groups: SessionApiResponse['groups'] = [], field: SessionField) {
return groups.reduce((acc, group) => acc + group.totals[field], 0);
}
Expand Down Expand Up @@ -343,3 +347,15 @@ export function filterSessionsInTimeWindow(
groups,
};
}

export function getCrashFreeIcon(crashFreePercent: number, iconSize: IconSize = 'sm') {
if (crashFreePercent < CRASH_FREE_DANGER_THRESHOLD) {
return <IconFire color="red300" size={iconSize} />;
}

if (crashFreePercent < CRASH_FREE_WARNING_THRESHOLD) {
return <IconWarning color="yellow300" size={iconSize} />;
}

return <IconCheckmark isCircled color="green300" size={iconSize} />;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import FeatureTourModal from 'app/components/modals/featureTourModal';
import {t} from 'app/locale';
import {Organization} from 'app/types';
import {trackAnalyticsEvent} from 'app/utils/analytics';
import {RELEASES_TOUR_STEPS} from 'app/views/releases/list/releasePromo';
import {RELEASES_TOUR_STEPS} from 'app/views/releases/list/releasesPromo';

const DOCS_URL = 'https://docs.sentry.io/product/releases/';
const DOCS_HEALTH_URL = 'https://docs.sentry.io/product/releases/health/';
Expand Down
2 changes: 1 addition & 1 deletion static/app/views/projectDetail/projectLatestReleases.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import overflowEllipsis from 'app/styles/overflowEllipsis';
import space from 'app/styles/space';
import {Organization, Release} from 'app/types';
import {analytics} from 'app/utils/analytics';
import {RELEASES_TOUR_STEPS} from 'app/views/releases/list/releasePromo';
import {RELEASES_TOUR_STEPS} from 'app/views/releases/list/releasesPromo';

import MissingReleasesButtons from './missingFeatureButtons/missingReleasesButtons';
import {SectionHeadingLink, SectionHeadingWrapper, SidebarSection} from './styles';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ import {formatVersion} from 'app/utils/formatters';
import routeTitleGen from 'app/utils/routeTitle';
import AsyncView from 'app/views/asyncView';

import {getCommitsByRepository, getQuery, getReposToRender} from '../utils';

import EmptyState from './emptyState';
import RepositorySwitcher from './repositorySwitcher';
import {getCommitsByRepository, getQuery, getReposToRender} from './utils';
import withReleaseRepos from './withReleaseRepos';

type Props = RouteComponentProps<{orgId: string; release: string}, {}> & {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ import {formatVersion} from 'app/utils/formatters';
import routeTitleGen from 'app/utils/routeTitle';
import AsyncView from 'app/views/asyncView';

import {getFilesByRepository, getQuery, getReposToRender} from '../utils';

import EmptyState from './emptyState';
import RepositorySwitcher from './repositorySwitcher';
import {getFilesByRepository, getQuery, getReposToRender} from './utils';
import withReleaseRepos from './withReleaseRepos';

type Props = RouteComponentProps<{orgId: string; release: string}, {}> & {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import withOrganization from 'app/utils/withOrganization';
import withRepositories from 'app/utils/withRepositories';
import EmptyMessage from 'app/views/settings/components/emptyMessage';

import {ReleaseContext} from '.';
import {ReleaseContext} from '..';

// These props are required when using this HoC
type DependentProps = RouteComponentProps<{orgId: string; release: string}, {}>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {Organization, Release, ReleaseMeta} from 'app/types';
import {trackAnalyticsEvent} from 'app/utils/analytics';
import {formatVersion} from 'app/utils/formatters';

import {isReleaseArchived} from '../utils';
import {isReleaseArchived} from '../../utils';

type Props = {
location: Location;
Expand Down
2 changes: 1 addition & 1 deletion static/app/views/releases/detail/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import AsyncView from 'app/views/asyncView';

import {getReleaseBounds, ReleaseBounds} from '../utils';

import ReleaseHeader from './releaseHeader';
import ReleaseHeader from './header/releaseHeader';

type ReleaseContextType = {
release: ReleaseWithHealth;
Expand Down
18 changes: 9 additions & 9 deletions static/app/views/releases/detail/overview/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,16 @@ import {TrendChangeType, TrendView} from 'app/views/performance/trends/types';
import {getReleaseParams, isReleaseArchived, ReleaseBounds} from '../../utils';
import {ReleaseContext} from '..';

import CommitAuthorBreakdown from './commitAuthorBreakdown';
import Deploys from './deploys';
import Issues from './issues';
import OtherProjects from './otherProjects';
import ProjectReleaseDetails from './projectReleaseDetails';
import ReleaseAdoption from './releaseAdoption';
import CommitAuthorBreakdown from './sidebar/commitAuthorBreakdown';
import Deploys from './sidebar/deploys';
import OtherProjects from './sidebar/otherProjects';
import ProjectReleaseDetails from './sidebar/projectReleaseDetails';
import ReleaseAdoption from './sidebar/releaseAdoption';
import ReleaseStats from './sidebar/releaseStats';
import TotalCrashFreeUsers from './sidebar/totalCrashFreeUsers';
import ReleaseArchivedNotice from './releaseArchivedNotice';
import ReleaseComparisonChart from './releaseComparisonChart';
import ReleaseStats from './releaseStats';
import TotalCrashFreeUsers from './totalCrashFreeUsers';
import ReleaseIssues from './releaseIssues';

const RELEASE_PERIOD_KEY = 'release';

Expand Down Expand Up @@ -374,7 +374,7 @@ class ReleaseOverview extends AsyncView<Props> {
/>
)}

<Issues
<ReleaseIssues
organization={organization}
selection={selection}
version={version}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import withOrganization from 'app/utils/withOrganization';
import {IssueSortOptions} from 'app/views/issueList/utils';

import {getReleaseParams, ReleaseBounds} from '../../utils';
import EmptyState from '../emptyState';
import EmptyState from '../commitsAndFiles/emptyState';

enum IssuesType {
NEW = 'new',
Expand Down Expand Up @@ -69,7 +69,7 @@ type State = {
onCursor?: () => void;
};

class Issues extends Component<Props, State> {
class ReleaseIssues extends Component<Props, State> {
static defaultProps = defaultProps;
state: State = this.getInitialState();

Expand Down Expand Up @@ -426,4 +426,4 @@ const StyledPagination = styled(Pagination)`
margin: 0;
`;

export default withApi(withOrganization(Issues));
export default withApi(withOrganization(ReleaseIssues));
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {Commit, User} from 'app/types';
import {percent} from 'app/utils';
import {userDisplayName} from 'app/utils/formatters';

import {SectionHeading, Wrapper} from './styles';
import {SectionHeading, Wrapper} from '../styles';

type GroupedAuthorCommits = {
[key: string]: {author: User | undefined; commitCount: number};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {t} from 'app/locale';
import space from 'app/styles/space';
import {Deploy} from 'app/types';

import {SectionHeading, Wrapper} from './styles';
import {SectionHeading, Wrapper} from '../styles';

type Props = {
version: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@ import {Location} from 'history';
import Button from 'app/components/button';
import Collapsible from 'app/components/collapsible';
import IdBadge from 'app/components/idBadge';
import {tn} from 'app/locale';
import {extractSelectionParameters} from 'app/components/organizations/globalSelectionHeader/utils';
import {t, tn} from 'app/locale';
import space from 'app/styles/space';
import {Organization, ReleaseProject} from 'app/types';

import ProjectLink from '../../list/releaseHealth/projectLink';

import {SectionHeading, Wrapper} from './styles';
import {SectionHeading, Wrapper} from '../styles';

type Props = {
projects: ReleaseProject[];
Expand Down Expand Up @@ -44,12 +43,21 @@ function OtherProjects({projects, location, version, organization}: Props) {
{projects.map(project => (
<Row key={project.id}>
<IdBadge project={project} avatarSize={16} />
<ProjectLink
location={location}
orgSlug={organization.slug}
releaseVersion={version}
project={project}
/>
<Button
size="xsmall"
to={{
pathname: `/organizations/${
organization.slug
}/releases/${encodeURIComponent(version)}/`,
query: {
...extractSelectionParameters(location.query),
project: project.id,
yAxis: undefined,
},
}}
>
{t('View')}
</Button>
</Row>
))}
</Collapsible>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Version from 'app/components/version';
import {t, tn} from 'app/locale';
import {ReleaseMeta, ReleaseWithHealth} from 'app/types';

import {SectionHeading, Wrapper} from './styles';
import {SectionHeading, Wrapper} from '../styles';

type Props = {
release: ReleaseWithHealth;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@ import {
SessionField,
} from 'app/types';
import {getAdoptionSeries, getCount} from 'app/utils/sessions';
import {isProjectMobileForReleases} from 'app/views/releases/list';
import {ADOPTION_STAGE_LABELS} from 'app/views/releases/list/releaseHealth/content';

import {getReleaseBounds, getReleaseParams} from '../../utils';
import {generateReleaseMarkLines, releaseMarkLinesLabels} from '../utils';

import {Wrapper} from './styles';
import {
ADOPTION_STAGE_LABELS,
getReleaseBounds,
getReleaseParams,
isMobileRelease,
} from '../../../utils';
import {generateReleaseMarkLines, releaseMarkLinesLabels} from '../../utils';
import {Wrapper} from '../styles';

type Props = {
release: ReleaseWithHealth;
Expand Down Expand Up @@ -204,14 +206,13 @@ function ReleaseComparisonChart({
releaseBounds: getReleaseBounds(release),
});

const isMobileProject = isProjectMobileForReleases(project.platform);
const adoptionStage = release.adoptionStages?.[project.slug]?.stage;
const adoptionStageLabel = ADOPTION_STAGE_LABELS[adoptionStage];
const multipleEnvironments = environment.length === 0 || environment.length > 1;

return (
<Wrapper>
{isMobileProject && (
{isMobileRelease(project.platform) && (
<Feature features={['release-adoption-stage']}>
<SidebarSectionTitle
title={t('Adoption Stage')}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@ import space from 'app/styles/space';
import {CrashFreeTimeBreakdown, Organization} from 'app/types';
import {defined} from 'app/utils';

import {displayCrashFreePercent} from '../../utils';

import {SectionHeading, Wrapper} from './styles';
import {displayCrashFreePercent} from '../../../utils';
import {SectionHeading, Wrapper} from '../styles';

type Props = AsyncComponent['props'] & {
location: Location;
Expand Down
41 changes: 2 additions & 39 deletions static/app/views/releases/detail/utils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,16 @@ import {
Commit,
CommitFile,
FilesByRepository,
GlobalSelection,
Organization,
ReleaseComparisonChartType,
ReleaseProject,
ReleaseWithHealth,
Repository,
} from 'app/types';
import {Series} from 'app/types/echarts';
import {getUtcDateString} from 'app/utils/dates';
import EventView from 'app/utils/discover/eventView';
import {decodeList} from 'app/utils/queryString';
import {Theme} from 'app/utils/theme';
import {MutableSearch} from 'app/utils/tokenizeSearch';
import {isProjectMobileForReleases} from 'app/views/releases/list';

import {getReleaseBounds, getReleaseParams} from '../utils';
import {getReleaseBounds, getReleaseParams, isMobileRelease} from '../utils';
import {commonTermsDescription, SessionTerm} from '../utils/sessionTerm';

export type CommitsByRepository = {
Expand Down Expand Up @@ -110,37 +104,6 @@ export function getReposToRender(repos: Array<string>, activeRepository?: Reposi
return [activeRepository.name];
}

/**
* Get high level transaction information for this release
*/
export function getReleaseEventView(
selection: GlobalSelection,
version: string,
_organization: Organization
): EventView {
const {projects, environments, datetime} = selection;
const {start, end, period} = datetime;

const discoverQuery = {
id: undefined,
version: 2,
name: `${t('Release Apdex')}`,
fields: ['apdex()'],
query: new MutableSearch([
`release:${version}`,
'event.type:transaction',
'count():>0',
]).formatString(),
range: period,
environment: environments,
projects,
start: start ? getUtcDateString(start) : undefined,
end: end ? getUtcDateString(end) : undefined,
} as const;

return EventView.fromSavedQuery(discoverQuery);
}

export const releaseComparisonChartLabels = {
[ReleaseComparisonChartType.CRASH_FREE_SESSIONS]: t('Crash Free Session Rate'),
[ReleaseComparisonChartType.HEALTHY_SESSIONS]: t('Healthy'),
Expand Down Expand Up @@ -273,7 +236,7 @@ export function generateReleaseMarkLines(
);
}

if (!isSingleEnv || !isProjectMobileForReleases(project.platform)) {
if (!isSingleEnv || !isMobileRelease(project.platform)) {
// for now want to show marklines only on mobile platforms with single environment selected
return markLines;
}
Expand Down
Loading