This is an automated email from the ASF dual-hosted git repository.

likyh pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-devlake.git


The following commit(s) were added to refs/heads/main by this push:
     new 3edc9824e refactor(config-ui): adjust the transformation cicd (#4972)
3edc9824e is described below

commit 3edc9824eb59b64db4646bcd80ed5050a0529946
Author: 青湛 <[email protected]>
AuthorDate: Thu Apr 20 22:24:07 2023 +0800

    refactor(config-ui): adjust the transformation cicd (#4972)
---
 .../components/transformation-select/index.tsx     |   2 +-
 config-ui/src/plugins/register/azure/config.tsx    |   2 +-
 config-ui/src/plugins/register/azure/styled.ts     |  61 +++++----
 .../src/plugins/register/azure/transformation.tsx  | 130 +++++++++---------
 .../bitbucket/assets/bitbucket-example.jpg         | Bin 0 -> 163075 bytes
 .../src/plugins/register/bitbucket/config.tsx      |   2 +-
 config-ui/src/plugins/register/bitbucket/styled.ts |  62 ++++-----
 .../plugins/register/bitbucket/transformation.tsx  | 134 ++++++++++---------
 config-ui/src/plugins/register/github/config.tsx   |   2 +-
 config-ui/src/plugins/register/github/styled.ts    |  63 +++++----
 .../src/plugins/register/github/transformation.tsx | 145 ++++++++++-----------
 config-ui/src/plugins/register/gitlab/config.tsx   |   2 +-
 config-ui/src/plugins/register/gitlab/styled.ts    |  39 +++---
 .../src/plugins/register/gitlab/transformation.tsx |  93 +++++++------
 config-ui/src/plugins/register/jenkins/config.ts   |   2 +-
 config-ui/src/plugins/register/jenkins/styled.ts   |  39 +++---
 .../plugins/register/jenkins/transformation.tsx    |  93 +++++++------
 17 files changed, 438 insertions(+), 433 deletions(-)

diff --git a/config-ui/src/plugins/components/transformation-select/index.tsx 
b/config-ui/src/plugins/components/transformation-select/index.tsx
index 67d0c3c2a..6b81310fb 100644
--- a/config-ui/src/plugins/components/transformation-select/index.tsx
+++ b/config-ui/src/plugins/components/transformation-select/index.tsx
@@ -93,7 +93,7 @@ export const TransformationSelect = ({
   const handleSubmit = () => !!selectedId && onSubmit(selectedId);
 
   return (
-    <Dialog isOpen title={title} footer={null} style={{ width: 820 }} 
onCancel={onCancel}>
+    <Dialog isOpen title={title} footer={null} style={{ width: 960 }} 
onCancel={onCancel}>
       {!ready || !data ? (
         <PageLoading />
       ) : step === 1 ? (
diff --git a/config-ui/src/plugins/register/azure/config.tsx 
b/config-ui/src/plugins/register/azure/config.tsx
index 3035e6543..eea381cf2 100644
--- a/config-ui/src/plugins/register/azure/config.tsx
+++ b/config-ui/src/plugins/register/azure/config.tsx
@@ -62,7 +62,7 @@ export const AzureConfig: PluginConfigType = {
   entities: ['CODE', 'CODEREVIEW', 'CROSS', 'CICD'],
   transformation: {
     deploymentPattern: '(deploy|push-image)',
-    productionPattern: 'production',
+    productionPattern: 'prod(.*)',
     refdiff: {
       tagsLimit: 10,
       tagsPattern: '/v\\d+\\.\\d+(\\.\\d+(-rc)*\\d*)*$/',
diff --git a/config-ui/src/plugins/register/azure/styled.ts 
b/config-ui/src/plugins/register/azure/styled.ts
index 932aa9bc8..323e34a07 100644
--- a/config-ui/src/plugins/register/azure/styled.ts
+++ b/config-ui/src/plugins/register/azure/styled.ts
@@ -19,38 +19,6 @@
 import styled from 'styled-components';
 
 export const Transfromation = styled.div`
-  .ci-cd {
-    h3 {
-      margin-top: 16px;
-
-      .bp4-tag {
-        margin-left: 4px;
-      }
-    }
-
-    .radio {
-      padding-left: 20px;
-      margin-bottom: 16px;
-
-      .input {
-        display: flex;
-        align-items: center;
-
-        & + .input {
-          margin-top: 8px;
-        }
-
-        p {
-          color: #292b3f;
-        }
-
-        .bp4-input-group {
-          margin: 0 4px;
-        }
-      }
-    }
-  }
-
   .additional-settings {
     h2 {
       display: flex;
@@ -96,3 +64,32 @@ export const Transfromation = styled.div`
     }
   }
 `;
+
+export const CICD = styled.div`
+  h3 {
+    margin-top: 16px;
+
+    .switch {
+      display: inline-flex;
+      align-items: center;
+      margin-left: 16px;
+      font-size: 14px;
+      font-weight: 400;
+
+      .bp4-switch {
+        margin-bottom: 0;
+      }
+    }
+  }
+
+  .text {
+    display: flex;
+    align-items: baseline;
+    margin-top: 16px;
+    padding-left: 24px;
+
+    .bp4-radio {
+      margin-right: 0;
+    }
+  }
+`;
diff --git a/config-ui/src/plugins/register/azure/transformation.tsx 
b/config-ui/src/plugins/register/azure/transformation.tsx
index 2ab24c521..9bb3de73e 100644
--- a/config-ui/src/plugins/register/azure/transformation.tsx
+++ b/config-ui/src/plugins/register/azure/transformation.tsx
@@ -17,9 +17,9 @@
  */
 
 import React, { useState, useEffect } from 'react';
-import { Tag, RadioGroup, Radio, InputGroup, Icon, Collapse, Intent } from 
'@blueprintjs/core';
+import { Tag, Switch, Radio, InputGroup, Icon, Collapse, Intent } from 
'@blueprintjs/core';
 
-import { ExternalLink, HelpTooltip } from '@/components';
+import { Divider, ExternalLink, HelpTooltip } from '@/components';
 
 import * as S from './styled';
 
@@ -29,7 +29,7 @@ interface Props {
 }
 
 export const AzureTransformation = ({ transformation, setTransformation }: 
Props) => {
-  const [enableCICD, setEnableCICD] = useState(1);
+  const [enableCICD, setEnableCICD] = useState(true);
   const [openAdditionalSettings, setOpenAdditionalSettings] = useState(false);
 
   useEffect(() => {
@@ -38,21 +38,23 @@ export const AzureTransformation = ({ transformation, 
setTransformation }: Props
     }
   }, [transformation]);
 
-  const handleChangeCICDEnable = (e: number) => {
-    if (e === 0) {
+  const handleChangeCICDEnable = (e: React.FormEvent<HTMLInputElement>) => {
+    const checked = (e.target as HTMLInputElement).checked;
+
+    if (checked) {
       setTransformation({
         ...transformation,
-        deploymentPattern: undefined,
-        productionPattern: undefined,
+        deploymentPattern: '(deploy|push-image)',
+        productionPattern: 'production',
       });
     } else {
       setTransformation({
         ...transformation,
-        deploymentPattern: '',
-        productionPattern: '',
+        deploymentPattern: undefined,
+        productionPattern: undefined,
       });
     }
-    setEnableCICD(e);
+    setEnableCICD(checked);
   };
 
   const handleChangeAdditionalSettingsOpen = () => {
@@ -67,67 +69,67 @@ export const AzureTransformation = ({ transformation, 
setTransformation }: Props
 
   return (
     <S.Transfromation>
-      <div className="ci-cd">
+      <S.CICD>
         <h2>CI/CD</h2>
         <h3>
           <span>Deployment</span>
-          <Tag minimal intent={Intent.PRIMARY} style={{ marginLeft: 4, 
fontWeight: 400 }}>
+          <Tag minimal intent={Intent.PRIMARY} style={{ marginLeft: 8 }}>
             DORA
           </Tag>
+          <div className="switch">
+            <span>Enable</span>
+            <Switch alignIndicator="right" inline checked={enableCICD} 
onChange={handleChangeCICDEnable} />
+          </div>
         </h3>
-        <p>Tell DevLake what CI builds are Deployments.</p>
-        <RadioGroup
-          selectedValue={enableCICD}
-          onChange={(e) => handleChangeCICDEnable(+(e.target as 
HTMLInputElement).value)}
-        >
-          <Radio label="Detect Deployment from Builds in Azure Pipelines" 
value={1} />
-          {enableCICD === 1 && (
-            <div className="radio">
-              <p>
-                Please fill in the following RegEx, as DevLake ONLY accounts 
for deployments in the production
-                environment for DORA metrics. Not sure what an Azure Build is?
-                <ExternalLink 
link="https://learn.microsoft.com/en-us/azure/devops/pipelines/get-started/what-is-azure-pipelines?view=azure-devops#continuous-testing";>
-                  See it here
-                </ExternalLink>
-              </p>
-              <div className="input">
-                <p>The Build name that matches</p>
-                <InputGroup
-                  placeholder="(?i)deploy"
-                  value={transformation.deploymentPattern}
-                  onChange={(e) =>
-                    setTransformation({
-                      ...transformation,
-                      deploymentPattern: e.target.value,
-                    })
-                  }
-                />
-                <p>
-                  will be registered as a `Deployment` in DevLake. <span 
style={{ color: '#E34040' }}>*</span>
-                </p>
-              </div>
-              <div className="input">
-                <p>The Build name that matches</p>
-                <InputGroup
-                  placeholder="(?i)production"
-                  value={transformation.productionPattern}
-                  onChange={(e) =>
-                    setTransformation({
-                      ...transformation,
-                      productionPattern: e.target.value,
-                    })
-                  }
-                />
-                <p>
-                  will be registered as a `Deployment` to the Production 
environment in DevLake.
-                  <HelpTooltip content="If you leave this field empty, all 
data will be tagged as in the Production environment. " />
-                </p>
-              </div>
+        {enableCICD && (
+          <>
+            <p>
+              Use Regular Expression to define Deployments in DevLake in order 
to measure DORA metrics.{' '}
+              <ExternalLink 
link="https://devlake.apache.org/docs/Configuration/GitHub#step-3---adding-transformation-rules-optional";>
+                Learn more
+              </ExternalLink>
+            </p>
+            <div style={{ marginTop: 16 }}>Convert a Azure Pipeline Run as a 
DevLake Deployment when: </div>
+            <div className="text">
+              <span>
+                The name of the <strong>Azure pipeline</strong> or <strong>one 
of its jobs</strong> matches
+              </span>
+              <InputGroup
+                style={{ width: 224, margin: '0 8px' }}
+                placeholder="(deploy|push-image)"
+                value={transformation.deploymentPattern ?? ''}
+                onChange={(e) =>
+                  setTransformation({
+                    ...transformation,
+                    deploymentPattern: e.target.value,
+                    productionPattern: !e.target.value ? '' : 
transformation.productionPattern,
+                  })
+                }
+              />
+              <i style={{ color: '#E34040' }}>*</i>
+              <HelpTooltip content="Azure Pipelines: 
https://learn.microsoft.com/en-us/azure/devops/pipelines/get-started/what-is-azure-pipelines?view=azure-devops#continuous-testing";
 />
             </div>
-          )}
-          <Radio label="Not using Builds in Azure Pipelines as Deployments" 
value={0} />
-        </RadioGroup>
-      </div>
+            <div className="text">
+              <span>If the name also matches</span>
+              <InputGroup
+                style={{ width: 120, margin: '0 8px' }}
+                disabled={!transformation.deploymentPattern}
+                placeholder="prod(.*)"
+                value={transformation.productionPattern ?? ''}
+                onChange={(e) =>
+                  setTransformation({
+                    ...transformation,
+                    productionPattern: e.target.value,
+                  })
+                }
+              />
+              <span>, this Deployment is a ‘Production Deployment’</span>
+              <HelpTooltip content="If you leave this field empty, all DevLake 
Deployments will be tagged as in the Production environment. " />
+            </div>
+          </>
+        )}
+      </S.CICD>
+      <Divider />
       {/* Additional Settings */}
       <div className="additional-settings">
         <h2 onClick={handleChangeAdditionalSettingsOpen}>
diff --git 
a/config-ui/src/plugins/register/bitbucket/assets/bitbucket-example.jpg 
b/config-ui/src/plugins/register/bitbucket/assets/bitbucket-example.jpg
new file mode 100644
index 000000000..b196eac3c
Binary files /dev/null and 
b/config-ui/src/plugins/register/bitbucket/assets/bitbucket-example.jpg differ
diff --git a/config-ui/src/plugins/register/bitbucket/config.tsx 
b/config-ui/src/plugins/register/bitbucket/config.tsx
index 5e36af037..5244234b2 100644
--- a/config-ui/src/plugins/register/bitbucket/config.tsx
+++ b/config-ui/src/plugins/register/bitbucket/config.tsx
@@ -65,7 +65,7 @@ export const BitBucketConfig: PluginConfigType = {
     issueStatusDone: 'closed',
     issueStatusOther: 'on hold,wontfix,duplicate,invalid',
     deploymentPattern: '(deploy|push-image)',
-    productionPattern: 'production',
+    productionPattern: 'prod(.*)',
     refdiff: {
       tagsLimit: 10,
       tagsPattern: '/v\\d+\\.\\d+(\\.\\d+(-rc)*\\d*)*$/',
diff --git a/config-ui/src/plugins/register/bitbucket/styled.ts 
b/config-ui/src/plugins/register/bitbucket/styled.ts
index e583dcd91..c17e78cc6 100644
--- a/config-ui/src/plugins/register/bitbucket/styled.ts
+++ b/config-ui/src/plugins/register/bitbucket/styled.ts
@@ -18,7 +18,7 @@
 
 import styled from 'styled-components';
 
-export const TransformationWrapper = styled.div`
+export const Transformation = styled.div`
   .issue-tracking {
     .issue-type {
       .title {
@@ -31,39 +31,6 @@ export const TransformationWrapper = styled.div`
     }
   }
 
-  .ci-cd {
-    h3 {
-      margin-top: 16px;
-
-      .bp4-tag {
-        margin-left: 4px;
-      }
-    }
-
-    .radio {
-      padding-left: 20px;
-      margin-bottom: 16px;
-
-      .input {
-        display: flex;
-        align-items: center;
-        flex-wrap: wrap;
-
-        & + .input {
-          margin-top: 8px;
-        }
-
-        p {
-          color: #292b3f;
-        }
-
-        .bp4-input-group {
-          margin: 0 4px;
-        }
-      }
-    }
-  }
-
   .additional-settings {
     h2 {
       display: flex;
@@ -109,3 +76,30 @@ export const TransformationWrapper = styled.div`
     }
   }
 `;
+
+export const CICD = styled.div`
+  h3 {
+    margin-top: 16px;
+
+    .switch {
+      display: inline-flex;
+      align-items: center;
+      margin-left: 16px;
+      font-size: 14px;
+      font-weight: 400;
+
+      .bp4-switch {
+        margin-bottom: 0;
+      }
+    }
+  }
+
+  .text {
+    display: flex;
+    align-items: baseline;
+
+    .bp4-radio {
+      margin-right: 0;
+    }
+  }
+`;
diff --git a/config-ui/src/plugins/register/bitbucket/transformation.tsx 
b/config-ui/src/plugins/register/bitbucket/transformation.tsx
index 90a3741a7..e14313981 100644
--- a/config-ui/src/plugins/register/bitbucket/transformation.tsx
+++ b/config-ui/src/plugins/register/bitbucket/transformation.tsx
@@ -17,10 +17,11 @@
  */
 
 import React, { useMemo, useState, useEffect } from 'react';
-import { FormGroup, InputGroup, Tag, Radio, Icon, Collapse, Intent, Checkbox } 
from '@blueprintjs/core';
+import { FormGroup, InputGroup, Tag, Radio, Icon, Collapse, Intent, Switch } 
from '@blueprintjs/core';
 
 import { ExternalLink, HelpTooltip, Divider, MultiSelector } from 
'@/components';
 
+import ExampleJpg from './assets/bitbucket-example.jpg';
 import * as S from './styled';
 
 interface Props {
@@ -31,7 +32,8 @@ interface Props {
 const ALL_STATES = ['new', 'open', 'resolved', 'closed', 'on hold', 'wontfix', 
'duplicate', 'invalid'];
 
 export const BitbucketTransformation = ({ transformation, setTransformation }: 
Props) => {
-  const [enableCICD, setEnableCICD] = useState(false);
+  const [enableCICD, setEnableCICD] = useState(true);
+  const [useCustom, setUseCustom] = useState(false);
   const [openAdditionalSettings, setOpenAdditionalSettings] = useState(false);
 
   useEffect(() => {
@@ -50,15 +52,42 @@ export const BitbucketTransformation = ({ transformation, 
setTransformation }: P
     [transformation],
   );
 
-  const handleChangeCICDEnable = (b: boolean) => {
-    if (!b) {
+  const handleChangeUseCustom = (uc: boolean) => {
+    if (!uc) {
       setTransformation({
         ...transformation,
         deploymentPattern: '',
         productionPattern: '',
       });
+    } else {
+      setTransformation({
+        ...transformation,
+        deploymentPattern: '(deploy|push-image)',
+        productionPattern: '',
+      });
+    }
+
+    setUseCustom(uc);
+  };
+
+  const handleChangeCICDEnable = (e: React.FormEvent<HTMLInputElement>) => {
+    const checked = (e.target as HTMLInputElement).checked;
+
+    if (checked) {
+      setUseCustom(false);
+      setTransformation({
+        ...transformation,
+        deploymentPattern: '',
+        productionPattern: '',
+      });
+    } else {
+      setTransformation({
+        ...transformation,
+        deploymentPattern: undefined,
+        productionPattern: undefined,
+      });
     }
-    setEnableCICD(b);
+    setEnableCICD(checked);
   };
 
   const handleChangeAdditionalSettingsOpen = () => {
@@ -72,7 +101,7 @@ export const BitbucketTransformation = ({ transformation, 
setTransformation }: P
   };
 
   return (
-    <S.TransformationWrapper>
+    <S.Transformation>
       {/* Issue Tracking */}
       <div className="issue-tracking">
         <h2>Issue Tracking</h2>
@@ -141,69 +170,54 @@ export const BitbucketTransformation = ({ transformation, 
setTransformation }: P
       </div>
       <Divider />
       {/* CI/CD */}
-      <div className="ci-cd">
+      <S.CICD>
         <h2>CI/CD</h2>
         <h3>
           <span>Deployment</span>
-          <Tag minimal intent={Intent.PRIMARY}>
+          <Tag minimal intent={Intent.PRIMARY} style={{ marginLeft: 8 }}>
             DORA
           </Tag>
+          <div className="switch">
+            <span>Enable</span>
+            <Switch alignIndicator="right" inline checked={enableCICD} 
onChange={handleChangeCICDEnable} />
+          </div>
         </h3>
-        <p>
-          DevLake uses BitBucket{' '}
-          <ExternalLink 
link="https://support.atlassian.com/bitbucket-cloud/docs/set-up-and-monitor-deployments/";>
-            deployments
-          </ExternalLink>{' '}
-          as DevLake deployments. If you are NOT using BitBucket deployments, 
DevLake provides the option to detect
-          deployments from BitBucket pipeline steps.{' '}
-          <ExternalLink 
link="https://devlake.apache.org/docs/Configuration/BitBucket#step-3---adding-transformation-rules-optional";>
-            Learn more
-          </ExternalLink>
-        </p>
-        <Checkbox
-          label="Detect Deployments from Pipeline steps in BitBucket"
-          checked={enableCICD}
-          onChange={(e) => handleChangeCICDEnable((e.target as 
HTMLInputElement).checked)}
-        />
         {enableCICD && (
-          <div className="radio">
-            <div className="input">
-              <p>The Pipeline step name that matches</p>
-              <InputGroup
-                placeholder="(deploy|push-image)"
-                value={transformation.deploymentPattern}
-                onChange={(e) =>
-                  setTransformation({
-                    ...transformation,
-                    deploymentPattern: e.target.value,
-                  })
-                }
-              />
-              <p>
-                will be registered as a `Deployment` in DevLake. <span 
style={{ color: '#E34040' }}>*</span>
-              </p>
+          <>
+            <p>
+              Use Regular Expression to define Deployments in DevLake in order 
to measure DORA metrics.{' '}
+              <ExternalLink 
link="https://devlake.apache.org/docs/Configuration/GitHub#step-3---adding-transformation-rules-optional";>
+                Learn more
+              </ExternalLink>
+            </p>
+            <div style={{ margin: '16px 0' }}>Convert a BitBucket Pipeline as 
a DevLake Deployment when: </div>
+            <div className="text">
+              <Radio checked={!useCustom} onChange={() => 
handleChangeUseCustom(false)} />
+              <span>It has one or more BitBucket deployments. See the 
example.</span>
+              <HelpTooltip content={<img src={ExampleJpg} alt="" width={400} 
/>} />
             </div>
-            <div className="input">
-              <p>The Pipeline step name that matches</p>
-              <InputGroup
-                disabled={!transformation.deploymentPattern}
-                placeholder="production"
-                value={transformation.productionPattern}
-                onChange={(e) =>
-                  setTransformation({
-                    ...transformation,
-                    productionPattern: e.target.value,
-                  })
-                }
-              />
-              <p>
-                will be registered as a `Deployment` to the Production 
environment in DevLake.
-                <HelpTooltip content="If you leave this field empty, all data 
will be tagged as in the Production environment. " />
-              </p>
+            <div className="text">
+              <Radio checked={useCustom} onChange={() => 
handleChangeUseCustom(true)} />
+              <div style={{ display: 'flex', alignItems: 'center' }}>
+                <span>Its branch/tag name or one of its pipeline steps’ names 
matches</span>
+                <InputGroup
+                  style={{ width: 224, margin: '0 8px' }}
+                  placeholder="(deploy|push-image)"
+                  value={transformation.deploymentPattern ?? ''}
+                  onChange={(e) =>
+                    setTransformation({
+                      ...transformation,
+                      deploymentPattern: e.target.value,
+                      productionPattern: !e.target.value ? '' : 
transformation.productionPattern,
+                    })
+                  }
+                />
+                <HelpTooltip content="If you leave this field empty, all 
DevLake Deployments will be tagged as in the Production environment. " />
+              </div>
             </div>
-          </div>
+          </>
         )}
-      </div>
+      </S.CICD>
       <Divider />
       {/* Additional Settings */}
       <div className="additional-settings">
@@ -255,6 +269,6 @@ export const BitbucketTransformation = ({ transformation, 
setTransformation }: P
           </div>
         </Collapse>
       </div>
-    </S.TransformationWrapper>
+    </S.Transformation>
   );
 };
diff --git a/config-ui/src/plugins/register/github/config.tsx 
b/config-ui/src/plugins/register/github/config.tsx
index 9189c5911..a5976b0c4 100644
--- a/config-ui/src/plugins/register/github/config.tsx
+++ b/config-ui/src/plugins/register/github/config.tsx
@@ -86,7 +86,7 @@ export const GitHubConfig: PluginConfigType = {
     issueComponent: 'component(.*)',
     issueSeverity: 'severity(.*)',
     deploymentPattern: '(deploy|push-image)',
-    productionPattern: 'production',
+    productionPattern: 'prod(.*)',
     prType: 'type(.*)',
     prComponent: 'component(.*)',
     prBodyClosePattern:
diff --git a/config-ui/src/plugins/register/github/styled.ts 
b/config-ui/src/plugins/register/github/styled.ts
index ae2b38e37..08cc93834 100644
--- a/config-ui/src/plugins/register/github/styled.ts
+++ b/config-ui/src/plugins/register/github/styled.ts
@@ -24,7 +24,7 @@ export const DataScope = styled.div`
   }
 `;
 
-export const TransformationWrapper = styled.div`
+export const Transformation = styled.div`
   .issue-tracking {
     .issue-type {
       .title {
@@ -37,38 +37,6 @@ export const TransformationWrapper = styled.div`
     }
   }
 
-  .ci-cd {
-    h3 {
-      margin-top: 16px;
-
-      .bp4-tag {
-        margin-left: 4px;
-      }
-    }
-
-    .radio {
-      padding-left: 20px;
-      margin-bottom: 16px;
-
-      .input {
-        display: flex;
-        align-items: center;
-
-        & + .input {
-          margin-top: 8px;
-        }
-
-        p {
-          color: #292b3f;
-        }
-
-        .bp4-input-group {
-          margin: 0 4px;
-        }
-      }
-    }
-  }
-
   .additional-settings {
     h2 {
       display: flex;
@@ -114,3 +82,32 @@ export const TransformationWrapper = styled.div`
     }
   }
 `;
+
+export const CICD = styled.div`
+  h3 {
+    margin-top: 16px;
+
+    .switch {
+      display: inline-flex;
+      align-items: center;
+      margin-left: 16px;
+      font-size: 14px;
+      font-weight: 400;
+
+      .bp4-switch {
+        margin-bottom: 0;
+      }
+    }
+  }
+
+  .text {
+    display: flex;
+    align-items: baseline;
+    margin-top: 16px;
+    padding-left: 24px;
+
+    .bp4-radio {
+      margin-right: 0;
+    }
+  }
+`;
diff --git a/config-ui/src/plugins/register/github/transformation.tsx 
b/config-ui/src/plugins/register/github/transformation.tsx
index b910e4368..ec84a5689 100644
--- a/config-ui/src/plugins/register/github/transformation.tsx
+++ b/config-ui/src/plugins/register/github/transformation.tsx
@@ -16,19 +16,8 @@
  *
  */
 
-import React, { useEffect, useState } from 'react';
-import {
-  FormGroup,
-  InputGroup,
-  TextArea,
-  Tag,
-  RadioGroup,
-  Radio,
-  Icon,
-  Collapse,
-  Intent,
-  Colors,
-} from '@blueprintjs/core';
+import React, { useState, useEffect } from 'react';
+import { FormGroup, InputGroup, TextArea, Tag, Switch, Radio, Icon, Collapse, 
Intent, Colors } from '@blueprintjs/core';
 
 import { ExternalLink, HelpTooltip, Divider } from '@/components';
 
@@ -40,7 +29,7 @@ interface Props {
 }
 
 export const GitHubTransformation = ({ transformation, setTransformation }: 
Props) => {
-  const [enableCICD, setEnableCICD] = useState(1);
+  const [enableCICD, setEnableCICD] = useState(true);
   const [openAdditionalSettings, setOpenAdditionalSettings] = useState(false);
 
   useEffect(() => {
@@ -49,21 +38,23 @@ export const GitHubTransformation = ({ transformation, 
setTransformation }: Prop
     }
   }, [transformation]);
 
-  const handleChangeCICDEnable = (e: number) => {
-    if (e === 0) {
+  const handleChangeCICDEnable = (e: React.FormEvent<HTMLInputElement>) => {
+    const checked = (e.target as HTMLInputElement).checked;
+
+    if (checked) {
       setTransformation({
         ...transformation,
-        deploymentPattern: undefined,
-        productionPattern: undefined,
+        deploymentPattern: '(deploy|push-image)',
+        productionPattern: 'production',
       });
     } else {
       setTransformation({
         ...transformation,
-        deploymentPattern: '',
-        productionPattern: '',
+        deploymentPattern: undefined,
+        productionPattern: undefined,
       });
     }
-    setEnableCICD(e);
+    setEnableCICD(checked);
   };
 
   const handleChangeAdditionalSettingsOpen = () => {
@@ -77,7 +68,7 @@ export const GitHubTransformation = ({ transformation, 
setTransformation }: Prop
   };
 
   return (
-    <S.TransformationWrapper>
+    <S.Transformation>
       {/* Issue Tracking */}
       <div className="issue-tracking">
         <h2>Issue Tracking</h2>
@@ -206,68 +197,66 @@ export const GitHubTransformation = ({ transformation, 
setTransformation }: Prop
       </div>
       <Divider />
       {/* CI/CD */}
-      <div className="ci-cd">
+      <S.CICD>
         <h2>CI/CD</h2>
         <h3>
           <span>Deployment</span>
-          <Tag minimal intent={Intent.PRIMARY}>
+          <Tag minimal intent={Intent.PRIMARY} style={{ marginLeft: 8 }}>
             DORA
           </Tag>
+          <div className="switch">
+            <span>Enable</span>
+            <Switch alignIndicator="right" inline checked={enableCICD} 
onChange={handleChangeCICDEnable} />
+          </div>
         </h3>
-        <p>Tell DevLake what CI jobs are Deployments.</p>
-        <RadioGroup
-          selectedValue={enableCICD}
-          onChange={(e) => handleChangeCICDEnable(+(e.target as 
HTMLInputElement).value)}
-        >
-          <Radio label="Detect Deployment from Jobs in GitHub Action" 
value={1} />
-          {enableCICD === 1 && (
-            <div className="radio">
-              <p>
-                Please fill in the following RegEx, as DevLake ONLY accounts 
for deployments in the production
-                environment for DORA metrics. Not sure what a GitHub Action 
job is?{' '}
-                <ExternalLink 
link="https://docs.github.com/en/actions/using-jobs/using-jobs-in-a-workflow";>
-                  See it here
-                </ExternalLink>
-              </p>
-              <div className="input">
-                <p>The job name that matches</p>
-                <InputGroup
-                  placeholder="(deploy|push-image)"
-                  value={transformation.deploymentPattern ?? ''}
-                  onChange={(e) =>
-                    setTransformation({
-                      ...transformation,
-                      deploymentPattern: e.target.value,
-                    })
-                  }
-                />
-                <p>
-                  will be registered as a `Deployment` in DevLake. <span 
style={{ color: '#E34040' }}>*</span>
-                </p>
-              </div>
-              <div className="input">
-                <p>The job name that matches</p>
-                <InputGroup
-                  disabled={!transformation.deploymentPattern}
-                  placeholder="production"
-                  value={transformation.productionPattern ?? ''}
-                  onChange={(e) =>
-                    setTransformation({
-                      ...transformation,
-                      productionPattern: e.target.value,
-                    })
-                  }
-                />
-                <p>
-                  will be registered as a `Deployment` to the Production 
environment in DevLake.
-                  <HelpTooltip content="If you leave this field empty, all 
data will be tagged as in the Production environment. " />
-                </p>
-              </div>
+        {enableCICD && (
+          <>
+            <p>
+              Use Regular Expression to define Deployments in DevLake in order 
to measure DORA metrics.{' '}
+              <ExternalLink 
link="https://devlake.apache.org/docs/Configuration/GitHub#step-3---adding-transformation-rules-optional";>
+                Learn more
+              </ExternalLink>
+            </p>
+            <div style={{ marginTop: 16 }}>Convert a GitHub Workflow run as a 
DevLake Deployment when: </div>
+            <div className="text">
+              <span>
+                The name of the <strong>GitHub workflow run</strong> or 
<strong>one of its jobs</strong> matches
+              </span>
+              <InputGroup
+                style={{ width: 224, margin: '0 8px' }}
+                placeholder="(deploy|push-image)"
+                value={transformation.deploymentPattern ?? ''}
+                onChange={(e) =>
+                  setTransformation({
+                    ...transformation,
+                    deploymentPattern: e.target.value,
+                    productionPattern: !e.target.value ? '' : 
transformation.productionPattern,
+                  })
+                }
+              />
+              <i style={{ color: '#E34040' }}>*</i>
+              <HelpTooltip content="GitHub Workflow Runs: 
https://docs.github.com/en/actions/managing-workflow-runs/manually-running-a-workflow";
 />
             </div>
-          )}
-          <Radio label="Not using any GitHub entities as Deployment" value={0} 
/>
-        </RadioGroup>
-      </div>
+            <div className="text">
+              <span>If the name also matches</span>
+              <InputGroup
+                style={{ width: 120, margin: '0 8px' }}
+                disabled={!transformation.deploymentPattern}
+                placeholder="prod(.*)"
+                value={transformation.productionPattern ?? ''}
+                onChange={(e) =>
+                  setTransformation({
+                    ...transformation,
+                    productionPattern: e.target.value,
+                  })
+                }
+              />
+              <span>, this Deployment is a ‘Production Deployment’</span>
+              <HelpTooltip content="If you leave this field empty, all DevLake 
Deployments will be tagged as in the Production environment. " />
+            </div>
+          </>
+        )}
+      </S.CICD>
       <Divider />
       {/* Code Review */}
       <div>
@@ -414,6 +403,6 @@ export const GitHubTransformation = ({ transformation, 
setTransformation }: Prop
           </div>
         </Collapse>
       </div>
-    </S.TransformationWrapper>
+    </S.Transformation>
   );
 };
diff --git a/config-ui/src/plugins/register/gitlab/config.tsx 
b/config-ui/src/plugins/register/gitlab/config.tsx
index 23700d61b..bf24eefea 100644
--- a/config-ui/src/plugins/register/gitlab/config.tsx
+++ b/config-ui/src/plugins/register/gitlab/config.tsx
@@ -71,6 +71,6 @@ export const GitLabConfig: PluginConfigType = {
   entities: ['CODE', 'TICKET', 'CODEREVIEW', 'CROSS', 'CICD'],
   transformation: {
     deploymentPattern: '(deploy|push-image)',
-    productionPattern: 'production',
+    productionPattern: 'prod(.*)',
   },
 };
diff --git a/config-ui/src/plugins/register/gitlab/styled.ts 
b/config-ui/src/plugins/register/gitlab/styled.ts
index 78de5577d..c53a287b9 100644
--- a/config-ui/src/plugins/register/gitlab/styled.ts
+++ b/config-ui/src/plugins/register/gitlab/styled.ts
@@ -24,34 +24,33 @@ export const DataScope = styled.div`
   }
 `;
 
-export const TransformationWrapper = styled.div`
+export const Transformation = styled.div``;
+
+export const CICD = styled.div`
   h3 {
     margin-top: 16px;
 
-    .bp4-tag {
-      margin-left: 4px;
-    }
-  }
-
-  .radio {
-    padding-left: 20px;
-    margin-bottom: 16px;
-
-    .input {
-      display: flex;
+    .switch {
+      display: inline-flex;
       align-items: center;
+      margin-left: 16px;
+      font-size: 14px;
+      font-weight: 400;
 
-      & + .input {
-        margin-top: 8px;
+      .bp4-switch {
+        margin-bottom: 0;
       }
+    }
+  }
 
-      p {
-        color: #292b3f;
-      }
+  .text {
+    display: flex;
+    align-items: baseline;
+    margin-top: 16px;
+    padding-left: 24px;
 
-      .bp4-input-group {
-        margin: 0 4px;
-      }
+    .bp4-radio {
+      margin-right: 0;
     }
   }
 `;
diff --git a/config-ui/src/plugins/register/gitlab/transformation.tsx 
b/config-ui/src/plugins/register/gitlab/transformation.tsx
index 254f85c22..6f09fcec8 100644
--- a/config-ui/src/plugins/register/gitlab/transformation.tsx
+++ b/config-ui/src/plugins/register/gitlab/transformation.tsx
@@ -17,7 +17,7 @@
  */
 
 import React, { useState } from 'react';
-import { Tag, Intent, RadioGroup, Radio, InputGroup } from '@blueprintjs/core';
+import { Tag, Intent, Switch, InputGroup } from '@blueprintjs/core';
 
 import { ExternalLink, HelpTooltip } from '@/components';
 
@@ -29,66 +29,76 @@ interface Props {
 }
 
 export const GitLabTransformation = ({ transformation, setTransformation }: 
Props) => {
-  const [enable, setEnable] = useState(1);
+  const [enableCICD, setEnableCICD] = useState(true);
 
-  const handleChangeEnable = (e: number) => {
-    if (e === 0) {
+  const handleChangeCICDEnable = (e: React.FormEvent<HTMLInputElement>) => {
+    const checked = (e.target as HTMLInputElement).checked;
+
+    if (checked) {
       setTransformation({
         ...transformation,
-        deploymentPattern: undefined,
-        productionPattern: undefined,
+        deploymentPattern: '(deploy|push-image)',
+        productionPattern: 'production',
       });
     } else {
       setTransformation({
         ...transformation,
-        deploymentPattern: '',
-        productionPattern: '',
+        deploymentPattern: undefined,
+        productionPattern: undefined,
       });
     }
-    setEnable(e);
+    setEnableCICD(checked);
   };
 
   return (
-    <S.TransformationWrapper>
-      <h2>CI/CD</h2>
-      <h3>
-        <span>Deployment</span>
-        <Tag minimal intent={Intent.PRIMARY}>
-          DORA
-        </Tag>
-      </h3>
-      <p>Tell DevLake what CI jobs are Deployments.</p>
-      <RadioGroup selectedValue={enable} onChange={(e) => 
handleChangeEnable(+(e.target as HTMLInputElement).value)}>
-        <Radio label="Detect Deployments from Jobs in GitLab CI" value={1} />
-        {enable === 1 && (
-          <div className="radio">
+    <S.Transformation>
+      <S.CICD>
+        <h2>CI/CD</h2>
+        <h3>
+          <span>Deployment</span>
+          <Tag minimal intent={Intent.PRIMARY} style={{ marginLeft: 8 }}>
+            DORA
+          </Tag>
+          <div className="switch">
+            <span>Enable</span>
+            <Switch alignIndicator="right" inline checked={enableCICD} 
onChange={handleChangeCICDEnable} />
+          </div>
+        </h3>
+        {enableCICD && (
+          <>
             <p>
-              Please fill in the following RegEx, as DevLake ONLY accounts for 
deployments in the production environment
-              for DORA metrics. Not sure what a GitLab CI job is?{' '}
-              <ExternalLink link="https://docs.gitlab.com/ee/ci/jobs/";>See it 
here</ExternalLink>
+              Use Regular Expression to define Deployments in DevLake in order 
to measure DORA metrics.{' '}
+              <ExternalLink 
link="https://devlake.apache.org/docs/Configuration/GitHub#step-3---adding-transformation-rules-optional";>
+                Learn more
+              </ExternalLink>
             </p>
-            <div className="input">
-              <p>The job name that matches</p>
+            <div style={{ marginTop: 16 }}>Convert a GitLab Pipeline as a 
DevLake Deployment when: </div>
+            <div className="text">
+              <span>
+                The name of the <strong>GitLab pipeline</strong> or 
<strong>one of its jobs</strong> matches
+              </span>
               <InputGroup
+                style={{ width: 224, margin: '0 8px' }}
                 placeholder="(deploy|push-image)"
-                value={transformation.deploymentPattern}
+                value={transformation.deploymentPattern ?? ''}
                 onChange={(e) =>
                   setTransformation({
                     ...transformation,
                     deploymentPattern: e.target.value,
+                    productionPattern: !e.target.value ? '' : 
transformation.productionPattern,
                   })
                 }
               />
-              <p>
-                will be registered as a `Deployment` in DevLake. <span 
style={{ color: '#E34040' }}>*</span>
-              </p>
+              <i style={{ color: '#E34040' }}>*</i>
+              <HelpTooltip content="GitLab Pipelines: 
https://docs.gitlab.com/ee/ci/pipelines/"; />
             </div>
-            <div className="input">
-              <p>The job name that matches</p>
+            <div className="text">
+              <span>If the name also matches</span>
               <InputGroup
+                style={{ width: 120, margin: '0 8px' }}
                 disabled={!transformation.deploymentPattern}
-                placeholder="production"
-                value={transformation.productionPattern}
+                placeholder="prod(.*)"
+                value={transformation.productionPattern ?? ''}
                 onChange={(e) =>
                   setTransformation({
                     ...transformation,
@@ -96,15 +106,12 @@ export const GitLabTransformation = ({ transformation, 
setTransformation }: Prop
                   })
                 }
               />
-              <p>
-                will be registered as a `Deployment` to the Production 
environment in DevLake.
-                <HelpTooltip content="If you leave this field empty, all data 
will be tagged as in the Production environment. " />
-              </p>
+              <span>, this Deployment is a ‘Production Deployment’</span>
+              <HelpTooltip content="If you leave this field empty, all DevLake 
Deployments will be tagged as in the Production environment. " />
             </div>
-          </div>
+          </>
         )}
-        <Radio label="Not using GitLab CI Jobs as Deployment" value={0} />
-      </RadioGroup>
-    </S.TransformationWrapper>
+      </S.CICD>
+    </S.Transformation>
   );
 };
diff --git a/config-ui/src/plugins/register/jenkins/config.ts 
b/config-ui/src/plugins/register/jenkins/config.ts
index 2aca5d0f5..354159392 100644
--- a/config-ui/src/plugins/register/jenkins/config.ts
+++ b/config-ui/src/plugins/register/jenkins/config.ts
@@ -51,6 +51,6 @@ export const JenkinsConfig: PluginConfigType = {
   entities: ['CICD'],
   transformation: {
     deploymentPattern: '(deploy|push-image)',
-    productionPattern: 'production',
+    productionPattern: 'prod(.*)',
   },
 };
diff --git a/config-ui/src/plugins/register/jenkins/styled.ts 
b/config-ui/src/plugins/register/jenkins/styled.ts
index 8c64ba989..3de9b32b9 100644
--- a/config-ui/src/plugins/register/jenkins/styled.ts
+++ b/config-ui/src/plugins/register/jenkins/styled.ts
@@ -18,34 +18,33 @@
 
 import styled from 'styled-components';
 
-export const TransformationWrapper = styled.div`
+export const Transformation = styled.div``;
+
+export const CICD = styled.div`
   h3 {
     margin-top: 16px;
 
-    .bp4-tag {
-      margin-left: 4px;
-    }
-  }
-
-  .radio {
-    padding-left: 20px;
-    margin-bottom: 16px;
-
-    .input {
-      display: flex;
+    .switch {
+      display: inline-flex;
       align-items: center;
+      margin-left: 16px;
+      font-size: 14px;
+      font-weight: 400;
 
-      & + .input {
-        margin-top: 8px;
+      .bp4-switch {
+        margin-bottom: 0;
       }
+    }
+  }
 
-      p {
-        color: #292b3f;
-      }
+  .text {
+    display: flex;
+    align-items: baseline;
+    margin-top: 16px;
+    padding-left: 24px;
 
-      .bp4-input-group {
-        margin: 0 4px;
-      }
+    .bp4-radio {
+      margin-right: 0;
     }
   }
 `;
diff --git a/config-ui/src/plugins/register/jenkins/transformation.tsx 
b/config-ui/src/plugins/register/jenkins/transformation.tsx
index 17fef0c46..5a6090ea2 100644
--- a/config-ui/src/plugins/register/jenkins/transformation.tsx
+++ b/config-ui/src/plugins/register/jenkins/transformation.tsx
@@ -17,7 +17,7 @@
  */
 
 import React, { useState } from 'react';
-import { Tag, Intent, RadioGroup, Radio, InputGroup } from '@blueprintjs/core';
+import { Tag, Intent, Switch, InputGroup } from '@blueprintjs/core';
 
 import * as S from './styled';
 import { ExternalLink, HelpTooltip } from '@/components';
@@ -28,66 +28,76 @@ interface Props {
 }
 
 export const JenkinsTransformation = ({ transformation, setTransformation }: 
Props) => {
-  const [enable, setEnable] = useState(1);
+  const [enableCICD, setEnableCICD] = useState(true);
 
-  const handleChangeEnable = (e: number) => {
-    if (e === 0) {
+  const handleChangeCICDEnable = (e: React.FormEvent<HTMLInputElement>) => {
+    const checked = (e.target as HTMLInputElement).checked;
+
+    if (checked) {
       setTransformation({
         ...transformation,
-        deploymentPattern: undefined,
-        productionPattern: undefined,
+        deploymentPattern: '(deploy|push-image)',
+        productionPattern: 'production',
       });
     } else {
       setTransformation({
         ...transformation,
-        deploymentPattern: '',
-        productionPattern: '',
+        deploymentPattern: undefined,
+        productionPattern: undefined,
       });
     }
-    setEnable(e);
+    setEnableCICD(checked);
   };
 
   return (
-    <S.TransformationWrapper>
-      <h2>CI/CD</h2>
-      <h3>
-        <span>Deployment</span>
-        <Tag minimal intent={Intent.PRIMARY}>
-          DORA
-        </Tag>
-      </h3>
-      <p>Tell DevLake what CI builds are Deployments.</p>
-      <RadioGroup selectedValue={enable} onChange={(e) => 
handleChangeEnable(+(e.target as HTMLInputElement).value)}>
-        <Radio label="Detect Deployments from Jenkins Builds" value={1} />
-        {enable === 1 && (
-          <div className="radio">
+    <S.Transformation>
+      <S.CICD>
+        <h2>CI/CD</h2>
+        <h3>
+          <span>Deployment</span>
+          <Tag minimal intent={Intent.PRIMARY} style={{ marginLeft: 8 }}>
+            DORA
+          </Tag>
+          <div className="switch">
+            <span>Enable</span>
+            <Switch alignIndicator="right" inline checked={enableCICD} 
onChange={handleChangeCICDEnable} />
+          </div>
+        </h3>
+        {enableCICD && (
+          <>
             <p>
-              Please fill in the following RegEx, as DevLake ONLY accounts for 
deployments in the production environment
-              for DORA metrics. Not sure what a Jenkins Build is?{' '}
-              <ExternalLink 
link="https://www.jenkins.io/doc/book/pipeline/#overview";>See it 
here</ExternalLink>
+              Use Regular Expression to define Deployments in DevLake in order 
to measure DORA metrics.{' '}
+              <ExternalLink 
link="https://devlake.apache.org/docs/Configuration/GitHub#step-3---adding-transformation-rules-optional";>
+                Learn more
+              </ExternalLink>
             </p>
-            <div className="input">
-              <p>The Build name that matches</p>
+            <div style={{ marginTop: 16 }}>Convert a Jenkins Build as a 
DevLake Deployment when: </div>
+            <div className="text">
+              <span>
+                The name of the <strong>Jenkins build</strong> or <strong>one 
of its jobs</strong> matches
+              </span>
               <InputGroup
+                style={{ width: 224, margin: '0 8px' }}
                 placeholder="(deploy|push-image)"
-                value={transformation.deploymentPattern}
+                value={transformation.deploymentPattern ?? ''}
                 onChange={(e) =>
                   setTransformation({
                     ...transformation,
                     deploymentPattern: e.target.value,
+                    productionPattern: !e.target.value ? '' : 
transformation.productionPattern,
                   })
                 }
               />
-              <p>
-                will be registered as a `Deployment` in DevLake. <span 
style={{ color: '#E34040' }}>*</span>
-              </p>
+              <i style={{ color: '#E34040' }}>*</i>
+              <HelpTooltip content="Jenkins Builds: 
https://www.jenkins.io/doc/pipeline/steps/pipeline-build-step/"; />
             </div>
-            <div className="input">
-              <p>The Build name that matches</p>
+            <div className="text">
+              <span>If the name also matches</span>
               <InputGroup
+                style={{ width: 120, margin: '0 8px' }}
                 disabled={!transformation.deploymentPattern}
-                placeholder="production"
-                value={transformation.productionPattern}
+                placeholder="prod(.*)"
+                value={transformation.productionPattern ?? ''}
                 onChange={(e) =>
                   setTransformation({
                     ...transformation,
@@ -95,15 +105,12 @@ export const JenkinsTransformation = ({ transformation, 
setTransformation }: Pro
                   })
                 }
               />
-              <p>
-                will be registered as a `Deployment` to the Production 
environment in DevLake.
-                <HelpTooltip content="If you leave this field empty, all data 
will be tagged as in the Production environment. " />
-              </p>
+              <span>, this Deployment is a ‘Production Deployment’</span>
+              <HelpTooltip content="If you leave this field empty, all DevLake 
Deployments will be tagged as in the Production environment. " />
             </div>
-          </div>
+          </>
         )}
-        <Radio label="Not using Jenkins Builds as Deployments" value={0} />
-      </RadioGroup>
-    </S.TransformationWrapper>
+      </S.CICD>
+    </S.Transformation>
   );
 };


Reply via email to