Skip to content

Commit

Permalink
feat(import): backport-add-gitlab-annotations
Browse files Browse the repository at this point in the history
  • Loading branch information
abhinandan13jan committed Dec 5, 2024
1 parent 04ab3eb commit 8a3a0d1
Show file tree
Hide file tree
Showing 10 changed files with 161 additions and 20 deletions.
20 changes: 19 additions & 1 deletion src/components/ImportForm/ComponentSection/GitOptions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,24 @@ import * as React from 'react';
import { ExpandableSection, FormSection, PageSection } from '@patternfly/react-core';
import { InputField } from 'formik-pf';
import HelpPopover from '../../HelpPopover';
import { GitProviderDropdown } from './GitProviderDropdown';

const GitOptions: React.FC<React.PropsWithChildren<unknown>> = () => {
type GitOptionProps = {
isGitAdvancedOpen: boolean;
setGitAdvancedOpen: (x) => void;
};

const GitOptions: React.FC<React.PropsWithChildren<GitOptionProps>> = ({
isGitAdvancedOpen,
setGitAdvancedOpen,
}) => {
return (
<ExpandableSection
toggleTextExpanded="Hide advanced Git options"
toggleTextCollapsed="Show advanced Git options"
data-test="advanced-git-options"
isExpanded={isGitAdvancedOpen}
onToggle={() => setGitAdvancedOpen((x) => !x)}
>
<PageSection>
<FormSection>
Expand All @@ -27,6 +39,12 @@ const GitOptions: React.FC<React.PropsWithChildren<unknown>> = () => {
<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." />
}
/>
<GitProviderDropdown name="gitProviderAnnotation" />
<InputField
name="gitURLAnnotation"
label="Git url annotation"
data-test="url-annotation"
/>
</FormSection>
</PageSection>
</ExpandableSection>
Expand Down
34 changes: 34 additions & 0 deletions src/components/ImportForm/ComponentSection/GitProviderDropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React from 'react';
import { useField } from 'formik';
import DropdownField from '../../../shared/components/formik-fields/DropdownField';
import { GIT_PROVIDER_ANNOTATION_VALUE } from '../../../utils/component-utils';

type GitProviderDropdownProps = Omit<
React.ComponentProps<typeof DropdownField>,
'items' | 'label' | 'placeholder'
>;

export const GitProviderDropdown: React.FC<React.PropsWithChildren<GitProviderDropdownProps>> = (
props,
) => {
const [{ value }, , { setValue }] = useField<string>(props.name);

const dropdownItems = [
{ key: GIT_PROVIDER_ANNOTATION_VALUE.GITHUB, value: GIT_PROVIDER_ANNOTATION_VALUE.GITHUB },
{ key: GIT_PROVIDER_ANNOTATION_VALUE.GITLAB, value: GIT_PROVIDER_ANNOTATION_VALUE.GITLAB },
{ key: GIT_PROVIDER_ANNOTATION_VALUE.OTHERS, value: GIT_PROVIDER_ANNOTATION_VALUE.OTHERS },
];

return (
<div className="pf-v5-u-mb-md">
<DropdownField
{...props}
label="Git provider annotation"
placeholder={'Select git provider'}
value={value}
items={dropdownItems}
onChange={(provider: string) => setValue(provider)}
/>
</div>
);
};
38 changes: 32 additions & 6 deletions src/components/ImportForm/ComponentSection/SourceSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@ import { ValidatedOptions } from '@patternfly/react-core';
import { useField, useFormikContext } from 'formik';
import { InputField, SwitchField } from 'formik-pf';
import GitUrlParse from 'git-url-parse';
import { detectGitType, GitProvider } from '../../../shared/utils/git-utils';
import { GIT_PROVIDER_ANNOTATION_VALUE } from '../../../utils/component-utils';
import { ImportFormValues } from '../type';
import GitOptions from './GitOptions';

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

const handleChange = React.useCallback(
(event) => {
if (validated && !touchedValues.componentName) {
async (event) => {
if (validated) {
const gitType = detectGitType(event.target?.value as string);
if (gitType !== GitProvider.GITHUB && gitType !== GitProvider.GITLAB) {
await setFieldValue('gitProviderAnnotation', '');
setGitAdvancedOpen(true);
}
if (gitType === GitProvider.GITHUB) {
await setFieldValue('gitProviderAnnotation', GIT_PROVIDER_ANNOTATION_VALUE.GITHUB);
setGitAdvancedOpen(false);
}
if (gitType === GitProvider.GITLAB) {
await setFieldValue('gitProviderAnnotation', GIT_PROVIDER_ANNOTATION_VALUE.GITLAB);
setGitAdvancedOpen(false);

Check warning on line 35 in src/components/ImportForm/ComponentSection/SourceSection.tsx

View check run for this annotation

Codecov / codecov/patch

src/components/ImportForm/ComponentSection/SourceSection.tsx#L35

Added line #L35 was not covered by tests
}

let parsed: GitUrlParse.GitUrl;

Check warning on line 38 in src/components/ImportForm/ComponentSection/SourceSection.tsx

View check run for this annotation

Codecov / codecov/patch

src/components/ImportForm/ComponentSection/SourceSection.tsx#L38

Added line #L38 was not covered by tests
let name: string;
try {
name = GitUrlParse(event.target?.value ?? '').name;
parsed = GitUrlParse(event.target?.value ?? '');
await setFieldValue('gitURLAnnotation', parsed?.resource);
name = parsed.name;
} catch {
name = '';
await setFieldValue('gitURLAnnotation', '');
}
if (!touchedValues.componentName) {
await setFieldValue('componentName', name);
}
void setFieldValue('componentName', name);
}
},
[setFieldValue, touchedValues.componentName, validated],
);

return (
<>
<InputField
Expand All @@ -37,13 +61,15 @@ export const SourceSection = () => {
placeholder="Enter your source"
validated={validated}
isRequired
data-test="enter-source"
data-testid="enter-source"
onChange={handleChange}
/>
{validated === ValidatedOptions.success ? (
<SwitchField name="isPrivateRepo" label="Should the image produced be private?" />
) : null}
{validated === ValidatedOptions.success ? <GitOptions /> : null}
{validated === ValidatedOptions.success ? (
<GitOptions isGitAdvancedOpen={isGitAdvancedOpen} setGitAdvancedOpen={setGitAdvancedOpen} />
) : null}
</>
);
};
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { screen, waitFor } from '@testing-library/react';
import { screen, waitFor, configure } from '@testing-library/react';
import { userEvent } from '@testing-library/user-event';
import { formikRenderer } from '../../../../utils/test-utils';
import { ComponentSection } from '../ComponentSection';
import '@testing-library/jest-dom';

configure({ testIdAttribute: 'data-test' });

describe('ComponentSection', () => {
it('should render component section', () => {
formikRenderer(<ComponentSection />, { source: { git: { url: '' } } });
Expand All @@ -22,19 +24,43 @@ describe('ComponentSection', () => {
await user.tab();
await waitFor(() => screen.getByText('Show advanced Git options'));
});
it('should get private image repo switch when git src is ready', async () => {

it('should expand git options if source url is others', async () => {
formikRenderer(<ComponentSection />, {
source: { git: { url: '' } },
});
const user = userEvent.setup();
const source = screen.getByPlaceholderText('Enter your source');

await user.type(source, 'https://github.com/abcd/repo.git');
await user.type(source, 'https://bitbucket.com/abcd/repo.git');
await user.tab();
await waitFor(() => screen.getByText('Hide advanced Git options'));
});

it('should show advanced Annotation section', async () => {
formikRenderer(<ComponentSection />, {
source: { git: { url: '' } },
});
const user = userEvent.setup();
const source = screen.getByPlaceholderText('Enter your source');

await user.type(source, 'https://bitbucket.com/abcd/repo.git');
await user.tab();
await waitFor(() => screen.getByTestId('url-annotation'));
});

it('should populate annotation fields', async () => {
formikRenderer(<ComponentSection />, {
source: { git: { url: '' } },
});
const user = userEvent.setup();
const source = screen.getByPlaceholderText('Enter your source');

const switchCheckbox = screen.getByLabelText('Should the image produced be private?');
expect(switchCheckbox).not.toBeChecked();
await user.click(switchCheckbox);
expect(switchCheckbox).toBeChecked();
await user.type(source, 'https://gitlab.com/abcd/repo.git');
await user.tab();
await waitFor(() =>
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
expect((screen.getByTestId('url-annotation') as HTMLInputElement).value).toBe('gitlab.com'),
);
});
});
2 changes: 2 additions & 0 deletions src/components/ImportForm/GitImportForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ export const GitImportForm: React.FC<{ applicationName: string }> = ({ applicati
inAppContext: !!applicationName,
showComponent: !!applicationName,
componentName: '',
gitProviderAnnotation: '',
gitURLAnnotation: '',
isPrivateRepo: false,
source: {
git: {
Expand Down
6 changes: 4 additions & 2 deletions src/components/ImportForm/submit-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ export const createResources = async (
source,
application,
componentName,
gitProviderAnnotation,
gitURLAnnotation,
inAppContext,
importSecrets = [],
pipeline,
Expand All @@ -66,7 +68,7 @@ export const createResources = async (
}
if (showComponent) {
await createComponent(
{ componentName, application, source },
{ componentName, application, source, gitProviderAnnotation, gitURLAnnotation },
applicationName,
namespace,
workspace,
Expand Down Expand Up @@ -102,7 +104,7 @@ export const createResources = async (
await createSecrets(importSecrets, workspace, namespace, true);

createdComponent = await createComponent(
{ componentName, application, source },
{ componentName, application, gitProviderAnnotation, source, gitURLAnnotation },
applicationName,
namespace,
workspace,
Expand Down
2 changes: 2 additions & 0 deletions src/components/ImportForm/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ export type ImportFormValues = {
inAppContext: boolean;
showComponent: boolean;
componentName: string;
gitProviderAnnotation?: string;
gitURLAnnotation?: string;
isPrivateRepo: boolean;
source: {
git: {
Expand Down
2 changes: 2 additions & 0 deletions src/types/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ export enum NudgeStats {

export type ComponentSpecs = {
componentName: string;
gitProviderAnnotation?: string;
gitURLAnnotation?: string;
application: string;
secret?: string;
source?: ComponentSource;
Expand Down
8 changes: 8 additions & 0 deletions src/utils/component-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ export const BUILD_REQUEST_ANNOTATION = 'build.appstudio.openshift.io/request';

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

export const GIT_PROVIDER_ANNOTATION = 'git-provider';
export const GIT_PROVIDER_ANNOTATION_VALUE = {
GITHUB: 'github',
GITLAB: 'gitlab',
OTHERS: 'others',
};
export const GITLAB_PROVIDER_URL_ANNOTATION = 'git-provider-url';

export enum ComponentBuildState {
enabled = 'enabled',
disabled = 'disabled',
Expand Down
29 changes: 25 additions & 4 deletions src/utils/create-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,12 @@ import {
ImageRepositoryVisibility,
} from '../types';
import { ComponentSpecs } from './../types/component';
import { BUILD_REQUEST_ANNOTATION, BuildRequest } from './component-utils';
import {
BuildRequest,
BUILD_REQUEST_ANNOTATION,
GIT_PROVIDER_ANNOTATION,
GITLAB_PROVIDER_URL_ANNOTATION,
} from './component-utils';

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

Expand Down Expand Up @@ -104,7 +109,17 @@ export const createComponent = (
enablePac: boolean = true,
annotations?: { [key: string]: string },
) => {
const { componentName, containerImage, source, replicas, resources, env, targetPort } = component;
const {
componentName,
gitProviderAnnotation,
gitURLAnnotation,
containerImage,
source,
replicas,
resources,
env,
targetPort,
} = component;

Check warning on line 122 in src/utils/create-utils.ts

View check run for this annotation

Codecov / codecov/patch

src/utils/create-utils.ts#L122

Added line #L122 was not covered by tests

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

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

// merge additional annotations
if (annotations) {
resource.metadata.annotations = { ...resource.metadata.annotations, ...annotations };
if (annotations || gitProviderAnnotation || gitURLAnnotation) {
// Add gitlab annotaions in case of gitlab repo
const newAnnotations = annotations;
if (gitProviderAnnotation || gitURLAnnotation) {
newAnnotations[GIT_PROVIDER_ANNOTATION] = gitProviderAnnotation;
newAnnotations[GITLAB_PROVIDER_URL_ANNOTATION] = gitURLAnnotation;
}
resource.metadata.annotations = { ...resource.metadata.annotations, ...newAnnotations };
}

return verb === 'create'
Expand Down

0 comments on commit 8a3a0d1

Please sign in to comment.