feat: [AH-844]: Implement Maven Repository List, create, update, update, setupclient setup (#3294)

* feat: [AH-844]: correct spelling mistake
* feat: [AH-844]: fix PR comments
* feat: [AH-844]: add new mavenCentral source in upstream proxy
* feat: [AH-844]: Support Maven Central Source in Upstream registry flow
* feat: [AH-844]: Implement Maven Repository List, create, update, update, setupclient setup
This commit is contained in:
Shivanand Sonnad 2025-01-23 07:44:24 +00:00 committed by Harness
parent 8890cfb783
commit d27437dd2c
16 changed files with 228 additions and 41 deletions

View File

@ -51,7 +51,7 @@
"@codemirror/view": "^6.9.6", "@codemirror/view": "^6.9.6",
"@harnessio/design-system": "^2.1.1", "@harnessio/design-system": "^2.1.1",
"@harnessio/icons": "^2.1.9", "@harnessio/icons": "^2.1.9",
"@harnessio/react-har-service-client": "^0.6.0", "@harnessio/react-har-service-client": "^0.7.0",
"@harnessio/react-ssca-manager-client": "^0.65.0", "@harnessio/react-ssca-manager-client": "^0.65.0",
"@harnessio/uicore": "^4.1.2", "@harnessio/uicore": "^4.1.2",
"@tanstack/react-query": "4.20.4", "@tanstack/react-query": "4.20.4",

View File

@ -134,5 +134,6 @@ export interface MFEAppProps {
export enum FeatureFlags { export enum FeatureFlags {
HAR_GENERIC_ARTIFACT_ENABLED = 'HAR_GENERIC_ARTIFACT_ENABLED', HAR_GENERIC_ARTIFACT_ENABLED = 'HAR_GENERIC_ARTIFACT_ENABLED',
HAR_TRIGGERS = 'HAR_TRIGGERS' HAR_TRIGGERS = 'HAR_TRIGGERS',
HAR_MAVEN_ARTIFACT_ENABLED = 'HAR_MAVEN_ARTIFACT_ENABLED'
} }

View File

@ -25,3 +25,4 @@ export { useGetSpaceRef } from './useGetSpaceRef'
export { useParentContextObj } from './useParentContextObj' export { useParentContextObj } from './useParentContextObj'
export { useLicenseStore } from './useLicenseStore' export { useLicenseStore } from './useLicenseStore'
export { useFeatureFlags, useFeatureFlag } from './useFeatureFlag' export { useFeatureFlags, useFeatureFlag } from './useFeatureFlag'
export { useGetUpstreamRepositoryPackageTypes } from './useGetUpstreamRepositoryPackageTypes'

View File

@ -67,6 +67,7 @@ const RepositoryTypes: RepositoryTypeListItem[] = [
label: 'repositoryTypes.maven', label: 'repositoryTypes.maven',
value: RepositoryPackageType.MAVEN, value: RepositoryPackageType.MAVEN,
icon: 'maven-repository-type', icon: 'maven-repository-type',
featureFlag: FeatureFlags.HAR_MAVEN_ARTIFACT_ENABLED,
tooltip: 'Coming Soon!', tooltip: 'Coming Soon!',
disabled: true disabled: true
}, },

View File

@ -0,0 +1,68 @@
/*
* Copyright 2024 Harness, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import type { IconName } from '@harnessio/icons'
import { FeatureFlags } from '@ar/MFEAppTypes'
import type { StringsMap } from '@ar/frameworks/strings'
import { UpstreamProxyPackageType } from '@ar/pages/upstream-proxy-details/types'
import { useFeatureFlags } from './useFeatureFlag'
export interface UpstreamRepositoryPackageTypeListItem {
label: keyof StringsMap
value: UpstreamProxyPackageType
icon: IconName
disabled?: boolean
tooltip?: string
featureFlag?: FeatureFlags
}
export const useGetUpstreamRepositoryPackageTypes = (): UpstreamRepositoryPackageTypeListItem[] => {
const featureFlags = useFeatureFlags()
return UpstreamProxyPackageTypeList.map(repo => {
if (repo.disabled && repo.featureFlag && featureFlags[repo.featureFlag]) {
return {
...repo,
disabled: false,
tooltip: undefined
}
}
return repo
})
}
export const UpstreamProxyPackageTypeList: UpstreamRepositoryPackageTypeListItem[] = [
{
label: 'repositoryTypes.docker',
value: UpstreamProxyPackageType.DOCKER,
icon: 'docker-step'
},
{
label: 'repositoryTypes.helm',
value: UpstreamProxyPackageType.HELM,
icon: 'service-helm'
},
{
label: 'repositoryTypes.maven',
value: UpstreamProxyPackageType.MAVEN,
featureFlag: FeatureFlags.HAR_MAVEN_ARTIFACT_ENABLED,
icon: 'maven-repository-type',
tooltip: 'Coming Soon!',
disabled: true
}
]

View File

@ -0,0 +1,130 @@
/*
* Copyright 2024 Harness, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react'
import type { IconName } from '@harnessio/icons'
import { RepositoryConfigType, RepositoryPackageType } from '@ar/common/types'
import UpstreamProxyActions from '@ar/pages/upstream-proxy-details/components/UpstreamProxyActions/UpstreamProxyActions'
import UpstreamProxyConfigurationForm from '@ar/pages/upstream-proxy-details/components/Forms/UpstreamProxyConfigurationForm'
import UpstreamProxyCreateFormContent from '@ar/pages/upstream-proxy-details/components/FormContent/UpstreamProxyCreateFormContent'
import UpstreamProxyDetailsHeader from '@ar/pages/upstream-proxy-details/components/UpstreamProxyDetailsHeader/UpstreamProxyDetailsHeader'
import {
type CreateRepositoryFormProps,
type RepositoryActionsProps,
type RepositoryConfigurationFormProps,
type RepositoryDetailsHeaderProps,
RepositoryStep,
type RepositoySetupClientProps
} from '@ar/frameworks/RepositoryStep/Repository'
import {
UpstreamProxyAuthenticationMode,
type UpstreamRegistryRequest,
UpstreamRepositoryURLInputSource
} from '@ar/pages/upstream-proxy-details/types'
import type { Repository, VirtualRegistryRequest } from '../types'
import RepositoryActions from '../components/Actions/RepositoryActions'
import RedirectPageView from '../components/RedirectPageView/RedirectPageView'
import SetupClientContent from '../components/SetupClientContent/SetupClientContent'
import RepositoryConfigurationForm from '../components/Forms/RepositoryConfigurationForm'
import RepositoryCreateFormContent from '../components/FormContent/RepositoryCreateFormContent'
import RepositoryDetailsHeader from '../components/RepositoryDetailsHeader/RepositoryDetailsHeader'
export class MavenRepositoryType extends RepositoryStep<VirtualRegistryRequest> {
protected packageType = RepositoryPackageType.MAVEN
protected repositoryName = 'Maven Repository'
protected repositoryIcon: IconName = 'maven-repository-type'
protected supportedScanners = []
protected supportsUpstreamProxy = true
protected supportedUpstreamURLSources = [
UpstreamRepositoryURLInputSource.MavenCentral,
UpstreamRepositoryURLInputSource.Custom
]
protected defaultValues: VirtualRegistryRequest = {
packageType: RepositoryPackageType.MAVEN,
identifier: '',
config: {
type: RepositoryConfigType.VIRTUAL
},
scanners: []
}
protected defaultUpstreamProxyValues: UpstreamRegistryRequest = {
packageType: RepositoryPackageType.MAVEN,
identifier: '',
config: {
type: RepositoryConfigType.UPSTREAM,
authType: UpstreamProxyAuthenticationMode.ANONYMOUS,
source: UpstreamRepositoryURLInputSource.Custom,
url: ''
},
cleanupPolicy: [],
scanners: []
}
renderCreateForm(props: CreateRepositoryFormProps): JSX.Element {
const { type } = props
if (type === RepositoryConfigType.VIRTUAL) {
return <RepositoryCreateFormContent isEdit={false} />
} else {
return <UpstreamProxyCreateFormContent isEdit={false} readonly={false} />
}
}
renderCofigurationForm(props: RepositoryConfigurationFormProps<Repository>): JSX.Element {
const { type } = props
if (type === RepositoryConfigType.VIRTUAL) {
return <RepositoryConfigurationForm ref={props.formikRef} readonly={props.readonly} />
} else {
return <UpstreamProxyConfigurationForm ref={props.formikRef} readonly={props.readonly} />
}
}
renderActions(props: RepositoryActionsProps<Repository>): JSX.Element {
if (props.type === RepositoryConfigType.VIRTUAL) {
return <RepositoryActions data={props.data} readonly={props.readonly} pageType={props.pageType} />
}
return <UpstreamProxyActions data={props.data} readonly={props.readonly} pageType={props.pageType} />
}
renderSetupClient(props: RepositoySetupClientProps): JSX.Element {
const { repoKey, onClose, artifactKey, versionKey } = props
return (
<SetupClientContent
repoKey={repoKey}
artifactKey={artifactKey}
versionKey={versionKey}
onClose={onClose}
packageType={RepositoryPackageType.GENERIC}
/>
)
}
renderRepositoryDetailsHeader(props: RepositoryDetailsHeaderProps<Repository>): JSX.Element {
const { type } = props
if (type === RepositoryConfigType.VIRTUAL) {
return <RepositoryDetailsHeader data={props.data} />
} else {
return <UpstreamProxyDetailsHeader data={props.data} />
}
}
renderRedirectPage(): JSX.Element {
return <RedirectPageView />
}
}

View File

@ -16,9 +16,11 @@
import repositoryFactory from '@ar/frameworks/RepositoryStep/RepositoryFactory' import repositoryFactory from '@ar/frameworks/RepositoryStep/RepositoryFactory'
import { DockerRepositoryType } from './DockerRepository/DockerRepositoryType' import { DockerRepositoryType } from './DockerRepository/DockerRepositoryType'
import { MavenRepositoryType } from './MavenRepository/MavenRepository'
import { HelmRepositoryType } from './HelmRepository/HelmRepositoryType' import { HelmRepositoryType } from './HelmRepository/HelmRepositoryType'
import { GenericRepositoryType } from './GenericRepository/GenericRepositoryType' import { GenericRepositoryType } from './GenericRepository/GenericRepositoryType'
repositoryFactory.registerStep(new DockerRepositoryType()) repositoryFactory.registerStep(new DockerRepositoryType())
repositoryFactory.registerStep(new HelmRepositoryType()) repositoryFactory.registerStep(new HelmRepositoryType())
repositoryFactory.registerStep(new GenericRepositoryType()) repositoryFactory.registerStep(new GenericRepositoryType())
repositoryFactory.registerStep(new MavenRepositoryType())

View File

@ -54,5 +54,9 @@ export const URLSourceToSupportedAuthTypesMapping: Record<
[UpstreamRepositoryURLInputSource.Custom]: [ [UpstreamRepositoryURLInputSource.Custom]: [
UpstreamProxyAuthenticationMode.USER_NAME_AND_PASSWORD, UpstreamProxyAuthenticationMode.USER_NAME_AND_PASSWORD,
UpstreamProxyAuthenticationMode.ANONYMOUS UpstreamProxyAuthenticationMode.ANONYMOUS
],
[UpstreamRepositoryURLInputSource.MavenCentral]: [
UpstreamProxyAuthenticationMode.USER_NAME_AND_PASSWORD,
UpstreamProxyAuthenticationMode.ANONYMOUS
] ]
} }

View File

@ -29,7 +29,7 @@ import {
} from '@harnessio/uicore' } from '@harnessio/uicore'
import { useCreateRegistryMutation } from '@harnessio/react-har-service-client' import { useCreateRegistryMutation } from '@harnessio/react-har-service-client'
import { useAppStore, useGetSpaceRef } from '@ar/hooks' import { useAppStore, useGetSpaceRef, useGetUpstreamRepositoryPackageTypes } from '@ar/hooks'
import { useStrings } from '@ar/frameworks/strings' import { useStrings } from '@ar/frameworks/strings'
import { decodeRef } from '@ar/hooks/useGetSpaceRef' import { decodeRef } from '@ar/hooks/useGetSpaceRef'
import { setFormikRef } from '@ar/common/utils' import { setFormikRef } from '@ar/common/utils'
@ -41,7 +41,6 @@ import {
UpstreamRegistry, UpstreamRegistry,
UpstreamRegistryRequest UpstreamRegistryRequest
} from '@ar/pages/upstream-proxy-details/types' } from '@ar/pages/upstream-proxy-details/types'
import { UpstreamProxyPackageTypeList } from '@ar/pages/upstream-proxy-details/constants'
import CreateRepositoryWidget from '@ar/frameworks/RepositoryStep/CreateRepositoryWidget' import CreateRepositoryWidget from '@ar/frameworks/RepositoryStep/CreateRepositoryWidget'
import repositoryFactory from '@ar/frameworks/RepositoryStep/RepositoryFactory' import repositoryFactory from '@ar/frameworks/RepositoryStep/RepositoryFactory'
@ -67,6 +66,7 @@ function FormContent(props: FormContentProps): JSX.Element {
const { getString } = useStrings() const { getString } = useStrings()
const { values } = formikProps const { values } = formikProps
const { packageType } = values const { packageType } = values
const packageTypeList = useGetUpstreamRepositoryPackageTypes()
return ( return (
<Container> <Container>
@ -77,7 +77,7 @@ function FormContent(props: FormContentProps): JSX.Element {
<Container> <Container>
<ThumbnailSelect <ThumbnailSelect
name="packageType" name="packageType"
items={UpstreamProxyPackageTypeList.map(each => ({ items={packageTypeList.map(each => ({
...each, ...each,
label: getString(each.label) label: getString(each.label)
}))} }))}

View File

@ -117,7 +117,11 @@ export function getFormattedFormDataForAuthType(
} else if (draft.config.authType === UpstreamProxyAuthenticationMode.ANONYMOUS) { } else if (draft.config.authType === UpstreamProxyAuthenticationMode.ANONYMOUS) {
set(draft, 'config.auth', null) set(draft, 'config.auth', null)
} }
if (draft.config.source === UpstreamRepositoryURLInputSource.Dockerhub) { if (
[UpstreamRepositoryURLInputSource.Dockerhub, UpstreamRepositoryURLInputSource.MavenCentral].includes(
draft.config.source as UpstreamRepositoryURLInputSource
)
) {
set(draft, 'config.url', '') set(draft, 'config.url', '')
} }
}) })

View File

@ -33,5 +33,9 @@ export const UpstreamURLSourceConfig: Record<UpstreamRepositoryURLInputSource, R
[UpstreamRepositoryURLInputSource.Custom]: { [UpstreamRepositoryURLInputSource.Custom]: {
label: 'upstreamProxyDetails.createForm.source.custom', label: 'upstreamProxyDetails.createForm.source.custom',
value: UpstreamRepositoryURLInputSource.Custom value: UpstreamRepositoryURLInputSource.Custom
},
[UpstreamRepositoryURLInputSource.MavenCentral]: {
label: 'upstreamProxyDetails.createForm.source.mavenCentral',
value: UpstreamRepositoryURLInputSource.MavenCentral
} }
} }

View File

@ -14,37 +14,6 @@
* limitations under the License. * limitations under the License.
*/ */
import type { IconName } from '@harnessio/icons'
import type { StringsMap } from '@ar/strings/types'
import { UpstreamProxyPackageType } from './types'
interface UpstreamProxyPackageTypeListType {
label: keyof StringsMap
value: UpstreamProxyPackageType
icon: IconName
disabled?: boolean
tooltip?: string
}
export const UpstreamProxyPackageTypeList: UpstreamProxyPackageTypeListType[] = [
{
label: 'repositoryTypes.docker',
value: UpstreamProxyPackageType.DOCKER,
icon: 'docker-step'
},
{
label: 'repositoryTypes.helm',
value: UpstreamProxyPackageType.HELM,
icon: 'service-helm'
},
{
label: 'repositoryTypes.maven',
value: UpstreamProxyPackageType.MAVEN,
icon: 'maven-repository-type',
tooltip: 'Comming Soon!',
disabled: true
}
]
export enum UpstreamProxyDetailsTab { export enum UpstreamProxyDetailsTab {
PACKAGES = 'packages', PACKAGES = 'packages',
CONFIGURATION = 'configuration' CONFIGURATION = 'configuration'

View File

@ -12,6 +12,7 @@ createForm:
dockerHub: Docker Hub dockerHub: Docker Hub
ecr: AWS ECR ecr: AWS ECR
custom: Custom custom: Custom
mavenCentral: Maven Central
authentication: authentication:
title: Authentication title: Authentication
userNameAndPassword: Username and Password userNameAndPassword: Username and Password

View File

@ -26,6 +26,7 @@ export enum UpstreamProxyPackageType {
export enum UpstreamRepositoryURLInputSource { export enum UpstreamRepositoryURLInputSource {
Dockerhub = 'Dockerhub', Dockerhub = 'Dockerhub',
MavenCentral = 'MavenCentral',
AwsEcr = 'AwsEcr', AwsEcr = 'AwsEcr',
Custom = 'Custom' Custom = 'Custom'
} }

View File

@ -141,6 +141,7 @@ export interface StringsMap {
'upstreamProxyDetails.createForm.source.custom': string 'upstreamProxyDetails.createForm.source.custom': string
'upstreamProxyDetails.createForm.source.dockerHub': string 'upstreamProxyDetails.createForm.source.dockerHub': string
'upstreamProxyDetails.createForm.source.ecr': string 'upstreamProxyDetails.createForm.source.ecr': string
'upstreamProxyDetails.createForm.source.mavenCentral': string
'upstreamProxyDetails.createForm.source.title': string 'upstreamProxyDetails.createForm.source.title': string
'upstreamProxyDetails.createForm.title': string 'upstreamProxyDetails.createForm.title': string
'upstreamProxyDetails.createForm.url': string 'upstreamProxyDetails.createForm.url': string

View File

@ -1945,10 +1945,10 @@
yargs "^17.6.2" yargs "^17.6.2"
zod "^3.19.1" zod "^3.19.1"
"@harnessio/react-har-service-client@^0.6.0": "@harnessio/react-har-service-client@^0.7.0":
version "0.6.0" version "0.7.0"
resolved "https://registry.yarnpkg.com/@harnessio/react-har-service-client/-/react-har-service-client-0.6.0.tgz#25253fd935fe6a28a5d26d98148ba0ba51d545ef" resolved "https://registry.yarnpkg.com/@harnessio/react-har-service-client/-/react-har-service-client-0.7.0.tgz#e78e1b1e770586ed3f5215b0bc7277b8b12dcd8f"
integrity sha512-jCCCInwmVoCWrambIop6dK8SvJXHpsq+8MdZNPbguMPjJgqR0d6i6Ms+4lpfBswJ/5TVVEvo/uFJhlAUVtf2fQ== integrity sha512-810Z3OLEcPxul/PQdb92S8/DKG8tA83hbMgGdA0v+7+e4cCnIigSYP9lvUa2i7I8Bm8LtP4kiipg8aky90m70w==
dependencies: dependencies:
"@harnessio/oats-cli" "^3.0.0" "@harnessio/oats-cli" "^3.0.0"