]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-14436 Explain how to set up Jenkins with GitLab
authorWouter Admiraal <wouter.admiraal@sonarsource.com>
Tue, 16 Feb 2021 15:31:32 +0000 (16:31 +0100)
committersonartech <sonartech@sonarsource.com>
Fri, 19 Feb 2021 20:07:20 +0000 (20:07 +0000)
25 files changed:
server/sonar-web/src/main/js/components/tutorials/TutorialSelectionRenderer.tsx
server/sonar-web/src/main/js/components/tutorials/__tests__/TutorialSelectionRenderer-test.tsx
server/sonar-web/src/main/js/components/tutorials/jenkins/JenkinsTutorial.tsx
server/sonar-web/src/main/js/components/tutorials/jenkins/MultiBranchPipelineStep.tsx
server/sonar-web/src/main/js/components/tutorials/jenkins/PipelineStep.tsx
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/WebhookStepGitLab.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/jenkins/WebhookStepGithub.tsx
server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/MultiBranchPipelineStep-test.tsx
server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/PipelineStep-test.tsx
server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/PreRequisitesStep-test.tsx
server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/WebhookStepGitLab-test.tsx [new file with mode: 0644]
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__/MultiBranchPipelineStep-test.tsx.snap
server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/PipelineStep-test.tsx.snap
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__/WebhookStepGitLab-test.tsx.snap [new file with mode: 0644]
server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/WebhookStepGithub-test.tsx.snap
server/sonar-web/src/main/js/types/__tests__/alm-settings-test.ts [new file with mode: 0644]
server/sonar-web/src/main/js/types/alm-settings.ts
sonar-core/src/main/resources/org/sonar/l10n/core.properties

index 40674894fd561eaa22d633ef2cf8976348934420..0689d78aff4f1c93169df80b8bf762799a995801 100644 (file)
@@ -45,7 +45,8 @@ export default function TutorialSelectionRenderer(props: TutorialSelectionRender
   }
 
   const jenkinsAvailable =
-    projectBinding && [AlmKeys.BitbucketServer, AlmKeys.GitHub].includes(projectBinding.alm);
+    projectBinding &&
+    [AlmKeys.BitbucketServer, AlmKeys.GitHub, AlmKeys.GitLab].includes(projectBinding.alm);
 
   return (
     <>
index e78d4381b6247f56883ec3dd4ac1c8f3c82d4bb4..7efd8c10f88317d856219c5a10572dd1f7037750 100644 (file)
@@ -24,6 +24,7 @@ import {
   mockBitbucketBindingDefinition,
   mockProjectAzureBindingResponse,
   mockProjectBitbucketBindingResponse,
+  mockProjectGithubBindingResponse,
   mockProjectGitLabBindingResponse
 } from '../../../helpers/mocks/alm-settings';
 import { mockComponent, mockLoggedInUser } from '../../../helpers/testMocks';
@@ -61,7 +62,7 @@ it('should render correctly', () => {
   ).toMatchSnapshot('azure pipelines tutorial');
 });
 
