aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js
diff options
context:
space:
mode:
authorGrégoire Aubert <gregoire.aubert@sonarsource.com>2018-10-22 16:23:54 +0200
committerSonarTech <sonartech@sonarsource.com>2018-11-16 20:21:04 +0100
commit9a64997f8446afe86429895b3795b2d61a448221 (patch)
treeb1209ba93de6600dc3012ba869e91f5ce1182f03 /server/sonar-web/src/main/js
parent07546d5e1f4047a1030a91d0ffaa39fb96e66a41 (diff)
downloadsonarqube-9a64997f8446afe86429895b3795b2d61a448221.tar.gz
sonarqube-9a64997f8446afe86429895b3795b2d61a448221.zip
SONAR-11321 Retry up to 5 times to get the alm organization
Diffstat (limited to 'server/sonar-web/src/main/js')
-rw-r--r--server/sonar-web/src/main/js/api/alm-integration.ts28
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/AlmApplicationInstalling.tsx36
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/ChooseRemoteOrganizationStep.tsx2
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/CreateOrganization.tsx36
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__tests__/ChooseRemoteOrganizationStep-test.tsx2
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__tests__/CreateOrganization-test.tsx1
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/ChooseRemoteOrganizationStep-test.tsx.snap4
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/CreateOrganization-test.tsx.snap6
-rw-r--r--server/sonar-web/src/main/js/apps/create/organization/utils.ts7
9 files changed, 99 insertions, 23 deletions
diff --git a/server/sonar-web/src/main/js/api/alm-integration.ts b/server/sonar-web/src/main/js/api/alm-integration.ts
index 568eb2407ff..9b9df940713 100644
--- a/server/sonar-web/src/main/js/api/alm-integration.ts
+++ b/server/sonar-web/src/main/js/api/alm-integration.ts
@@ -29,16 +29,30 @@ export function getAlmAppInfo(): Promise<{ application: AlmApplication }> {
return getJSON('/api/alm_integration/show_app_info').catch(throwGlobalError);
}
-export function getAlmOrganization(data: { installationId: string }): Promise<AlmOrganization> {
- return getJSON('/api/alm_integration/show_organization', data).then(
- ({ organization }) => ({
- ...organization,
- name: organization.name || organization.key
- }),
- throwGlobalError
+function fetchAlmOrganization(data: { installationId: string }, remainingTries: number) {
+ return getJSON('/api/alm_integration/show_organization', data).catch(
+ (error: { response: Response }) => {
+ remainingTries--;
+ if (error.response.status === 404) {
+ if (remainingTries > 0) {
+ return new Promise(resolve => {
+ setTimeout(() => resolve(fetchAlmOrganization(data, remainingTries)), 500);
+ });
+ }
+ return Promise.reject();
+ }
+ return throwGlobalError(error);
+ }
);
}
+export function getAlmOrganization(data: { installationId: string }): Promise<AlmOrganization> {
+ return fetchAlmOrganization(data, 5).then(({ organization }) => ({
+ ...organization,
+ name: organization.name || organization.key
+ }));
+}
+
export function getRepositories(data: {
organization: string;
}): Promise<{ repositories: AlmRepository[] }> {
diff --git a/server/sonar-web/src/main/js/apps/create/organization/AlmApplicationInstalling.tsx b/server/sonar-web/src/main/js/apps/create/organization/AlmApplicationInstalling.tsx
new file mode 100644
index 00000000000..72c6dc0197d
--- /dev/null
+++ b/server/sonar-web/src/main/js/apps/create/organization/AlmApplicationInstalling.tsx
@@ -0,0 +1,36 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2018 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import * as React from 'react';
+import { translate } from '../../../helpers/l10n';
+
+export default function AlmApplicationInstalling({ almKey }: { almKey?: string }) {
+ return (
+ <div className="sonarcloud page page-limited">
+ <div className="huge-spacer-top text-center">
+ <i className="spinner" />
+ <p className="big-spacer-top">
+ {almKey
+ ? translate('onboarding.import_organization.installing', almKey)
+ : translate('onboarding.import_organization.installing')}
+ </p>
+ </div>
+ </div>
+ );
+}
diff --git a/server/sonar-web/src/main/js/apps/create/organization/ChooseRemoteOrganizationStep.tsx b/server/sonar-web/src/main/js/apps/create/organization/ChooseRemoteOrganizationStep.tsx
index 602d3139d47..96318218442 100644
--- a/server/sonar-web/src/main/js/apps/create/organization/ChooseRemoteOrganizationStep.tsx
+++ b/server/sonar-web/src/main/js/apps/create/organization/ChooseRemoteOrganizationStep.tsx
@@ -35,7 +35,7 @@ export default class ChooseRemoteOrganizationStep extends React.PureComponent<Pr
return (
<div className="boxed-group-inner">
{almInstallId && (
- <Alert className="markdown big-spacer-bottom width-60" variant="warning">
+ <Alert className="markdown big-spacer-bottom width-60" variant="error">
{translate('onboarding.create_organization.import_org_not_found')}
<ul>
<li>{translate('onboarding.create_organization.import_org_not_found.tips_1')}</li>
diff --git a/server/sonar-web/src/main/js/apps/create/organization/CreateOrganization.tsx b/server/sonar-web/src/main/js/apps/create/organization/CreateOrganization.tsx
index 17c0e3a83ee..f3301cf3e6b 100644
--- a/server/sonar-web/src/main/js/apps/create/organization/CreateOrganization.tsx
+++ b/server/sonar-web/src/main/js/apps/create/organization/CreateOrganization.tsx
@@ -25,6 +25,7 @@ import { Helmet } from 'react-helmet';
import { FormattedMessage } from 'react-intl';
import { Link, withRouter, WithRouterProps } from 'react-router';
import { formatPrice, parseQuery } from './utils';
+import AlmApplicationInstalling from './AlmApplicationInstalling';
import AutoOrganizationCreate from './AutoOrganizationCreate';
import ManualOrganizationCreate from './ManualOrganizationCreate';
import DeferredSpinner from '../../../components/common/DeferredSpinner';
@@ -68,6 +69,7 @@ interface Props {
interface State {
almApplication?: AlmApplication;
almOrganization?: AlmOrganization;
+ almOrgLoading: boolean;
loading: boolean;
organization?: Organization;
subscriptionPlans?: SubscriptionPlan[];
@@ -82,7 +84,7 @@ interface LocationState {
export class CreateOrganization extends React.PureComponent<Props & WithRouterProps, State> {
mounted = false;
- state: State = { loading: true };
+ state: State = { almOrgLoading: false, loading: true };
componentDidMount() {
this.mounted = true;
@@ -96,7 +98,7 @@ export class CreateOrganization extends React.PureComponent<Props & WithRouterPr
const query = parseQuery(this.props.location.query);
if (query.almInstallId) {
- initRequests.push(this.fetchAlmOrganization(query.almInstallId));
+ this.fetchAlmOrganization(query.almInstallId);
}
}
Promise.all(initRequests).then(this.stopLoading, this.stopLoading);
@@ -116,11 +118,19 @@ export class CreateOrganization extends React.PureComponent<Props & WithRouterPr
};
fetchAlmOrganization = (installationId: string) => {
- return getAlmOrganization({ installationId }).then(almOrganization => {
- if (this.mounted) {
- this.setState({ almOrganization });
+ this.setState({ almOrgLoading: true });
+ return getAlmOrganization({ installationId }).then(
+ almOrganization => {
+ if (this.mounted) {
+ this.setState({ almOrganization, almOrgLoading: false });
+ }
+ },
+ () => {
+ if (this.mounted) {
+ this.setState({ almOrgLoading: false });
+ }
}
- });
+ );
};
fetchSubscriptionPlans = () => {
@@ -158,9 +168,14 @@ export class CreateOrganization extends React.PureComponent<Props & WithRouterPr
render() {
const { currentUser, location } = this.props;
- const { almApplication, almOrganization, loading, subscriptionPlans } = this.state;
const state = (location.state || {}) as LocationState;
const query = parseQuery(location.query);
+
+ if (this.state.almOrgLoading) {
+ return <AlmApplicationInstalling almKey={query.almKey} />;
+ }
+
+ const { almApplication, almOrganization, subscriptionPlans } = this.state;
const importPersonalOrg = isPersonal(almOrganization)
? this.props.userOrganizations.find(o => o.key === currentUser.personalOrganization)
: undefined;
@@ -172,7 +187,7 @@ export class CreateOrganization extends React.PureComponent<Props & WithRouterPr
: translate('onboarding.create_organization.page.description');
const startedPrice = subscriptionPlans && subscriptionPlans[0] && subscriptionPlans[0].price;
const formattedPrice = formatPrice(startedPrice);
- const showManualTab = state.tab === 'manual' && !query.almInstallId;
+ const showManualTab = state.tab === 'manual' && !almOrganization;
return (
<>
@@ -198,8 +213,7 @@ export class CreateOrganization extends React.PureComponent<Props & WithRouterPr
</p>
)}
</header>
-
- {loading ? (
+ {this.state.loading ? (
<DeferredSpinner />
) : (
<>
@@ -224,7 +238,7 @@ export class CreateOrganization extends React.PureComponent<Props & WithRouterPr
)
},
{
- disabled: Boolean(query.almInstallId),
+ disabled: Boolean(almOrganization),
key: 'manual',
node: translate('onboarding.create_organization.create_manually')
}
diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/ChooseRemoteOrganizationStep-test.tsx b/server/sonar-web/src/main/js/apps/create/organization/__tests__/ChooseRemoteOrganizationStep-test.tsx
index 6721e089b15..c11537a0ef4 100644
--- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/ChooseRemoteOrganizationStep-test.tsx
+++ b/server/sonar-web/src/main/js/apps/create/organization/__tests__/ChooseRemoteOrganizationStep-test.tsx
@@ -25,7 +25,7 @@ it('should render', () => {
expect(shallowRender()).toMatchSnapshot();
});
-it('should display a warning message', () => {
+it('should display an alert message', () => {
expect(shallowRender({ almInstallId: 'foo' }).find('Alert')).toMatchSnapshot();
});
diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/CreateOrganization-test.tsx b/server/sonar-web/src/main/js/apps/create/organization/__tests__/CreateOrganization-test.tsx
index 330f8062730..7db9ebf2636 100644
--- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/CreateOrganization-test.tsx
+++ b/server/sonar-web/src/main/js/apps/create/organization/__tests__/CreateOrganization-test.tsx
@@ -84,6 +84,7 @@ it('should render with auto tab selected and manual disabled', async () => {
currentUser: { ...user, externalProvider: 'github' },
location: { query: { installation_id: 'foo' } } as Location // eslint-disable-line camelcase
});
+ expect(wrapper).toMatchSnapshot();
await waitAndUpdate(wrapper);
expect(wrapper).toMatchSnapshot();
});
diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/ChooseRemoteOrganizationStep-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/ChooseRemoteOrganizationStep-test.tsx.snap
index 3a79e945db1..227a1be6a19 100644
--- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/ChooseRemoteOrganizationStep-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/ChooseRemoteOrganizationStep-test.tsx.snap
@@ -1,9 +1,9 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`should display a warning message 1`] = `
+exports[`should display an alert message 1`] = `
<Alert
className="markdown big-spacer-bottom width-60"
- variant="warning"
+ variant="error"
>
onboarding.create_organization.import_org_not_found
<ul>
diff --git a/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/CreateOrganization-test.tsx.snap b/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/CreateOrganization-test.tsx.snap
index c25c32f3e2c..9d3dcf6dbc8 100644
--- a/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/CreateOrganization-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/create/organization/__tests__/__snapshots__/CreateOrganization-test.tsx.snap
@@ -83,6 +83,12 @@ exports[`should render with auto tab displayed 1`] = `
`;
exports[`should render with auto tab selected and manual disabled 1`] = `
+<AlmApplicationInstalling
+ almKey="github"
+/>
+`;
+
+exports[`should render with auto tab selected and manual disabled 2`] = `
<Fragment>
<HelmetWrapper
defer={true}
diff --git a/server/sonar-web/src/main/js/apps/create/organization/utils.ts b/server/sonar-web/src/main/js/apps/create/organization/utils.ts
index bfe1825632a..71795b85c78 100644
--- a/server/sonar-web/src/main/js/apps/create/organization/utils.ts
+++ b/server/sonar-web/src/main/js/apps/create/organization/utils.ts
@@ -31,6 +31,7 @@ export function formatPrice(price?: number, noSign?: boolean) {
export interface Query {
almInstallId?: string;
+ almKey?: string;
}
export const parseQuery = memoize(
@@ -38,7 +39,11 @@ export const parseQuery = memoize(
return {
almInstallId:
parseAsOptionalString(urlQuery['installation_id']) ||
- parseAsOptionalString(urlQuery['clientKey'])
+ parseAsOptionalString(urlQuery['clientKey']),
+ almKey:
+ (urlQuery['installation_id'] && 'github') ||
+ (urlQuery['clientKey'] && 'bitbucket') ||
+ undefined
};
}
);