]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-14354 Jenkins tutorial for CE
authorJeremy Davis <jeremy.davis@sonarsource.com>
Wed, 27 Jan 2021 10:18:21 +0000 (11:18 +0100)
committersonartech <sonartech@sonarsource.com>
Thu, 4 Feb 2021 20:07:07 +0000 (20:07 +0000)
22 files changed:
server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsTutorial.tsx
server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsfileStep.tsx
server/sonar-web/src/main/js/components/tutorials/jenkins/PipelineStep.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/jenkins/PreRequisitesStep.tsx
server/sonar-web/src/main/js/components/tutorials/jenkins/WebhookStep.tsx
server/sonar-web/src/main/js/components/tutorials/jenkins/WebhookStepBitbucket.tsx
server/sonar-web/src/main/js/components/tutorials/jenkins/WebhookStepGithub.tsx
server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/JenkinsTutorial-test.tsx
server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/JenkinsfileStep-test.tsx
server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/PipelineStep-test.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/PreRequisitesStep-test.tsx
server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/WebhookStep-test.tsx
server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/WebhookStepBitbucket-test.tsx
server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/WebhookStepGithub-test.tsx
server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/JenkinsTutorial-test.tsx.snap
server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/JenkinsfileStep-test.tsx.snap
server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/PipelineStep-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/PreRequisitesStep-test.tsx.snap
server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/WebhookStep-test.tsx.snap
server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/WebhookStepBitbucket-test.tsx.snap
server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/WebhookStepGithub-test.tsx.snap
sonar-core/src/main/resources/org/sonar/l10n/core.properties

index 62d937fefe8f8e52c586385090a4a5b6916164b0..fe91dd16adf66e40f58af19e10b85e108600f56b 100644 (file)
@@ -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'
   };
 };
index 4eab0390317f574a7d9a4cd5cf482cfbd03b1e53..e81304b0772e33bddce1c6e4d0158c4d68c52ba4 100644 (file)
@@ -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 (file)
index 0000000..ccb2fb5
--- /dev/null
@@ -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')}
+    />
+  );
+}
index 6cec150d673e942f53429229fd7350921e149081..1f369992c3f503e71c4a397182c7b05a130c5ee1 100644 (file)
@@ -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">
index 7f13471c37e2c34cf584c0aa74fc11fcf2c27669..a337323434676bdbc7f6e0e8ab7afffee39b9f4e 100644 (file)
@@ -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}
         />
       );
index 094e99d846c1ca54bc53feae382bbf33c7cc46d2..7ccbbe19c942a34c79aab40fc1cdb1b233aab83a 100644 (file)
@@ -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>
index 41f1db6547bd11721807946d1e77ea42521a5610..cfc41ee7c89446b4849030dc5124fa22b7378837 100644 (file)
@@ -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>
index 83d6a5a41dda162f256ab376cf56118739b823f6..2c84533dc07aa1dc62753fe4a27c0ff16203bfc0 100644 (file)
@@ -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()}
index d738038d7c54e0017a7c25a734257963f72d0904..bdab1582f6054d95f7da31cdf1def6bea6e26348 100644 (file)
  */
 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 (file)
index 0000000..e27883b
--- /dev/null
@@ -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} />
+  );
+}
index 3c3745c60d3481202cf42c16582d4362366e4eda..c2ffc748a20b6a8393d2fdc4b6795544adf1658e 100644 (file)
@@ -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()}
index a1d47f949261fa7e98be6ff68a21c5a355e4691c..b7479be8a46e264fae2498c864c835fe9c9c16c7 100644 (file)
@@ -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()}
index e34899ae75bbe6b3cd5f61b2826cbc1a8b836398..3c7034bff7dbabf9c8cf7ba17a99397bf2042312 100644 (file)
@@ -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}
     />
index 3bdb8fa1044eb80a8d7014e93bbab146538b45da..4194473ddbca3a9625468f547291f6215610c3a5 100644 (file)
@@ -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}
     />
index c38b75a11f3c84f8dd65988507e0a9215c632051..ef940ad24376386c41ef71f2621565e01370a02c 100644 (file)
@@ -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 [],
index b704fce4f68dfcc4ac971b0f24176a9ff3a62660..a4610804993e771ab532ea16ab98d72b52f31f9f 100644 (file)
@@ -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 (file)
index 0000000..1bcc7cd
--- /dev/null
@@ -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>
+`;
index 4e673fc52d45e959673adc6f3c7f9a9087def874..a05a5368f9f6dd87b85127034592cb25c95bcb7f 100644 (file)
@@ -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>
+`;
index d5aa70897c042f728d41030703422ed7b5fa9c7f..2aec46e6c86e9d7eefa760f622acae2a4ba377ed 100644 (file)
@@ -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",
index 650389b64933c743529ebbf0a919f8960e4c7e10..1f2930ec5da53f982a92782af6005ca26ececf21 100644 (file)
@@ -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>
index 86134f7a25ff2ea5e6f192af14ee0d6dde36a4fd..15656a6f801e5b54abb4050160d06cb9cdf0b579 100644 (file)
@@ -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>
index 680894af399280163959fe0de19c427ebada41d8..dd89a7b0e6efd97fe087775c0e0f954e7b4269e3 100644 (file)
@@ -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.