diff options
author | Jeremy Davis <jeremy.davis@sonarsource.com> | 2021-01-27 11:18:21 +0100 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2021-02-04 20:07:07 +0000 |
commit | 3dc692ce6ea5381356cab7ff3d9e61f3f71ec86c (patch) | |
tree | 3cbcec5e8cd11e2677cd3265ac9f61c9640bc6c1 | |
parent | 38069298aa720559a7630734131491a6b207948c (diff) | |
download | sonarqube-3dc692ce6ea5381356cab7ff3d9e61f3f71ec86c.tar.gz sonarqube-3dc692ce6ea5381356cab7ff3d9e61f3f71ec86c.zip |
SONAR-14354 Jenkins tutorial for CE
22 files changed, 769 insertions, 38 deletions
diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsTutorial.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsTutorial.tsx index 62d937fefe8..fe91dd16adf 100644 --- a/server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsTutorial.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsTutorial.tsx @@ -21,7 +21,7 @@ import * as React from 'react'; import { connect } from 'react-redux'; import { Alert } from 'sonar-ui-common/components/ui/Alert'; import { translate } from 'sonar-ui-common/helpers/l10n'; -import { getCurrentUserSetting, Store } from '../../../store/rootReducer'; +import { getAppState, getCurrentUserSetting, Store } from '../../../store/rootReducer'; import { setCurrentUserSetting } from '../../../store/users'; import { AlmBindingDefinition, @@ -31,11 +31,13 @@ import { } from '../../../types/alm-settings'; import JenkinsfileStep from './JenkinsfileStep'; import MultiBranchPipelineStep from './MultiBranchPipelineStep'; +import PipelineStep from './PipelineStep'; import PreRequisitesStep from './PreRequisitesStep'; import WebhookStep from './WebhookStep'; export interface JenkinsTutorialProps { almBinding?: AlmBindingDefinition; + branchesEnabled: boolean; component: T.Component; projectBinding: ProjectAlmBindingResponse; setCurrentUserSetting: (setting: T.CurrentUserSetting) => void; @@ -52,7 +54,7 @@ enum Steps { const USER_SETTING_SKIP_BITBUCKET_PREREQS = 'tutorials.jenkins.skipBitbucketPreReqs'; export function JenkinsTutorial(props: JenkinsTutorialProps) { - const { almBinding, component, projectBinding, skipPreReqs } = props; + const { almBinding, branchesEnabled, component, projectBinding, skipPreReqs } = props; const [step, setStep] = React.useState( skipPreReqs ? Steps.MultiBranchPipeline : Steps.PreRequisites ); @@ -75,6 +77,7 @@ export function JenkinsTutorial(props: JenkinsTutorialProps) { <PreRequisitesStep alm={projectBinding.alm} + branchesEnabled={branchesEnabled} onDone={() => setStep(Steps.MultiBranchPipeline)} onOpen={() => setStep(Steps.PreRequisites)} onChangeSkipNextTime={skip => { @@ -87,17 +90,27 @@ export function JenkinsTutorial(props: JenkinsTutorialProps) { skipNextTime={skipPreReqs} /> - <MultiBranchPipelineStep - almBinding={almBinding} - finished={step > Steps.MultiBranchPipeline} - onDone={() => setStep(Steps.Webhook)} - onOpen={() => setStep(Steps.MultiBranchPipeline)} - open={step === Steps.MultiBranchPipeline} - projectBinding={projectBinding} - /> + {branchesEnabled ? ( + <MultiBranchPipelineStep + almBinding={almBinding} + finished={step > Steps.MultiBranchPipeline} + onDone={() => setStep(Steps.Webhook)} + onOpen={() => setStep(Steps.MultiBranchPipeline)} + open={step === Steps.MultiBranchPipeline} + projectBinding={projectBinding} + /> + ) : ( + <PipelineStep + finished={step > Steps.MultiBranchPipeline} + onDone={() => setStep(Steps.Webhook)} + onOpen={() => setStep(Steps.MultiBranchPipeline)} + open={step === Steps.MultiBranchPipeline} + /> + )} <WebhookStep almBinding={almBinding} + branchesEnabled={branchesEnabled} finished={step > Steps.Webhook} onDone={() => setStep(Steps.Jenkinsfile)} onOpen={() => setStep(Steps.Webhook)} @@ -110,8 +123,11 @@ export function JenkinsTutorial(props: JenkinsTutorialProps) { ); } -const mapStateToProps = (state: Store): Pick<JenkinsTutorialProps, 'skipPreReqs'> => { +const mapStateToProps = ( + state: Store +): Pick<JenkinsTutorialProps, 'branchesEnabled' | 'skipPreReqs'> => { return { + branchesEnabled: Boolean(getAppState(state).branchesEnabled), skipPreReqs: getCurrentUserSetting(state, USER_SETTING_SKIP_BITBUCKET_PREREQS) === 'true' }; }; diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsfileStep.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsfileStep.tsx index 4eab0390317..e81304b0772 100644 --- a/server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsfileStep.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsfileStep.tsx @@ -20,6 +20,7 @@ import * as React from 'react'; import { translate } from 'sonar-ui-common/helpers/l10n'; import { getBaseUrl } from 'sonar-ui-common/helpers/urls'; +import { withAppState } from '../../hoc/withAppState'; import RenderOptions from '../components/RenderOptions'; import SentenceWithHighlights from '../components/SentenceWithHighlights'; import Step from '../components/Step'; @@ -30,6 +31,7 @@ import Maven from './buildtool-steps/Maven'; import Other from './buildtool-steps/Other'; export interface JenkinsfileStepProps { + appState: T.AppState; component: T.Component; open: boolean; } @@ -43,8 +45,12 @@ const BUILDTOOL_COMPONENT_MAP: { [BuildTools.Other]: Other }; -export default function JenkinsfileStep(props: JenkinsfileStepProps) { - const { component, open } = props; +export function JenkinsfileStep(props: JenkinsfileStepProps) { + const { + appState: { branchesEnabled }, + component, + open + } = props; const [buildTool, setBuildTool] = React.useState<BuildTools | undefined>(undefined); return ( <Step @@ -89,7 +95,11 @@ export default function JenkinsfileStep(props: JenkinsfileStepProps) { <p className="little-spacer-bottom"> <strong>{translate('onboarding.tutorial.with.jenkins.commit')}</strong> </p> - <p>{translate('onboarding.tutorial.with.jenkins.commit.why')}</p> + <p> + {branchesEnabled + ? translate('onboarding.tutorial.with.jenkins.commit.why') + : translate('onboarding.tutorial.with.jenkins.commit.why.no_branches')} + </p> </div> </div> <div className="display-flex-row huge-spacer-bottom"> @@ -118,3 +128,5 @@ export default function JenkinsfileStep(props: JenkinsfileStepProps) { /> ); } + +export default withAppState(JenkinsfileStep); diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/PipelineStep.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/PipelineStep.tsx new file mode 100644 index 00000000000..ccb2fb55bc4 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/PipelineStep.tsx @@ -0,0 +1,90 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 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 { Button } from 'sonar-ui-common/components/controls/buttons'; +import { translate } from 'sonar-ui-common/helpers/l10n'; +import LabelActionPair from '../components/LabelActionPair'; +import SentenceWithHighlights from '../components/SentenceWithHighlights'; +import Step from '../components/Step'; + +export interface PipelineStepProps { + finished: boolean; + onDone: () => void; + onOpen: () => void; + open: boolean; +} + +export default function PipelineStep(props: PipelineStepProps) { + const { finished, open } = props; + return ( + <Step + finished={finished} + onOpen={props.onOpen} + open={open} + renderForm={() => ( + <div className="boxed-group-inner"> + <p className="big-spacer-bottom"> + {translate('onboarding.tutorial.with.jenkins.pipeline.intro')} + </p> + <ol className="list-styled"> + <li> + <SentenceWithHighlights + highlightKeys={['new_item', 'type']} + translationKey="onboarding.tutorial.with.jenkins.pipeline.step1" + /> + </li> + <li> + <SentenceWithHighlights + highlightKeys={['tab', 'option']} + translationKey="onboarding.tutorial.with.jenkins.pipeline.step2" + /> + </li> + <li> + <SentenceWithHighlights + highlightKeys={['tab']} + translationKey="onboarding.tutorial.with.jenkins.pipeline.step3" + /> + <ul className="list-styled"> + <li> + <LabelActionPair translationKey="onboarding.tutorial.with.jenkins.pipeline.step3.definition" /> + </li> + <li> + <LabelActionPair translationKey="onboarding.tutorial.with.jenkins.pipeline.step3.scm" /> + </li> + <li> + <LabelActionPair translationKey="onboarding.tutorial.with.jenkins.pipeline.step3.script_path" /> + </li> + </ul> + </li> + <li> + <SentenceWithHighlights + highlightKeys={['save']} + translationKey="onboarding.tutorial.with.jenkins.pipeline.step4" + /> + </li> + </ol> + <Button onClick={props.onDone}>{translate('continue')}</Button> + </div> + )} + stepNumber={1} + stepTitle={translate('onboarding.tutorial.with.jenkins.pipeline.title')} + /> + ); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/PreRequisitesStep.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/PreRequisitesStep.tsx index 6cec150d673..1f369992c3f 100644 --- a/server/sonar-web/src/main/js/components/tutorials/jenkins/PreRequisitesStep.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/PreRequisitesStep.tsx @@ -29,6 +29,7 @@ import Step from '../components/Step'; export interface PreRequisitesStepProps { alm: AlmKeys; + branchesEnabled: boolean; onChangeSkipNextTime: (skip: boolean) => void; onDone: () => void; onOpen: () => void; @@ -37,7 +38,7 @@ export interface PreRequisitesStepProps { } export default function PreRequisitesStep(props: PreRequisitesStepProps) { - const { alm, open, skipNextTime } = props; + const { alm, branchesEnabled, open, skipNextTime } = props; return ( <Step finished={!open} @@ -52,9 +53,11 @@ export default function PreRequisitesStep(props: PreRequisitesStepProps) { /> </p> <ul className="list-styled big-spacer-bottom"> - <li> - {translate('onboarding.tutorial.with.jenkins.prereqs.plugins.branch_source', alm)} - </li> + {branchesEnabled && ( + <li> + {translate('onboarding.tutorial.with.jenkins.prereqs.plugins.branch_source', alm)} + </li> + )} <li>{translate('onboarding.tutorial.with.jenkins.prereqs.plugins.sonar_scanner')}</li> </ul> <p className="big-spacer-bottom"> diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/WebhookStep.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/WebhookStep.tsx index 7f13471c37e..a3373234346 100644 --- a/server/sonar-web/src/main/js/components/tutorials/jenkins/WebhookStep.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/WebhookStep.tsx @@ -34,6 +34,7 @@ import WebhookStepGithub from './WebhookStepGithub'; export interface WebhookStepProps { almBinding?: AlmBindingDefinition; + branchesEnabled: boolean; finished: boolean; onDone: () => void; onOpen: () => void; @@ -42,13 +43,14 @@ export interface WebhookStepProps { } function renderAlmSpecificInstructions(props: WebhookStepProps) { - const { almBinding, projectBinding } = props; + const { almBinding, branchesEnabled, projectBinding } = props; switch (projectBinding.alm) { case AlmKeys.Bitbucket: return ( <WebhookStepBitbucket almBinding={isBitbucketBindingDefinition(almBinding) ? almBinding : undefined} + branchesEnabled={branchesEnabled} projectBinding={projectBinding} /> ); @@ -57,6 +59,7 @@ function renderAlmSpecificInstructions(props: WebhookStepProps) { return ( <WebhookStepGithub almBinding={isGithubBindingDefinition(almBinding) ? almBinding : undefined} + branchesEnabled={branchesEnabled} projectBinding={projectBinding} /> ); diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/WebhookStepBitbucket.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/WebhookStepBitbucket.tsx index 094e99d846c..7ccbbe19c94 100644 --- a/server/sonar-web/src/main/js/components/tutorials/jenkins/WebhookStepBitbucket.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/WebhookStepBitbucket.tsx @@ -28,15 +28,18 @@ import SentenceWithHighlights from '../components/SentenceWithHighlights'; export interface WebhookStepBitbucketProps { almBinding?: BitbucketBindingDefinition; + branchesEnabled: boolean; projectBinding: ProjectAlmBindingResponse; } -function buildUrlSnippet(ownUrl = '***BITBUCKET_URL***') { - return `***JENKINS_URL***/bitbucket-scmsource-hook/notify?server_url=${ownUrl}`; +function buildUrlSnippet(branchesEnabled: boolean, ownUrl = '***BITBUCKET_URL***') { + return branchesEnabled + ? `***JENKINS_URL***/bitbucket-scmsource-hook/notify?server_url=${ownUrl}` + : '***JENKINS_URL***/job/JENKINS_JOB_NAME/build?token=JENKINS_BUILD_TRIGGER_TOKEN'; } export default function WebhookStepBitbucket(props: WebhookStepBitbucketProps) { - const { almBinding, projectBinding } = props; + const { almBinding, branchesEnabled, projectBinding } = props; const linkUrl = almBinding && @@ -66,10 +69,15 @@ export default function WebhookStepBitbucket(props: WebhookStepBitbucketProps) { <p> <LabelActionPair translationKey="onboarding.tutorial.with.jenkins.webhook.bitbucket.step1.url" /> </p> - <CodeSnippet isOneLine={true} snippet={buildUrlSnippet(almBinding && almBinding.url)} /> - <Alert variant="info"> - {translate('onboarding.tutorial.with.jenkins.webhook.bitbucket.step1.url.warning')} - </Alert> + <CodeSnippet + isOneLine={true} + snippet={buildUrlSnippet(branchesEnabled, almBinding && almBinding.url)} + /> + {branchesEnabled && ( + <Alert variant="info"> + {translate('onboarding.tutorial.with.jenkins.webhook.bitbucket.step1.url.warning')} + </Alert> + )} </li> </ul> </li> @@ -82,9 +90,11 @@ export default function WebhookStepBitbucket(props: WebhookStepBitbucketProps) { <li> <LabelActionPair translationKey="onboarding.tutorial.with.jenkins.webhook.bitbucket.step2.repo" /> </li> - <li> - <LabelActionPair translationKey="onboarding.tutorial.with.jenkins.webhook.bitbucket.step2.pr" /> - </li> + {branchesEnabled && ( + <li> + <LabelActionPair translationKey="onboarding.tutorial.with.jenkins.webhook.bitbucket.step2.pr" /> + </li> + )} </ul> </li> <li> diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/WebhookStepGithub.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/WebhookStepGithub.tsx index 41f1db6547b..cfc41ee7c89 100644 --- a/server/sonar-web/src/main/js/components/tutorials/jenkins/WebhookStepGithub.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/WebhookStepGithub.tsx @@ -28,14 +28,19 @@ import { buildGithubLink } from '../utils'; export interface WebhookStepGithubProps { almBinding?: GithubBindingDefinition; + branchesEnabled: boolean; projectBinding: ProjectAlmBindingResponse; } export default function WebhookStepGithub(props: WebhookStepGithubProps) { - const { almBinding, projectBinding } = props; + const { almBinding, branchesEnabled, projectBinding } = props; const linkUrl = almBinding && `${buildGithubLink(almBinding, projectBinding)}/settings/hooks`; + const webhookUrl = branchesEnabled + ? '/github-webhook/' + : '/job/JENKINS_JOB_NAME/build?token=JENKINS_BUILD_TRIGGER_TOKEN'; + return ( <> <li> @@ -57,7 +62,7 @@ export default function WebhookStepGithub(props: WebhookStepGithubProps) { <p> <LabelActionPair translationKey="onboarding.tutorial.with.jenkins.webhook.github.step1.url" /> </p> - <CodeSnippet isOneLine={true} snippet="/github-webhook/" /> + <CodeSnippet isOneLine={true} snippet={webhookUrl} /> </li> </ul> </li> @@ -72,9 +77,13 @@ export default function WebhookStepGithub(props: WebhookStepGithubProps) { {translate('onboarding.tutorial.with.jenkins.webhook.github.step2.repo')} </strong> </li> - <li> - <strong>{translate('onboarding.tutorial.with.jenkins.webhook.github.step2.pr')}</strong> - </li> + {branchesEnabled && ( + <li> + <strong> + {translate('onboarding.tutorial.with.jenkins.webhook.github.step2.pr')} + </strong> + </li> + )} </ul> </li> <li> diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/JenkinsTutorial-test.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/JenkinsTutorial-test.tsx index 83d6a5a41dd..2c84533dc07 100644 --- a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/JenkinsTutorial-test.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/JenkinsTutorial-test.tsx @@ -33,6 +33,7 @@ import WebhookStep from '../WebhookStep'; it('should render correctly', () => { expect(shallowRender()).toMatchSnapshot('default'); + expect(shallowRender({ branchesEnabled: false })).toMatchSnapshot('branches not enabled'); expect( shallowRender({ projectBinding: mockProjectAlmBindingResponse({ alm: AlmKeys.Azure }) }) ).toMatchSnapshot('unsupported alm'); @@ -106,6 +107,7 @@ it('should correctly skip the pre-reqs step if the user requested it', () => { function shallowRender(props: Partial<JenkinsTutorialProps> = {}) { return shallow<JenkinsTutorialProps>( <JenkinsTutorial + branchesEnabled={true} component={mockComponent()} projectBinding={mockProjectBitbucketBindingResponse()} setCurrentUserSetting={jest.fn()} diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/JenkinsfileStep-test.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/JenkinsfileStep-test.tsx index d738038d7c5..bdab1582f60 100644 --- a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/JenkinsfileStep-test.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/JenkinsfileStep-test.tsx @@ -19,11 +19,11 @@ */ import { shallow, ShallowWrapper } from 'enzyme'; import * as React from 'react'; -import { mockComponent } from '../../../../helpers/testMocks'; +import { mockAppState, mockComponent } from '../../../../helpers/testMocks'; import RenderOptions from '../../components/RenderOptions'; import Step from '../../components/Step'; import { BuildTools } from '../../types'; -import JenkinsfileStep, { JenkinsfileStepProps } from '../JenkinsfileStep'; +import { JenkinsfileStep, JenkinsfileStepProps } from '../JenkinsfileStep'; import { renderStepContent } from '../test-utils'; it('should render correctly', () => { @@ -32,6 +32,12 @@ it('should render correctly', () => { expect(renderStepContent(wrapper)).toMatchSnapshot('initial content'); }); +it('should render correctly with no branches', () => { + const wrapper = shallowRender({ appState: mockAppState({ branchesEnabled: false }) }); + selectBuildTool(wrapper, BuildTools.Gradle); + expect(renderStepContent(wrapper)).toMatchSnapshot(); +}); + it('should render correctly for Maven', () => { const wrapper = shallowRender(); selectBuildTool(wrapper, BuildTools.Maven); @@ -68,6 +74,11 @@ function selectBuildTool(wrapper: ShallowWrapper<JenkinsfileStepProps>, tool: Bu function shallowRender(props: Partial<JenkinsfileStepProps> = {}) { return shallow<JenkinsfileStepProps>( - <JenkinsfileStep component={mockComponent()} open={true} {...props} /> + <JenkinsfileStep + appState={mockAppState({ branchesEnabled: true })} + component={mockComponent()} + open={true} + {...props} + /> ); } diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/PipelineStep-test.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/PipelineStep-test.tsx new file mode 100644 index 00000000000..e27883b5685 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/PipelineStep-test.tsx @@ -0,0 +1,35 @@ +/* + * SonarQube + * Copyright (C) 2009-2021 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 PipelineStep, { PipelineStepProps } from '../PipelineStep'; +import { renderStepContent } from '../test-utils'; + +it('should render correctly', () => { + const wrapper = shallowRender(); + expect(wrapper).toMatchSnapshot('Step wrapper'); + expect(renderStepContent(wrapper)).toMatchSnapshot('content'); +}); + +function shallowRender(props: Partial<PipelineStepProps> = {}) { + return shallow<PipelineStepProps>( + <PipelineStep finished={false} onDone={jest.fn()} onOpen={jest.fn()} open={true} {...props} /> + ); +} diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/PreRequisitesStep-test.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/PreRequisitesStep-test.tsx index 3c3745c60d3..c2ffc748a20 100644 --- a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/PreRequisitesStep-test.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/PreRequisitesStep-test.tsx @@ -27,12 +27,17 @@ it('should render correctly', () => { const wrapper = shallowRender(); expect(wrapper).toMatchSnapshot('Step wrapper'); expect(renderStepContent(wrapper)).toMatchSnapshot('content'); + + expect(renderStepContent(shallowRender({ branchesEnabled: false }))).toMatchSnapshot( + 'content for branches disabled' + ); }); function shallowRender(props: Partial<PreRequisitesStepProps> = {}) { return shallow<PreRequisitesStepProps>( <PreRequisitesStep alm={AlmKeys.Bitbucket} + branchesEnabled={true} onChangeSkipNextTime={jest.fn()} onDone={jest.fn()} onOpen={jest.fn()} diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/WebhookStep-test.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/WebhookStep-test.tsx index a1d47f94926..b7479be8a46 100644 --- a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/WebhookStep-test.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/WebhookStep-test.tsx @@ -55,6 +55,7 @@ function shallowRender(props: Partial<WebhookStepProps> = {}) { return shallow<WebhookStepProps>( <WebhookStep almBinding={mockBitbucketBindingDefinition()} + branchesEnabled={true} finished={false} onDone={jest.fn()} onOpen={jest.fn()} diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/WebhookStepBitbucket-test.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/WebhookStepBitbucket-test.tsx index e34899ae75b..3c7034bff7d 100644 --- a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/WebhookStepBitbucket-test.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/WebhookStepBitbucket-test.tsx @@ -28,12 +28,14 @@ import WebhookStepBitbucket, { WebhookStepBitbucketProps } from '../WebhookStepB it('should render correctly', () => { expect(shallowRender()).toMatchSnapshot(); expect(shallowRender({ almBinding: undefined })).toMatchSnapshot('with no alm binding'); + expect(shallowRender({ branchesEnabled: false })).toMatchSnapshot('with branches disabled'); }); function shallowRender(props: Partial<WebhookStepBitbucketProps> = {}) { return shallow<WebhookStepBitbucketProps>( <WebhookStepBitbucket almBinding={mockBitbucketBindingDefinition()} + branchesEnabled={true} projectBinding={mockProjectBitbucketBindingResponse()} {...props} /> diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/WebhookStepGithub-test.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/WebhookStepGithub-test.tsx index 3bdb8fa1044..4194473ddbc 100644 --- a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/WebhookStepGithub-test.tsx +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/WebhookStepGithub-test.tsx @@ -28,12 +28,14 @@ import WebhookStepGithub, { WebhookStepGithubProps } from '../WebhookStepGithub' it('should render correctly', () => { expect(shallowRender()).toMatchSnapshot(); expect(shallowRender({ almBinding: undefined })).toMatchSnapshot('with no alm binding'); + expect(shallowRender({ branchesEnabled: false })).toMatchSnapshot('with branches disabled'); }); function shallowRender(props: Partial<WebhookStepGithubProps> = {}) { return shallow<WebhookStepGithubProps>( <WebhookStepGithub almBinding={mockGithubBindingDefinition()} + branchesEnabled={true} projectBinding={mockProjectGithubBindingResponse()} {...props} /> diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/JenkinsTutorial-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/JenkinsTutorial-test.tsx.snap index c38b75a11f3..ef940ad2437 100644 --- a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/JenkinsTutorial-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/JenkinsTutorial-test.tsx.snap @@ -1,5 +1,75 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`should render correctly: branches not enabled 1`] = ` +<Fragment> + <div + className="page-header big-spacer-bottom" + > + <h1 + className="page-title" + > + onboarding.tutorial.with.jenkins.title + </h1> + </div> + <PreRequisitesStep + alm="bitbucket" + branchesEnabled={false} + onChangeSkipNextTime={[Function]} + onDone={[Function]} + onOpen={[Function]} + open={true} + skipNextTime={false} + /> + <PipelineStep + finished={false} + onDone={[Function]} + onOpen={[Function]} + open={false} + /> + <WebhookStep + branchesEnabled={false} + finished={false} + onDone={[Function]} + onOpen={[Function]} + open={false} + projectBinding={ + Object { + "alm": "bitbucket", + "key": "foo", + "monorepo": true, + "repository": "PROJECT_KEY", + "slug": "repo-slug", + } + } + /> + <Connect(withAppState(JenkinsfileStep)) + component={ + Object { + "breadcrumbs": Array [], + "key": "my-project", + "name": "MyProject", + "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 [], + } + } + open={false} + /> +</Fragment> +`; + exports[`should render correctly: default 1`] = ` <Fragment> <div @@ -13,6 +83,7 @@ exports[`should render correctly: default 1`] = ` </div> <PreRequisitesStep alm="bitbucket" + branchesEnabled={true} onChangeSkipNextTime={[Function]} onDone={[Function]} onOpen={[Function]} @@ -35,6 +106,7 @@ exports[`should render correctly: default 1`] = ` } /> <WebhookStep + branchesEnabled={true} finished={false} onDone={[Function]} onOpen={[Function]} @@ -49,7 +121,7 @@ exports[`should render correctly: default 1`] = ` } } /> - <JenkinsfileStep + <Connect(withAppState(JenkinsfileStep)) component={ Object { "breadcrumbs": Array [], diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/JenkinsfileStep-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/JenkinsfileStep-test.tsx.snap index b704fce4f68..a4610804993 100644 --- a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/JenkinsfileStep-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/JenkinsfileStep-test.tsx.snap @@ -484,6 +484,127 @@ exports[`should render correctly for Other 1`] = ` </div> `; +exports[`should render correctly with no branches 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", + "dotnet", + "other", + ] + } + /> + </li> + <Gradle + component={ + Object { + "breadcrumbs": Array [], + "key": "my-project", + "name": "MyProject", + "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 [], + } + } + /> + </ol> + <React.Fragment> + <hr + className="huge-spacer-top huge-spacer-bottom" + /> + <div + className="abs-width-600" + > + <p + className="big-spacer-bottom" + > + <SentenceWithHighlights + highlightKeys={ + Array [ + "all_set", + ] + } + translationKey="onboarding.tutorial.with.jenkins.all_set" + /> + </p> + <div + className="display-flex-row big-spacer-bottom" + > + <div> + <img + alt="" + className="big-spacer-right" + src="/images/tutorials/commit.svg" + width={30} + /> + </div> + <div> + <p + className="little-spacer-bottom" + > + <strong> + onboarding.tutorial.with.jenkins.commit + </strong> + </p> + <p> + onboarding.tutorial.with.jenkins.commit.why.no_branches + </p> + </div> + </div> + <div + className="display-flex-row huge-spacer-bottom" + > + <div> + <img + alt="" + className="big-spacer-right" + src="/images/tutorials/refresh.svg" + width={30} + /> + </div> + <div> + <p + className="little-spacer-bottom" + > + <strong> + onboarding.tutorial.with.jenkins.refresh + </strong> + </p> + <p> + onboarding.tutorial.with.jenkins.refresh.why + </p> + </div> + </div> + </div> + </React.Fragment> +</div> +`; + exports[`should render correctly: Step wrapper 1`] = ` <Step finished={false} diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/PipelineStep-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/PipelineStep-test.tsx.snap new file mode 100644 index 00000000000..1bcc7cdd415 --- /dev/null +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/PipelineStep-test.tsx.snap @@ -0,0 +1,94 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`should render correctly: Step wrapper 1`] = ` +<Step + finished={false} + onOpen={[MockFunction]} + open={true} + renderForm={[Function]} + stepNumber={1} + stepTitle="onboarding.tutorial.with.jenkins.pipeline.title" +/> +`; + +exports[`should render correctly: content 1`] = ` +<div + className="boxed-group-inner" +> + <p + className="big-spacer-bottom" + > + onboarding.tutorial.with.jenkins.pipeline.intro + </p> + <ol + className="list-styled" + > + <li> + <SentenceWithHighlights + highlightKeys={ + Array [ + "new_item", + "type", + ] + } + translationKey="onboarding.tutorial.with.jenkins.pipeline.step1" + /> + </li> + <li> + <SentenceWithHighlights + highlightKeys={ + Array [ + "tab", + "option", + ] + } + translationKey="onboarding.tutorial.with.jenkins.pipeline.step2" + /> + </li> + <li> + <SentenceWithHighlights + highlightKeys={ + Array [ + "tab", + ] + } + translationKey="onboarding.tutorial.with.jenkins.pipeline.step3" + /> + <ul + className="list-styled" + > + <li> + <LabelActionPair + translationKey="onboarding.tutorial.with.jenkins.pipeline.step3.definition" + /> + </li> + <li> + <LabelActionPair + translationKey="onboarding.tutorial.with.jenkins.pipeline.step3.scm" + /> + </li> + <li> + <LabelActionPair + translationKey="onboarding.tutorial.with.jenkins.pipeline.step3.script_path" + /> + </li> + </ul> + </li> + <li> + <SentenceWithHighlights + highlightKeys={ + Array [ + "save", + ] + } + translationKey="onboarding.tutorial.with.jenkins.pipeline.step4" + /> + </li> + </ol> + <Button + onClick={[MockFunction]} + > + continue + </Button> +</div> +`; diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/PreRequisitesStep-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/PreRequisitesStep-test.tsx.snap index 4e673fc52d4..a05a5368f9f 100644 --- a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/PreRequisitesStep-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/PreRequisitesStep-test.tsx.snap @@ -86,3 +86,77 @@ exports[`should render correctly: content 1`] = ` </Button> </div> `; + +exports[`should render correctly: content for branches disabled 1`] = ` +<div + className="boxed-group-inner" +> + <p + className="big-spacer-bottom" + > + <SentenceWithHighlights + highlightKeys={ + Array [ + "must_have", + ] + } + translationKey="onboarding.tutorial.with.jenkins.prereqs.intro" + /> + </p> + <ul + className="list-styled big-spacer-bottom" + > + <li> + onboarding.tutorial.with.jenkins.prereqs.plugins.sonar_scanner + </li> + </ul> + <p + className="big-spacer-bottom" + > + <FormattedMessage + defaultMessage="onboarding.tutorial.with.jenkins.prereqs.step_by_step_guide" + id="onboarding.tutorial.with.jenkins.prereqs.step_by_step_guide" + values={ + Object { + "link": <Link + onlyActiveOnIndex={false} + style={Object {}} + target="_blank" + to="/documentation/analysis/jenkins/" + > + onboarding.tutorial.with.jenkins.prereqs.step_by_step_guide.link + </Link>, + } + } + /> + </p> + <p + className="big-spacer-bottom" + > + onboarding.tutorial.with.jenkins.prereqs.following_are_recommendations + </p> + <p + className="big-spacer-bottom display-flex-center" + > + <label + className="cursor-pointer" + htmlFor="skip-prereqs" + onClick={[Function]} + > + onboarding.tutorial.with.jenkins.prereqs.skip_next_time + </label> + <Checkbox + checked={true} + className="little-spacer-left" + id="skip-prereqs" + onCheck={[MockFunction]} + thirdState={false} + /> + </p> + <Button + onClick={[MockFunction]} + > + onboarding.tutorial.with.jenkins.prereqs.done + </Button> +</div> +`; diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/WebhookStep-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/WebhookStep-test.tsx.snap index d5aa70897c0..2aec46e6c86 100644 --- a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/WebhookStep-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/WebhookStep-test.tsx.snap @@ -75,6 +75,7 @@ exports[`it should render correctly for bitbucket: content 1`] = ` "url": "http://bbs.enterprise.com", } } + branchesEnabled={true} projectBinding={ Object { "alm": "bitbucket", @@ -140,6 +141,7 @@ exports[`it should render correctly for github: content 1`] = ` "url": "http://github.enterprise.com", } } + branchesEnabled={true} projectBinding={ Object { "alm": "github", diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/WebhookStepBitbucket-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/WebhookStepBitbucket-test.tsx.snap index 650389b6493..1f2930ec5da 100644 --- a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/WebhookStepBitbucket-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/WebhookStepBitbucket-test.tsx.snap @@ -83,6 +83,79 @@ exports[`should render correctly 1`] = ` </Fragment> `; +exports[`should render correctly: with branches disabled 1`] = ` +<Fragment> + <li> + <FormattedMessage + defaultMessage="onboarding.tutorial.with.jenkins.webhook.step1.sentence" + id="onboarding.tutorial.with.jenkins.webhook.step1.sentence" + values={ + Object { + "link": <a + href="http://bbs.enterprise.com/plugins/servlet/webhooks/projects/PROJECT_KEY/repos/repo-slug/create" + rel="noopener noreferrer" + target="_blank" + > + onboarding.tutorial.with.jenkins.webhook.bitbucket.step1.link + </a>, + } + } + /> + <ul + className="list-styled" + > + <li> + <LabelActionPair + translationKey="onboarding.tutorial.with.jenkins.webhook.step1.name" + /> + </li> + <li + className="abs-width-600" + > + <p> + <LabelActionPair + translationKey="onboarding.tutorial.with.jenkins.webhook.bitbucket.step1.url" + /> + </p> + <CodeSnippet + isOneLine={true} + snippet="***JENKINS_URL***/job/JENKINS_JOB_NAME/build?token=JENKINS_BUILD_TRIGGER_TOKEN" + /> + </li> + </ul> + </li> + <li> + <SentenceWithHighlights + highlightKeys={ + Array [ + "events", + ] + } + translationKey="onboarding.tutorial.with.jenkins.webhook.bitbucket.step2" + /> + <ul + className="list-styled" + > + <li> + <LabelActionPair + translationKey="onboarding.tutorial.with.jenkins.webhook.bitbucket.step2.repo" + /> + </li> + </ul> + </li> + <li> + <SentenceWithHighlights + highlightKeys={ + Array [ + "create", + ] + } + translationKey="onboarding.tutorial.with.jenkins.webhook.step3" + /> + </li> +</Fragment> +`; + exports[`should render correctly: with no alm binding 1`] = ` <Fragment> <li> diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/WebhookStepGithub-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/WebhookStepGithub-test.tsx.snap index 86134f7a25f..15656a6f801 100644 --- a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/WebhookStepGithub-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/WebhookStepGithub-test.tsx.snap @@ -74,6 +74,75 @@ exports[`should render correctly 1`] = ` </Fragment> `; +exports[`should render correctly: with branches disabled 1`] = ` +<Fragment> + <li> + <FormattedMessage + defaultMessage="onboarding.tutorial.with.jenkins.webhook.step1.sentence" + id="onboarding.tutorial.with.jenkins.webhook.step1.sentence" + values={ + Object { + "link": <a + href="http://github.enterprise.com/PROJECT_KEY/settings/hooks" + rel="noopener noreferrer" + target="_blank" + > + onboarding.tutorial.with.jenkins.webhook.github.step1.link + </a>, + } + } + /> + <ul + className="list-styled" + > + <li + className="abs-width-600" + > + <p> + <LabelActionPair + translationKey="onboarding.tutorial.with.jenkins.webhook.github.step1.url" + /> + </p> + <CodeSnippet + isOneLine={true} + snippet="/job/JENKINS_JOB_NAME/build?token=JENKINS_BUILD_TRIGGER_TOKEN" + /> + </li> + </ul> + </li> + <li> + <SentenceWithHighlights + highlightKeys={ + Array [ + "events", + "option", + ] + } + translationKey="onboarding.tutorial.with.jenkins.webhook.github.step2" + /> + <ul + className="list-styled" + > + <li> + <strong> + onboarding.tutorial.with.jenkins.webhook.github.step2.repo + </strong> + </li> + </ul> + </li> + <li> + <SentenceWithHighlights + highlightKeys={ + Array [ + "create", + ] + } + translationKey="onboarding.tutorial.with.jenkins.webhook.step3" + /> + </li> +</Fragment> +`; + exports[`should render correctly: with no alm binding 1`] = ` <Fragment> <li> diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties index 680894af399..dd89a7b0e6e 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -3417,6 +3417,30 @@ onboarding.tutorial.with.jenkins.multi_branch_pipeline.step3.script_path.action= onboarding.tutorial.with.jenkins.multi_branch_pipeline.step4.sentence=Click {save}. onboarding.tutorial.with.jenkins.multi_branch_pipeline.step4.sentence.save=Save + +onboarding.tutorial.with.jenkins.pipeline.title=Create a Pipeline Job +onboarding.tutorial.with.jenkins.pipeline.intro=Create a Pipeline in order to automatically analyze your project. +onboarding.tutorial.with.jenkins.pipeline.step1.sentence=From Jenkins' dashboard, click {new_item} and create a {type}. +onboarding.tutorial.with.jenkins.pipeline.step1.sentence.new_item=New Item +onboarding.tutorial.with.jenkins.pipeline.step1.sentence.type=Pipeline Job + +onboarding.tutorial.with.jenkins.pipeline.step2.sentence=Under {tab}, choose {option}. You must set a unique, secret token for this field. +onboarding.tutorial.with.jenkins.pipeline.step2.sentence.tab=Build Triggers +onboarding.tutorial.with.jenkins.pipeline.step2.sentence.option=Trigger builds remotely + +onboarding.tutorial.with.jenkins.pipeline.step3.sentence=Under {tab}, make sure the parameters are set as follows: +onboarding.tutorial.with.jenkins.pipeline.step3.sentence.tab=Pipeline +onboarding.tutorial.with.jenkins.pipeline.step3.definition.label=Definition +onboarding.tutorial.with.jenkins.pipeline.step3.definition.action=Pipeline script from SCM +onboarding.tutorial.with.jenkins.pipeline.step3.scm.label=SCM +onboarding.tutorial.with.jenkins.pipeline.step3.scm.action=Your SCM (Git, SVN, etc). Make sure to only build your main branch. +onboarding.tutorial.with.jenkins.pipeline.step3.script_path.label=Script Path +onboarding.tutorial.with.jenkins.pipeline.step3.script_path.action=Jenkinsfile + +onboarding.tutorial.with.jenkins.pipeline.step4.sentence=Click {save}. +onboarding.tutorial.with.jenkins.pipeline.step4.sentence.save=Save + + onboarding.tutorial.with.jenkins.webhook.bitbucket.title=Create a Bitbucket Server Webhook onboarding.tutorial.with.jenkins.webhook.github.title=Create a GitHub Webhook onboarding.tutorial.with.jenkins.webhook.intro.sentence=Create a Webhook in your repository to trigger the Jenkins job on push. Already have a Webhook configured? {link} @@ -3481,6 +3505,7 @@ onboarding.tutorial.with.jenkins.all_set.sentence={all_set} and ready to improve onboarding.tutorial.with.jenkins.all_set.sentence.all_set=You're all set onboarding.tutorial.with.jenkins.commit=Commit and push your code to start the analysis. onboarding.tutorial.with.jenkins.commit.why=Each new push you make on your branches or pull requests will trigger a new analysis in SonarQube. +onboarding.tutorial.with.jenkins.commit.why.no_branches=Each new push you make on your main branch will trigger a new analysis in SonarQube. onboarding.tutorial.with.jenkins.refresh=This page will then refresh with your analysis results. onboarding.tutorial.with.jenkins.refresh.why=If the page doesn't refresh after a while, please double-check the analysis configuration. |