release.tsx 4.6 KB

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