Skip to content

Commit 8a3a0d1

Browse files
feat(import): backport-add-gitlab-annotations
1 parent 04ab3eb commit 8a3a0d1

File tree

10 files changed

+161
-20
lines changed

10 files changed

+161
-20
lines changed

src/components/ImportForm/ComponentSection/GitOptions.tsx

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,24 @@ import * as React from 'react';
22
import { ExpandableSection, FormSection, PageSection } from '@patternfly/react-core';
33
import { InputField } from 'formik-pf';
44
import HelpPopover from '../../HelpPopover';
5+
import { GitProviderDropdown } from './GitProviderDropdown';
56

6-
const GitOptions: React.FC<React.PropsWithChildren<unknown>> = () => {
7+
type GitOptionProps = {
8+
isGitAdvancedOpen: boolean;
9+
setGitAdvancedOpen: (x) => void;
10+
};
11+
12+
const GitOptions: React.FC<React.PropsWithChildren<GitOptionProps>> = ({
13+
isGitAdvancedOpen,
14+
setGitAdvancedOpen,
15+
}) => {
716
return (
817
<ExpandableSection
918
toggleTextExpanded="Hide advanced Git options"
1019
toggleTextCollapsed="Show advanced Git options"
20+
data-test="advanced-git-options"
21+
isExpanded={isGitAdvancedOpen}
22+
onToggle={() => setGitAdvancedOpen((x) => !x)}
1123
>
1224
<PageSection>
1325
<FormSection>
@@ -27,6 +39,12 @@ const GitOptions: React.FC<React.PropsWithChildren<unknown>> = () => {
2739
<HelpPopover bodyContent="Make sure this path is correct. You might get an error if your build context folder is your root directory but your Dockerfile is in a subdirectory of that folder." />
2840
}
2941
/>
42+
<GitProviderDropdown name="gitProviderAnnotation" />
43+
<InputField
44+
name="gitURLAnnotation"
45+
label="Git url annotation"
46+
data-test="url-annotation"
47+
/>
3048
</FormSection>
3149
</PageSection>
3250
</ExpandableSection>
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import React from 'react';
2+
import { useField } from 'formik';
3+
import DropdownField from '../../../shared/components/formik-fields/DropdownField';
4+
import { GIT_PROVIDER_ANNOTATION_VALUE } from '../../../utils/component-utils';
5+
6+
type GitProviderDropdownProps = Omit<
7+
React.ComponentProps<typeof DropdownField>,
8+
'items' | 'label' | 'placeholder'
9+
>;
10+
11+
export const GitProviderDropdown: React.FC<React.PropsWithChildren<GitProviderDropdownProps>> = (
12+
props,
13+
) => {
14+
const [{ value }, , { setValue }] = useField<string>(props.name);
15+
16+
const dropdownItems = [
17+
{ key: GIT_PROVIDER_ANNOTATION_VALUE.GITHUB, value: GIT_PROVIDER_ANNOTATION_VALUE.GITHUB },
18+
{ key: GIT_PROVIDER_ANNOTATION_VALUE.GITLAB, value: GIT_PROVIDER_ANNOTATION_VALUE.GITLAB },
19+
{ key: GIT_PROVIDER_ANNOTATION_VALUE.OTHERS, value: GIT_PROVIDER_ANNOTATION_VALUE.OTHERS },
20+
];
21+
22+
return (
23+
<div className="pf-v5-u-mb-md">
24+
<DropdownField
25+
{...props}
26+
label="Git provider annotation"
27+
placeholder={'Select git provider'}
28+
value={value}
29+
items={dropdownItems}
30+
onChange={(provider: string) => setValue(provider)}
31+
/>
32+
</div>
33+
);
34+
};

src/components/ImportForm/ComponentSection/SourceSection.tsx

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@ import { ValidatedOptions } from '@patternfly/react-core';
33
import { useField, useFormikContext } from 'formik';
44
import { InputField, SwitchField } from 'formik-pf';
55
import GitUrlParse from 'git-url-parse';
6+
import { detectGitType, GitProvider } from '../../../shared/utils/git-utils';
7+
import { GIT_PROVIDER_ANNOTATION_VALUE } from '../../../utils/component-utils';
68
import { ImportFormValues } from '../type';
79
import GitOptions from './GitOptions';
810

911
export const SourceSection = () => {
1012
const [, { touched, error }] = useField('source.git.url');
13+
const [isGitAdvancedOpen, setGitAdvancedOpen] = React.useState<boolean>(false);
1114
const { touched: touchedValues, setFieldValue } = useFormikContext<ImportFormValues>();
1215
const validated = touched
1316
? touched && !error
@@ -16,19 +19,40 @@ export const SourceSection = () => {
1619
: ValidatedOptions.default;
1720

1821
const handleChange = React.useCallback(
19-
(event) => {
20-
if (validated && !touchedValues.componentName) {
22+
async (event) => {
23+
if (validated) {
24+
const gitType = detectGitType(event.target?.value as string);
25+
if (gitType !== GitProvider.GITHUB && gitType !== GitProvider.GITLAB) {
26+
await setFieldValue('gitProviderAnnotation', '');
27+
setGitAdvancedOpen(true);
28+
}
29+
if (gitType === GitProvider.GITHUB) {
30+
await setFieldValue('gitProviderAnnotation', GIT_PROVIDER_ANNOTATION_VALUE.GITHUB);
31+
setGitAdvancedOpen(false);
32+
}
33+
if (gitType === GitProvider.GITLAB) {
34+
await setFieldValue('gitProviderAnnotation', GIT_PROVIDER_ANNOTATION_VALUE.GITLAB);
35+
setGitAdvancedOpen(false);
36+
}
37+
38+
let parsed: GitUrlParse.GitUrl;
2139
let name: string;
2240
try {
23-
name = GitUrlParse(event.target?.value ?? '').name;
41+
parsed = GitUrlParse(event.target?.value ?? '');
42+
await setFieldValue('gitURLAnnotation', parsed?.resource);
43+
name = parsed.name;
2444
} catch {
2545
name = '';
46+
await setFieldValue('gitURLAnnotation', '');
47+
}
48+
if (!touchedValues.componentName) {
49+
await setFieldValue('componentName', name);
2650
}
27-
void setFieldValue('componentName', name);
2851
}
2952
},
3053
[setFieldValue, touchedValues.componentName, validated],
3154
);
55+
3256
return (
3357
<>
3458
<InputField
@@ -37,13 +61,15 @@ export const SourceSection = () => {
3761
placeholder="Enter your source"
3862
validated={validated}
3963
isRequired
40-
data-test="enter-source"
64+
data-testid="enter-source"
4165
onChange={handleChange}
4266
/>
4367
{validated === ValidatedOptions.success ? (
4468
<SwitchField name="isPrivateRepo" label="Should the image produced be private?" />
4569
) : null}
46-
{validated === ValidatedOptions.success ? <GitOptions /> : null}
70+
{validated === ValidatedOptions.success ? (
71+
<GitOptions isGitAdvancedOpen={isGitAdvancedOpen} setGitAdvancedOpen={setGitAdvancedOpen} />
72+
) : null}
4773
</>
4874
);
4975
};

src/components/ImportForm/ComponentSection/__tests__/ComponentSection.spec.tsx

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
import { screen, waitFor } from '@testing-library/react';
1+
import { screen, waitFor, configure } from '@testing-library/react';
22
import { userEvent } from '@testing-library/user-event';
33
import { formikRenderer } from '../../../../utils/test-utils';
44
import { ComponentSection } from '../ComponentSection';
55
import '@testing-library/jest-dom';
66

7+
configure({ testIdAttribute: 'data-test' });
8+
79
describe('ComponentSection', () => {
810
it('should render component section', () => {
911
formikRenderer(<ComponentSection />, { source: { git: { url: '' } } });
@@ -22,19 +24,43 @@ describe('ComponentSection', () => {
2224
await user.tab();
2325
await waitFor(() => screen.getByText('Show advanced Git options'));
2426
});
25-
it('should get private image repo switch when git src is ready', async () => {
27+
28+
it('should expand git options if source url is others', async () => {
2629
formikRenderer(<ComponentSection />, {
2730
source: { git: { url: '' } },
2831
});
2932
const user = userEvent.setup();
3033
const source = screen.getByPlaceholderText('Enter your source');
3134

32-
await user.type(source, 'https://github.com/abcd/repo.git');
35+
await user.type(source, 'https://bitbucket.com/abcd/repo.git');
36+
await user.tab();
37+
await waitFor(() => screen.getByText('Hide advanced Git options'));
38+
});
39+
40+
it('should show advanced Annotation section', async () => {
41+
formikRenderer(<ComponentSection />, {
42+
source: { git: { url: '' } },
43+
});
44+
const user = userEvent.setup();
45+
const source = screen.getByPlaceholderText('Enter your source');
46+
47+
await user.type(source, 'https://bitbucket.com/abcd/repo.git');
3348
await user.tab();
49+
await waitFor(() => screen.getByTestId('url-annotation'));
50+
});
51+
52+
it('should populate annotation fields', async () => {
53+
formikRenderer(<ComponentSection />, {
54+
source: { git: { url: '' } },
55+
});
56+
const user = userEvent.setup();
57+
const source = screen.getByPlaceholderText('Enter your source');
3458

35-
const switchCheckbox = screen.getByLabelText('Should the image produced be private?');
36-
expect(switchCheckbox).not.toBeChecked();
37-
await user.click(switchCheckbox);
38-
expect(switchCheckbox).toBeChecked();
59+
await user.type(source, 'https://gitlab.com/abcd/repo.git');
60+
await user.tab();
61+
await waitFor(() =>
62+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
63+
expect((screen.getByTestId('url-annotation') as HTMLInputElement).value).toBe('gitlab.com'),
64+
);
3965
});
4066
});

src/components/ImportForm/GitImportForm.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ export const GitImportForm: React.FC<{ applicationName: string }> = ({ applicati
2626
inAppContext: !!applicationName,
2727
showComponent: !!applicationName,
2828
componentName: '',
29+
gitProviderAnnotation: '',
30+
gitURLAnnotation: '',
2931
isPrivateRepo: false,
3032
source: {
3133
git: {

src/components/ImportForm/submit-utils.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ export const createResources = async (
4040
source,
4141
application,
4242
componentName,
43+
gitProviderAnnotation,
44+
gitURLAnnotation,
4345
inAppContext,
4446
importSecrets = [],
4547
pipeline,
@@ -66,7 +68,7 @@ export const createResources = async (
6668
}
6769
if (showComponent) {
6870
await createComponent(
69-
{ componentName, application, source },
71+
{ componentName, application, source, gitProviderAnnotation, gitURLAnnotation },
7072
applicationName,
7173
namespace,
7274
workspace,
@@ -102,7 +104,7 @@ export const createResources = async (
102104
await createSecrets(importSecrets, workspace, namespace, true);
103105

104106
createdComponent = await createComponent(
105-
{ componentName, application, source },
107+
{ componentName, application, gitProviderAnnotation, source, gitURLAnnotation },
106108
applicationName,
107109
namespace,
108110
workspace,

src/components/ImportForm/type.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ export type ImportFormValues = {
55
inAppContext: boolean;
66
showComponent: boolean;
77
componentName: string;
8+
gitProviderAnnotation?: string;
9+
gitURLAnnotation?: string;
810
isPrivateRepo: boolean;
911
source: {
1012
git: {

src/types/component.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ export enum NudgeStats {
2929

3030
export type ComponentSpecs = {
3131
componentName: string;
32+
gitProviderAnnotation?: string;
33+
gitURLAnnotation?: string;
3234
application: string;
3335
secret?: string;
3436
source?: ComponentSource;

src/utils/component-utils.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@ export const BUILD_REQUEST_ANNOTATION = 'build.appstudio.openshift.io/request';
1414

1515
export const BUILD_STATUS_ANNOTATION = 'build.appstudio.openshift.io/status';
1616

17+
export const GIT_PROVIDER_ANNOTATION = 'git-provider';
18+
export const GIT_PROVIDER_ANNOTATION_VALUE = {
19+
GITHUB: 'github',
20+
GITLAB: 'gitlab',
21+
OTHERS: 'others',
22+
};
23+
export const GITLAB_PROVIDER_URL_ANNOTATION = 'git-provider-url';
24+
1725
export enum ComponentBuildState {
1826
enabled = 'enabled',
1927
disabled = 'disabled',

src/utils/create-utils.ts

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,12 @@ import {
3333
ImageRepositoryVisibility,
3434
} from '../types';
3535
import { ComponentSpecs } from './../types/component';
36-
import { BUILD_REQUEST_ANNOTATION, BuildRequest } from './component-utils';
36+
import {
37+
BuildRequest,
38+
BUILD_REQUEST_ANNOTATION,
39+
GIT_PROVIDER_ANNOTATION,
40+
GITLAB_PROVIDER_URL_ANNOTATION,
41+
} from './component-utils';
3742

3843
export const sanitizeName = (name: string) => name.split(/ |\./).join('-').toLowerCase();
3944

@@ -104,7 +109,17 @@ export const createComponent = (
104109
enablePac: boolean = true,
105110
annotations?: { [key: string]: string },
106111
) => {
107-
const { componentName, containerImage, source, replicas, resources, env, targetPort } = component;
112+
const {
113+
componentName,
114+
gitProviderAnnotation,
115+
gitURLAnnotation,
116+
containerImage,
117+
source,
118+
replicas,
119+
resources,
120+
env,
121+
targetPort,
122+
} = component;
108123

109124
const name = component.componentName.split(/ |\./).join('-').toLowerCase();
110125

@@ -140,8 +155,14 @@ export const createComponent = (
140155
verb === 'update' ? { ...originalComponent, spec: newComponent.spec } : newComponent;
141156

142157
// merge additional annotations
143-
if (annotations) {
144-
resource.metadata.annotations = { ...resource.metadata.annotations, ...annotations };
158+
if (annotations || gitProviderAnnotation || gitURLAnnotation) {
159+
// Add gitlab annotaions in case of gitlab repo
160+
const newAnnotations = annotations;
161+
if (gitProviderAnnotation || gitURLAnnotation) {
162+
newAnnotations[GIT_PROVIDER_ANNOTATION] = gitProviderAnnotation;
163+
newAnnotations[GITLAB_PROVIDER_URL_ANNOTATION] = gitURLAnnotation;
164+
}
165+
resource.metadata.annotations = { ...resource.metadata.annotations, ...newAnnotations };
145166
}
146167

147168
return verb === 'create'

0 commit comments

Comments
 (0)