release.tsx 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. import * as Sentry from '@sentry/react';
  2. import {
  3. addErrorMessage,
  4. addLoadingMessage,
  5. addSuccessMessage,
  6. } from 'sentry/actionCreators/indicator';
  7. import type {Client} from 'sentry/api';
  8. import {t} from 'sentry/locale';
  9. import ReleaseStore, {getReleaseStoreKey} from 'sentry/stores/releaseStore';
  10. import type {Deploy, Release} from 'sentry/types/release';
  11. import {ReleaseStatus} from 'sentry/types/release';
  12. type ParamsGet = {
  13. orgSlug: string;
  14. projectSlug: string;
  15. releaseVersion: string;
  16. };
  17. export function getProjectRelease(api: Client, params: ParamsGet) {
  18. const {orgSlug, projectSlug, releaseVersion} = params;
  19. const path = `/projects/${orgSlug}/${projectSlug}/releases/${encodeURIComponent(
  20. releaseVersion
  21. )}/`;
  22. // HACK(leedongwei): Actions fired by the ActionCreators are queued to
  23. // the back of the event loop, allowing another getRelease for the same
  24. // release to be fired before the loading state is updated in store.
  25. // This hack short-circuits that and update the state immediately.
  26. ReleaseStore.state.releaseLoading[getReleaseStoreKey(projectSlug, releaseVersion)] =
  27. true;
  28. ReleaseStore.loadRelease(orgSlug, projectSlug, releaseVersion);
  29. return api
  30. .requestPromise(path, {
  31. method: 'GET',
  32. })
  33. .then((res: Release) => {
  34. ReleaseStore.loadReleaseSuccess(projectSlug, releaseVersion, res);
  35. })
  36. .catch(err => {
  37. // This happens when a Project is not linked to a specific Release
  38. if (err.status === 404) {
  39. ReleaseStore.loadReleaseSuccess(projectSlug, releaseVersion, null);
  40. return;
  41. }
  42. ReleaseStore.loadReleaseError(projectSlug, releaseVersion, err);
  43. Sentry.withScope(scope => {
  44. scope.setLevel('warning');
  45. scope.setFingerprint(['getRelease-action-creator']);
  46. Sentry.captureException(err);
  47. });
  48. });
  49. }
  50. export function getReleaseDeploys(api: Client, params: ParamsGet) {
  51. const {orgSlug, projectSlug, releaseVersion} = params;
  52. const path = `/organizations/${orgSlug}/releases/${encodeURIComponent(
  53. releaseVersion
  54. )}/deploys/`;
  55. // HACK(leedongwei): Same as above
  56. ReleaseStore.state.deploysLoading[getReleaseStoreKey(projectSlug, releaseVersion)] =
  57. true;
  58. ReleaseStore.loadDeploys(orgSlug, projectSlug, releaseVersion);
  59. return api
  60. .requestPromise(path, {
  61. method: 'GET',
  62. })
  63. .then((res: Deploy[]) => {
  64. ReleaseStore.loadDeploysSuccess(projectSlug, releaseVersion, res);
  65. })
  66. .catch(err => {
  67. // This happens when a Project is not linked to a specific Release
  68. if (err.status === 404) {
  69. ReleaseStore.loadDeploysSuccess(projectSlug, releaseVersion, null);
  70. return;
  71. }
  72. ReleaseStore.loadDeploysError(projectSlug, releaseVersion, err);
  73. Sentry.withScope(scope => {
  74. scope.setLevel('warning');
  75. scope.setFingerprint(['getReleaseDeploys-action-creator']);
  76. Sentry.captureException(err);
  77. });
  78. });
  79. }
  80. export function archiveRelease(api: Client, params: ParamsGet) {
  81. const {orgSlug, projectSlug, releaseVersion} = params;
  82. ReleaseStore.loadRelease(orgSlug, projectSlug, releaseVersion);
  83. addLoadingMessage(t('Archiving Release\u2026'));
  84. return api
  85. .requestPromise(`/organizations/${orgSlug}/releases/`, {
  86. method: 'POST',
  87. data: {
  88. status: ReleaseStatus.ARCHIVED,
  89. projects: [],
  90. version: releaseVersion,
  91. },
  92. })
  93. .then((release: Release) => {
  94. ReleaseStore.loadReleaseSuccess(projectSlug, releaseVersion, release);
  95. addSuccessMessage(t('Release was successfully archived.'));
  96. })
  97. .catch(error => {
  98. ReleaseStore.loadReleaseError(projectSlug, releaseVersion, error);
  99. addErrorMessage(
  100. error.responseJSON?.detail ?? t('Release could not be be archived.')
  101. );
  102. throw error;
  103. });
  104. }
  105. export function restoreRelease(api: Client, params: ParamsGet) {
  106. const {orgSlug, projectSlug, releaseVersion} = params;
  107. ReleaseStore.loadRelease(orgSlug, projectSlug, releaseVersion);
  108. addLoadingMessage(t('Restoring Release\u2026'));
  109. return api
  110. .requestPromise(`/organizations/${orgSlug}/releases/`, {
  111. method: 'POST',
  112. data: {
  113. status: ReleaseStatus.ACTIVE,
  114. projects: [],
  115. version: releaseVersion,
  116. },
  117. })
  118. .then((release: Release) => {
  119. ReleaseStore.loadReleaseSuccess(projectSlug, releaseVersion, release);
  120. addSuccessMessage(t('Release was successfully restored.'));
  121. })
  122. .catch(error => {
  123. ReleaseStore.loadReleaseError(projectSlug, releaseVersion, error);
  124. addErrorMessage(
  125. error.responseJSON?.detail ?? t('Release could not be be restored.')
  126. );
  127. throw error;
  128. });
  129. }