From 06ff639dcb42926e367c66f7a9507edfb26f0bf0 Mon Sep 17 00:00:00 2001 From: dkarpele Date: Fri, 9 Oct 2026 18:56:43 +0200 Subject: [PATCH 1/2] feat: add OCI Generator for AppSet Signed-off-by: dkarpele Co-authored-by: Claude Signed-off-by: dkarpele --- docs/applicationsets.md | 2 +- src/gitops/components/appset/Generators.tsx | 3 + .../appset/generators/OCIGenerator.tsx | 56 +++++++++++++++++++ src/gitops/components/appset/index.ts | 1 + .../useShowOperandsInAllNamespaces.ts | 4 +- src/gitops/models/ApplicationSetModel.ts | 13 +++++ src/plugin/utils/useClusterVersion.tsx | 3 +- 7 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 src/gitops/components/appset/generators/OCIGenerator.tsx diff --git a/docs/applicationsets.md b/docs/applicationsets.md index c09a116f1..8def78d24 100644 --- a/docs/applicationsets.md +++ b/docs/applicationsets.md @@ -102,7 +102,7 @@ The editor includes a **Schema** side panel that describes ApplicationSet fields The **Generators** tab shows the ApplicationSet generator configuration in a structured view. -Supported generator presentations include **List**, **Cluster**, **git**, **Matrix**, **Merge**, and **Union**. Other generator types use a generic view that shows the configuration as JSON. +Supported generator presentations include **List**, **Cluster**, **git**, **OCI**, **Matrix**, **Merge**, and **Union**. Other generator types use a generic view that shows the configuration as JSON. If no generators are configured, the tab shows an empty state. diff --git a/src/gitops/components/appset/Generators.tsx b/src/gitops/components/appset/Generators.tsx index aaa154dfa..4cf70bea4 100644 --- a/src/gitops/components/appset/Generators.tsx +++ b/src/gitops/components/appset/Generators.tsx @@ -3,6 +3,7 @@ import * as React from 'react'; import ClusterGenerator from './generators/ClusterGenerator'; import GenericGenerator from './generators/GenericGenerator'; import GitGenerator from './generators/GitGenerator'; +import OCIGenerator from './generators/OCIGenerator'; import ListGenerator from './generators/ListGenerator'; import MatrixGenerator from './generators/MatrixGenerator'; import MergeGenerator from './generators/MergeGenerator'; @@ -22,6 +23,8 @@ const Generators: React.FC = ({ generators }) => { return ; case 'git': return ; + case 'oci': + return ; case 'list': return ; case 'merge': diff --git a/src/gitops/components/appset/generators/OCIGenerator.tsx b/src/gitops/components/appset/generators/OCIGenerator.tsx new file mode 100644 index 000000000..936adbb52 --- /dev/null +++ b/src/gitops/components/appset/generators/OCIGenerator.tsx @@ -0,0 +1,56 @@ +import * as React from 'react'; + +import { + DescriptionList, + DescriptionListDescription, + DescriptionListGroup, + DescriptionListTerm, +} from '@patternfly/react-core'; +import { ContainerNodeIcon } from '@patternfly/react-icons'; +import { OCIAppSetGenerator } from "@gitops/models/ApplicationSetModel"; +import GeneratorView from './GeneratorView'; + +interface OCIGeneratorProps { + generator: OCIAppSetGenerator; +} + +const OCIGenerator: React.FC = ({ generator }) => { + const generatorType = generator.files ? 'File' : 'Directory'; + + return ( + } title={`OCI (${generatorType})`}> + + {generator.repoURL && ( + + Repository + {generator.repoURL} + + )} + {generator.revision && ( + + Revision + {generator.revision} + + )} + {generator.directories && ( + + Directories + + {generator.directories.length} directory(ies) + + + )} + {generator.files && ( + + Files + + {generator.files.length} file(s) + + + )} + + + ); +}; + +export default OCIGenerator; diff --git a/src/gitops/components/appset/index.ts b/src/gitops/components/appset/index.ts index e035b6c0c..5685d3d56 100644 --- a/src/gitops/components/appset/index.ts +++ b/src/gitops/components/appset/index.ts @@ -8,6 +8,7 @@ export { default as GeneratorsTab } from './GeneratorsTab'; export { default as ClusterGenerator } from './generators/ClusterGenerator'; export { default as GenericGenerator } from './generators/GenericGenerator'; export { default as GitGenerator } from './generators/GitGenerator'; +export { default as OCIGenerator } from './generators/OCIGenerator'; export { default as ListGenerator } from './generators/ListGenerator'; export { default as MatrixGenerator } from './generators/MatrixGenerator'; export { default as MergeGenerator } from './generators/MergeGenerator'; diff --git a/src/gitops/components/shared/AllNamespaces/useShowOperandsInAllNamespaces.ts b/src/gitops/components/shared/AllNamespaces/useShowOperandsInAllNamespaces.ts index ff535b349..dc3776dae 100644 --- a/src/gitops/components/shared/AllNamespaces/useShowOperandsInAllNamespaces.ts +++ b/src/gitops/components/shared/AllNamespaces/useShowOperandsInAllNamespaces.ts @@ -7,7 +7,9 @@ type UseShowOperandsInAllNamespaces = () => [boolean, (value: boolean) => void]; export const useShowOperandsInAllNamespaces: UseShowOperandsInAllNamespaces = () => { const dispatch = useDispatch(); const showOperandsInAllNamespaces = useSelector((state: RootStateOrAny) => - state.UI.get('showOperandsInAllNamespaces'), + typeof state.UI?.get === 'function' + ? state.UI.get('showOperandsInAllNamespaces') + : state.UI?.showOperandsInAllNamespaces, ); const setShowOperandsInAllNamespaces = useCallback( (value: boolean) => dispatch(uiActionsSetShowOperandsInAllNamespaces(value)), diff --git a/src/gitops/models/ApplicationSetModel.ts b/src/gitops/models/ApplicationSetModel.ts index 88c2863d0..11ae6002a 100644 --- a/src/gitops/models/ApplicationSetModel.ts +++ b/src/gitops/models/ApplicationSetModel.ts @@ -53,6 +53,18 @@ export type GitAppSetGenerator = { }[]; }; +export type OCIAppSetGenerator = { + repoURL: string; + revision?: string; + files?: { + path: string; + }[]; + directories?: { + exclude: boolean; + path: string; + }[]; +}; + export type SCMProviderAppSetGenerator = { awsCodeCommit?: object; azureDevOps?: object; @@ -89,6 +101,7 @@ export type ClusterDecisionresource = { export type AppSetGenerator = { clusters?: ClusterAppSetGenerator; git?: GitAppSetGenerator; + oci?: OCIAppSetGenerator; list?: ListAppSetGenerator; matrix?: MatrixAppSetGenerator; merge?: MergeAppSetGenerator; diff --git a/src/plugin/utils/useClusterVersion.tsx b/src/plugin/utils/useClusterVersion.tsx index a5a95c68b..0770f4b0f 100644 --- a/src/plugin/utils/useClusterVersion.tsx +++ b/src/plugin/utils/useClusterVersion.tsx @@ -32,7 +32,8 @@ export type FlagsObject = { [key: string]: boolean }; export const getFlagsObject = ({ [featureReducerName]: featureState, -}: RootStateOrAny): FlagsObject => featureState.toObject(); +}: RootStateOrAny): FlagsObject => + typeof featureState?.toObject === 'function' ? featureState.toObject() : featureState; const getClusterVersionFlag = (state: RootStateOrAny) => getFlagsObject(state)?.['CLUSTER_VERSION']; From b7b2f3edb7576178831a44c5ba185e897aff0d6f Mon Sep 17 00:00:00 2001 From: dkarpele Date: Fri, 9 Oct 2026 20:23:52 +0200 Subject: [PATCH 2/2] Use the array length when selecting the OCI generator type. Signed-off-by: dkarpele --- src/gitops/components/appset/generators/GitGenerator.tsx | 2 +- src/gitops/components/appset/generators/OCIGenerator.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gitops/components/appset/generators/GitGenerator.tsx b/src/gitops/components/appset/generators/GitGenerator.tsx index 3aed2e33f..d8071f3e1 100644 --- a/src/gitops/components/appset/generators/GitGenerator.tsx +++ b/src/gitops/components/appset/generators/GitGenerator.tsx @@ -15,7 +15,7 @@ interface GitGeneratorProps { } const GitGenerator: React.FC = ({ generator }) => { - const generatorType = generator.files ? 'File' : 'Directory'; + const generatorType = generator.files?.length ? 'File' : 'Directory'; return ( } title={`git (${generatorType})`}> diff --git a/src/gitops/components/appset/generators/OCIGenerator.tsx b/src/gitops/components/appset/generators/OCIGenerator.tsx index 936adbb52..912e2185a 100644 --- a/src/gitops/components/appset/generators/OCIGenerator.tsx +++ b/src/gitops/components/appset/generators/OCIGenerator.tsx @@ -15,7 +15,7 @@ interface OCIGeneratorProps { } const OCIGenerator: React.FC = ({ generator }) => { - const generatorType = generator.files ? 'File' : 'Directory'; + const generatorType = generator.files?.length ? 'File' : 'Directory'; return ( } title={`OCI (${generatorType})`}>