--- /dev/null
+Paste an existing token value into the input field.
+
+---
+
+See also: [User Token](/user-guide/user-token/)
import OnboardingAddMembersIcon from 'sonar-ui-common/components/icons/OnboardingAddMembersIcon';
import { translate } from 'sonar-ui-common/helpers/l10n';
import { Router, withRouter } from '../../../components/hoc/withRouter';
-import '../../../components/tutorials/styles.css';
import './OrganizationEmpty.css';
interface Props {
import { getAlmDefinitionsNoCatch, getProjectAlmBinding } from '../../api/alm-settings';
import { AlmBindingDefinition, AlmKeys, ProjectAlmBindingResponse } from '../../types/alm-settings';
import { withRouter } from '../hoc/withRouter';
-import './styles.css';
import TutorialSelectionRenderer from './TutorialSelectionRenderer';
import { TutorialModes } from './types';
]);
if (this.mounted) {
- // We only support Bitbucket & GitHub for now.
+ // We only support Bitbucket, GitHub & Gitlab for now.
if (
projectBinding === undefined ||
- (projectBinding.alm !== AlmKeys.Bitbucket && projectBinding.alm !== AlmKeys.GitHub)
+ ![AlmKeys.Bitbucket, AlmKeys.GitHub, AlmKeys.GitLab].includes(projectBinding.alm)
) {
this.setState({ loading: false, forceManual: true });
} else {
import * as React from 'react';
import { translate } from 'sonar-ui-common/helpers/l10n';
import { getBaseUrl } from 'sonar-ui-common/helpers/urls';
-import { AlmBindingDefinition, ProjectAlmBindingResponse } from '../../types/alm-settings';
+import { AlmBindingDefinition, AlmKeys, ProjectAlmBindingResponse } from '../../types/alm-settings';
+import GitLabCITutorial from './gitlabci/GitLabCITutorial';
import JenkinsTutorial from './jenkins/JenkinsTutorial';
import ManualTutorial from './manual/ManualTutorial';
import { TutorialModes } from './types';
return <i className="spinner" />;
}
+ const jenkinsAvailable =
+ projectBinding && [AlmKeys.Bitbucket, AlmKeys.GitHub].includes(projectBinding.alm);
+
return (
<>
{selectedTutorial === undefined && (
</h1>
</header>
- <div className="display-flex-space-around">
- <button
- className="button button-huge display-flex-column tutorial-mode-jenkins"
- onClick={() => props.onSelectTutorial(TutorialModes.Jenkins)}
- type="button">
- <img
- alt="" // Should be ignored by screen readers
- height={80}
- src={`${getBaseUrl()}/images/tutorials/jenkins.svg`}
- />
- <div className="medium big-spacer-top">
- {translate('onboarding.tutorial.choose_method.jenkins')}
- </div>
- </button>
+ <div className="display-flex-justify-center">
+ {projectBinding?.alm === AlmKeys.GitLab && (
+ <button
+ className="button button-huge display-flex-column spacer-left spacer-right tutorial-mode-gitlab"
+ onClick={() => props.onSelectTutorial(TutorialModes.GitLabCI)}
+ type="button">
+ <img
+ alt="" // Should be ignored by screen readers
+ height={80}
+ src={`${getBaseUrl()}/images/alm/gitlab.svg`}
+ />
+ <div className="medium big-spacer-top">
+ {translate('onboarding.tutorial.choose_method.gitlab_ci')}
+ </div>
+ </button>
+ )}
+
+ {jenkinsAvailable && (
+ <button
+ className="button button-huge display-flex-column spacer-left spacer-right tutorial-mode-jenkins"
+ onClick={() => props.onSelectTutorial(TutorialModes.Jenkins)}
+ type="button">
+ <img
+ alt="" // Should be ignored by screen readers
+ height={80}
+ src={`${getBaseUrl()}/images/tutorials/jenkins.svg`}
+ />
+ <div className="medium big-spacer-top">
+ {translate('onboarding.tutorial.choose_method.jenkins')}
+ </div>
+ </button>
+ )}
<button
- className="button button-huge display-flex-column tutorial-mode-manual"
+ className="button button-huge display-flex-column spacer-left spacer-right tutorial-mode-manual"
onClick={() => props.onSelectTutorial(TutorialModes.Manual)}
type="button">
<img
projectBinding={projectBinding}
/>
)}
+
+ {selectedTutorial === TutorialModes.GitLabCI && projectBinding !== undefined && (
+ <GitLabCITutorial
+ component={component}
+ currentUser={currentUser}
+ projectBinding={projectBinding}
+ />
+ )}
</>
);
}
expect(wrapper.state().forceManual).toBe(false);
});
-it('should select manual if project is bound to any other ALM', async () => {
- (getProjectAlmBinding as jest.Mock).mockResolvedValueOnce({ alm: AlmKeys.GitLab });
+it('should select manual if project is bound to unsupported ALM', async () => {
+ (getProjectAlmBinding as jest.Mock).mockResolvedValueOnce({ alm: AlmKeys.Azure });
const wrapper = shallowRender();
await waitAndUpdate(wrapper);
expect(wrapper.state().forceManual).toBe(true);
import { click } from 'sonar-ui-common/helpers/testUtils';
import {
mockBitbucketBindingDefinition,
- mockProjectBitbucketBindingResponse
+ mockProjectBitbucketBindingResponse,
+ mockProjectGitLabBindingResponse
} from '../../../helpers/mocks/alm-settings';
import { mockComponent, mockLoggedInUser } from '../../../helpers/testMocks';
import TutorialSelectionRenderer, {
it('should render correctly', () => {
expect(shallowRender()).toMatchSnapshot('selection');
+ expect(shallowRender({ projectBinding: mockProjectBitbucketBindingResponse() })).toMatchSnapshot(
+ 'selection with jenkins available'
+ );
expect(shallowRender({ loading: true })).toMatchSnapshot('loading');
expect(shallowRender({ selectedTutorial: TutorialModes.Manual })).toMatchSnapshot(
'manual tutorial'
projectBinding: mockProjectBitbucketBindingResponse()
})
).toMatchSnapshot('jenkins tutorial');
+ expect(
+ shallowRender({
+ selectedTutorial: TutorialModes.GitLabCI,
+ projectBinding: mockProjectGitLabBindingResponse()
+ })
+ ).toMatchSnapshot('gitlab tutorial');
});
it('should allow mode selection', () => {
const onSelectTutorial = jest.fn();
- const wrapper = shallowRender({ onSelectTutorial });
+ const wrapper = shallowRender({
+ onSelectTutorial,
+ projectBinding: mockProjectBitbucketBindingResponse()
+ });
click(wrapper.find('button.tutorial-mode-jenkins'));
expect(onSelectTutorial).toHaveBeenLastCalledWith(TutorialModes.Jenkins);
expect(onSelectTutorial).toHaveBeenLastCalledWith(TutorialModes.Manual);
});
+it('should allow gitlab selection', () => {
+ const onSelectTutorial = jest.fn();
+ const wrapper = shallowRender({
+ onSelectTutorial,
+ projectBinding: mockProjectGitLabBindingResponse()
+ });
+
+ click(wrapper.find('button.tutorial-mode-gitlab'));
+ expect(onSelectTutorial).toHaveBeenLastCalledWith(TutorialModes.GitLabCI);
+});
+
function shallowRender(props: Partial<TutorialSelectionRendererProps> = {}) {
return shallow<TutorialSelectionRendererProps>(
<TutorialSelectionRenderer
// Jest Snapshot v1, https://goo.gl/fbAQLP
+exports[`should render correctly: gitlab tutorial 1`] = `
+<Fragment>
+ <GitLabCITutorial
+ component={
+ Object {
+ "breadcrumbs": Array [],
+ "key": "my-project",
+ "name": "MyProject",
+ "organization": "foo",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ }
+ }
+ currentUser={
+ Object {
+ "groups": Array [],
+ "isLoggedIn": true,
+ "login": "luke",
+ "name": "Skywalker",
+ "scmAccounts": Array [],
+ }
+ }
+ projectBinding={
+ Object {
+ "alm": "gitlab",
+ "key": "foo",
+ "repository": "PROJECT_KEY",
+ "url": "https://gitlab.com/api/v4",
+ }
+ }
+ />
+</Fragment>
+`;
+
exports[`should render correctly: jenkins tutorial 1`] = `
<Fragment>
<Connect(JenkinsTutorial)
</h1>
</header>
<div
- className="display-flex-space-around"
+ className="display-flex-justify-center"
+ >
+ <button
+ className="button button-huge display-flex-column spacer-left spacer-right tutorial-mode-manual"
+ onClick={[Function]}
+ type="button"
+ >
+ <img
+ alt=""
+ height={80}
+ src="/images/sonarcloud/analysis/manual.svg"
+ />
+ <div
+ className="medium big-spacer-top"
+ >
+ onboarding.tutorial.choose_method.manual
+ </div>
+ </button>
+ </div>
+ </div>
+</Fragment>
+`;
+
+exports[`should render correctly: selection with jenkins available 1`] = `
+<Fragment>
+ <div
+ className="tutorial-selection"
+ >
+ <header
+ className="spacer-top spacer-bottom padded"
+ >
+ <h1
+ className="text-center big-spacer-bottom"
+ >
+ onboarding.tutorial.choose_method
+ </h1>
+ </header>
+ <div
+ className="display-flex-justify-center"
>
<button
- className="button button-huge display-flex-column tutorial-mode-jenkins"
+ className="button button-huge display-flex-column spacer-left spacer-right tutorial-mode-jenkins"
onClick={[Function]}
type="button"
>
</div>
</button>
<button
- className="button button-huge display-flex-column tutorial-mode-manual"
+ className="button button-huge display-flex-column spacer-left spacer-right tutorial-mode-manual"
onClick={[Function]}
type="button"
>
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 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 { FormattedMessage } from 'react-intl';
+import { Link } from 'react-router';
+import { Button, DeleteButton } from 'sonar-ui-common/components/controls/buttons';
+import { ClipboardIconButton } from 'sonar-ui-common/components/controls/clipboard';
+import SimpleModal from 'sonar-ui-common/components/controls/SimpleModal';
+import { Alert } from 'sonar-ui-common/components/ui/Alert';
+import DeferredSpinner from 'sonar-ui-common/components/ui/DeferredSpinner';
+import { translate, translateWithParameters } from 'sonar-ui-common/helpers/l10n';
+import { generateToken, getTokens, revokeToken } from '../../../api/user-tokens';
+import { getUniqueTokenName } from '../utils';
+
+interface State {
+ loading: boolean;
+ token?: string;
+ tokenName: string;
+}
+
+interface Props {
+ component: T.Component;
+ currentUser: T.LoggedInUser;
+ onClose: (token?: string) => void;
+}
+
+export default class EditTokenModal extends React.PureComponent<Props, State> {
+ mounted = false;
+ state: State = {
+ loading: true,
+ tokenName: ''
+ };
+
+ componentDidMount() {
+ this.mounted = true;
+ this.getTokensAndName();
+ }
+
+ componentWillUnmount() {
+ this.mounted = false;
+ }
+
+ getTokensAndName = async () => {
+ const { component, currentUser } = this.props;
+
+ const tokens = await getTokens(currentUser.login);
+
+ if (this.mounted) {
+ this.setState({
+ loading: false,
+ tokenName: getUniqueTokenName(tokens, `Analyze "${component.name}"`)
+ });
+ }
+ };
+
+ getNewToken = async () => {
+ const { tokenName } = this.state;
+
+ const { token } = await generateToken({ name: tokenName });
+
+ if (this.mounted) {
+ this.setState({
+ token,
+ tokenName
+ });
+ }
+ };
+
+ handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
+ this.setState({
+ tokenName: event.target.value
+ });
+ };
+
+ handleTokenRevoke = async () => {
+ const { tokenName } = this.state;
+
+ if (tokenName) {
+ await revokeToken({ name: tokenName });
+
+ if (this.mounted) {
+ this.setState({
+ token: '',
+ tokenName: ''
+ });
+ }
+ }
+ };
+
+ render() {
+ const { loading, token, tokenName } = this.state;
+
+ const header = translate('onboarding.token.generate_token');
+
+ return (
+ <SimpleModal header={header} onClose={this.props.onClose} onSubmit={this.props.onClose}>
+ {({ onCloseClick }) => (
+ <>
+ <div className="modal-head">
+ <h2>{header}</h2>
+ </div>
+
+ <div className="modal-body">
+ <p className="spacer-bottom">
+ <FormattedMessage
+ defaultMessage={translate('onboarding.token.text')}
+ id="onboarding.token.text"
+ values={{
+ link: (
+ <Link target="_blank" to="/account/security">
+ {translate('onboarding.token.text.user_account')}
+ </Link>
+ )
+ }}
+ />
+ </p>
+
+ {token ? (
+ <>
+ <span className="text-middle">
+ {tokenName}
+ {': '}
+ </span>
+ <div className="display-float-center">
+ <code className="rule spacer-right">{token}</code>
+
+ <ClipboardIconButton copyValue={token} />
+
+ <DeleteButton onClick={this.handleTokenRevoke} />
+ </div>
+
+ <Alert className="big-spacer-top" variant="warning">
+ {translateWithParameters('users.tokens.new_token_created', token)}
+ </Alert>
+ </>
+ ) : (
+ <div className="big-spacer-top">
+ {loading ? (
+ <DeferredSpinner />
+ ) : (
+ <>
+ <input
+ className="input-super-large spacer-right text-middle"
+ onChange={this.handleChange}
+ placeholder={translate('onboarding.token.generate_token.placeholder')}
+ required={true}
+ type="text"
+ value={tokenName}
+ />
+ <Button
+ className="text-middle"
+ disabled={!tokenName}
+ onClick={this.getNewToken}>
+ {translate('onboarding.token.generate')}
+ </Button>
+ </>
+ )}
+ </div>
+ )}
+ </div>
+ <div className="modal-foot">
+ <Button onClick={onCloseClick}>{translate('continue')}</Button>
+ </div>
+ </>
+ )}
+ </SimpleModal>
+ );
+ }
+}
.onboarding-step ol.list-styled > li {
position: relative;
- counter-increment: step-counter;
+ counter-increment: li;
margin-bottom: calc(2 * var(--gridSize));
- padding-left: calc(4 * var(--gridSize));
}
.onboarding-step ol.list-styled > li::before {
- content: counter(step-counter);
- color: white;
- background-color: var(--blue);
- display: inline-flex;
- border-radius: 50%;
+ display: inline-block;
width: 16px;
- position: absolute;
- left: 0;
- font-size: 10px;
height: 16px;
- justify-content: center;
- align-items: center;
+ margin-right: 8px;
+ color: #fff;
+ font-size: 12px;
+ line-height: 16px;
+ direction: rtl;
+ text-align: center;
+ background-color: #4b9fd5;
+ border-radius: 50%;
+ content: counter(li);
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 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 { shallow } from 'enzyme';
+import * as React from 'react';
+import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
+import { generateToken, getTokens, revokeToken } from '../../../../api/user-tokens';
+import { mockComponent, mockEvent, mockLoggedInUser } from '../../../../helpers/testMocks';
+import { getUniqueTokenName } from '../../utils';
+import EditTokenModal from '../EditTokenModal';
+
+jest.mock('../../../../api/user-tokens', () => ({
+ generateToken: jest.fn().mockResolvedValue({
+ name: 'baz',
+ createdAt: '2019-01-21T08:06:00+0100',
+ login: 'luke',
+ token: 'token_value'
+ }),
+ getTokens: jest.fn().mockResolvedValue([
+ {
+ name: 'foo',
+ createdAt: '2019-01-15T15:06:33+0100',
+ lastConnectionDate: '2019-01-18T15:06:33+0100'
+ },
+ { name: 'bar', createdAt: '2019-01-18T15:06:33+0100' }
+ ]),
+ revokeToken: jest.fn().mockResolvedValue(Promise.resolve())
+}));
+
+jest.mock('../../utils', () => ({
+ getUniqueTokenName: jest.fn().mockReturnValue('lightsaber-9000')
+}));
+
+beforeEach(() => {
+ jest.clearAllMocks();
+});
+
+it('should render correctly', () => {
+ expect(shallowRender()).toMatchSnapshot();
+});
+
+it('should get tokens and unique name', async () => {
+ const wrapper = shallowRender();
+ const { getTokensAndName } = wrapper.instance();
+
+ getTokensAndName();
+ await waitAndUpdate(wrapper);
+
+ expect(getTokens).toHaveBeenCalled();
+ expect(getUniqueTokenName).toHaveBeenCalled();
+ expect(wrapper.state('tokenName')).toBe('lightsaber-9000');
+});
+
+it('should get a new token', async () => {
+ const wrapper = shallowRender();
+ const { getNewToken } = wrapper.instance();
+
+ getNewToken();
+ await waitAndUpdate(wrapper);
+
+ expect(generateToken).toHaveBeenCalled();
+ expect(wrapper.state('token')).toBe('token_value');
+});
+
+it('should handle token revocation', async () => {
+ const wrapper = shallowRender();
+ const { getTokensAndName, handleTokenRevoke } = wrapper.instance();
+
+ getTokensAndName();
+ await waitAndUpdate(wrapper);
+ handleTokenRevoke();
+ await waitAndUpdate(wrapper);
+
+ expect(revokeToken).toHaveBeenCalled();
+ expect(wrapper.state('token')).toBe('');
+ expect(wrapper.state('tokenName')).toBe('');
+});
+
+it('should handle change on user input', () => {
+ const wrapper = shallowRender();
+ const instance = wrapper.instance();
+
+ instance.handleChange(mockEvent({ target: { value: 'my-token' } }));
+ expect(wrapper.state('tokenName')).toBe('my-token');
+});
+
+function shallowRender(props: Partial<EditTokenModal['props']> = {}) {
+ return shallow<EditTokenModal>(
+ <EditTokenModal
+ component={mockComponent()}
+ currentUser={mockLoggedInUser()}
+ onClose={jest.fn()}
+ {...props}
+ />
+ );
+}
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<SimpleModal
+ header="onboarding.token.generate_token"
+ onClose={[MockFunction]}
+ onSubmit={[MockFunction]}
+>
+ <Component />
+</SimpleModal>
+`;
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 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 { FormattedMessage } from 'react-intl';
+import { Button } from 'sonar-ui-common/components/controls/buttons';
+import { ClipboardIconButton } from 'sonar-ui-common/components/controls/clipboard';
+import { translate } from 'sonar-ui-common/helpers/l10n';
+import { getHostUrl } from 'sonar-ui-common/helpers/urls';
+import EditTokenModal from '../components/EditTokenModal';
+import Step from '../components/Step';
+
+export interface EnvironmentVariablesStepProps {
+ component: T.Component;
+ currentUser: T.LoggedInUser;
+ finished: boolean;
+ onDone: () => void;
+ onOpen: () => void;
+ open: boolean;
+}
+
+const pipelineDescriptionLinkLabel = translate(
+ 'onboarding.tutorial.with.gitlab_ci.env_variables.description.link'
+);
+
+export default function EnvironmentVariablesStep(props: EnvironmentVariablesStepProps) {
+ const { component, currentUser, finished, open } = props;
+
+ const [isModalVisible, toggleModal] = React.useState(false);
+
+ const toggleTokenModal = () => toggleModal(!isModalVisible);
+ const closeTokenModal = () => toggleModal(false);
+
+ const fieldValueTranslation = translate(
+ 'onboarding.tutorial.with.gitlab_ci.env_variables.enter_field_value'
+ );
+
+ const renderForm = () => (
+ <div className="boxed-group-inner">
+ <h2 className="spacer-bottom spacer-top">
+ {translate('onboarding.tutorial.with.gitlab_ci.env_variables.section.title')}
+ </h2>
+
+ <FormattedMessage
+ defaultMessage={translate(
+ 'onboarding.tutorial.with.gitlab_ci.env_variables.section.description'
+ )}
+ id="onboarding.tutorial.with.gitlab_ci.env_variables.section.description"
+ values={{
+ /* This link will be added when the backend provides the project URL */
+ link: <strong>{pipelineDescriptionLinkLabel}</strong>
+ }}
+ />
+
+ <ol className="list-styled big-spacer-top">
+ <li className="big-spacer-bottom">
+ <FormattedMessage
+ defaultMessage={fieldValueTranslation}
+ id="onboarding.tutorial.with.gitlab_ci.env_variables.step1"
+ values={{
+ extra: <ClipboardIconButton copyValue="SONAR_TOKEN" />,
+ field: translate('onboarding.tutorial.with.gitlab_ci.env_variables.step1'),
+ value: <code className="rule">SONAR_TOKEN</code>
+ }}
+ />
+ </li>
+ <li className="big-spacer-bottom">
+ <FormattedMessage
+ defaultMessage={fieldValueTranslation}
+ id="onboarding.tutorial.with.gitlab_ci.env_variables.step2"
+ values={{
+ extra: (
+ <Button className="spacer-left" onClick={toggleTokenModal}>
+ {translate('onboarding.token.generate_token')}
+ </Button>
+ ),
+ field: translate('onboarding.tutorial.with.gitlab_ci.env_variables.step2'),
+ value: translate(
+ 'onboarding.tutorial.with.gitlab_ci.env_variables.section.step2.value'
+ )
+ }}
+ />
+ </li>
+ <li className="big-spacer-bottom">
+ {translate('onboarding.tutorial.with.gitlab_ci.env_variables.step3')}
+ </li>
+ <li className="big-spacer-bottom">
+ {translate('onboarding.tutorial.with.gitlab_ci.env_variables.section.step4')}
+ </li>
+ </ol>
+
+ <hr className="no-horizontal-margins" />
+
+ <h2 className="spacer-bottom big-spacer-top">
+ {translate('onboarding.tutorial.with.gitlab_ci.env_variables.section2.title')}
+ </h2>
+
+ <FormattedMessage
+ defaultMessage={translate(
+ 'onboarding.tutorial.with.gitlab_ci.env_variables.section2.description'
+ )}
+ id="onboarding.tutorial.with.gitlab_ci.env_variables.section2.description"
+ values={{
+ /* This link will be added when the backend provides the project URL */
+ link: <strong>{pipelineDescriptionLinkLabel}</strong>
+ }}
+ />
+
+ <ol className="list-styled big-spacer-top big-spacer-bottom">
+ <li className="big-spacer-bottom">
+ <FormattedMessage
+ defaultMessage={fieldValueTranslation}
+ id="onboarding.tutorial.with.gitlab_ci.env_variables.step1"
+ values={{
+ extra: <ClipboardIconButton copyValue="SONAR_HOST_URL" />,
+ field: translate('onboarding.tutorial.with.gitlab_ci.env_variables.step1'),
+ value: <code className="rule">SONAR_HOST_URL</code>
+ }}
+ />
+ </li>
+ <li className="big-spacer-bottom">
+ <FormattedMessage
+ defaultMessage={fieldValueTranslation}
+ id="onboarding.tutorial.with.gitlab_ci.env_variables.step2"
+ values={{
+ extra: <ClipboardIconButton copyValue={getHostUrl()} />,
+ field: translate('onboarding.tutorial.with.gitlab_ci.env_variables.step2'),
+ value: <code className="rule">{getHostUrl()}</code>
+ }}
+ />
+ </li>
+ <li className="big-spacer-bottom">
+ {translate('onboarding.tutorial.with.gitlab_ci.env_variables.step3')}
+ </li>
+ <li className="big-spacer-bottom">
+ {translate('onboarding.tutorial.with.gitlab_ci.env_variables.section2.step4')}
+ </li>
+ </ol>
+
+ <Button className="big-spacer-bottom" onClick={props.onDone}>
+ {translate('continue')}
+ </Button>
+ </div>
+ );
+
+ return (
+ <>
+ {isModalVisible && (
+ <EditTokenModal component={component} currentUser={currentUser} onClose={closeTokenModal} />
+ )}
+
+ <Step
+ finished={finished}
+ onOpen={props.onOpen}
+ open={open}
+ renderForm={renderForm}
+ stepNumber={2}
+ stepTitle={translate('onboarding.tutorial.with.gitlab_ci.env_variables.title')}
+ />
+ </>
+ );
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 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 { Alert } from 'sonar-ui-common/components/ui/Alert';
+import { translate } from 'sonar-ui-common/helpers/l10n';
+import { isProjectGitLabBindingResponse } from '../../../helpers/alm-settings';
+import { ProjectAlmBindingResponse } from '../../../types/alm-settings';
+import EnvironmentVariablesStep from './EnvironmentVariablesStep';
+import ProjectKeyStep from './ProjectKeyStep';
+import { BuildTools } from './types';
+import YmlFileStep from './YmlFileStep';
+
+export enum Steps {
+ PROJECT_KEY,
+ ENV_VARIABLES,
+ YML
+}
+
+export interface GitLabCITutorialProps {
+ component: T.Component;
+ currentUser: T.LoggedInUser;
+ projectBinding: ProjectAlmBindingResponse;
+}
+
+export default function GitLabCITutorial(props: GitLabCITutorialProps) {
+ const { component, currentUser, projectBinding } = props;
+
+ const [step, setStep] = React.useState(Steps.PROJECT_KEY);
+ const [buildTool, setBuildTool] = React.useState<BuildTools | undefined>();
+
+ // Failsafe; should never happen.
+ if (!isProjectGitLabBindingResponse(projectBinding)) {
+ return (
+ <Alert variant="error">{translate('onboarding.tutorial.with.gitlab_ci.unsupported')}</Alert>
+ );
+ }
+
+ return (
+ <>
+ <div className="page-header big-spacer-bottom">
+ <h1 className="page-title">{translate('onboarding.tutorial.with.gitlab_ci.title')}</h1>
+ </div>
+
+ <ProjectKeyStep
+ buildTool={buildTool}
+ component={component}
+ finished={step > Steps.PROJECT_KEY}
+ onDone={() => setStep(Steps.ENV_VARIABLES)}
+ onOpen={() => setStep(Steps.PROJECT_KEY)}
+ open={step === Steps.PROJECT_KEY}
+ setBuildTool={setBuildTool}
+ />
+
+ <EnvironmentVariablesStep
+ component={component}
+ currentUser={currentUser}
+ finished={step > Steps.ENV_VARIABLES}
+ onDone={() => setStep(Steps.YML)}
+ onOpen={() => setStep(Steps.ENV_VARIABLES)}
+ open={step === Steps.ENV_VARIABLES}
+ />
+
+ <YmlFileStep buildTool={buildTool} open={step === Steps.YML} />
+ </>
+ );
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 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 { FormattedMessage } from 'react-intl';
+import { Button } from 'sonar-ui-common/components/controls/buttons';
+import { ClipboardIconButton } from 'sonar-ui-common/components/controls/clipboard';
+import { translate } from 'sonar-ui-common/helpers/l10n';
+import CodeSnippet from '../../common/CodeSnippet';
+import RenderOptions from '../components/RenderOptions';
+import Step from '../components/Step';
+import { BuildTools } from './types';
+
+export interface ProjectKeyStepProps {
+ buildTool?: BuildTools;
+ component: T.Component;
+ finished: boolean;
+ onDone: () => void;
+ onOpen: () => void;
+ open: boolean;
+ setBuildTool: (tool: BuildTools) => void;
+}
+
+const mavenSnippet = (key: string) => `<properties>
+ <sonar.projectKey>${key}</sonar.projectKey>
+ <sonar.qualitygate.wait>true</sonar.qualitygate.wait>
+</properties>`;
+
+const gradleSnippet = (key: string) => `plugins {
+ id "org.sonarqube" version "3.0"
+}
+
+sonarqube {
+ properties {
+ property "sonar.projectKey", "${key}"
+ property "sonar.qualitygate.wait", true
+ }
+}`;
+
+const otherSnippet = (key: string) => `sonar.projectKey=${key}
+sonar.qualitygate.wait=true
+`;
+
+const snippetForBuildTool = {
+ [BuildTools.Maven]: mavenSnippet,
+ [BuildTools.Gradle]: gradleSnippet,
+ [BuildTools.Other]: otherSnippet
+};
+
+const filenameForBuildTool = {
+ [BuildTools.Maven]: 'pom.xml',
+ [BuildTools.Gradle]: 'build.gradle',
+ [BuildTools.Other]: 'sonar-project.properties'
+};
+
+export default function ProjectKeyStep(props: ProjectKeyStepProps) {
+ const { buildTool, component, finished, open } = props;
+
+ const renderForm = () => (
+ <div className="boxed-group-inner">
+ <ol className="list-styled">
+ <li>
+ {translate('onboarding.build')}
+ <RenderOptions
+ checked={buildTool}
+ name="buildtool"
+ onCheck={value => props.setBuildTool(value as BuildTools)}
+ optionLabelKey="onboarding.build"
+ options={Object.values(BuildTools)}
+ />
+ </li>
+ {buildTool !== undefined && (
+ <li className="abs-width-600">
+ <FormattedMessage
+ defaultMessage={translate(
+ `onboarding.tutorial.with.gitlab_ci.project_key.${buildTool}.step2`
+ )}
+ id={`onboarding.tutorial.with.gitlab_ci.project_key.${buildTool}.step2`}
+ values={{
+ file: (
+ <>
+ <code className="rule">{filenameForBuildTool[buildTool]}</code>
+ <ClipboardIconButton
+ className="little-spacer-left"
+ copyValue={filenameForBuildTool[buildTool]}
+ />
+ </>
+ )
+ }}
+ />
+ <CodeSnippet snippet={snippetForBuildTool[buildTool](component.key)} />
+ </li>
+ )}
+ </ol>
+ {buildTool !== undefined && <Button onClick={props.onDone}>{translate('continue')}</Button>}
+ </div>
+ );
+
+ return (
+ <Step
+ finished={finished}
+ onOpen={props.onOpen}
+ open={open}
+ renderForm={renderForm}
+ stepNumber={1}
+ stepTitle={translate('onboarding.tutorial.with.gitlab_ci.project_key.title')}
+ />
+ );
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 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 { FormattedMessage } from 'react-intl';
+import { Link } from 'react-router';
+import { ClipboardIconButton } from 'sonar-ui-common/components/controls/clipboard';
+import { translate } from 'sonar-ui-common/helpers/l10n';
+import Step from '../components/Step';
+import PipeCommandGradle from './commands/PipeCommandGradle';
+import PipeCommandMaven from './commands/PipeCommandMaven';
+import PipeCommandOther from './commands/PipeCommandOther';
+import { BuildTools } from './types';
+
+export interface YmlFileStepProps {
+ buildTool?: BuildTools;
+ open: boolean;
+}
+
+export default function YmlFileStep({ buildTool, open }: YmlFileStepProps) {
+ const renderForm = () => (
+ <div className="boxed-group-inner">
+ <div className="flex-columns">
+ <div className="flex-column-full">
+ {buildTool && (
+ <>
+ <div className="big-spacer-bottom">
+ <FormattedMessage
+ defaultMessage={translate('onboarding.tutorial.with.gitlab_ci.yml.description')}
+ id="onboarding.tutorial.with.gitlab_ci.yml.description"
+ values={{
+ filename: (
+ <>
+ <code className="rule">
+ {translate('onboarding.tutorial.with.gitlab_ci.yml.filename')}
+ </code>
+ <ClipboardIconButton
+ className="little-spacer-left"
+ copyValue={translate('onboarding.tutorial.with.gitlab_ci.yml.filename')}
+ />
+ </>
+ )
+ }}
+ />
+ </div>
+
+ <div className="big-spacer-bottom">
+ {buildTool === BuildTools.Maven && <PipeCommandMaven />}
+ {buildTool === BuildTools.Gradle && <PipeCommandGradle />}
+ {buildTool === BuildTools.Other && <PipeCommandOther />}
+ </div>
+
+ <p className="little-spacer-bottom">
+ {translate('onboarding.tutorial.with.gitlab_ci.yml.baseconfig')}
+ </p>
+
+ <p className="huge-spacer-bottom">
+ {translate('onboarding.tutorial.with.gitlab_ci.yml.existing')}
+ </p>
+
+ <hr className="no-horizontal-margins" />
+ <div>
+ <p className="big-spacer-bottom">
+ <strong>{translate('onboarding.tutorial.with.gitlab_ci.yml.done')} </strong>{' '}
+ <FormattedMessage
+ defaultMessage={translate(
+ 'onboarding.tutorial.with.gitlab_ci.yml.done.description'
+ )}
+ id="onboarding.tutorial.with.gitlab_ci.yml.done.description"
+ values={{
+ /* This link will be added when the backend provides the project URL */
+ link: translate(
+ 'onboarding.tutorial.with.gitlab_ci.yml.done.description.link'
+ )
+ }}
+ />
+ </p>
+ <p className="big-spacer-bottom">
+ <strong>
+ {translate('onboarding.tutorial.with.gitlab_ci.yml.done.then-what')}
+ </strong>{' '}
+ {translate('onboarding.tutorial.with.gitlab_ci.yml.done.then-what.description')}
+ </p>
+
+ <p className="big-spacer-bottom">
+ <FormattedMessage
+ defaultMessage={translate(
+ 'onboarding.tutorial.with.gitlab_ci.yml.done.links.title'
+ )}
+ id="onboarding.tutorial.with.gitlab_ci.yml.done.links.title"
+ values={{
+ links: (
+ <Link
+ rel="noopener noreferrer"
+ target="_blank"
+ to="/documentation/user-guide/quality-gates/">
+ {translate('onboarding.tutorial.with.gitlab_ci.yml.done.links.QG')}
+ </Link>
+ )
+ }}
+ />
+ </p>
+ </div>
+ </>
+ )}
+ </div>
+ </div>
+ </div>
+ );
+
+ return (
+ <Step
+ finished={false}
+ open={open}
+ renderForm={renderForm}
+ stepNumber={3}
+ stepTitle={translate('onboarding.tutorial.with.gitlab_ci.yml.title')}
+ />
+ );
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 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 { shallow } from 'enzyme';
+import * as React from 'react';
+import { mockComponent, mockLoggedInUser } from '../../../../helpers/testMocks';
+import { renderStepContent } from '../../jenkins/test-utils';
+import EnvironmentVariablesStep, {
+ EnvironmentVariablesStepProps
+} from '../EnvironmentVariablesStep';
+
+it('should render correctly', () => {
+ const wrapper = shallowRender();
+ expect(wrapper).toMatchSnapshot('Step wrapper');
+ expect(renderStepContent(wrapper)).toMatchSnapshot('initial content');
+});
+
+function shallowRender(props: Partial<EnvironmentVariablesStepProps> = {}) {
+ return shallow<EnvironmentVariablesStepProps>(
+ <EnvironmentVariablesStep
+ currentUser={mockLoggedInUser()}
+ component={mockComponent()}
+ finished={false}
+ onDone={jest.fn()}
+ onOpen={jest.fn()}
+ open={true}
+ {...props}
+ />
+ );
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 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 { shallow } from 'enzyme';
+import * as React from 'react';
+import {
+ mockProjectGithubBindingResponse,
+ mockProjectGitLabBindingResponse
+} from '../../../../helpers/mocks/alm-settings';
+import { mockComponent, mockLoggedInUser } from '../../../../helpers/testMocks';
+import GitLabCITutorial, { GitLabCITutorialProps } from '../GitLabCITutorial';
+
+it('should render correctly', () => {
+ expect(shallowRender()).toMatchSnapshot();
+ expect(shallowRender({ projectBinding: mockProjectGithubBindingResponse() })).toMatchSnapshot(
+ 'wrong alm'
+ );
+});
+
+function shallowRender(props: Partial<GitLabCITutorialProps> = {}) {
+ return shallow<GitLabCITutorialProps>(
+ <GitLabCITutorial
+ component={mockComponent()}
+ currentUser={mockLoggedInUser()}
+ projectBinding={mockProjectGitLabBindingResponse()}
+ {...props}
+ />
+ );
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 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 { shallow, ShallowWrapper } from 'enzyme';
+import * as React from 'react';
+import { mockComponent } from '../../../../helpers/testMocks';
+import RenderOptions from '../../components/RenderOptions';
+import { renderStepContent } from '../../jenkins/test-utils';
+import ProjectKeyStep, { ProjectKeyStepProps } from '../ProjectKeyStep';
+import { BuildTools } from '../types';
+
+it('should render correctly', () => {
+ const wrapper = shallowRender();
+ expect(wrapper).toMatchSnapshot('Step wrapper');
+ expect(renderStepContent(wrapper)).toMatchSnapshot('initial content');
+});
+
+it.each([[BuildTools.Maven], [BuildTools.Gradle], [BuildTools.Other]])(
+ 'should render correctly for build tool %s',
+ buildTool => {
+ expect(renderStepContent(shallowRender({ buildTool }))).toMatchSnapshot();
+ }
+);
+
+it('should correctly callback with selected build tool', () => {
+ const setBuildTool = jest.fn();
+ const wrapper = shallowRender({ setBuildTool });
+ selectBuildTool(wrapper, BuildTools.Maven);
+
+ expect(setBuildTool).toBeCalledWith(BuildTools.Maven);
+});
+
+function selectBuildTool(wrapper: ShallowWrapper<ProjectKeyStepProps>, tool: BuildTools) {
+ const content = new ShallowWrapper(renderStepContent(wrapper) as JSX.Element);
+ content
+ .find(RenderOptions)
+ .props()
+ .onCheck(tool);
+}
+
+function shallowRender(props: Partial<ProjectKeyStepProps> = {}) {
+ return shallow<ProjectKeyStepProps>(
+ <ProjectKeyStep
+ component={mockComponent()}
+ finished={false}
+ onDone={jest.fn()}
+ onOpen={jest.fn()}
+ open={true}
+ setBuildTool={jest.fn()}
+ {...props}
+ />
+ );
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 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 { shallow } from 'enzyme';
+import * as React from 'react';
+import { renderStepContent } from '../../jenkins/test-utils';
+import { BuildTools } from '../types';
+import YmlFileStep, { YmlFileStepProps } from '../YmlFileStep';
+
+it('should render correctly', () => {
+ const wrapper = shallowRender();
+ expect(wrapper).toMatchSnapshot('Step wrapper');
+ expect(renderStepContent(wrapper)).toMatchSnapshot('initial content');
+});
+
+it.each([[BuildTools.Maven], [BuildTools.Gradle], [BuildTools.Other]])(
+ 'should render correctly for build tool %s',
+ buildTool => {
+ expect(renderStepContent(shallowRender({ buildTool }))).toMatchSnapshot();
+ }
+);
+
+function shallowRender(props: Partial<YmlFileStepProps> = {}) {
+ return shallow<YmlFileStepProps>(<YmlFileStep open={true} {...props} />);
+}
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly: Step wrapper 1`] = `
+<Fragment>
+ <Step
+ finished={false}
+ onOpen={[MockFunction]}
+ open={true}
+ renderForm={[Function]}
+ stepNumber={2}
+ stepTitle="onboarding.tutorial.with.gitlab_ci.env_variables.title"
+ />
+</Fragment>
+`;
+
+exports[`should render correctly: initial content 1`] = `
+<div
+ className="boxed-group-inner"
+>
+ <h2
+ className="spacer-bottom spacer-top"
+ >
+ onboarding.tutorial.with.gitlab_ci.env_variables.section.title
+ </h2>
+ <FormattedMessage
+ defaultMessage="onboarding.tutorial.with.gitlab_ci.env_variables.section.description"
+ id="onboarding.tutorial.with.gitlab_ci.env_variables.section.description"
+ values={
+ Object {
+ "link": <strong>
+ onboarding.tutorial.with.gitlab_ci.env_variables.description.link
+ </strong>,
+ }
+ }
+ />
+ <ol
+ className="list-styled big-spacer-top"
+ >
+ <li
+ className="big-spacer-bottom"
+ >
+ <FormattedMessage
+ defaultMessage="onboarding.tutorial.with.gitlab_ci.env_variables.enter_field_value"
+ id="onboarding.tutorial.with.gitlab_ci.env_variables.step1"
+ values={
+ Object {
+ "extra": <ClipboardIconButton
+ copyValue="SONAR_TOKEN"
+ />,
+ "field": "onboarding.tutorial.with.gitlab_ci.env_variables.step1",
+ "value": <code
+ className="rule"
+ >
+ SONAR_TOKEN
+ </code>,
+ }
+ }
+ />
+ </li>
+ <li
+ className="big-spacer-bottom"
+ >
+ <FormattedMessage
+ defaultMessage="onboarding.tutorial.with.gitlab_ci.env_variables.enter_field_value"
+ id="onboarding.tutorial.with.gitlab_ci.env_variables.step2"
+ values={
+ Object {
+ "extra": <Button
+ className="spacer-left"
+ onClick={[Function]}
+ >
+ onboarding.token.generate_token
+ </Button>,
+ "field": "onboarding.tutorial.with.gitlab_ci.env_variables.step2",
+ "value": "onboarding.tutorial.with.gitlab_ci.env_variables.section.step2.value",
+ }
+ }
+ />
+ </li>
+ <li
+ className="big-spacer-bottom"
+ >
+ onboarding.tutorial.with.gitlab_ci.env_variables.step3
+ </li>
+ <li
+ className="big-spacer-bottom"
+ >
+ onboarding.tutorial.with.gitlab_ci.env_variables.section.step4
+ </li>
+ </ol>
+ <hr
+ className="no-horizontal-margins"
+ />
+ <h2
+ className="spacer-bottom big-spacer-top"
+ >
+ onboarding.tutorial.with.gitlab_ci.env_variables.section2.title
+ </h2>
+ <FormattedMessage
+ defaultMessage="onboarding.tutorial.with.gitlab_ci.env_variables.section2.description"
+ id="onboarding.tutorial.with.gitlab_ci.env_variables.section2.description"
+ values={
+ Object {
+ "link": <strong>
+ onboarding.tutorial.with.gitlab_ci.env_variables.description.link
+ </strong>,
+ }
+ }
+ />
+ <ol
+ className="list-styled big-spacer-top big-spacer-bottom"
+ >
+ <li
+ className="big-spacer-bottom"
+ >
+ <FormattedMessage
+ defaultMessage="onboarding.tutorial.with.gitlab_ci.env_variables.enter_field_value"
+ id="onboarding.tutorial.with.gitlab_ci.env_variables.step1"
+ values={
+ Object {
+ "extra": <ClipboardIconButton
+ copyValue="SONAR_HOST_URL"
+ />,
+ "field": "onboarding.tutorial.with.gitlab_ci.env_variables.step1",
+ "value": <code
+ className="rule"
+ >
+ SONAR_HOST_URL
+ </code>,
+ }
+ }
+ />
+ </li>
+ <li
+ className="big-spacer-bottom"
+ >
+ <FormattedMessage
+ defaultMessage="onboarding.tutorial.with.gitlab_ci.env_variables.enter_field_value"
+ id="onboarding.tutorial.with.gitlab_ci.env_variables.step2"
+ values={
+ Object {
+ "extra": <ClipboardIconButton
+ copyValue="http://localhost"
+ />,
+ "field": "onboarding.tutorial.with.gitlab_ci.env_variables.step2",
+ "value": <code
+ className="rule"
+ >
+ http://localhost
+ </code>,
+ }
+ }
+ />
+ </li>
+ <li
+ className="big-spacer-bottom"
+ >
+ onboarding.tutorial.with.gitlab_ci.env_variables.step3
+ </li>
+ <li
+ className="big-spacer-bottom"
+ >
+ onboarding.tutorial.with.gitlab_ci.env_variables.section2.step4
+ </li>
+ </ol>
+ <Button
+ className="big-spacer-bottom"
+ onClick={[MockFunction]}
+ >
+ continue
+ </Button>
+</div>
+`;
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<Fragment>
+ <div
+ className="page-header big-spacer-bottom"
+ >
+ <h1
+ className="page-title"
+ >
+ onboarding.tutorial.with.gitlab_ci.title
+ </h1>
+ </div>
+ <ProjectKeyStep
+ component={
+ Object {
+ "breadcrumbs": Array [],
+ "key": "my-project",
+ "name": "MyProject",
+ "organization": "foo",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ }
+ }
+ finished={false}
+ onDone={[Function]}
+ onOpen={[Function]}
+ open={true}
+ setBuildTool={[Function]}
+ />
+ <EnvironmentVariablesStep
+ component={
+ Object {
+ "breadcrumbs": Array [],
+ "key": "my-project",
+ "name": "MyProject",
+ "organization": "foo",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ }
+ }
+ currentUser={
+ Object {
+ "groups": Array [],
+ "isLoggedIn": true,
+ "login": "luke",
+ "name": "Skywalker",
+ "scmAccounts": Array [],
+ }
+ }
+ finished={false}
+ onDone={[Function]}
+ onOpen={[Function]}
+ open={false}
+ />
+ <YmlFileStep
+ open={false}
+ />
+</Fragment>
+`;
+
+exports[`should render correctly: wrong alm 1`] = `
+<Alert
+ variant="error"
+>
+ onboarding.tutorial.with.gitlab_ci.unsupported
+</Alert>
+`;
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly for build tool gradle 1`] = `
+<div
+ className="boxed-group-inner"
+>
+ <ol
+ className="list-styled"
+ >
+ <li>
+ onboarding.build
+ <RenderOptions
+ checked="gradle"
+ name="buildtool"
+ onCheck={[Function]}
+ optionLabelKey="onboarding.build"
+ options={
+ Array [
+ "maven",
+ "gradle",
+ "other",
+ ]
+ }
+ />
+ </li>
+ <li
+ className="abs-width-600"
+ >
+ <FormattedMessage
+ defaultMessage="onboarding.tutorial.with.gitlab_ci.project_key.gradle.step2"
+ id="onboarding.tutorial.with.gitlab_ci.project_key.gradle.step2"
+ values={
+ Object {
+ "file": <React.Fragment>
+ <code
+ className="rule"
+ >
+ build.gradle
+ </code>
+ <ClipboardIconButton
+ className="little-spacer-left"
+ copyValue="build.gradle"
+ />
+ </React.Fragment>,
+ }
+ }
+ />
+ <CodeSnippet
+ snippet="plugins {
+ id \\"org.sonarqube\\" version \\"3.0\\"
+}
+
+sonarqube {
+ properties {
+ property \\"sonar.projectKey\\", \\"my-project\\"
+ property \\"sonar.qualitygate.wait\\", true
+ }
+}"
+ />
+ </li>
+ </ol>
+ <Button
+ onClick={[MockFunction]}
+ >
+ continue
+ </Button>
+</div>
+`;
+
+exports[`should render correctly for build tool maven 1`] = `
+<div
+ className="boxed-group-inner"
+>
+ <ol
+ className="list-styled"
+ >
+ <li>
+ onboarding.build
+ <RenderOptions
+ checked="maven"
+ name="buildtool"
+ onCheck={[Function]}
+ optionLabelKey="onboarding.build"
+ options={
+ Array [
+ "maven",
+ "gradle",
+ "other",
+ ]
+ }
+ />
+ </li>
+ <li
+ className="abs-width-600"
+ >
+ <FormattedMessage
+ defaultMessage="onboarding.tutorial.with.gitlab_ci.project_key.maven.step2"
+ id="onboarding.tutorial.with.gitlab_ci.project_key.maven.step2"
+ values={
+ Object {
+ "file": <React.Fragment>
+ <code
+ className="rule"
+ >
+ pom.xml
+ </code>
+ <ClipboardIconButton
+ className="little-spacer-left"
+ copyValue="pom.xml"
+ />
+ </React.Fragment>,
+ }
+ }
+ />
+ <CodeSnippet
+ snippet="<properties>
+ <sonar.projectKey>my-project</sonar.projectKey>
+ <sonar.qualitygate.wait>true</sonar.qualitygate.wait>
+</properties>"
+ />
+ </li>
+ </ol>
+ <Button
+ onClick={[MockFunction]}
+ >
+ continue
+ </Button>
+</div>
+`;
+
+exports[`should render correctly for build tool other 1`] = `
+<div
+ className="boxed-group-inner"
+>
+ <ol
+ className="list-styled"
+ >
+ <li>
+ onboarding.build
+ <RenderOptions
+ checked="other"
+ name="buildtool"
+ onCheck={[Function]}
+ optionLabelKey="onboarding.build"
+ options={
+ Array [
+ "maven",
+ "gradle",
+ "other",
+ ]
+ }
+ />
+ </li>
+ <li
+ className="abs-width-600"
+ >
+ <FormattedMessage
+ defaultMessage="onboarding.tutorial.with.gitlab_ci.project_key.other.step2"
+ id="onboarding.tutorial.with.gitlab_ci.project_key.other.step2"
+ values={
+ Object {
+ "file": <React.Fragment>
+ <code
+ className="rule"
+ >
+ sonar-project.properties
+ </code>
+ <ClipboardIconButton
+ className="little-spacer-left"
+ copyValue="sonar-project.properties"
+ />
+ </React.Fragment>,
+ }
+ }
+ />
+ <CodeSnippet
+ snippet="sonar.projectKey=my-project
+sonar.qualitygate.wait=true
+"
+ />
+ </li>
+ </ol>
+ <Button
+ onClick={[MockFunction]}
+ >
+ continue
+ </Button>
+</div>
+`;
+
+exports[`should render correctly: Step wrapper 1`] = `
+<Step
+ finished={false}
+ onOpen={[MockFunction]}
+ open={true}
+ renderForm={[Function]}
+ stepNumber={1}
+ stepTitle="onboarding.tutorial.with.gitlab_ci.project_key.title"
+/>
+`;
+
+exports[`should render correctly: initial content 1`] = `
+<div
+ className="boxed-group-inner"
+>
+ <ol
+ className="list-styled"
+ >
+ <li>
+ onboarding.build
+ <RenderOptions
+ name="buildtool"
+ onCheck={[Function]}
+ optionLabelKey="onboarding.build"
+ options={
+ Array [
+ "maven",
+ "gradle",
+ "other",
+ ]
+ }
+ />
+ </li>
+ </ol>
+</div>
+`;
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly for build tool gradle 1`] = `
+<div
+ className="boxed-group-inner"
+>
+ <div
+ className="flex-columns"
+ >
+ <div
+ className="flex-column-full"
+ >
+ <React.Fragment>
+ <div
+ className="big-spacer-bottom"
+ >
+ <FormattedMessage
+ defaultMessage="onboarding.tutorial.with.gitlab_ci.yml.description"
+ id="onboarding.tutorial.with.gitlab_ci.yml.description"
+ values={
+ Object {
+ "filename": <React.Fragment>
+ <code
+ className="rule"
+ >
+ onboarding.tutorial.with.gitlab_ci.yml.filename
+ </code>
+ <ClipboardIconButton
+ className="little-spacer-left"
+ copyValue="onboarding.tutorial.with.gitlab_ci.yml.filename"
+ />
+ </React.Fragment>,
+ }
+ }
+ />
+ </div>
+ <div
+ className="big-spacer-bottom"
+ >
+ <PipeCommandGradle />
+ </div>
+ <p
+ className="little-spacer-bottom"
+ >
+ onboarding.tutorial.with.gitlab_ci.yml.baseconfig
+ </p>
+ <p
+ className="huge-spacer-bottom"
+ >
+ onboarding.tutorial.with.gitlab_ci.yml.existing
+ </p>
+ <hr
+ className="no-horizontal-margins"
+ />
+ <div>
+ <p
+ className="big-spacer-bottom"
+ >
+ <strong>
+ onboarding.tutorial.with.gitlab_ci.yml.done
+
+ </strong>
+
+ <FormattedMessage
+ defaultMessage="onboarding.tutorial.with.gitlab_ci.yml.done.description"
+ id="onboarding.tutorial.with.gitlab_ci.yml.done.description"
+ values={
+ Object {
+ "link": "onboarding.tutorial.with.gitlab_ci.yml.done.description.link",
+ }
+ }
+ />
+ </p>
+ <p
+ className="big-spacer-bottom"
+ >
+ <strong>
+ onboarding.tutorial.with.gitlab_ci.yml.done.then-what
+ </strong>
+
+ onboarding.tutorial.with.gitlab_ci.yml.done.then-what.description
+ </p>
+ <p
+ className="big-spacer-bottom"
+ >
+ <FormattedMessage
+ defaultMessage="onboarding.tutorial.with.gitlab_ci.yml.done.links.title"
+ id="onboarding.tutorial.with.gitlab_ci.yml.done.links.title"
+ values={
+ Object {
+ "links": <Link
+ onlyActiveOnIndex={false}
+ rel="noopener noreferrer"
+ style={Object {}}
+ target="_blank"
+ to="/documentation/user-guide/quality-gates/"
+ >
+ onboarding.tutorial.with.gitlab_ci.yml.done.links.QG
+ </Link>,
+ }
+ }
+ />
+ </p>
+ </div>
+ </React.Fragment>
+ </div>
+ </div>
+</div>
+`;
+
+exports[`should render correctly for build tool maven 1`] = `
+<div
+ className="boxed-group-inner"
+>
+ <div
+ className="flex-columns"
+ >
+ <div
+ className="flex-column-full"
+ >
+ <React.Fragment>
+ <div
+ className="big-spacer-bottom"
+ >
+ <FormattedMessage
+ defaultMessage="onboarding.tutorial.with.gitlab_ci.yml.description"
+ id="onboarding.tutorial.with.gitlab_ci.yml.description"
+ values={
+ Object {
+ "filename": <React.Fragment>
+ <code
+ className="rule"
+ >
+ onboarding.tutorial.with.gitlab_ci.yml.filename
+ </code>
+ <ClipboardIconButton
+ className="little-spacer-left"
+ copyValue="onboarding.tutorial.with.gitlab_ci.yml.filename"
+ />
+ </React.Fragment>,
+ }
+ }
+ />
+ </div>
+ <div
+ className="big-spacer-bottom"
+ >
+ <PipeCommandMaven />
+ </div>
+ <p
+ className="little-spacer-bottom"
+ >
+ onboarding.tutorial.with.gitlab_ci.yml.baseconfig
+ </p>
+ <p
+ className="huge-spacer-bottom"
+ >
+ onboarding.tutorial.with.gitlab_ci.yml.existing
+ </p>
+ <hr
+ className="no-horizontal-margins"
+ />
+ <div>
+ <p
+ className="big-spacer-bottom"
+ >
+ <strong>
+ onboarding.tutorial.with.gitlab_ci.yml.done
+
+ </strong>
+
+ <FormattedMessage
+ defaultMessage="onboarding.tutorial.with.gitlab_ci.yml.done.description"
+ id="onboarding.tutorial.with.gitlab_ci.yml.done.description"
+ values={
+ Object {
+ "link": "onboarding.tutorial.with.gitlab_ci.yml.done.description.link",
+ }
+ }
+ />
+ </p>
+ <p
+ className="big-spacer-bottom"
+ >
+ <strong>
+ onboarding.tutorial.with.gitlab_ci.yml.done.then-what
+ </strong>
+
+ onboarding.tutorial.with.gitlab_ci.yml.done.then-what.description
+ </p>
+ <p
+ className="big-spacer-bottom"
+ >
+ <FormattedMessage
+ defaultMessage="onboarding.tutorial.with.gitlab_ci.yml.done.links.title"
+ id="onboarding.tutorial.with.gitlab_ci.yml.done.links.title"
+ values={
+ Object {
+ "links": <Link
+ onlyActiveOnIndex={false}
+ rel="noopener noreferrer"
+ style={Object {}}
+ target="_blank"
+ to="/documentation/user-guide/quality-gates/"
+ >
+ onboarding.tutorial.with.gitlab_ci.yml.done.links.QG
+ </Link>,
+ }
+ }
+ />
+ </p>
+ </div>
+ </React.Fragment>
+ </div>
+ </div>
+</div>
+`;
+
+exports[`should render correctly for build tool other 1`] = `
+<div
+ className="boxed-group-inner"
+>
+ <div
+ className="flex-columns"
+ >
+ <div
+ className="flex-column-full"
+ >
+ <React.Fragment>
+ <div
+ className="big-spacer-bottom"
+ >
+ <FormattedMessage
+ defaultMessage="onboarding.tutorial.with.gitlab_ci.yml.description"
+ id="onboarding.tutorial.with.gitlab_ci.yml.description"
+ values={
+ Object {
+ "filename": <React.Fragment>
+ <code
+ className="rule"
+ >
+ onboarding.tutorial.with.gitlab_ci.yml.filename
+ </code>
+ <ClipboardIconButton
+ className="little-spacer-left"
+ copyValue="onboarding.tutorial.with.gitlab_ci.yml.filename"
+ />
+ </React.Fragment>,
+ }
+ }
+ />
+ </div>
+ <div
+ className="big-spacer-bottom"
+ >
+ <PipeCommandOther />
+ </div>
+ <p
+ className="little-spacer-bottom"
+ >
+ onboarding.tutorial.with.gitlab_ci.yml.baseconfig
+ </p>
+ <p
+ className="huge-spacer-bottom"
+ >
+ onboarding.tutorial.with.gitlab_ci.yml.existing
+ </p>
+ <hr
+ className="no-horizontal-margins"
+ />
+ <div>
+ <p
+ className="big-spacer-bottom"
+ >
+ <strong>
+ onboarding.tutorial.with.gitlab_ci.yml.done
+
+ </strong>
+
+ <FormattedMessage
+ defaultMessage="onboarding.tutorial.with.gitlab_ci.yml.done.description"
+ id="onboarding.tutorial.with.gitlab_ci.yml.done.description"
+ values={
+ Object {
+ "link": "onboarding.tutorial.with.gitlab_ci.yml.done.description.link",
+ }
+ }
+ />
+ </p>
+ <p
+ className="big-spacer-bottom"
+ >
+ <strong>
+ onboarding.tutorial.with.gitlab_ci.yml.done.then-what
+ </strong>
+
+ onboarding.tutorial.with.gitlab_ci.yml.done.then-what.description
+ </p>
+ <p
+ className="big-spacer-bottom"
+ >
+ <FormattedMessage
+ defaultMessage="onboarding.tutorial.with.gitlab_ci.yml.done.links.title"
+ id="onboarding.tutorial.with.gitlab_ci.yml.done.links.title"
+ values={
+ Object {
+ "links": <Link
+ onlyActiveOnIndex={false}
+ rel="noopener noreferrer"
+ style={Object {}}
+ target="_blank"
+ to="/documentation/user-guide/quality-gates/"
+ >
+ onboarding.tutorial.with.gitlab_ci.yml.done.links.QG
+ </Link>,
+ }
+ }
+ />
+ </p>
+ </div>
+ </React.Fragment>
+ </div>
+ </div>
+</div>
+`;
+
+exports[`should render correctly: Step wrapper 1`] = `
+<Step
+ finished={false}
+ open={true}
+ renderForm={[Function]}
+ stepNumber={3}
+ stepTitle="onboarding.tutorial.with.gitlab_ci.yml.title"
+/>
+`;
+
+exports[`should render correctly: initial content 1`] = `
+<div
+ className="boxed-group-inner"
+>
+ <div
+ className="flex-columns"
+ >
+ <div
+ className="flex-column-full"
+ />
+ </div>
+</div>
+`;
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 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 CodeSnippet from '../../../common/CodeSnippet';
+
+export default function PipeCommandGradle() {
+ const command = `sonarqube-check:
+ image: gradle:jre11-slim
+ variables:
+ SONAR_USER_HOME: "\${CI_PROJECT_DIR}/.sonar" # Defines the location of the analysis task cache
+ GIT_DEPTH: "0" # Tells git to fetch all the branches of the project, required by the analysis task
+ cache:
+ key: "\${CI_JOB_NAME}"
+ paths:
+ - .sonar/cache
+ script: gradle sonarqube
+ allow_failure: true
+ only:
+ - merge_requests
+ - master
+ - develop
+`;
+
+ return <CodeSnippet snippet={command} />;
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 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 CodeSnippet from '../../../common/CodeSnippet';
+
+export default function PipeCommandMaven() {
+ const command = `sonarqube-check:
+ image: maven:3.6.3-jdk-11
+ variables:
+ SONAR_USER_HOME: "\${CI_PROJECT_DIR}/.sonar" # Defines the location of the analysis task cache
+ GIT_DEPTH: "0" # Tells git to fetch all the branches of the project, required by the analysis task
+ cache:
+ key: "\${CI_JOB_NAME}"
+ paths:
+ - .sonar/cache
+ script:
+ - mvn verify sonar:sonar
+ allow_failure: true
+ only:
+ - merge_requests
+ - master
+ - develop
+`;
+
+ return <CodeSnippet snippet={command} />;
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 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 CodeSnippet from '../../../common/CodeSnippet';
+
+export default function PipeCommandOther() {
+ const command = `sonarqube-check:
+ image:
+ name: sonarsource/sonar-scanner-cli:latest
+ entrypoint: [""]
+ variables:
+ SONAR_USER_HOME: "\${CI_PROJECT_DIR}/.sonar" # Defines the location of the analysis task cache
+ GIT_DEPTH: "0" # Tells git to fetch all the branches of the project, required by the analysis task
+ cache:
+ key: "\${CI_JOB_NAME}"
+ paths:
+ - .sonar/cache
+ script:
+ - sonar-scanner
+ allow_failure: true
+ only:
+ - merge_requests
+ - master
+ - develop
+`;
+
+ return <CodeSnippet snippet={command} />;
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 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 { shallow } from 'enzyme';
+import * as React from 'react';
+import PipeCommandGradle from '../PipeCommandGradle';
+
+it('should render correctly', () => {
+ expect(shallow(<PipeCommandGradle />)).toMatchSnapshot();
+});
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 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 { shallow } from 'enzyme';
+import * as React from 'react';
+import PipeCommandMaven from '../PipeCommandMaven';
+
+it('should render correctly', () => {
+ expect(shallow(<PipeCommandMaven />)).toMatchSnapshot();
+});
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 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 { shallow } from 'enzyme';
+import * as React from 'react';
+import PipeCommandOther from '../PipeCommandOther';
+
+it('should render correctly', () => {
+ expect(shallow(<PipeCommandOther />)).toMatchSnapshot();
+});
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<CodeSnippet
+ snippet="sonarqube-check:
+ image: gradle:jre11-slim
+ variables:
+ SONAR_USER_HOME: \\"\${CI_PROJECT_DIR}/.sonar\\" # Defines the location of the analysis task cache
+ GIT_DEPTH: \\"0\\" # Tells git to fetch all the branches of the project, required by the analysis task
+ cache:
+ key: \\"\${CI_JOB_NAME}\\"
+ paths:
+ - .sonar/cache
+ script: gradle sonarqube
+ allow_failure: true
+ only:
+ - merge_requests
+ - master
+ - develop
+"
+/>
+`;
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<CodeSnippet
+ snippet="sonarqube-check:
+ image: maven:3.6.3-jdk-11
+ variables:
+ SONAR_USER_HOME: \\"\${CI_PROJECT_DIR}/.sonar\\" # Defines the location of the analysis task cache
+ GIT_DEPTH: \\"0\\" # Tells git to fetch all the branches of the project, required by the analysis task
+ cache:
+ key: \\"\${CI_JOB_NAME}\\"
+ paths:
+ - .sonar/cache
+ script:
+ - mvn verify sonar:sonar
+ allow_failure: true
+ only:
+ - merge_requests
+ - master
+ - develop
+"
+/>
+`;
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<CodeSnippet
+ snippet="sonarqube-check:
+ image:
+ name: sonarsource/sonar-scanner-cli:latest
+ entrypoint: [\\"\\"]
+ variables:
+ SONAR_USER_HOME: \\"\${CI_PROJECT_DIR}/.sonar\\" # Defines the location of the analysis task cache
+ GIT_DEPTH: \\"0\\" # Tells git to fetch all the branches of the project, required by the analysis task
+ cache:
+ key: \\"\${CI_JOB_NAME}\\"
+ paths:
+ - .sonar/cache
+ script:
+ - sonar-scanner
+ allow_failure: true
+ only:
+ - merge_requests
+ - master
+ - develop
+"
+/>
+`;
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 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.
+ */
+export enum BuildTools {
+ Maven = 'maven',
+ Gradle = 'gradle',
+ // MSBuild = 'msbuild', // Not yet supported
+ Other = 'other'
+}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2020 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.
- */
-.tutorial-selection {
- margin: 0 auto;
- max-width: 500px;
-}
*/
export enum TutorialModes {
Manual = 'manual',
- Jenkins = 'jenkins'
+ Jenkins = 'jenkins',
+ GitLabCI = 'gitlab-ci'
}
export interface LanguageConfig {
GithubBindingDefinition,
ProjectAlmBindingResponse,
ProjectBitbucketBindingResponse,
- ProjectGitHubBindingResponse
+ ProjectGitHubBindingResponse,
+ ProjectGitLabBindingResponse
} from '../types/alm-settings';
export function isProjectBitbucketBindingResponse(
return binding.alm === AlmKeys.GitHub;
}
+export function isProjectGitLabBindingResponse(
+ binding: ProjectAlmBindingResponse
+): binding is ProjectGitLabBindingResponse {
+ return binding.alm === AlmKeys.GitLab;
+}
+
export function isBitbucketBindingDefinition(
binding?: AlmBindingDefinition & { url?: string; personalAccessToken?: string }
): binding is BitbucketBindingDefinition {
GitlabBindingDefinition,
ProjectAlmBindingResponse,
ProjectBitbucketBindingResponse,
- ProjectGitHubBindingResponse
+ ProjectGitHubBindingResponse,
+ ProjectGitLabBindingResponse
} from '../../types/alm-settings';
export function mockAlmSettingsInstance(
...overrides
};
}
+
+export function mockProjectGitLabBindingResponse(
+ overrides: Partial<ProjectGitLabBindingResponse> = {}
+): ProjectGitLabBindingResponse {
+ return {
+ alm: AlmKeys.GitLab,
+ key: 'foo',
+ repository: 'PROJECT_KEY',
+ url: 'https://gitlab.com/api/v4',
+ ...overrides
+ };
+}
repository: string;
}
+export interface ProjectGitLabBindingResponse extends ProjectAlmBindingResponse {
+ alm: AlmKeys.GitLab;
+ repository: string;
+ url: string;
+}
+
export interface ProjectAlmBindingParams {
almSetting: string;
project: string;
onboarding.token.generate_token.placeholder=Enter a name for your token
onboarding.token.use_existing_token=Use existing token
onboarding.token.use_existing_token.placeholder=Enter your existing token
+onboarding.token.use_existing_token.label=Existing token value
onboarding.token.invalid_format=The token you have entered has invalid format.
onboarding.analysis.header=Run analysis on your project
onboarding.tutorial.choose_method=How do you want to analyze your repository?
onboarding.tutorial.choose_method.manual=Manually
onboarding.tutorial.choose_method.jenkins=With Jenkins
+onboarding.tutorial.choose_method.gitlab_ci=With GitLab CI
+
+onboarding.tutorial.with.gitlab_ci.title=Analyze your project with GitLab CI
+onboarding.tutorial.with.gitlab_ci.unsupported=This tutorial is only available for projects bound to GitLab.
+onboarding.tutorial.with.gitlab_ci.project_key.title=Set your project key
+onboarding.tutorial.with.gitlab_ci.project_key.maven.step2=Add the following to your {file} file:
+onboarding.tutorial.with.gitlab_ci.project_key.gradle.step2=Add the following to your {file} file:
+onboarding.tutorial.with.gitlab_ci.project_key.other.step2=Create a {file} file in your repository and paste the following code:
+
+onboarding.tutorial.with.gitlab_ci.env_variables.title=Add environment variables
+onboarding.tutorial.with.gitlab_ci.env_variables.enter_field_value=In the {field} field, enter {value} {extra}
+onboarding.tutorial.with.gitlab_ci.env_variables.description.link=Settings > CI/CD > Variables
+onboarding.tutorial.with.gitlab_ci.env_variables.section.title=a. Define the SonarQube Token environment variable
+onboarding.tutorial.with.gitlab_ci.env_variables.section.description=In GitLab, go to {link} to add the following variable and make sure it is available for your project:
+onboarding.tutorial.with.gitlab_ci.env_variables.edit.token.tooltip=Use an existing token or generate a new one.
+onboarding.tutorial.with.gitlab_ci.env_variables.step1=Key
+onboarding.tutorial.with.gitlab_ci.env_variables.step2=Value
+onboarding.tutorial.with.gitlab_ci.env_variables.section.step2.value=an existing token, or a newly generated one:
+onboarding.tutorial.with.gitlab_ci.env_variables.step3=Uncheck the "Protect Variable" checkbox
+onboarding.tutorial.with.gitlab_ci.env_variables.section.step4=Check the "Mask Variable" checkbox
+onboarding.tutorial.with.gitlab_ci.env_variables.section2.title=b. Define the SonarQube URL environment variable
+onboarding.tutorial.with.gitlab_ci.env_variables.section2.description=Still in {link} add a new variable and make sure it is available for your project:
+onboarding.tutorial.with.gitlab_ci.env_variables.section2.step4=Leave the "Mask variable" checkbox unchecked
+onboarding.tutorial.with.gitlab_ci.yml.title=Create or update the configuration file
+onboarding.tutorial.with.gitlab_ci.yml.description=Create or update your {filename} file with the following content.
+onboarding.tutorial.with.gitlab_ci.yml.filename=.gitlab-ci.yml
+onboarding.tutorial.with.gitlab_ci.yml.baseconfig=Note that this is a minimal base configuration to run a SonarQube analysis on your master branch and merge requests.
+onboarding.tutorial.with.gitlab_ci.yml.existing=If you already have a pipeline configured and running, you might want to add the example from this step to your existing yml file.
+onboarding.tutorial.with.gitlab_ci.yml.done=Is it done?
+onboarding.tutorial.with.gitlab_ci.yml.done.description=You should see the page refresh itself in a few moments with your analysis results if the {link}.
+onboarding.tutorial.with.gitlab_ci.yml.done.description.link=pipeline runs successfully
+onboarding.tutorial.with.gitlab_ci.yml.done.then-what=And then what?
+onboarding.tutorial.with.gitlab_ci.yml.done.then-what.description=Each new push triggers an analysis by SonarQube.
+onboarding.tutorial.with.gitlab_ci.yml.done.links.title=Check this useful link while you wait: {links}
+onboarding.tutorial.with.gitlab_ci.yml.done.links.QG=What is a Quality Gate?
onboarding.tutorial.with.jenkins.title=Analyze your project with Jenkins
onboarding.tutorial.with.jenkins.unsupported=This tutorial is only available for projects bound to Bitbucket Server or GitHub.