-it('should allow mode selection', () => {
+it('should allow mode selection for Bitbucket', () => {
   const onSelectTutorial = jest.fn();
   const wrapper = shallowRender({
     onSelectTutorial,
@@ -75,18 +76,38 @@ it('should allow mode selection', () => {
   expect(onSelectTutorial).toHaveBeenLastCalledWith(TutorialModes.Manual);
 });
 
-it('should allow gitlab selection', () => {
+it('should allow mode selection for Github', () => {
+  const onSelectTutorial = jest.fn();
+  const wrapper = shallowRender({
+    onSelectTutorial,
+    projectBinding: mockProjectGithubBindingResponse()
+  });
+
+  click(wrapper.find('button.tutorial-mode-jenkins'));
+  expect(onSelectTutorial).toHaveBeenLastCalledWith(TutorialModes.Jenkins);
+
+  click(wrapper.find('button.tutorial-mode-manual'));
+  expect(onSelectTutorial).toHaveBeenLastCalledWith(TutorialModes.Manual);
+});
+
+it('should allow mode selection for GitLab', () => {
   const onSelectTutorial = jest.fn();
   const wrapper = shallowRender({
     onSelectTutorial,
     projectBinding: mockProjectGitLabBindingResponse()
   });
 
+  click(wrapper.find('button.tutorial-mode-jenkins'));
+  expect(onSelectTutorial).toHaveBeenLastCalledWith(TutorialModes.Jenkins);
+
   click(wrapper.find('button.tutorial-mode-gitlab'));
   expect(onSelectTutorial).toHaveBeenLastCalledWith(TutorialModes.GitLabCI);
+
+  click(wrapper.find('button.tutorial-mode-manual'));
+  expect(onSelectTutorial).toHaveBeenLastCalledWith(TutorialModes.Manual);
 });
 
-it('should allow azure pipelines selection', () => {
+it('should allow mode selection for Azure DevOps', () => {
   const onSelectTutorial = jest.fn();
   const wrapper = shallowRender({
     onSelectTutorial,
@@ -95,6 +116,9 @@ it('should allow azure pipelines selection', () => {
 
   click(wrapper.find('button.azure-pipelines'));
   expect(onSelectTutorial).toHaveBeenLastCalledWith(TutorialModes.AzurePipelines);
+
+  click(wrapper.find('button.tutorial-mode-manual'));
+  expect(onSelectTutorial).toHaveBeenLastCalledWith(TutorialModes.Manual);
 });
 
 function shallowRender(props: Partial<TutorialSelectionRendererProps> = {}) {
index fe91dd16adf66e40f58af19e10b85e108600f56b..15ba4fc05baaf782d891f3d08739bd3655db06c3 100644 (file)
@@ -27,6 +27,7 @@ import {
   AlmBindingDefinition,
   isProjectBitbucketBindingResponse,
   isProjectGitHubBindingResponse,
+  isProjectGitLabBindingResponse,
   ProjectAlmBindingResponse
 } from '../../../types/alm-settings';
 import JenkinsfileStep from './JenkinsfileStep';
@@ -62,7 +63,8 @@ export function JenkinsTutorial(props: JenkinsTutorialProps) {
   // Failsafe; should never happen.
   if (
     !isProjectBitbucketBindingResponse(projectBinding) &&
-    !isProjectGitHubBindingResponse(projectBinding)
+    !isProjectGitHubBindingResponse(projectBinding) &&
+    !isProjectGitLabBindingResponse(projectBinding)
   ) {
     return (
       <Alert variant="error">{translate('onboarding.tutorial.with.jenkins.unsupported')}</Alert>
@@ -101,6 +103,7 @@ export function JenkinsTutorial(props: JenkinsTutorialProps) {
         />
       ) : (
         <PipelineStep
+          alm={projectBinding.alm}
           finished={step > Steps.MultiBranchPipeline}
           onDone={() => setStep(Steps.Webhook)}
           onOpen={() => setStep(Steps.MultiBranchPipeline)}
index 5ee7b051b673129f28f40ce09a9e590f245578ac..eda16fc1a5bae2328a8863ea735b5803d3013beb 100644 (file)
@@ -25,8 +25,10 @@ import {
   isGithubBindingDefinition,
   isProjectBitbucketBindingResponse,
   isProjectGitHubBindingResponse,
+  isProjectGitLabBindingResponse,
   ProjectBitbucketBindingResponse,
-  ProjectGitHubBindingResponse
+  ProjectGitHubBindingResponse,
+  ProjectGitLabBindingResponse
 } from '../../../types/alm-settings';
 import LabelActionPair from '../components/LabelActionPair';
 import LabelValuePair from '../components/LabelValuePair';
@@ -40,7 +42,10 @@ export interface MultiBranchPipelineStepProps {
   onDone: () => void;
   onOpen: () => void;
   open: boolean;
-  projectBinding: ProjectBitbucketBindingResponse | ProjectGitHubBindingResponse;
+  projectBinding:
+    | ProjectBitbucketBindingResponse
+    | ProjectGitHubBindingResponse
+    | ProjectGitLabBindingResponse;
 }
 
 export default function MultiBranchPipelineStep(props: MultiBranchPipelineStepProps) {
@@ -64,7 +69,7 @@ export default function MultiBranchPipelineStep(props: MultiBranchPipelineStepPr
             </li>
             <li>
               <SentenceWithHighlights
-                highlightKeys={['tab']}
+                highlightKeys={['tab', 'source']}
                 translationKey={`onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.${projectBinding.alm}`}
               />
               <ul className="list-styled">
@@ -107,10 +112,30 @@ export default function MultiBranchPipelineStep(props: MultiBranchPipelineStepPr
                     </li>
                   </>
                 )}
+                {isProjectGitLabBindingResponse(projectBinding) && (
+                  <>
+                    <li>
+                      <LabelActionPair translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.gitlab.creds" />
+                    </li>
+                    <li>
+                      <LabelActionPair translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.gitlab.owner" />
+                    </li>
+                    <li>
+                      <LabelActionPair translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.gitlab.repo" />
+                    </li>
+                  </>
+                )}
                 <li>
-                  <LabelActionPair translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.behaviour" />
+                  <LabelActionPair
+                    translationKey={`onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.${projectBinding.alm}.behaviour`}
+                  />
                 </li>
               </ul>
+              <p className="big-spacer-left padder-left">
+                {translate(
+                  'onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.leave_defaults'
+                )}
+              </p>
             </li>
             <li>
               <SentenceWithHighlights
index ccb2fb55bc433c4b7c3aa07e2d8c4f4742291acb..3fdbd0d319374534cdd1558e86b7e832151fc977 100644 (file)
 import * as React from 'react';
 import { Button } from 'sonar-ui-common/components/controls/buttons';
 import { translate } from 'sonar-ui-common/helpers/l10n';
+import { AlmKeys } from '../../../types/alm-settings';
 import LabelActionPair from '../components/LabelActionPair';
 import SentenceWithHighlights from '../components/SentenceWithHighlights';
 import Step from '../components/Step';
 
 export interface PipelineStepProps {
+  alm: AlmKeys;
   finished: boolean;
   onDone: () => void;
   onOpen: () => void;
@@ -32,7 +34,7 @@ export interface PipelineStepProps {
 }
 
 export default function PipelineStep(props: PipelineStepProps) {
-  const { finished, open } = props;
+  const { alm, finished, open } = props;
   return (
     <Step
       finished={finished}
@@ -51,10 +53,39 @@ export default function PipelineStep(props: PipelineStepProps) {
               />
             </li>
             <li>
-              <SentenceWithHighlights
-                highlightKeys={['tab', 'option']}
-                translationKey="onboarding.tutorial.with.jenkins.pipeline.step2"
-              />
+              {alm === AlmKeys.GitLab ? (
+                <>
+                  <SentenceWithHighlights
+                    highlightKeys={['tab', 'option']}
+                    translationKey="onboarding.tutorial.with.jenkins.pipeline.gitlab.step2.trigger"
+                  />
+                  <ul className="list-styled">
+                    <li>
+                      <SentenceWithHighlights
+                        highlightKeys={['triggers', 'push_events']}
+                        translationKey="onboarding.tutorial.with.jenkins.pipeline.gitlab.step2.pick_triggers"
+                      />
+                    </li>
+                    <li>
+                      <SentenceWithHighlights
+                        highlightKeys={['advanced']}
+                        translationKey="onboarding.tutorial.with.jenkins.pipeline.gitlab.step2.click_advanced"
+                      />
+                    </li>
+                    <li>
+                      <SentenceWithHighlights
+                        highlightKeys={['secret_token', 'generate']}
+                        translationKey="onboarding.tutorial.with.jenkins.pipeline.gitlab.step2.secret_token"
+                      />
+                    </li>
+                  </ul>
+                </>
+              ) : (
+                <SentenceWithHighlights
+                  highlightKeys={['tab', 'option']}
+                  translationKey="onboarding.tutorial.with.jenkins.pipeline.step2"
+                />
+              )}
             </li>
             <li>
               <SentenceWithHighlights
@@ -66,7 +97,10 @@ export default function PipelineStep(props: PipelineStepProps) {
                   <LabelActionPair translationKey="onboarding.tutorial.with.jenkins.pipeline.step3.definition" />
                 </li>
                 <li>
-                  <LabelActionPair translationKey="onboarding.tutorial.with.jenkins.pipeline.step3.scm" />
+                  <SentenceWithHighlights
+                    highlightKeys={['label', 'branches_to_build']}
+                    translationKey="onboarding.tutorial.with.jenkins.pipeline.step3.scm"
+                  />
                 </li>
                 <li>
                   <LabelActionPair translationKey="onboarding.tutorial.with.jenkins.pipeline.step3.script_path" />
index 1f369992c3f503e71c4a397182c7b05a130c5ee1..ad9c8a800cb1fddbfd6e3fef96517517336a75a8 100644 (file)
@@ -58,6 +58,9 @@ export default function PreRequisitesStep(props: PreRequisitesStepProps) {
                 {translate('onboarding.tutorial.with.jenkins.prereqs.plugins.branch_source', alm)}
               </li>
             )}
+            {!branchesEnabled && alm === AlmKeys.GitLab && (
+              <li>{translate('onboarding.tutorial.with.jenkins.prereqs.plugins.gitlab_plugin')}</li>
+            )}
             <li>{translate('onboarding.tutorial.with.jenkins.prereqs.plugins.sonar_scanner')}</li>
           </ul>
           <p className="big-spacer-bottom">
index 2349c1f90e8f6d660cbe9e5cc273f1bf5e77ef95..86d8129d9edf08aef4781999a35a9c62b2b85675 100644 (file)
@@ -31,6 +31,7 @@ import {
 import Step from '../components/Step';
 import WebhookStepBitbucket from './WebhookStepBitbucket';
 import WebhookStepGithub from './WebhookStepGithub';
+import WebhookStepGitLab from './WebhookStepGitLab';
 
 export interface WebhookStepProps {
   almBinding?: AlmBindingDefinition;
@@ -64,6 +65,9 @@ function renderAlmSpecificInstructions(props: WebhookStepProps) {
         />
       );
 
+    case AlmKeys.GitLab:
+      return <WebhookStepGitLab branchesEnabled={branchesEnabled} />;
+
     default:
       return null;
   }
index 7ccbbe19c942a34c79aab40fc1cdb1b233aab83a..51b6813312d12ef095a80978a4092781f7d40228 100644 (file)
@@ -34,8 +34,8 @@ export interface WebhookStepBitbucketProps {
 
 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';
+    ? `***JENKINS_SERVER_URL***/bitbucket-scmsource-hook/notify?server_url=${ownUrl}`
+    : '***JENKINS_SERVER_URL***/job/***JENKINS_JOB_NAME***/build?token=***JENKINS_BUILD_TRIGGER_TOKEN***';
 }
 
 export default function WebhookStepBitbucket(props: WebhookStepBitbucketProps) {
diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/WebhookStepGitLab.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/WebhookStepGitLab.tsx
new file mode 100644 (file)
index 0000000..3ab1a43
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * 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 { FormattedMessage } from 'react-intl';
+import { translate } from 'sonar-ui-common/helpers/l10n';
+import CodeSnippet from '../../common/CodeSnippet';
+import LabelActionPair from '../components/LabelActionPair';
+import SentenceWithHighlights from '../components/SentenceWithHighlights';
+
+export interface WebhookStepGitLabProps {
+  branchesEnabled: boolean;
+}
+
+export default function WebhookStepGitLab({ branchesEnabled }: WebhookStepGitLabProps) {
+  return (
+    <>
+      <li>
+        <FormattedMessage
+          defaultMessage={translate('onboarding.tutorial.with.jenkins.webhook.step1.sentence')}
+          id="onboarding.tutorial.with.jenkins.webhook.step1.sentence"
+          values={{
+            link: translate('onboarding.tutorial.with.jenkins.webhook.gitlab.step1.link')
+          }}
+        />
+        <ul className="list-styled">
+          {branchesEnabled ? (
+            <li className="abs-width-600">
+              <p>
+                <LabelActionPair translationKey="onboarding.tutorial.with.jenkins.webhook.gitlab.step1.url_with_branches" />
+              </p>
+              <CodeSnippet
+                isOneLine={true}
+                snippet="***JENKINS_SERVER_URL***/gitlab-webhook/post"
+              />
+            </li>
+          ) : (
+            <>
+              <li>
+                <LabelActionPair translationKey="onboarding.tutorial.with.jenkins.webhook.gitlab.step1.url_no_branches" />
+              </li>
+              <li>
+                <LabelActionPair translationKey="onboarding.tutorial.with.jenkins.webhook.gitlab.step1.secret_token" />
+              </li>
+            </>
+          )}
+        </ul>
+      </li>
+      <li>
+        <SentenceWithHighlights
+          highlightKeys={['trigger']}
+          translationKey="onboarding.tutorial.with.jenkins.webhook.gitlab.step2"
+        />
+        <ul className="list-styled">
+          <li>
+            <strong>
+              {translate('onboarding.tutorial.with.jenkins.webhook.gitlab.step2.repo')}
+            </strong>
+          </li>
+          {branchesEnabled && (
+            <li>
+              <strong>
+                {translate('onboarding.tutorial.with.jenkins.webhook.gitlab.step2.mr')}
+              </strong>
+            </li>
+          )}
+        </ul>
+      </li>
+      <li>
+        <SentenceWithHighlights
+          highlightKeys={['add_webhook']}
+          translationKey="onboarding.tutorial.with.jenkins.webhook.gitlab.step3"
+        />
+      </li>
+    </>
+  );
+}
index cfc41ee7c89446b4849030dc5124fa22b7378837..37ffc16ddb2b6ccc6a67b21d1e9e5c54a0022e67 100644 (file)
@@ -38,8 +38,8 @@ export default function WebhookStepGithub(props: WebhookStepGithubProps) {
   const linkUrl = almBinding && `${buildGithubLink(almBinding, projectBinding)}/settings/hooks`;
 
   const webhookUrl = branchesEnabled
-    ? '/github-webhook/'
-    : '/job/JENKINS_JOB_NAME/build?token=JENKINS_BUILD_TRIGGER_TOKEN';
+    ? '***JENKINS_SERVER_URL***/github-webhook/'
+    : '***JENKINS_SERVER_URL***/job/***JENKINS_JOB_NAME***/build?token=***JENKINS_BUILD_TRIGGER_TOKEN***';
 
   return (
     <>
index be64d2fbb82529d807fb1951c5a54ab460ccc2ca..5be36aa33105e42be1df83f7656f48a6f7c20ba4 100644 (file)
@@ -21,7 +21,8 @@ import { shallow } from 'enzyme';
 import * as React from 'react';
 import {
   mockProjectBitbucketBindingResponse,
-  mockProjectGithubBindingResponse
+  mockProjectGithubBindingResponse,
+  mockProjectGitLabBindingResponse
 } from '../../../../helpers/mocks/alm-settings';
 import MultiBranchPipelineStep, { MultiBranchPipelineStepProps } from '../MultiBranchPipelineStep';
 import { renderStepContent } from '../test-utils';
@@ -33,6 +34,9 @@ it('should render correctly', () => {
   expect(
     renderStepContent(shallowRender({ projectBinding: mockProjectGithubBindingResponse() }))
   ).toMatchSnapshot('content for github');
+  expect(
+    renderStepContent(shallowRender({ projectBinding: mockProjectGitLabBindingResponse() }))
+  ).toMatchSnapshot('content for gitlab');
 });
 
 function shallowRender(props: Partial<MultiBranchPipelineStepProps> = {}) {
index e27883b5685a2194225697591d5608bf65d91b3b..3d4398144f45adb97024a1357adf3be9651f245b 100644 (file)
@@ -19,6 +19,7 @@
  */
 import { shallow } from 'enzyme';
 import * as React from 'react';
+import { AlmKeys } from '../../../../types/alm-settings';
 import PipelineStep, { PipelineStepProps } from '../PipelineStep';
 import { renderStepContent } from '../test-utils';
 
@@ -26,10 +27,20 @@ it('should render correctly', () => {
   const wrapper = shallowRender();
   expect(wrapper).toMatchSnapshot('Step wrapper');
   expect(renderStepContent(wrapper)).toMatchSnapshot('content');
+  expect(renderStepContent(shallowRender({ alm: AlmKeys.GitLab }))).toMatchSnapshot(
+    'gitlab content'
+  );
 });
 
 function shallowRender(props: Partial<PipelineStepProps> = {}) {
   return shallow<PipelineStepProps>(
-    <PipelineStep finished={false} onDone={jest.fn()} onOpen={jest.fn()} open={true} {...props} />
+    <PipelineStep
+      alm={AlmKeys.GitHub}
+      finished={false}
+      onDone={jest.fn()}
+      onOpen={jest.fn()}
+      open={true}
+      {...props}
+    />
   );
 }
index 89d5cbf9bb028fc94db4cd1dcd8d5d2fd9c41379..ca7481d85f07a9d60b653466e56ab796432a8cbf 100644 (file)
@@ -31,6 +31,9 @@ it('should render correctly', () => {
   expect(renderStepContent(shallowRender({ branchesEnabled: false }))).toMatchSnapshot(
     'content for branches disabled'
   );
+  expect(
+    renderStepContent(shallowRender({ alm: AlmKeys.GitLab, branchesEnabled: false }))
+  ).toMatchSnapshot('content for branches disabled, gitlab');
 });
 
 function shallowRender(props: Partial<PreRequisitesStepProps> = {}) {
diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/WebhookStepGitLab-test.tsx b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/WebhookStepGitLab-test.tsx
new file mode 100644 (file)
index 0000000..b44c615
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * 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 WebhookStepGitLab, { WebhookStepGitLabProps } from '../WebhookStepGitLab';
+
+it('should render correctly', () => {
+  expect(shallowRender()).toMatchSnapshot('default');
+  expect(shallowRender({ branchesEnabled: false })).toMatchSnapshot('with branches disabled');
+});
+
+function shallowRender(props: Partial<WebhookStepGitLabProps> = {}) {
+  return shallow<WebhookStepGitLabProps>(<WebhookStepGitLab branchesEnabled={true} {...props} />);
+}
index ef940ad24376386c41ef71f2621565e01370a02c..b6759ddfa3880680a1c53e2c3aa737f64075e350 100644 (file)
@@ -21,6 +21,7 @@ exports[`should render correctly: branches not enabled 1`] = `
     skipNextTime={false}
   />
   <PipelineStep
+    alm="bitbucket"
     finished={false}
     onDone={[Function]}
     onOpen={[Function]}
index cab0b2febbae16cd8d5b30b92b38b58b7cc6addf..e5efd1b0cfd69d10a428014e72655f7743b0c61c 100644 (file)
@@ -39,6 +39,7 @@ exports[`should render correctly: content for bitbucket 1`] = `
         highlightKeys={
           Array [
             "tab",
+            "source",
           ]
         }
         translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.bitbucket"
@@ -72,10 +73,15 @@ exports[`should render correctly: content for bitbucket 1`] = `
         </React.Fragment>
         <li>
           <LabelActionPair
-            translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.behaviour"
+            translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.bitbucket.behaviour"
           />
         </li>
       </ul>
+      <p
+        className="big-spacer-left padder-left"
+      >
+        onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.leave_defaults
+      </p>
     </li>
     <li>
       <SentenceWithHighlights
@@ -148,6 +154,7 @@ exports[`should render correctly: content for github 1`] = `
         highlightKeys={
           Array [
             "tab",
+            "source",
           ]
         }
         translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.github"
@@ -169,11 +176,124 @@ exports[`should render correctly: content for github 1`] = `
         </React.Fragment>
         <li>
           <LabelActionPair
-            translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.behaviour"
+            translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.github.behaviour"
+          />
+        </li>
+      </ul>
+      <p
+        className="big-spacer-left padder-left"
+      >
+        onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.leave_defaults
+      </p>
+    </li>
+    <li>
+      <SentenceWithHighlights
+        highlightKeys={
+          Array [
+            "tab",
+          ]
+        }
+        translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step3"
+      />
+      <ul
+        className="list-styled"
+      >
+        <li>
+          <LabelActionPair
+            translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step3.mode"
+          />
+        </li>
+        <li>
+          <LabelActionPair
+            translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step3.script_path"
           />
         </li>
       </ul>
     </li>
+    <li>
+      <SentenceWithHighlights
+        highlightKeys={
+          Array [
+            "save",
+          ]
+        }
+        translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step4"
+      />
+    </li>
+  </ol>
+  <Button
+    onClick={[MockFunction]}
+  >
+    continue
+  </Button>
+</div>
+`;
+
+exports[`should render correctly: content for gitlab 1`] = `
+<div
+  className="boxed-group-inner"
+>
+  <p
+    className="big-spacer-bottom"
+  >
+    onboarding.tutorial.with.jenkins.multi_branch_pipeline.intro
+  </p>
+  <ol
+    className="list-styled"
+  >
+    <li>
+      <SentenceWithHighlights
+        highlightKeys={
+          Array [
+            "new_item",
+            "type",
+          ]
+        }
+        translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step1"
+      />
+    </li>
+    <li>
+      <SentenceWithHighlights
+        highlightKeys={
+          Array [
+            "tab",
+            "source",
+          ]
+        }
+        translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.gitlab"
+      />
+      <ul
+        className="list-styled"
+      >
+        <React.Fragment>
+          <li>
+            <LabelActionPair
+              translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.gitlab.creds"
+            />
+          </li>
+          <li>
+            <LabelActionPair
+              translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.gitlab.owner"
+            />
+          </li>
+          <li>
+            <LabelActionPair
+              translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.gitlab.repo"
+            />
+          </li>
+        </React.Fragment>
+        <li>
+          <LabelActionPair
+            translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.gitlab.behaviour"
+          />
+        </li>
+      </ul>
+      <p
+        className="big-spacer-left padder-left"
+      >
+        onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.leave_defaults
+      </p>
+    </li>
     <li>
       <SentenceWithHighlights
         highlightKeys={
index 1bcc7cdd4153b589b1b972e695fd29b5063c922b..6527408f3d8d415909a6c3a427398f978270f93a 100644 (file)
@@ -62,8 +62,140 @@ exports[`should render correctly: content 1`] = `
             translationKey="onboarding.tutorial.with.jenkins.pipeline.step3.definition"
           />
         </li>
+        <li>
+          <SentenceWithHighlights
+            highlightKeys={
+              Array [
+                "label",
+                "branches_to_build",
+              ]
+            }
+            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>
+`;
+
+exports[`should render correctly: gitlab 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>
+      <React.Fragment>
+        <SentenceWithHighlights
+          highlightKeys={
+            Array [
+              "tab",
+              "option",
+            ]
+          }
+          translationKey="onboarding.tutorial.with.jenkins.pipeline.gitlab.step2.trigger"
+        />
+        <ul
+          className="list-styled"
+        >
+          <li>
+            <SentenceWithHighlights
+              highlightKeys={
+                Array [
+                  "triggers",
+                  "push_events",
+                ]
+              }
+              translationKey="onboarding.tutorial.with.jenkins.pipeline.gitlab.step2.pick_triggers"
+            />
+          </li>
+          <li>
+            <SentenceWithHighlights
+              highlightKeys={
+                Array [
+                  "advanced",
+                ]
+              }
+              translationKey="onboarding.tutorial.with.jenkins.pipeline.gitlab.step2.click_advanced"
+            />
+          </li>
+          <li>
+            <SentenceWithHighlights
+              highlightKeys={
+                Array [
+                  "secret_token",
+                  "generate",
+                ]
+              }
+              translationKey="onboarding.tutorial.with.jenkins.pipeline.gitlab.step2.secret_token"
+            />
+          </li>
+        </ul>
+      </React.Fragment>
+    </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>
+          <SentenceWithHighlights
+            highlightKeys={
+              Array [
+                "label",
+                "branches_to_build",
+              ]
+            }
             translationKey="onboarding.tutorial.with.jenkins.pipeline.step3.scm"
           />
         </li>
index a05a5368f9f6dd87b85127034592cb25c95bcb7f..ba632b2ab79c1e249f5f880174f439186a2d391a 100644 (file)
@@ -160,3 +160,80 @@ exports[`should render correctly: content for branches disabled 1`] = `
   </Button>
 </div>
 `;
+
+exports[`should render correctly: content for branches disabled, gitlab 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.gitlab_plugin
+    </li>
+    <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 2aec46e6c86e9d7eefa760f622acae2a4ba377ed..17b5fd12b0f51d2de46169f4f5822f8a8c711481 100644 (file)
@@ -194,7 +194,11 @@ exports[`it should render correctly for gitlab: content 1`] = `
   </p>
   <ol
     className="list-styled"
-  />
+  >
+    <WebhookStepGitLab
+      branchesEnabled={true}
+    />
+  </ol>
   <Button
     onClick={[MockFunction]}
   >
index 1f2930ec5da53f982a92782af6005ca26ececf21..385b172e1b16111db2c1ca74733ed83377d34b6a 100644 (file)
@@ -36,7 +36,7 @@ exports[`should render correctly 1`] = `
         </p>
         <CodeSnippet
           isOneLine={true}
-          snippet="***JENKINS_URL***/bitbucket-scmsource-hook/notify?server_url=http://bbs.enterprise.com"
+          snippet="***JENKINS_SERVER_URL***/bitbucket-scmsource-hook/notify?server_url=http://bbs.enterprise.com"
         />
         <Alert
           variant="info"
@@ -119,7 +119,7 @@ exports[`should render correctly: with branches disabled 1`] = `
         </p>
         <CodeSnippet
           isOneLine={true}
-          snippet="***JENKINS_URL***/job/JENKINS_JOB_NAME/build?token=JENKINS_BUILD_TRIGGER_TOKEN"
+          snippet="***JENKINS_SERVER_URL***/job/***JENKINS_JOB_NAME***/build?token=***JENKINS_BUILD_TRIGGER_TOKEN***"
         />
       </li>
     </ul>
@@ -186,7 +186,7 @@ exports[`should render correctly: with no alm binding 1`] = `
         </p>
         <CodeSnippet
           isOneLine={true}
-          snippet="***JENKINS_URL***/bitbucket-scmsource-hook/notify?server_url=***BITBUCKET_URL***"
+          snippet="***JENKINS_SERVER_URL***/bitbucket-scmsource-hook/notify?server_url=***BITBUCKET_URL***"
         />
         <Alert
           variant="info"
diff --git a/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/WebhookStepGitLab-test.tsx.snap b/server/sonar-web/src/main/js/components/tutorials/jenkins/__tests__/__snapshots__/WebhookStepGitLab-test.tsx.snap
new file mode 100644 (file)
index 0000000..08056fb
--- /dev/null
@@ -0,0 +1,127 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly: default 1`] = `
+<Fragment>
+  <li>
+    <FormattedMessage
+      defaultMessage="onboarding.tutorial.with.jenkins.webhook.step1.sentence"
+      id="onboarding.tutorial.with.jenkins.webhook.step1.sentence"
+      values={
+        Object {
+          "link": "onboarding.tutorial.with.jenkins.webhook.gitlab.step1.link",
+        }
+      }
+    />
+    <ul
+      className="list-styled"
+    >
+      <li
+        className="abs-width-600"
+      >
+        <p>
+          <LabelActionPair
+            translationKey="onboarding.tutorial.with.jenkins.webhook.gitlab.step1.url_with_branches"
+          />
+        </p>
+        <CodeSnippet
+          isOneLine={true}
+          snippet="***JENKINS_SERVER_URL***/gitlab-webhook/post"
+        />
+      </li>
+    </ul>
+  </li>
+  <li>
+    <SentenceWithHighlights
+      highlightKeys={
+        Array [
+          "trigger",
+        ]
+      }
+      translationKey="onboarding.tutorial.with.jenkins.webhook.gitlab.step2"
+    />
+    <ul
+      className="list-styled"
+    >
+      <li>
+        <strong>
+          onboarding.tutorial.with.jenkins.webhook.gitlab.step2.repo
+        </strong>
+      </li>
+      <li>
+        <strong>
+          onboarding.tutorial.with.jenkins.webhook.gitlab.step2.mr
+        </strong>
+      </li>
+    </ul>
+  </li>
+  <li>
+    <SentenceWithHighlights
+      highlightKeys={
+        Array [
+          "add_webhook",
+        ]
+      }
+      translationKey="onboarding.tutorial.with.jenkins.webhook.gitlab.step3"
+    />
+  </li>
+</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": "onboarding.tutorial.with.jenkins.webhook.gitlab.step1.link",
+        }
+      }
+    />
+    <ul
+      className="list-styled"
+    >
+      <li>
+        <LabelActionPair
+          translationKey="onboarding.tutorial.with.jenkins.webhook.gitlab.step1.url_no_branches"
+        />
+      </li>
+      <li>
+        <LabelActionPair
+          translationKey="onboarding.tutorial.with.jenkins.webhook.gitlab.step1.secret_token"
+        />
+      </li>
+    </ul>
+  </li>
+  <li>
+    <SentenceWithHighlights
+      highlightKeys={
+        Array [
+          "trigger",
+        ]
+      }
+      translationKey="onboarding.tutorial.with.jenkins.webhook.gitlab.step2"
+    />
+    <ul
+      className="list-styled"
+    >
+      <li>
+        <strong>
+          onboarding.tutorial.with.jenkins.webhook.gitlab.step2.repo
+        </strong>
+      </li>
+    </ul>
+  </li>
+  <li>
+    <SentenceWithHighlights
+      highlightKeys={
+        Array [
+          "add_webhook",
+        ]
+      }
+      translationKey="onboarding.tutorial.with.jenkins.webhook.gitlab.step3"
+    />
+  </li>
+</Fragment>
+`;
index 15656a6f801e5b54abb4050160d06cb9cdf0b579..0c42dfe5c4706c0a8eb7350154bad6ed3ae8583b 100644 (file)
@@ -31,7 +31,7 @@ exports[`should render correctly 1`] = `
         </p>
         <CodeSnippet
           isOneLine={true}
-          snippet="/github-webhook/"
+          snippet="***JENKINS_SERVER_URL***/github-webhook/"
         />
       </li>
     </ul>
@@ -105,7 +105,7 @@ exports[`should render correctly: with branches disabled 1`] = `
         </p>
         <CodeSnippet
           isOneLine={true}
-          snippet="/job/JENKINS_JOB_NAME/build?token=JENKINS_BUILD_TRIGGER_TOKEN"
+          snippet="***JENKINS_SERVER_URL***/job/***JENKINS_JOB_NAME***/build?token=***JENKINS_BUILD_TRIGGER_TOKEN***"
         />
       </li>
     </ul>
@@ -168,7 +168,7 @@ exports[`should render correctly: with no alm binding 1`] = `
         </p>
         <CodeSnippet
           isOneLine={true}
-          snippet="/github-webhook/"
+          snippet="***JENKINS_SERVER_URL***/github-webhook/"
         />
       </li>
     </ul>
diff --git a/server/sonar-web/src/main/js/types/__tests__/alm-settings-test.ts b/server/sonar-web/src/main/js/types/__tests__/alm-settings-test.ts
new file mode 100644 (file)
index 0000000..e859c1e
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * 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 {
+  mockBitbucketCloudBindingDefinition,
+  mockGithubBindingDefinition,
+  mockGitlabBindingDefinition
+} from '../../helpers/mocks/alm-settings';
+import { isGitLabBindingDefinition } from '../alm-settings';
+
+describe('isGitLabBindingDefinition', () => {
+  it('correctly returns false for non-GitLab bindings', () => {
+    expect(isGitLabBindingDefinition(mockBitbucketCloudBindingDefinition())).toBe(false);
+    expect(isGitLabBindingDefinition(mockGithubBindingDefinition())).toBe(false);
+  });
+
+  it('correctly returns true for GitLab bindings', () => {
+    expect(isGitLabBindingDefinition(mockGitlabBindingDefinition())).toBe(true);
+  });
+});
index 2a1a0d1893bff078f5318c5d82b486b2033becfc..7a546ccbbb91fd4ff89f671bacd9da15a4d2c3b9 100644 (file)
@@ -196,3 +196,16 @@ export function isGithubBindingDefinition(
 ): binding is GithubBindingDefinition {
   return binding !== undefined && binding.appId !== undefined && binding.url !== undefined;
 }
+
+export function isGitLabBindingDefinition(
+  binding?: AlmBindingDefinition | GithubBindingDefinition | BitbucketCloudBindingDefinition
+): binding is GitlabBindingDefinition {
+  // There's too much overlap with the others. We must not only validate that certain fields are
+  // present, we must also validate that others are NOT present. And even so, we cannot be 100%
+  // sure, as right now, Azure, Bitbucket Server, and GitLab have the same signature.
+  return (
+    binding !== undefined &&
+    (binding as GithubBindingDefinition).appId === undefined &&
+    (binding as BitbucketCloudBindingDefinition).workspace === undefined
+  );
+}
index 7f8e0e19de395c0eaf4b0d88610943052643572d..669eb617325fffd9602cfcc6e172802b073ce283 100644 (file)
@@ -3405,6 +3405,8 @@ onboarding.tutorial.with.jenkins.prereqs.intro.sentence=To run your project anal
 onboarding.tutorial.with.jenkins.prereqs.intro.sentence.must_have=must be installed and configured:
 onboarding.tutorial.with.jenkins.prereqs.plugins.branch_source.bitbucket=Bitbucket Branch Source plugin for Jenkins - version 2.7 or later
 onboarding.tutorial.with.jenkins.prereqs.plugins.branch_source.github=GitHub Branch Source plugin for Jenkins - version 2.7.1 or later
+onboarding.tutorial.with.jenkins.prereqs.plugins.branch_source.gitlab=GitLab Branch Source plugin for Jenkins - version 1.5.3 or later
+onboarding.tutorial.with.jenkins.prereqs.plugins.gitlab_plugin=GitLab plugin for Jenkins - version 1.5.13 or later
 onboarding.tutorial.with.jenkins.prereqs.plugins.sonar_scanner=SonarQube Scanner plugin for Jenkins - version 2.11 or later
 onboarding.tutorial.with.jenkins.prereqs.step_by_step_guide=For a step by step guide on installing and configuring those plugins in Jenkins, visit the {link} documentation page.
 onboarding.tutorial.with.jenkins.prereqs.step_by_step_guide.link=Analysis Prerequisites
@@ -3417,8 +3419,9 @@ onboarding.tutorial.with.jenkins.multi_branch_pipeline.step1.sentence=From Jenki
 onboarding.tutorial.with.jenkins.multi_branch_pipeline.step1.sentence.new_item=New Item
 onboarding.tutorial.with.jenkins.multi_branch_pipeline.step1.sentence.type=Multibranch Pipeline Job
 
-onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.bitbucket.sentence=Under {tab}, add a Bitbucket source and enter the following information:
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.bitbucket.sentence=Under {tab}, add a {source} source and enter the following information:
 onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.bitbucket.sentence.tab=Branch Sources
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.bitbucket.sentence.source=Bitbucket
 onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.bitbucket.server.label=Server
 onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.bitbucket.server.action=select the instance hosting the repository you want to analyze.
 onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.bitbucket.creds.label=Credentials
@@ -3428,15 +3431,34 @@ onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.bitbucket.owner.act
 onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.bitbucket.repo.label=Repository
 onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.bitbucket.repo.action=select the repository you want to analyze.
 
-onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.github.sentence=Under {tab}, add a GitHub source and enter the following information:
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.github.sentence=Under {tab}, add a {source} source and enter the following information:
 onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.github.sentence.tab=Branch Sources
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.github.sentence.source=GitHub
 onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.github.creds.label=Credentials
 onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.github.creds.action=select or add your GitHub credentials.
 onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.github.repo_url.label=Repository HTTPS URL
 onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.github.repo_url.action=enter your repository URL.
 
-onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.behaviour.label=Behavior
-onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.behaviour.action=make sure Exclude branches that are also filed as PRs is selected.
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.gitlab.sentence=Under {tab}, add a {source} source and enter the following information:
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.gitlab.sentence.tab=Branch Sources
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.gitlab.sentence.source=GitLab Project
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.gitlab.creds.label=Checkout Credentials
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.gitlab.creds.action=select or add your GitLab credentials.
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.gitlab.owner.label=Owner
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.gitlab.owner.action=enter the name of your user or your group.
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.gitlab.repo.label=Projects
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.gitlab.repo.action=select your project.
+
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.bitbucket.behaviour.label=Behavior
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.bitbucket.behaviour.action=make sure "Exclude branches that are also filed as PRs" is selected.
+
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.github.behaviour.label=Behavior
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.github.behaviour.action=make sure "Exclude branches that are also filed as PRs" is selected.
+
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.gitlab.behaviour.label=Behaviours
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.gitlab.behaviour.action=make sure "Only branches that are not also filed as MRs" is selected.
+
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.leave_defaults=You can leave the other settings at the defaults.
 
 onboarding.tutorial.with.jenkins.multi_branch_pipeline.step3.sentence=Jump to the {tab} section and make sure the parameters are set as follows:
 onboarding.tutorial.with.jenkins.multi_branch_pipeline.step3.sentence.tab=Build Configuration
@@ -3458,12 +3480,25 @@ onboarding.tutorial.with.jenkins.pipeline.step2.sentence=Under {tab}, choose {op
 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.gitlab.step2.trigger.sentence=Under {tab}, choose {option}. Write down the webhook URL provided. You will need it when configuring the webhook in GitLab.
+onboarding.tutorial.with.jenkins.pipeline.gitlab.step2.trigger.sentence.tab=Build Triggers
+onboarding.tutorial.with.jenkins.pipeline.gitlab.step2.trigger.sentence.option=Build when a change is pushed to GitLab
+onboarding.tutorial.with.jenkins.pipeline.gitlab.step2.pick_triggers.sentence=Under {triggers}, only select {push_events}.
+onboarding.tutorial.with.jenkins.pipeline.gitlab.step2.pick_triggers.sentence.triggers=Enabled GitLab triggers
+onboarding.tutorial.with.jenkins.pipeline.gitlab.step2.pick_triggers.sentence.push_events=Push events
+onboarding.tutorial.with.jenkins.pipeline.gitlab.step2.click_advanced.sentence=Click on {advanced}
+onboarding.tutorial.with.jenkins.pipeline.gitlab.step2.click_advanced.sentence.advanced=Advanced...
+onboarding.tutorial.with.jenkins.pipeline.gitlab.step2.secret_token.sentence=Find the {secret_token} text field, and click on {generate}. Write down the secret token. You will need it when configuring the webhook in GitLab.
+onboarding.tutorial.with.jenkins.pipeline.gitlab.step2.secret_token.sentence.secret_token=Secret token
+onboarding.tutorial.with.jenkins.pipeline.gitlab.step2.secret_token.sentence.generate=Generate
+
 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.scm.sentence={label} Configure your SCM. Make sure to only build your main branch. For example, if your main branch is called "main", put "*/main" under {branches_to_build}.
+onboarding.tutorial.with.jenkins.pipeline.step3.scm.sentence.label=SCM:
+onboarding.tutorial.with.jenkins.pipeline.step3.scm.sentence.branches_to_build=Branches to build
 onboarding.tutorial.with.jenkins.pipeline.step3.script_path.label=Script Path
 onboarding.tutorial.with.jenkins.pipeline.step3.script_path.action=Jenkinsfile
 
@@ -3473,31 +3508,45 @@ 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.gitlab.title=Create a GitLab 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}
 onboarding.tutorial.with.jenkins.webhook.intro.link=Skip this step.
 onboarding.tutorial.with.jenkins.webhook.step1.sentence=Go to the {link} and enter the following information:
 onboarding.tutorial.with.jenkins.webhook.bitbucket.step1.link=Bitbucket Server Webhook creation page for your repository
 onboarding.tutorial.with.jenkins.webhook.github.step1.link=GitHub Webhook creation page for your repository
+onboarding.tutorial.with.jenkins.webhook.gitlab.step1.link=GitLab Webhook creation page for your repository
 onboarding.tutorial.with.jenkins.webhook.step1.name.label=Name
 onboarding.tutorial.with.jenkins.webhook.step1.name.action=give a unique name.
 onboarding.tutorial.with.jenkins.webhook.bitbucket.step1.url.label=URL
-onboarding.tutorial.with.jenkins.webhook.bitbucket.step1.url.action=Enter the following URL, replacing the tokens as needed:
+onboarding.tutorial.with.jenkins.webhook.bitbucket.step1.url.action=Enter the following URL, replacing the values between *** as needed:
 onboarding.tutorial.with.jenkins.webhook.bitbucket.step1.url.warning=The Bitbucket Server URL must be identical to the one in your Jenkins configuration. Watch out for any missing or extra "/" at the end.
 onboarding.tutorial.with.jenkins.webhook.github.step1.url.label=URL
-onboarding.tutorial.with.jenkins.webhook.github.step1.url.action=Enter your Jenkins instance URL and add the following path:
+onboarding.tutorial.with.jenkins.webhook.github.step1.url.action=Enter the following URL, replacing the values between *** as needed:
+onboarding.tutorial.with.jenkins.webhook.gitlab.step1.url_with_branches.label=URL
+onboarding.tutorial.with.jenkins.webhook.gitlab.step1.url_with_branches.action=Enter the following URL, replacing the values between *** as needed:
+onboarding.tutorial.with.jenkins.webhook.gitlab.step1.url_no_branches.label=URL
+onboarding.tutorial.with.jenkins.webhook.gitlab.step1.url_no_branches.action=Enter the URL you wrote down in the previous step.
+onboarding.tutorial.with.jenkins.webhook.gitlab.step1.secret_token.label=Secret Token
+onboarding.tutorial.with.jenkins.webhook.gitlab.step1.secret_token.action=Enter the generated token you wrote down in the previous step.
 onboarding.tutorial.with.jenkins.webhook.bitbucket.step2.sentence=Under {events}, make sure the following options are checked:
 onboarding.tutorial.with.jenkins.webhook.bitbucket.step2.sentence.events=Events
 onboarding.tutorial.with.jenkins.webhook.github.step2.sentence=Under {events} select {option} and check the following:
 onboarding.tutorial.with.jenkins.webhook.github.step2.sentence.events=Which events would you like to trigger this webhook?
 onboarding.tutorial.with.jenkins.webhook.github.step2.sentence.option=Let me select individual events
+onboarding.tutorial.with.jenkins.webhook.gitlab.step2.sentence=Under {trigger} check the following:
+onboarding.tutorial.with.jenkins.webhook.gitlab.step2.sentence.trigger=Trigger
 onboarding.tutorial.with.jenkins.webhook.bitbucket.step2.repo.label=Repository
 onboarding.tutorial.with.jenkins.webhook.bitbucket.step2.repo.action=Push
 onboarding.tutorial.with.jenkins.webhook.bitbucket.step2.pr.label=Pull Request
 onboarding.tutorial.with.jenkins.webhook.bitbucket.step2.pr.action=Opened
 onboarding.tutorial.with.jenkins.webhook.github.step2.repo=Pushes
 onboarding.tutorial.with.jenkins.webhook.github.step2.pr=Pull Requests
+onboarding.tutorial.with.jenkins.webhook.gitlab.step2.repo=Push events
+onboarding.tutorial.with.jenkins.webhook.gitlab.step2.mr=Merge request events
 onboarding.tutorial.with.jenkins.webhook.step3.sentence=Click {create}.
 onboarding.tutorial.with.jenkins.webhook.step3.sentence.create=Create
+onboarding.tutorial.with.jenkins.webhook.gitlab.step3.sentence=Click {add_webhook}.
+onboarding.tutorial.with.jenkins.webhook.gitlab.step3.sentence.add_webhook=Add webhook
 onboarding.tutorial.with.jenkins.jenkinsfile.title=Create a Jenkinsfile
 onboarding.tutorial.with.jenkins.jenkinsfile.jenkinsfile_step.sentence=Create a {file} file in your repository and paste the following code:
 onboarding.tutorial.with.jenkins.jenkinsfile.maven.step2.sentence=Add the following to your {file} file: