aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorPhilippe Perrin <philippe.perrin@sonarsource.com>2023-06-09 17:21:05 +0200
committersonartech <sonartech@sonarsource.com>2023-06-14 09:51:06 +0000
commit815cf53518e591b48b8af46f9840e4cc54c4bb65 (patch)
tree9e209127f4f0d1c2eeecdfb5826cd279101822dd /server
parentfb56254f6aedba9c8c63dee5ef73cca636f1ccab (diff)
downloadsonarqube-815cf53518e591b48b8af46f9840e4cc54c4bb65.tar.gz
sonarqube-815cf53518e591b48b8af46f9840e4cc54c4bb65.zip
SONAR-19457 New code definition is made part of Bitbucket Cloud project onboarding
Diffstat (limited to 'server')
-rw-r--r--server/sonar-web/src/main/js/api/alm-integrations.ts23
-rw-r--r--server/sonar-web/src/main/js/api/mocks/AlmIntegrationsServiceMock.ts2
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudProjectCreate.tsx34
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudProjectCreateRender.tsx3
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudSearchForm.tsx197
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/CreateProjectPage.tsx2
-rw-r--r--server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloud-it.tsx24
7 files changed, 135 insertions, 150 deletions
diff --git a/server/sonar-web/src/main/js/api/alm-integrations.ts b/server/sonar-web/src/main/js/api/alm-integrations.ts
index 7e81ff101ba..f33562053c0 100644
--- a/server/sonar-web/src/main/js/api/alm-integrations.ts
+++ b/server/sonar-web/src/main/js/api/alm-integrations.ts
@@ -173,14 +173,21 @@ export function getGithubClientId(almSetting: string): Promise<{ clientId?: stri
return getJSON('/api/alm_integrations/get_github_client_id', { almSetting });
}
-export function importBitbucketCloudRepository(
- almSetting: string,
- repositorySlug: string
-): Promise<{ project: ProjectBase }> {
- return postJSON('/api/alm_integrations/import_bitbucketcloud_repo', {
- almSetting,
- repositorySlug,
- }).catch(throwGlobalError);
+export function setupBitbucketCloudProjectCreation(data: {
+ almSetting: string;
+ repositorySlug: string;
+}) {
+ return (newCodeDefinitionType?: string, newCodeDefinitionValue?: string) =>
+ importBitbucketCloudRepository({ ...data, newCodeDefinitionType, newCodeDefinitionValue });
+}
+
+export function importBitbucketCloudRepository(data: {
+ almSetting: string;
+ repositorySlug: string;
+ newCodeDefinitionType?: string;
+ newCodeDefinitionValue?: string;
+}): Promise<{ project: ProjectBase }> {
+ return postJSON('/api/alm_integrations/import_bitbucketcloud_repo', data).catch(throwGlobalError);
}
export function importGithubRepository(
diff --git a/server/sonar-web/src/main/js/api/mocks/AlmIntegrationsServiceMock.ts b/server/sonar-web/src/main/js/api/mocks/AlmIntegrationsServiceMock.ts
index 05a6d32f6b8..59c1c9b3011 100644
--- a/server/sonar-web/src/main/js/api/mocks/AlmIntegrationsServiceMock.ts
+++ b/server/sonar-web/src/main/js/api/mocks/AlmIntegrationsServiceMock.ts
@@ -58,6 +58,7 @@ import {
searchForBitbucketServerRepositories,
setAlmPersonalAccessToken,
setupAzureProjectCreation,
+ setupBitbucketCloudProjectCreation,
setupBitbucketServerProjectCreation,
} from '../alm-integrations';
@@ -187,6 +188,7 @@ export default class AlmIntegrationsServiceMock {
jest.mocked(setAlmPersonalAccessToken).mockImplementation(this.setAlmPersonalAccessToken);
jest.mocked(getGitlabProjects).mockImplementation(this.getGitlabProjects);
jest.mocked(importGitlabProject).mockImplementation(this.importProject);
+ jest.mocked(setupBitbucketCloudProjectCreation).mockReturnValue(() => this.importProject());
jest.mocked(importBitbucketCloudRepository).mockImplementation(this.importProject);
jest.mocked(getGithubClientId).mockImplementation(this.getGithubClientId);
jest.mocked(getGithubOrganizations).mockImplementation(this.getGithubOrganizations);
diff --git a/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudProjectCreate.tsx b/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudProjectCreate.tsx
index 41adf4c9baa..0a4a2baf20c 100644
--- a/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudProjectCreate.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudProjectCreate.tsx
@@ -19,26 +19,26 @@
*/
import * as React from 'react';
import {
- importBitbucketCloudRepository,
searchForBitbucketCloudRepositories,
+ setupBitbucketCloudProjectCreation,
} from '../../../../api/alm-integrations';
import { Location, Router } from '../../../../components/hoc/withRouter';
import { BitbucketCloudRepository } from '../../../../types/alm-integration';
import { AlmSettingsInstance } from '../../../../types/alm-settings';
import { Paging } from '../../../../types/types';
+import { CreateProjectApiCallback } from '../types';
import BitbucketCloudProjectCreateRenderer from './BitbucketCloudProjectCreateRender';
interface Props {
canAdmin: boolean;
almInstances: AlmSettingsInstance[];
loadingBindings: boolean;
- onProjectCreate: (projectKey: string) => void;
location: Location;
router: Router;
+ onProjectSetupDone: (createProject: CreateProjectApiCallback) => void;
}
interface State {
- importingSlug?: string;
isLastPage?: boolean;
loading: boolean;
loadingMore: boolean;
@@ -189,26 +189,16 @@ export default class BitbucketCloudProjectCreate extends React.PureComponent<Pro
);
};
- handleImport = async (repositorySlug: string) => {
+ handleImport = (repositorySlug: string) => {
const { selectedAlmInstance } = this.state;
- if (!selectedAlmInstance) {
- return;
- }
-
- this.setState({ importingSlug: repositorySlug });
-
- const result = await importBitbucketCloudRepository(
- selectedAlmInstance.key,
- repositorySlug
- ).catch(() => undefined);
-
- if (this.mounted) {
- this.setState({ importingSlug: undefined });
-
- if (result) {
- this.props.onProjectCreate(result.project.key);
- }
+ if (selectedAlmInstance) {
+ this.props.onProjectSetupDone(
+ setupBitbucketCloudProjectCreation({
+ almSetting: selectedAlmInstance.key,
+ repositorySlug,
+ })
+ );
}
};
@@ -226,7 +216,6 @@ export default class BitbucketCloudProjectCreate extends React.PureComponent<Pro
render() {
const { canAdmin, loadingBindings, location, almInstances } = this.props;
const {
- importingSlug,
isLastPage = true,
selectedAlmInstance,
loading,
@@ -239,7 +228,6 @@ export default class BitbucketCloudProjectCreate extends React.PureComponent<Pro
} = this.state;
return (
<BitbucketCloudProjectCreateRenderer
- importingSlug={importingSlug}
isLastPage={isLastPage}
selectedAlmInstance={selectedAlmInstance}
almInstances={almInstances}
diff --git a/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudProjectCreateRender.tsx b/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudProjectCreateRender.tsx
index 28356e43449..770e8cac2ec 100644
--- a/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudProjectCreateRender.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudProjectCreateRender.tsx
@@ -29,7 +29,6 @@ import WrongBindingCountAlert from '../components/WrongBindingCountAlert';
import BitbucketCloudSearchForm from './BitbucketCloudSearchForm';
export interface BitbucketCloudProjectCreateRendererProps {
- importingSlug?: string;
isLastPage: boolean;
canAdmin?: boolean;
loading: boolean;
@@ -53,7 +52,6 @@ export default function BitbucketCloudProjectCreateRenderer(
) {
const {
almInstances,
- importingSlug,
isLastPage,
selectedAlmInstance,
canAdmin,
@@ -105,7 +103,6 @@ export default function BitbucketCloudProjectCreateRenderer(
/>
) : (
<BitbucketCloudSearchForm
- importingSlug={importingSlug}
isLastPage={isLastPage}
loadingMore={loadingMore}
searchQuery={searchQuery}
diff --git a/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudSearchForm.tsx b/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudSearchForm.tsx
index d52b70a176a..8b90691f348 100644
--- a/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudSearchForm.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/BitbucketCloud/BitbucketCloudSearchForm.tsx
@@ -33,11 +33,9 @@ import { getProjectUrl, queryToSearch } from '../../../../helpers/urls';
import { BitbucketCloudRepository } from '../../../../types/alm-integration';
import { ComponentQualifier } from '../../../../types/component';
import { MetricType } from '../../../../types/metrics';
-import InstanceNewCodeDefinitionComplianceWarning from '../components/InstanceNewCodeDefinitionComplianceWarning';
import { CreateProjectModes } from '../types';
export interface BitbucketCloudSearchFormProps {
- importingSlug?: string;
isLastPage: boolean;
loadingMore: boolean;
onImport: (repositorySlug: string) => void;
@@ -53,14 +51,7 @@ function getRepositoryUrl(workspace: string, slug: string) {
}
export default function BitbucketCloudSearchForm(props: BitbucketCloudSearchFormProps) {
- const {
- importingSlug,
- isLastPage,
- loadingMore,
- repositories = [],
- searching,
- searchQuery,
- } = props;
+ const { isLastPage, loadingMore, repositories = [], searching, searchQuery } = props;
if (repositories.length === 0 && searchQuery.length === 0 && !searching) {
return (
@@ -86,109 +77,101 @@ export default function BitbucketCloudSearchForm(props: BitbucketCloudSearchForm
}
return (
- <>
- <InstanceNewCodeDefinitionComplianceWarning />
- <div className="boxed-group big-padded create-project-import">
- <SearchBox
- className="spacer"
- loading={searching}
- minLength={3}
- onChange={props.onSearch}
- placeholder={translate('onboarding.create_project.search_prompt')}
- />
+ <div className="boxed-group big-padded create-project-import">
+ <SearchBox
+ className="spacer"
+ loading={searching}
+ minLength={3}
+ onChange={props.onSearch}
+ placeholder={translate('onboarding.create_project.search_prompt')}
+ />
- <hr />
+ <hr />
- {repositories.length === 0 ? (
- <div className="padded">{translate('no_results')}</div>
- ) : (
- <table className="data zebra zebra-hover">
- <tbody>
- {repositories.map((repository) => (
- <tr key={repository.uuid}>
+ {repositories.length === 0 ? (
+ <div className="padded">{translate('no_results')}</div>
+ ) : (
+ <table className="data zebra zebra-hover">
+ <tbody>
+ {repositories.map((repository) => (
+ <tr key={repository.uuid}>
+ <td>
+ <Tooltip overlay={repository.slug}>
+ <strong className="project-name display-inline-block text-ellipsis">
+ {repository.sqProjectKey ? (
+ <Link to={getProjectUrl(repository.sqProjectKey)}>
+ <QualifierIcon
+ className="spacer-right"
+ qualifier={ComponentQualifier.Project}
+ />
+ {repository.name}
+ </Link>
+ ) : (
+ repository.name
+ )}
+ </strong>
+ </Tooltip>
+ <br />
+ <Tooltip overlay={repository.projectKey}>
+ <span className="text-muted project-path display-inline-block text-ellipsis">
+ {repository.projectKey}
+ </span>
+ </Tooltip>
+ </td>
+ <td>
+ <Link
+ className="display-inline-flex-center big-spacer-right"
+ to={getRepositoryUrl(repository.workspace, repository.slug)}
+ target="_blank"
+ >
+ {translate('onboarding.create_project.bitbucketcloud.link')}
+ </Link>
+ </td>
+ {repository.sqProjectKey ? (
<td>
- <Tooltip overlay={repository.slug}>
- <strong className="project-name display-inline-block text-ellipsis">
- {repository.sqProjectKey ? (
- <Link to={getProjectUrl(repository.sqProjectKey)}>
- <QualifierIcon
- className="spacer-right"
- qualifier={ComponentQualifier.Project}
- />
- {repository.name}
- </Link>
- ) : (
- repository.name
- )}
- </strong>
- </Tooltip>
- <br />
- <Tooltip overlay={repository.projectKey}>
- <span className="text-muted project-path display-inline-block text-ellipsis">
- {repository.projectKey}
- </span>
- </Tooltip>
+ <span className="display-flex-center display-flex-justify-end already-set-up">
+ <CheckIcon className="little-spacer-right" size={12} />
+ {translate('onboarding.create_project.repository_imported')}
+ </span>
</td>
- <td>
- <Link
- className="display-inline-flex-center big-spacer-right"
- to={getRepositoryUrl(repository.workspace, repository.slug)}
- target="_blank"
+ ) : (
+ <td className="text-right">
+ <Button
+ onClick={() => {
+ props.onImport(repository.slug);
+ }}
>
- {translate('onboarding.create_project.bitbucketcloud.link')}
- </Link>
+ {translate('onboarding.create_project.set_up')}
+ </Button>
</td>
- {repository.sqProjectKey ? (
- <td>
- <span className="display-flex-center display-flex-justify-end already-set-up">
- <CheckIcon className="little-spacer-right" size={12} />
- {translate('onboarding.create_project.repository_imported')}
- </span>
- </td>
- ) : (
- <td className="text-right">
- <Button
- disabled={Boolean(importingSlug)}
- onClick={() => {
- props.onImport(repository.slug);
- }}
- >
- {translate('onboarding.create_project.set_up')}
- <DeferredSpinner
- className="spacer-left"
- loading={importingSlug === repository.slug}
- />
- </Button>
- </td>
- )}
- </tr>
- ))}
- </tbody>
- </table>
- )}
- <footer className="spacer-top note text-center">
- {isLastPage &&
- translateWithParameters(
- 'x_of_y_shown',
- formatMeasure(repositories.length, MetricType.Integer, null),
- formatMeasure(repositories.length, MetricType.Integer, null)
- )}
- {!isLastPage && (
- <Button
- className="spacer-left"
- disabled={loadingMore}
- data-test="show-more"
- onClick={props.onLoadMore}
- >
- {translate('show_more')}
- </Button>
+ )}
+ </tr>
+ ))}
+ </tbody>
+ </table>
+ )}
+ <footer className="spacer-top note text-center">
+ {isLastPage &&
+ translateWithParameters(
+ 'x_of_y_shown',
+ formatMeasure(repositories.length, MetricType.Integer, null),
+ formatMeasure(repositories.length, MetricType.Integer, null)
)}
- <DeferredSpinner
- className="text-bottom spacer-left position-absolute"
- loading={loadingMore}
- />
- </footer>
- </div>
- </>
+ {!isLastPage && (
+ <Button
+ className="spacer-left"
+ disabled={loadingMore}
+ data-test="show-more"
+ onClick={props.onLoadMore}
+ >
+ {translate('show_more')}
+ </Button>
+ )}
+ <DeferredSpinner
+ className="text-bottom spacer-left position-absolute"
+ loading={loadingMore}
+ />
+ </footer>
+ </div>
);
}
diff --git a/server/sonar-web/src/main/js/apps/create/project/CreateProjectPage.tsx b/server/sonar-web/src/main/js/apps/create/project/CreateProjectPage.tsx
index 2f0734b6481..fe3e7e1dda0 100644
--- a/server/sonar-web/src/main/js/apps/create/project/CreateProjectPage.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/CreateProjectPage.tsx
@@ -231,7 +231,7 @@ export class CreateProjectPage extends React.PureComponent<CreateProjectPageProp
canAdmin={!!canAdmin}
loadingBindings={loading}
location={location}
- onProjectCreate={this.handleProjectCreate}
+ onProjectSetupDone={this.handleProjectSetupDone}
router={router}
almInstances={bitbucketCloudSettings}
/>
diff --git a/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloud-it.tsx b/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloud-it.tsx
index ee4792f5d19..376024a2e44 100644
--- a/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloud-it.tsx
+++ b/server/sonar-web/src/main/js/apps/create/project/__tests__/BitbucketCloud-it.tsx
@@ -124,9 +124,7 @@ it('should show import project feature when PAT is already set', async () => {
expect(screen.getByText('BitbucketCloud Repo 1')).toBeInTheDocument();
expect(screen.getByText('BitbucketCloud Repo 2')).toBeInTheDocument();
- projectItem = screen.getByRole('row', {
- name: 'qualifier.TRK BitbucketCloud Repo 1 project opens_in_new_window onboarding.create_project.bitbucketcloud.link onboarding.create_project.repository_imported',
- });
+ projectItem = screen.getByRole('row', { name: /BitbucketCloud Repo 1/ });
expect(
within(projectItem).getByText('onboarding.create_project.repository_imported')
).toBeInTheDocument();
@@ -139,14 +137,24 @@ it('should show import project feature when PAT is already set', async () => {
'/dashboard?id=key'
);
- projectItem = screen.getByRole('row', {
- name: 'BitbucketCloud Repo 2 project opens_in_new_window onboarding.create_project.bitbucketcloud.link onboarding.create_project.set_up',
- });
- const importProjectButton = within(projectItem).getByRole('button', {
+ projectItem = screen.getByRole('row', { name: /BitbucketCloud Repo 2/ });
+ const setupButton = within(projectItem).getByRole('button', {
name: 'onboarding.create_project.set_up',
});
- await user.click(importProjectButton);
+ await user.click(setupButton);
+
+ expect(
+ screen.getByRole('heading', { name: 'onboarding.create_project.new_code_definition.title' })
+ ).toBeInTheDocument();
+
+ await user.click(screen.getByRole('radio', { name: 'new_code_definition.global_setting' }));
+ await user.click(
+ screen.getByRole('button', {
+ name: 'onboarding.create_project.new_code_definition.create_project',
+ })
+ );
+
expect(await screen.findByText('/dashboard?id=key')).toBeInTheDocument();
});