Repository: kubesphere/ks-devops
Pull request #478 (2022-02-25 05:50:20)

Move CRD application into a new group gitops
<!-- Thanks for sending a pull request! Here are some tips for you:

1. If you want **faster** PR reviews, read how: https://github.com/kubesphere/community/blob/master/developer-guide/development/the-pr-author-guide-to-getting-through-code-review.md
2. In case you want to know how your PR got reviewed, read: https://github.com/kubesphere/community/blob/master/developer-guide/development/code-review-guide.md
3. Here are some coding conventions followed by the KubeSphere community: https://github.com/kubesphere/community/blob/master/developer-guide/development/coding-conventions.md
4. Additional open-source best practice: https://github.com/LinuxSuRen/open-source-best-practice
-->

### What type of PR is this?
<!-- 
Add one of the following kinds:
/kind bug
/kind cleanup
/kind documentation
/kind feature
/kind design
/kind chore

Optionally add one or more of the following kinds if applicable:
/kind api-change
/kind deprecation
/kind failing-test
/kind flake
/kind regression
-->

### What this PR does / why we need it:
/kind chore

Create a new CRD group `gitops` to store all things related to GitOps.

Why do I create a new CRD group? Because always putting new CRDs into the v1alpha1 might letting users or contributors feel confused. So, in the future. It is best to expand this project with a new group instead of putting it into the core part.

### Which issue(s) this PR fixes:
<!--
Usage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`.
_If PR is about `failing-tests or flakes`, please post the related issues/tests in a comment and do not use `Fixes`_*
Please leave it or change # to be None if there is no corresponding issue that exists
-->
Fixes #

### Special notes for reviewers:
<!--
You can use the following command to let the DevOps SIG members help you to review your PR.
/cc @kubesphere/sig-devops 
And please avoid cc any individual.
-->
Please check the following list before waiting reviewers:

- [ ] Already committed the CRD files to [the Helm Chart](https://github.com/kubesphere-sigs/ks-devops-helm-chart/) if you created some new CRDs
- [ ] Already [added the permission](https://github.com/kubesphere/ks-installer/blob/9e063b085a0e43fdb3d0d9e3e7f4149146f14b9c/roles/ks-core/prepare/files/ks-init/role-templates.yaml) for the new API
- [ ] Already added the RBAC markers for the new controllers

### Does this PR introduce a user-facing change??
<!--
If no, just write "None" in the release-note block below.
If yes, a release note is required:
Enter your extended-release note in the block below. If the PR requires additional action from users switching to the new release, include the string "action required".

Please keep the note be same as your PR title if you believe it should be in the release notes.
-->
```release-note
None
```


ks-ci-bot: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/kubesphere/ks-devops/pull/478#" title="Author self-approved">LinuxSuRen</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=kubesphere%2Fks-devops).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/kubesphere/ks-devops/blob/master/OWNERS)~~ [LinuxSuRen]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
codecov[bot]: # [Codecov](https://codecov.io/gh/kubesphere/ks-devops/pull/478?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubesphere) Report
> Merging [#478](https://codecov.io/gh/kubesphere/ks-devops/pull/478?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubesphere) (c9897e4) into [master](https://codecov.io/gh/kubesphere/ks-devops/commit/7090ba5f4af621bd33eff993017092d1e80b9bc6?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubesphere) (7090ba5) will **increase** coverage by `0.08%`.
> The diff coverage is `100.00%`.

> :exclamation: Current head c9897e4 differs from pull request most recent head 9d4a7d7. Consider uploading reports for the commit 9d4a7d7 to get more accurate results

[![Impacted file tree graph](https://codecov.io/gh/kubesphere/ks-devops/pull/478/graphs/tree.svg?width=650&height=150&src=pr&token=qSK4RBbyNg&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubesphere)](https://codecov.io/gh/kubesphere/ks-devops/pull/478?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubesphere)

```diff
@@            Coverage Diff             @@
##           master     #478      +/-   ##
==========================================
+ Coverage   76.94%   77.02%   +0.08%     
==========================================
  Files         132      134       +2     
  Lines       22676    22740      +64     
==========================================
+ Hits        17448    17516      +68     
+ Misses       5038     5030       -8     
- Partials      190      194       +4     
```

| Flag | Coverage Δ | |
|---|---|---|
| unittests | `77.02% <100.00%> (+0.08%)` | :arrow_up: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubesphere#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Impacted Files](https://codecov.io/gh/kubesphere/ks-devops/pull/478?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubesphere) | Coverage Δ | |
|---|---|---|
| [controllers/argocd/application\_controller.go](https://codecov.io/gh/kubesphere/ks-devops/pull/478/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubesphere#diff-Y29udHJvbGxlcnMvYXJnb2NkL2FwcGxpY2F0aW9uX2NvbnRyb2xsZXIuZ28=) | `62.26% <ø> (ø)` | |
| [pkg/api/devops/v1alpha1/clustertemplate\_types.go](https://codecov.io/gh/kubesphere/ks-devops/pull/478/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubesphere#diff-cGtnL2FwaS9kZXZvcHMvdjFhbHBoYTEvY2x1c3RlcnRlbXBsYXRlX3R5cGVzLmdv) | `50.00% <ø> (ø)` | |
| [pkg/api/gitops/v1alpha1/application.go](https://codecov.io/gh/kubesphere/ks-devops/pull/478/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubesphere#diff-cGtnL2FwaS9naXRvcHMvdjFhbHBoYTEvYXBwbGljYXRpb24uZ28=) | `100.00% <ø> (ø)` | |
| [pkg/kapis/devops/v1alpha1/register.go](https://codecov.io/gh/kubesphere/ks-devops/pull/478/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubesphere#diff-cGtnL2thcGlzL2Rldm9wcy92MWFscGhhMS9yZWdpc3Rlci5nbw==) | `100.00% <ø> (ø)` | |
| [pkg/kapis/devops/v1alpha1/template/handler.go](https://codecov.io/gh/kubesphere/ks-devops/pull/478/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubesphere#diff-cGtnL2thcGlzL2Rldm9wcy92MWFscGhhMS90ZW1wbGF0ZS9oYW5kbGVyLmdv) | `100.00% <ø> (ø)` | |
| [pkg/kapis/devops/v1alpha1/template/route.go](https://codecov.io/gh/kubesphere/ks-devops/pull/478/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubesphere#diff-cGtnL2thcGlzL2Rldm9wcy92MWFscGhhMS90ZW1wbGF0ZS9yb3V0ZS5nbw==) | `0.00% <ø> (ø)` | |
| [...kapis/devops/v1alpha1/template/template\_handler.go](https://codecov.io/gh/kubesphere/ks-devops/pull/478/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubesphere#diff-cGtnL2thcGlzL2Rldm9wcy92MWFscGhhMS90ZW1wbGF0ZS90ZW1wbGF0ZV9oYW5kbGVyLmdv) | `92.85% <ø> (ø)` | |
| [pkg/api/gitops/v1alpha1/groupversion\_info.go](https://codecov.io/gh/kubesphere/ks-devops/pull/478/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubesphere#diff-cGtnL2FwaS9naXRvcHMvdjFhbHBoYTEvZ3JvdXB2ZXJzaW9uX2luZm8uZ28=) | `100.00% <100.00%> (ø)` | |
| [pkg/kapis/gitops/v1alpha1/argocd/handler.go](https://codecov.io/gh/kubesphere/ks-devops/pull/478/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubesphere#diff-cGtnL2thcGlzL2dpdG9wcy92MWFscGhhMS9hcmdvY2QvaGFuZGxlci5nbw==) | `100.00% <100.00%> (ø)` | |
| [pkg/kapis/gitops/v1alpha1/argocd/route.go](https://codecov.io/gh/kubesphere/ks-devops/pull/478/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubesphere#diff-cGtnL2thcGlzL2dpdG9wcy92MWFscGhhMS9hcmdvY2Qvcm91dGUuZ28=) | `100.00% <100.00%> (ø)` | |
| ... and [7 more](https://codecov.io/gh/kubesphere/ks-devops/pull/478/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubesphere) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/kubesphere/ks-devops/pull/478?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubesphere).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubesphere)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/kubesphere/ks-devops/pull/478?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubesphere). Last update [7090ba5...9d4a7d7](https://codecov.io/gh/kubesphere/ks-devops/pull/478?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubesphere). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kubesphere).

ks-ci-bot: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/kubesphere/ks-devops/pull/478#pullrequestreview-893351689" title="LGTM">JohnNiang</a>*, *<a href="https://github.com/kubesphere/ks-devops/pull/478#" title="Author self-approved">LinuxSuRen</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=kubesphere%2Fks-devops).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/kubesphere/ks-devops/blob/master/OWNERS)~~ [LinuxSuRen]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->

Patch:
diff --git a/Makefile b/Makefile
index 4ba4a72..18d0652 100644
--- a/Makefile
+++ b/Makefile
@@ -9,7 +9,7 @@ TOOLS_IMG ?= ${DOCKER_REPO}/devops-tools:$(VERSION)-$(COMMIT)
 # Produce CRDs that work back to Kubernetes 1.11 (no version conversion)
 CRD_OPTIONS ?= "crd:trivialVersions=true"
 
-GV="devops.kubesphere.io:v1alpha1 devops.kubesphere.io:v1alpha3"
+GV="devops.kubesphere.io:v1alpha1 devops.kubesphere.io:v1alpha3 gitops.kubesphere.io:v1alpha1"
 
 # Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
 ifeq (,$(shell go env GOBIN))
diff --git a/PROJECT b/PROJECT
index be17c3b..78ebfad 100644
--- a/PROJECT
+++ b/PROJECT
@@ -13,4 +13,7 @@ resources:
 - group: devops
   kind: ClusterTemplate
   version: v1alpha1
+- group: gitops
+  kind: Application
+  version: v1alpha1
 version: "2"
diff --git a/config/crd/bases/devops.kubesphere.io_fakes.yaml b/config/crd/bases/devops.kubesphere.io_fakes.yaml
deleted file mode 100644
index 7691477..0000000
--- a/config/crd/bases/devops.kubesphere.io_fakes.yaml
+++ /dev/null
@@ -1,55 +0,0 @@
-
----
-apiVersion: apiextensions.k8s.io/v1
-kind: CustomResourceDefinition
-metadata:
-  annotations:
-    controller-gen.kubebuilder.io/version: v0.6.2
-  creationTimestamp: null
-  name: fakes.devops.kubesphere.io
-spec:
-  group: devops.kubesphere.io
-  names:
-    kind: Fake
-    listKind: FakeList
-    plural: fakes
-    singular: fake
-  scope: Namespaced
-  versions:
-  - name: v1alpha3
-    schema:
-      openAPIV3Schema:
-        description: Fake is the Schema for the fakes API
-        properties:
-          apiVersion:
-            description: 'APIVersion defines the versioned schema of this representation
-              of an object. Servers should convert recognized schemas to the latest
-              internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
-            type: string
-          kind:
-            description: 'Kind is a string value representing the REST resource this
-              object represents. Servers may infer this from the endpoint the client
-              submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
-            type: string
-          metadata:
-            type: object
-          spec:
-            description: FakeSpec defines the desired state of Fake
-            properties:
-              foo:
-                description: Foo is an example field of Fake. Edit Fake_types.go to
-                  remove/update
-                type: string
-            type: object
-          status:
-            description: FakeStatus defines the observed state of Fake
-            type: object
-        type: object
-    served: true
-    storage: true
-status:
-  acceptedNames:
-    kind: ""
-    plural: ""
-  conditions: []
-  storedVersions: []
diff --git a/config/crd/bases/devops.kubesphere.io_applications.yaml b/config/crd/bases/gitops.kubesphere.io_applications.yaml
similarity index 99%
rename from config/crd/bases/devops.kubesphere.io_applications.yaml
rename to config/crd/bases/gitops.kubesphere.io_applications.yaml
index 41d5513..a602c18 100644
--- a/config/crd/bases/devops.kubesphere.io_applications.yaml
+++ b/config/crd/bases/gitops.kubesphere.io_applications.yaml
@@ -6,9 +6,9 @@ metadata:
   annotations:
     controller-gen.kubebuilder.io/version: v0.6.2
   creationTimestamp: null
-  name: applications.devops.kubesphere.io
+  name: applications.gitops.kubesphere.io
 spec:
-  group: devops.kubesphere.io
+  group: gitops.kubesphere.io
   names:
     kind: Application
     listKind: ApplicationList
diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml
index ca40e9b..08a35ff 100644
--- a/config/rbac/role.yaml
+++ b/config/rbac/role.yaml
@@ -15,6 +15,15 @@ rules:
   - get
   - list
   - update
+- apiGroups:
+  - ""
+  resources:
+  - secrets
+  verbs:
+  - create
+  - get
+  - list
+  - update
 - apiGroups:
   - apiextensions.k8s.io
   resources:
@@ -51,21 +60,21 @@ rules:
   - get
   - update
 - apiGroups:
-  - devops.kubesphere.io
+  - cluster.kubesphere.io
   resources:
-  - addonStrategies
+  - clusters
   verbs:
-  - create
-  - delete
   - get
-  - update
+  - list
+  - watch
 - apiGroups:
   - devops.kubesphere.io
   resources:
-  - applications
+  - addonStrategies
   verbs:
+  - create
+  - delete
   - get
-  - list
   - update
 - apiGroups:
   - devops.kubesphere.io
@@ -189,3 +198,11 @@ rules:
   - patch
   - update
   - watch
+- apiGroups:
+  - gitops.kubesphere.io
+  resources:
+  - applications
+  verbs:
+  - get
+  - list
+  - update
diff --git a/controllers/argocd/application_controller.go b/controllers/argocd/application_controller.go
index 281b41c..604c9f5 100644
--- a/controllers/argocd/application_controller.go
+++ b/controllers/argocd/application_controller.go
@@ -26,13 +26,13 @@ import (
 	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
 	"k8s.io/apimachinery/pkg/types"
 	"k8s.io/client-go/tools/record"
-	"kubesphere.io/devops/pkg/api/devops/v1alpha1"
+	"kubesphere.io/devops/pkg/api/gitops/v1alpha1"
 	"kubesphere.io/devops/pkg/utils/k8sutil"
 	ctrl "sigs.k8s.io/controller-runtime"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 )
 
-//+kubebuilder:rbac:groups=devops.kubesphere.io,resources=applications,verbs=get;list;update
+//+kubebuilder:rbac:groups=gitops.kubesphere.io,resources=applications,verbs=get;list;update
 //+kubebuilder:rbac:groups=argoproj.io,resources=applications,verbs=get;list;create;update
 
 // ApplicationReconciler is the reconciler of the Application
diff --git a/pkg/api/devops/v1alpha1/clustertemplate_types.go b/pkg/api/devops/v1alpha1/clustertemplate_types.go
index 59bdcd2..b86ed5b 100644
--- a/pkg/api/devops/v1alpha1/clustertemplate_types.go
+++ b/pkg/api/devops/v1alpha1/clustertemplate_types.go
@@ -20,12 +20,12 @@ import (
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
 
+var _ TemplateObject = &ClusterTemplate{}
+
 //+kubebuilder:object:root=true
 //+kubebuilder:subresource:status
 //+kubebuilder:resource:scope=Cluster
 
-var _ TemplateObject = &ClusterTemplate{}
-
 // ClusterTemplate is the Schema for the clustertemplates API
 type ClusterTemplate struct {
 	metav1.TypeMeta   `json:",inline"`
diff --git a/pkg/api/devops/v1alpha1/template_interface.go b/pkg/api/devops/v1alpha1/template_interface.go
index d85990d..0899c9f 100644
--- a/pkg/api/devops/v1alpha1/template_interface.go
+++ b/pkg/api/devops/v1alpha1/template_interface.go
@@ -20,6 +20,8 @@ import (
 	"k8s.io/apimachinery/pkg/runtime"
 )
 
+// +kubebuilder:object:generate=false
+
 // TemplateObject is implemented by Template and ClusterTemplate.
 type TemplateObject interface {
 	v1.Object
diff --git a/pkg/api/devops/v1alpha1/zz_generated.deepcopy.go b/pkg/api/devops/v1alpha1/zz_generated.deepcopy.go
index cdd04f4..18029b8 100644
--- a/pkg/api/devops/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/api/devops/v1alpha1/zz_generated.deepcopy.go
@@ -23,7 +23,7 @@ package v1alpha1
 
 import (
 	"k8s.io/api/core/v1"
-	runtime "k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/apimachinery/pkg/runtime"
 )
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
@@ -205,334 +205,6 @@ func (in *AddonStrategyList) DeepCopyObject() runtime.Object {
 	return nil
 }
 
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *Application) DeepCopyInto(out *Application) {
-	*out = *in
-	out.TypeMeta = in.TypeMeta
-	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
-	in.Spec.DeepCopyInto(&out.Spec)
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Application.
-func (in *Application) DeepCopy() *Application {
-	if in == nil {
-		return nil
-	}
-	out := new(Application)
-	in.DeepCopyInto(out)
-	return out
-}
-
-// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
-func (in *Application) DeepCopyObject() runtime.Object {
-	if c := in.DeepCopy(); c != nil {
-		return c
-	}
-	return nil
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *ApplicationDestination) DeepCopyInto(out *ApplicationDestination) {
-	*out = *in
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationDestination.
-func (in *ApplicationDestination) DeepCopy() *ApplicationDestination {
-	if in == nil {
-		return nil
-	}
-	out := new(ApplicationDestination)
-	in.DeepCopyInto(out)
-	return out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *ApplicationList) DeepCopyInto(out *ApplicationList) {
-	*out = *in
-	out.TypeMeta = in.TypeMeta
-	in.ListMeta.DeepCopyInto(&out.ListMeta)
-	if in.Items != nil {
-		in, out := &in.Items, &out.Items
-		*out = make([]Application, len(*in))
-		for i := range *in {
-			(*in)[i].DeepCopyInto(&(*out)[i])
-		}
-	}
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationList.
-func (in *ApplicationList) DeepCopy() *ApplicationList {
-	if in == nil {
-		return nil
-	}
-	out := new(ApplicationList)
-	in.DeepCopyInto(out)
-	return out
-}
-
-// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
-func (in *ApplicationList) DeepCopyObject() runtime.Object {
-	if c := in.DeepCopy(); c != nil {
-		return c
-	}
-	return nil
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *ApplicationSource) DeepCopyInto(out *ApplicationSource) {
-	*out = *in
-	if in.Helm != nil {
-		in, out := &in.Helm, &out.Helm
-		*out = new(ApplicationSourceHelm)
-		(*in).DeepCopyInto(*out)
-	}
-	if in.Kustomize != nil {
-		in, out := &in.Kustomize, &out.Kustomize
-		*out = new(ApplicationSourceKustomize)
-		(*in).DeepCopyInto(*out)
-	}
-	if in.Ksonnet != nil {
-		in, out := &in.Ksonnet, &out.Ksonnet
-		*out = new(ApplicationSourceKsonnet)
-		(*in).DeepCopyInto(*out)
-	}
-	if in.Directory != nil {
-		in, out := &in.Directory, &out.Directory
-		*out = new(ApplicationSourceDirectory)
-		(*in).DeepCopyInto(*out)
-	}
-	if in.Plugin != nil {
-		in, out := &in.Plugin, &out.Plugin
-		*out = new(ApplicationSourcePlugin)
-		(*in).DeepCopyInto(*out)
-	}
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationSource.
-func (in *ApplicationSource) DeepCopy() *ApplicationSource {
-	if in == nil {
-		return nil
-	}
-	out := new(ApplicationSource)
-	in.DeepCopyInto(out)
-	return out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *ApplicationSourceDirectory) DeepCopyInto(out *ApplicationSourceDirectory) {
-	*out = *in
-	in.Jsonnet.DeepCopyInto(&out.Jsonnet)
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationSourceDirectory.
-func (in *ApplicationSourceDirectory) DeepCopy() *ApplicationSourceDirectory {
-	if in == nil {
-		return nil
-	}
-	out := new(ApplicationSourceDirectory)
-	in.DeepCopyInto(out)
-	return out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *ApplicationSourceHelm) DeepCopyInto(out *ApplicationSourceHelm) {
-	*out = *in
-	if in.ValueFiles != nil {
-		in, out := &in.ValueFiles, &out.ValueFiles
-		*out = make([]string, len(*in))
-		copy(*out, *in)
-	}
-	if in.Parameters != nil {
-		in, out := &in.Parameters, &out.Parameters
-		*out = make([]HelmParameter, len(*in))
-		copy(*out, *in)
-	}
-	if in.FileParameters != nil {
-		in, out := &in.FileParameters, &out.FileParameters
-		*out = make([]HelmFileParameter, len(*in))
-		copy(*out, *in)
-	}
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationSourceHelm.
-func (in *ApplicationSourceHelm) DeepCopy() *ApplicationSourceHelm {
-	if in == nil {
-		return nil
-	}
-	out := new(ApplicationSourceHelm)
-	in.DeepCopyInto(out)
-	return out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *ApplicationSourceJsonnet) DeepCopyInto(out *ApplicationSourceJsonnet) {
-	*out = *in
-	if in.ExtVars != nil {
-		in, out := &in.ExtVars, &out.ExtVars
-		*out = make([]JsonnetVar, len(*in))
-		copy(*out, *in)
-	}
-	if in.TLAs != nil {
-		in, out := &in.TLAs, &out.TLAs
-		*out = make([]JsonnetVar, len(*in))
-		copy(*out, *in)
-	}
-	if in.Libs != nil {
-		in, out := &in.Libs, &out.Libs
-		*out = make([]string, len(*in))
-		copy(*out, *in)
-	}
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationSourceJsonnet.
-func (in *ApplicationSourceJsonnet) DeepCopy() *ApplicationSourceJsonnet {
-	if in == nil {
-		return nil
-	}
-	out := new(ApplicationSourceJsonnet)
-	in.DeepCopyInto(out)
-	return out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *ApplicationSourceKsonnet) DeepCopyInto(out *ApplicationSourceKsonnet) {
-	*out = *in
-	if in.Parameters != nil {
-		in, out := &in.Parameters, &out.Parameters
-		*out = make([]KsonnetParameter, len(*in))
-		copy(*out, *in)
-	}
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationSourceKsonnet.
-func (in *ApplicationSourceKsonnet) DeepCopy() *ApplicationSourceKsonnet {
-	if in == nil {
-		return nil
-	}
-	out := new(ApplicationSourceKsonnet)
-	in.DeepCopyInto(out)
-	return out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *ApplicationSourceKustomize) DeepCopyInto(out *ApplicationSourceKustomize) {
-	*out = *in
-	if in.Images != nil {
-		in, out := &in.Images, &out.Images
-		*out = make(KustomizeImages, len(*in))
-		copy(*out, *in)
-	}
-	if in.CommonLabels != nil {
-		in, out := &in.CommonLabels, &out.CommonLabels
-		*out = make(map[string]string, len(*in))
-		for key, val := range *in {
-			(*out)[key] = val
-		}
-	}
-	if in.CommonAnnotations != nil {
-		in, out := &in.CommonAnnotations, &out.CommonAnnotations
-		*out = make(map[string]string, len(*in))
-		for key, val := range *in {
-			(*out)[key] = val
-		}
-	}
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationSourceKustomize.
-func (in *ApplicationSourceKustomize) DeepCopy() *ApplicationSourceKustomize {
-	if in == nil {
-		return nil
-	}
-	out := new(ApplicationSourceKustomize)
-	in.DeepCopyInto(out)
-	return out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *ApplicationSourcePlugin) DeepCopyInto(out *ApplicationSourcePlugin) {
-	*out = *in
-	if in.Env != nil {
-		in, out := &in.Env, &out.Env
-		*out = make(Env, len(*in))
-		for i := range *in {
-			if (*in)[i] != nil {
-				in, out := &(*in)[i], &(*out)[i]
-				*out = new(EnvEntry)
-				**out = **in
-			}
-		}
-	}
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationSourcePlugin.
-func (in *ApplicationSourcePlugin) DeepCopy() *ApplicationSourcePlugin {
-	if in == nil {
-		return nil
-	}
-	out := new(ApplicationSourcePlugin)
-	in.DeepCopyInto(out)
-	return out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *ApplicationSpec) DeepCopyInto(out *ApplicationSpec) {
-	*out = *in
-	if in.ArgoApp != nil {
-		in, out := &in.ArgoApp, &out.ArgoApp
-		*out = new(ArgoApplication)
-		(*in).DeepCopyInto(*out)
-	}
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationSpec.
-func (in *ApplicationSpec) DeepCopy() *ApplicationSpec {
-	if in == nil {
-		return nil
-	}
-	out := new(ApplicationSpec)
-	in.DeepCopyInto(out)
-	return out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *ArgoApplication) DeepCopyInto(out *ArgoApplication) {
-	*out = *in
-	in.Source.DeepCopyInto(&out.Source)
-	out.Destination = in.Destination
-	if in.SyncPolicy != nil {
-		in, out := &in.SyncPolicy, &out.SyncPolicy
-		*out = new(SyncPolicy)
-		(*in).DeepCopyInto(*out)
-	}
-	if in.IgnoreDifferences != nil {
-		in, out := &in.IgnoreDifferences, &out.IgnoreDifferences
-		*out = make([]ResourceIgnoreDifferences, len(*in))
-		for i := range *in {
-			(*in)[i].DeepCopyInto(&(*out)[i])
-		}
-	}
-	if in.Info != nil {
-		in, out := &in.Info, &out.Info
-		*out = make([]Info, len(*in))
-		copy(*out, *in)
-	}
-	if in.RevisionHistoryLimit != nil {
-		in, out := &in.RevisionHistoryLimit, &out.RevisionHistoryLimit
-		*out = new(int64)
-		**out = **in
-	}
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArgoApplication.
-func (in *ArgoApplication) DeepCopy() *ArgoApplication {
-	if in == nil {
-		return nil
-	}
-	out := new(ArgoApplication)
-	in.DeepCopyInto(out)
-	return out
-}
-
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *AuthConfig) DeepCopyInto(out *AuthConfig) {
 	*out = *in
@@ -553,26 +225,6 @@ func (in *AuthConfig) DeepCopy() *AuthConfig {
 	return out
 }
 
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *Backoff) DeepCopyInto(out *Backoff) {
-	*out = *in
-	if in.Factor != nil {
-		in, out := &in.Factor, &out.Factor
-		*out = new(int64)
-		**out = **in
-	}
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Backoff.
-func (in *Backoff) DeepCopy() *Backoff {
-	if in == nil {
-		return nil
-	}
-	out := new(Backoff)
-	in.DeepCopyInto(out)
-	return out
-}
-
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *CGroupLimits) DeepCopyInto(out *CGroupLimits) {
 	*out = *in
@@ -772,46 +424,6 @@ func (in DockerConfigMap) DeepCopy() DockerConfigMap {
 	return *out
 }
 
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in Env) DeepCopyInto(out *Env) {
-	{
-		in := &in
-		*out = make(Env, len(*in))
-		for i := range *in {
-			if (*in)[i] != nil {
-				in, out := &(*in)[i], &(*out)[i]
-				*out = new(EnvEntry)
-				**out = **in
-			}
-		}
-	}
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Env.
-func (in Env) DeepCopy() Env {
-	if in == nil {
-		return nil
-	}
-	out := new(Env)
-	in.DeepCopyInto(out)
-	return *out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *EnvEntry) DeepCopyInto(out *EnvEntry) {
-	*out = *in
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvEntry.
-func (in *EnvEntry) DeepCopy() *EnvEntry {
-	if in == nil {
-		return nil
-	}
-	out := new(EnvEntry)
-	in.DeepCopyInto(out)
-	return out
-}
-
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *EnvironmentSpec) DeepCopyInto(out *EnvironmentSpec) {
 	*out = *in
@@ -910,100 +522,6 @@ func (in *GitRepositorySpec) DeepCopy() *GitRepositorySpec {
 	return out
 }
 
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *HelmFileParameter) DeepCopyInto(out *HelmFileParameter) {
-	*out = *in
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HelmFileParameter.
-func (in *HelmFileParameter) DeepCopy() *HelmFileParameter {
-	if in == nil {
-		return nil
-	}
-	out := new(HelmFileParameter)
-	in.DeepCopyInto(out)
-	return out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *HelmParameter) DeepCopyInto(out *HelmParameter) {
-	*out = *in
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HelmParameter.
-func (in *HelmParameter) DeepCopy() *HelmParameter {
-	if in == nil {
-		return nil
-	}
-	out := new(HelmParameter)
-	in.DeepCopyInto(out)
-	return out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *Info) DeepCopyInto(out *Info) {
-	*out = *in
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Info.
-func (in *Info) DeepCopy() *Info {
-	if in == nil {
-		return nil
-	}
-	out := new(Info)
-	in.DeepCopyInto(out)
-	return out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *JsonnetVar) DeepCopyInto(out *JsonnetVar) {
-	*out = *in
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JsonnetVar.
-func (in *JsonnetVar) DeepCopy() *JsonnetVar {
-	if in == nil {
-		return nil
-	}
-	out := new(JsonnetVar)
-	in.DeepCopyInto(out)
-	return out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *KsonnetParameter) DeepCopyInto(out *KsonnetParameter) {
-	*out = *in
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KsonnetParameter.
-func (in *KsonnetParameter) DeepCopy() *KsonnetParameter {
-	if in == nil {
-		return nil
-	}
-	out := new(KsonnetParameter)
-	in.DeepCopyInto(out)
-	return out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in KustomizeImages) DeepCopyInto(out *KustomizeImages) {
-	{
-		in := &in
-		*out = make(KustomizeImages, len(*in))
-		copy(*out, *in)
-	}
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KustomizeImages.
-func (in KustomizeImages) DeepCopy() KustomizeImages {
-	if in == nil {
-		return nil
-	}
-	out := new(KustomizeImages)
-	in.DeepCopyInto(out)
-	return *out
-}
-
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *Parameter) DeepCopyInto(out *Parameter) {
 	*out = *in
@@ -1054,56 +572,6 @@ func (in *ProxyConfig) DeepCopy() *ProxyConfig {
 	return out
 }
 
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *ResourceIgnoreDifferences) DeepCopyInto(out *ResourceIgnoreDifferences) {
-	*out = *in
-	if in.JSONPointers != nil {
-		in, out := &in.JSONPointers, &out.JSONPointers
-		*out = make([]string, len(*in))
-		copy(*out, *in)
-	}
-	if in.JQPathExpressions != nil {
-		in, out := &in.JQPathExpressions, &out.JQPathExpressions
-		*out = make([]string, len(*in))
-		copy(*out, *in)
-	}
-	if in.ManagedFieldsManagers != nil {
-		in, out := &in.ManagedFieldsManagers, &out.ManagedFieldsManagers
-		*out = make([]string, len(*in))
-		copy(*out, *in)
-	}
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceIgnoreDifferences.
-func (in *ResourceIgnoreDifferences) DeepCopy() *ResourceIgnoreDifferences {
-	if in == nil {
-		return nil
-	}
-	out := new(ResourceIgnoreDifferences)
-	in.DeepCopyInto(out)
-	return out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *RetryStrategy) DeepCopyInto(out *RetryStrategy) {
-	*out = *in
-	if in.Backoff != nil {
-		in, out := &in.Backoff, &out.Backoff
-		*out = new(Backoff)
-		(*in).DeepCopyInto(*out)
-	}
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RetryStrategy.
-func (in *RetryStrategy) DeepCopy() *RetryStrategy {
-	if in == nil {
-		return nil
-	}
-	out := new(RetryStrategy)
-	in.DeepCopyInto(out)
-	return out
-}
-
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *S2iAutoScale) DeepCopyInto(out *S2iAutoScale) {
 	*out = *in
@@ -1677,126 +1145,6 @@ func (in *S2iRunStatus) DeepCopy() *S2iRunStatus {
 	return out
 }
 
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in SyncOptions) DeepCopyInto(out *SyncOptions) {
-	{
-		in := &in
-		*out = make(SyncOptions, len(*in))
-		copy(*out, *in)
-	}
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SyncOptions.
-func (in SyncOptions) DeepCopy() SyncOptions {
-	if in == nil {
-		return nil
-	}
-	out := new(SyncOptions)
-	in.DeepCopyInto(out)
-	return *out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *SyncPolicy) DeepCopyInto(out *SyncPolicy) {
-	*out = *in
-	if in.Automated != nil {
-		in, out := &in.Automated, &out.Automated
-		*out = new(SyncPolicyAutomated)
-		**out = **in
-	}
-	if in.SyncOptions != nil {
-		in, out := &in.SyncOptions, &out.SyncOptions
-		*out = make(SyncOptions, len(*in))
-		copy(*out, *in)
-	}
-	if in.Retry != nil {
-		in, out := &in.Retry, &out.Retry
-		*out = new(RetryStrategy)
-		(*in).DeepCopyInto(*out)
-	}
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SyncPolicy.
-func (in *SyncPolicy) DeepCopy() *SyncPolicy {
-	if in == nil {
-		return nil
-	}
-	out := new(SyncPolicy)
-	in.DeepCopyInto(out)
-	return out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *SyncPolicyAutomated) DeepCopyInto(out *SyncPolicyAutomated) {
-	*out = *in
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SyncPolicyAutomated.
-func (in *SyncPolicyAutomated) DeepCopy() *SyncPolicyAutomated {
-	if in == nil {
-		return nil
-	}
-	out := new(SyncPolicyAutomated)
-	in.DeepCopyInto(out)
-	return out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *SyncStrategy) DeepCopyInto(out *SyncStrategy) {
-	*out = *in
-	if in.Apply != nil {
-		in, out := &in.Apply, &out.Apply
-		*out = new(SyncStrategyApply)
-		**out = **in
-	}
-	if in.Hook != nil {
-		in, out := &in.Hook, &out.Hook
-		*out = new(SyncStrategyHook)
-		**out = **in
-	}
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SyncStrategy.
-func (in *SyncStrategy) DeepCopy() *SyncStrategy {
-	if in == nil {
-		return nil
-	}
-	out := new(SyncStrategy)
-	in.DeepCopyInto(out)
-	return out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *SyncStrategyApply) DeepCopyInto(out *SyncStrategyApply) {
-	*out = *in
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SyncStrategyApply.
-func (in *SyncStrategyApply) DeepCopy() *SyncStrategyApply {
-	if in == nil {
-		return nil
-	}
-	out := new(SyncStrategyApply)
-	in.DeepCopyInto(out)
-	return out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *SyncStrategyHook) DeepCopyInto(out *SyncStrategyHook) {
-	*out = *in
-	out.SyncStrategyApply = in.SyncStrategyApply
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SyncStrategyHook.
-func (in *SyncStrategyHook) DeepCopy() *SyncStrategyHook {
-	if in == nil {
-		return nil
-	}
-	out := new(SyncStrategyHook)
-	in.DeepCopyInto(out)
-	return out
-}
-
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *Template) DeepCopyInto(out *Template) {
 	*out = *in
diff --git a/pkg/api/devops/v1alpha1/application.go b/pkg/api/gitops/v1alpha1/application.go
similarity index 99%
rename from pkg/api/devops/v1alpha1/application.go
rename to pkg/api/gitops/v1alpha1/application.go
index 90d8475..84c1d38 100644
--- a/pkg/api/devops/v1alpha1/application.go
+++ b/pkg/api/gitops/v1alpha1/application.go
@@ -16,7 +16,9 @@ limitations under the License.
 
 package v1alpha1
 
-import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+import (
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
 
 // ApplicationSpec is the specification of the Application
 type ApplicationSpec struct {
diff --git a/pkg/api/gitops/v1alpha1/groupversion_info.go b/pkg/api/gitops/v1alpha1/groupversion_info.go
new file mode 100644
index 0000000..0babe4a
--- /dev/null
+++ b/pkg/api/gitops/v1alpha1/groupversion_info.go
@@ -0,0 +1,46 @@
+/*
+Copyright 2022 The KubeSphere Authors.
+
+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.
+*/
+
+// NOTE: Boilerplate only.  Ignore this file.
+
+// Package v1alpha1 contains API Schema definitions for the gitops v1alpha1 API group
+// +k8s:openapi-gen=true
+// +k8s:deepcopy-gen=package,register
+// +k8s:conversion-gen=kubesphere.io/gitops/api
+// +k8s:defaulter-gen=TypeMeta
+// +groupName=gitops.kubesphere.io
+package v1alpha1
+
+import (
+	"k8s.io/apimachinery/pkg/runtime/schema"
+	"sigs.k8s.io/controller-runtime/pkg/runtime/scheme"
+)
+
+var (
+	// GroupVersion is group version used to register these objects
+	GroupVersion = schema.GroupVersion{Group: "gitops.kubesphere.io", Version: "v1alpha1"}
+
+	// SchemeBuilder is used to add go types to the GroupVersionKind scheme
+	SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
+
+	// AddToScheme is required by pkg/client/...
+	AddToScheme = SchemeBuilder.AddToScheme
+)
+
+// Resource is required by pkg/client/listers/...
+func Resource(resource string) schema.GroupResource {
+	return GroupVersion.WithResource(resource).GroupResource()
+}
diff --git a/pkg/api/gitops/v1alpha1/zz_generated.deepcopy.go b/pkg/api/gitops/v1alpha1/zz_generated.deepcopy.go
new file mode 100644
index 0000000..cff3d31
--- /dev/null
+++ b/pkg/api/gitops/v1alpha1/zz_generated.deepcopy.go
@@ -0,0 +1,678 @@
+//go:build !ignore_autogenerated
+// +build !ignore_autogenerated
+
+/*
+Copyright 2022 The KubeSphere Authors.
+
+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.
+*/
+
+// Code generated by controller-gen. DO NOT EDIT.
+
+package v1alpha1
+
+import (
+	runtime "k8s.io/apimachinery/pkg/runtime"
+)
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *Application) DeepCopyInto(out *Application) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+	in.Spec.DeepCopyInto(&out.Spec)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Application.
+func (in *Application) DeepCopy() *Application {
+	if in == nil {
+		return nil
+	}
+	out := new(Application)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *Application) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApplicationDestination) DeepCopyInto(out *ApplicationDestination) {
+	*out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationDestination.
+func (in *ApplicationDestination) DeepCopy() *ApplicationDestination {
+	if in == nil {
+		return nil
+	}
+	out := new(ApplicationDestination)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApplicationList) DeepCopyInto(out *ApplicationList) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ListMeta.DeepCopyInto(&out.ListMeta)
+	if in.Items != nil {
+		in, out := &in.Items, &out.Items
+		*out = make([]Application, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationList.
+func (in *ApplicationList) DeepCopy() *ApplicationList {
+	if in == nil {
+		return nil
+	}
+	out := new(ApplicationList)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *ApplicationList) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApplicationSource) DeepCopyInto(out *ApplicationSource) {
+	*out = *in
+	if in.Helm != nil {
+		in, out := &in.Helm, &out.Helm
+		*out = new(ApplicationSourceHelm)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.Kustomize != nil {
+		in, out := &in.Kustomize, &out.Kustomize
+		*out = new(ApplicationSourceKustomize)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.Ksonnet != nil {
+		in, out := &in.Ksonnet, &out.Ksonnet
+		*out = new(ApplicationSourceKsonnet)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.Directory != nil {
+		in, out := &in.Directory, &out.Directory
+		*out = new(ApplicationSourceDirectory)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.Plugin != nil {
+		in, out := &in.Plugin, &out.Plugin
+		*out = new(ApplicationSourcePlugin)
+		(*in).DeepCopyInto(*out)
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationSource.
+func (in *ApplicationSource) DeepCopy() *ApplicationSource {
+	if in == nil {
+		return nil
+	}
+	out := new(ApplicationSource)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApplicationSourceDirectory) DeepCopyInto(out *ApplicationSourceDirectory) {
+	*out = *in
+	in.Jsonnet.DeepCopyInto(&out.Jsonnet)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationSourceDirectory.
+func (in *ApplicationSourceDirectory) DeepCopy() *ApplicationSourceDirectory {
+	if in == nil {
+		return nil
+	}
+	out := new(ApplicationSourceDirectory)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApplicationSourceHelm) DeepCopyInto(out *ApplicationSourceHelm) {
+	*out = *in
+	if in.ValueFiles != nil {
+		in, out := &in.ValueFiles, &out.ValueFiles
+		*out = make([]string, len(*in))
+		copy(*out, *in)
+	}
+	if in.Parameters != nil {
+		in, out := &in.Parameters, &out.Parameters
+		*out = make([]HelmParameter, len(*in))
+		copy(*out, *in)
+	}
+	if in.FileParameters != nil {
+		in, out := &in.FileParameters, &out.FileParameters
+		*out = make([]HelmFileParameter, len(*in))
+		copy(*out, *in)
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationSourceHelm.
+func (in *ApplicationSourceHelm) DeepCopy() *ApplicationSourceHelm {
+	if in == nil {
+		return nil
+	}
+	out := new(ApplicationSourceHelm)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApplicationSourceJsonnet) DeepCopyInto(out *ApplicationSourceJsonnet) {
+	*out = *in
+	if in.ExtVars != nil {
+		in, out := &in.ExtVars, &out.ExtVars
+		*out = make([]JsonnetVar, len(*in))
+		copy(*out, *in)
+	}
+	if in.TLAs != nil {
+		in, out := &in.TLAs, &out.TLAs
+		*out = make([]JsonnetVar, len(*in))
+		copy(*out, *in)
+	}
+	if in.Libs != nil {
+		in, out := &in.Libs, &out.Libs
+		*out = make([]string, len(*in))
+		copy(*out, *in)
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationSourceJsonnet.
+func (in *ApplicationSourceJsonnet) DeepCopy() *ApplicationSourceJsonnet {
+	if in == nil {
+		return nil
+	}
+	out := new(ApplicationSourceJsonnet)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApplicationSourceKsonnet) DeepCopyInto(out *ApplicationSourceKsonnet) {
+	*out = *in
+	if in.Parameters != nil {
+		in, out := &in.Parameters, &out.Parameters
+		*out = make([]KsonnetParameter, len(*in))
+		copy(*out, *in)
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationSourceKsonnet.
+func (in *ApplicationSourceKsonnet) DeepCopy() *ApplicationSourceKsonnet {
+	if in == nil {
+		return nil
+	}
+	out := new(ApplicationSourceKsonnet)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApplicationSourceKustomize) DeepCopyInto(out *ApplicationSourceKustomize) {
+	*out = *in
+	if in.Images != nil {
+		in, out := &in.Images, &out.Images
+		*out = make(KustomizeImages, len(*in))
+		copy(*out, *in)
+	}
+	if in.CommonLabels != nil {
+		in, out := &in.CommonLabels, &out.CommonLabels
+		*out = make(map[string]string, len(*in))
+		for key, val := range *in {
+			(*out)[key] = val
+		}
+	}
+	if in.CommonAnnotations != nil {
+		in, out := &in.CommonAnnotations, &out.CommonAnnotations
+		*out = make(map[string]string, len(*in))
+		for key, val := range *in {
+			(*out)[key] = val
+		}
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationSourceKustomize.
+func (in *ApplicationSourceKustomize) DeepCopy() *ApplicationSourceKustomize {
+	if in == nil {
+		return nil
+	}
+	out := new(ApplicationSourceKustomize)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApplicationSourcePlugin) DeepCopyInto(out *ApplicationSourcePlugin) {
+	*out = *in
+	if in.Env != nil {
+		in, out := &in.Env, &out.Env
+		*out = make(Env, len(*in))
+		for i := range *in {
+			if (*in)[i] != nil {
+				in, out := &(*in)[i], &(*out)[i]
+				*out = new(EnvEntry)
+				**out = **in
+			}
+		}
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationSourcePlugin.
+func (in *ApplicationSourcePlugin) DeepCopy() *ApplicationSourcePlugin {
+	if in == nil {
+		return nil
+	}
+	out := new(ApplicationSourcePlugin)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ApplicationSpec) DeepCopyInto(out *ApplicationSpec) {
+	*out = *in
+	if in.ArgoApp != nil {
+		in, out := &in.ArgoApp, &out.ArgoApp
+		*out = new(ArgoApplication)
+		(*in).DeepCopyInto(*out)
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationSpec.
+func (in *ApplicationSpec) DeepCopy() *ApplicationSpec {
+	if in == nil {
+		return nil
+	}
+	out := new(ApplicationSpec)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ArgoApplication) DeepCopyInto(out *ArgoApplication) {
+	*out = *in
+	in.Source.DeepCopyInto(&out.Source)
+	out.Destination = in.Destination
+	if in.SyncPolicy != nil {
+		in, out := &in.SyncPolicy, &out.SyncPolicy
+		*out = new(SyncPolicy)
+		(*in).DeepCopyInto(*out)
+	}
+	if in.IgnoreDifferences != nil {
+		in, out := &in.IgnoreDifferences, &out.IgnoreDifferences
+		*out = make([]ResourceIgnoreDifferences, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	if in.Info != nil {
+		in, out := &in.Info, &out.Info
+		*out = make([]Info, len(*in))
+		copy(*out, *in)
+	}
+	if in.RevisionHistoryLimit != nil {
+		in, out := &in.RevisionHistoryLimit, &out.RevisionHistoryLimit
+		*out = new(int64)
+		**out = **in
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ArgoApplication.
+func (in *ArgoApplication) DeepCopy() *ArgoApplication {
+	if in == nil {
+		return nil
+	}
+	out := new(ArgoApplication)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *Backoff) DeepCopyInto(out *Backoff) {
+	*out = *in
+	if in.Factor != nil {
+		in, out := &in.Factor, &out.Factor
+		*out = new(int64)
+		**out = **in
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Backoff.
+func (in *Backoff) DeepCopy() *Backoff {
+	if in == nil {
+		return nil
+	}
+	out := new(Backoff)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in Env) DeepCopyInto(out *Env) {
+	{
+		in := &in
+		*out = make(Env, len(*in))
+		for i := range *in {
+			if (*in)[i] != nil {
+				in, out := &(*in)[i], &(*out)[i]
+				*out = new(EnvEntry)
+				**out = **in
+			}
+		}
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Env.
+func (in Env) DeepCopy() Env {
+	if in == nil {
+		return nil
+	}
+	out := new(Env)
+	in.DeepCopyInto(out)
+	return *out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *EnvEntry) DeepCopyInto(out *EnvEntry) {
+	*out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvEntry.
+func (in *EnvEntry) DeepCopy() *EnvEntry {
+	if in == nil {
+		return nil
+	}
+	out := new(EnvEntry)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *HelmFileParameter) DeepCopyInto(out *HelmFileParameter) {
+	*out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HelmFileParameter.
+func (in *HelmFileParameter) DeepCopy() *HelmFileParameter {
+	if in == nil {
+		return nil
+	}
+	out := new(HelmFileParameter)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *HelmParameter) DeepCopyInto(out *HelmParameter) {
+	*out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HelmParameter.
+func (in *HelmParameter) DeepCopy() *HelmParameter {
+	if in == nil {
+		return nil
+	}
+	out := new(HelmParameter)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *Info) DeepCopyInto(out *Info) {
+	*out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Info.
+func (in *Info) DeepCopy() *Info {
+	if in == nil {
+		return nil
+	}
+	out := new(Info)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *JsonnetVar) DeepCopyInto(out *JsonnetVar) {
+	*out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JsonnetVar.
+func (in *JsonnetVar) DeepCopy() *JsonnetVar {
+	if in == nil {
+		return nil
+	}
+	out := new(JsonnetVar)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *KsonnetParameter) DeepCopyInto(out *KsonnetParameter) {
+	*out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KsonnetParameter.
+func (in *KsonnetParameter) DeepCopy() *KsonnetParameter {
+	if in == nil {
+		return nil
+	}
+	out := new(KsonnetParameter)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in KustomizeImages) DeepCopyInto(out *KustomizeImages) {
+	{
+		in := &in
+		*out = make(KustomizeImages, len(*in))
+		copy(*out, *in)
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KustomizeImages.
+func (in KustomizeImages) DeepCopy() KustomizeImages {
+	if in == nil {
+		return nil
+	}
+	out := new(KustomizeImages)
+	in.DeepCopyInto(out)
+	return *out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ResourceIgnoreDifferences) DeepCopyInto(out *ResourceIgnoreDifferences) {
+	*out = *in
+	if in.JSONPointers != nil {
+		in, out := &in.JSONPointers, &out.JSONPointers
+		*out = make([]string, len(*in))
+		copy(*out, *in)
+	}
+	if in.JQPathExpressions != nil {
+		in, out := &in.JQPathExpressions, &out.JQPathExpressions
+		*out = make([]string, len(*in))
+		copy(*out, *in)
+	}
+	if in.ManagedFieldsManagers != nil {
+		in, out := &in.ManagedFieldsManagers, &out.ManagedFieldsManagers
+		*out = make([]string, len(*in))
+		copy(*out, *in)
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceIgnoreDifferences.
+func (in *ResourceIgnoreDifferences) DeepCopy() *ResourceIgnoreDifferences {
+	if in == nil {
+		return nil
+	}
+	out := new(ResourceIgnoreDifferences)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *RetryStrategy) DeepCopyInto(out *RetryStrategy) {
+	*out = *in
+	if in.Backoff != nil {
+		in, out := &in.Backoff, &out.Backoff
+		*out = new(Backoff)
+		(*in).DeepCopyInto(*out)
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RetryStrategy.
+func (in *RetryStrategy) DeepCopy() *RetryStrategy {
+	if in == nil {
+		return nil
+	}
+	out := new(RetryStrategy)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in SyncOptions) DeepCopyInto(out *SyncOptions) {
+	{
+		in := &in
+		*out = make(SyncOptions, len(*in))
+		copy(*out, *in)
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SyncOptions.
+func (in SyncOptions) DeepCopy() SyncOptions {
+	if in == nil {
+		return nil
+	}
+	out := new(SyncOptions)
+	in.DeepCopyInto(out)
+	return *out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *SyncPolicy) DeepCopyInto(out *SyncPolicy) {
+	*out = *in
+	if in.Automated != nil {
+		in, out := &in.Automated, &out.Automated
+		*out = new(SyncPolicyAutomated)
+		**out = **in
+	}
+	if in.SyncOptions != nil {
+		in, out := &in.SyncOptions, &out.SyncOptions
+		*out = make(SyncOptions, len(*in))
+		copy(*out, *in)
+	}
+	if in.Retry != nil {
+		in, out := &in.Retry, &out.Retry
+		*out = new(RetryStrategy)
+		(*in).DeepCopyInto(*out)
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SyncPolicy.
+func (in *SyncPolicy) DeepCopy() *SyncPolicy {
+	if in == nil {
+		return nil
+	}
+	out := new(SyncPolicy)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *SyncPolicyAutomated) DeepCopyInto(out *SyncPolicyAutomated) {
+	*out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SyncPolicyAutomated.
+func (in *SyncPolicyAutomated) DeepCopy() *SyncPolicyAutomated {
+	if in == nil {
+		return nil
+	}
+	out := new(SyncPolicyAutomated)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *SyncStrategy) DeepCopyInto(out *SyncStrategy) {
+	*out = *in
+	if in.Apply != nil {
+		in, out := &in.Apply, &out.Apply
+		*out = new(SyncStrategyApply)
+		**out = **in
+	}
+	if in.Hook != nil {
+		in, out := &in.Hook, &out.Hook
+		*out = new(SyncStrategyHook)
+		**out = **in
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SyncStrategy.
+func (in *SyncStrategy) DeepCopy() *SyncStrategy {
+	if in == nil {
+		return nil
+	}
+	out := new(SyncStrategy)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *SyncStrategyApply) DeepCopyInto(out *SyncStrategyApply) {
+	*out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SyncStrategyApply.
+func (in *SyncStrategyApply) DeepCopy() *SyncStrategyApply {
+	if in == nil {
+		return nil
+	}
+	out := new(SyncStrategyApply)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *SyncStrategyHook) DeepCopyInto(out *SyncStrategyHook) {
+	*out = *in
+	out.SyncStrategyApply = in.SyncStrategyApply
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SyncStrategyHook.
+func (in *SyncStrategyHook) DeepCopy() *SyncStrategyHook {
+	if in == nil {
+		return nil
+	}
+	out := new(SyncStrategyHook)
+	in.DeepCopyInto(out)
+	return out
+}
diff --git a/pkg/apiserver/apiserver.go b/pkg/apiserver/apiserver.go
index 65b810c..af39a70 100644
--- a/pkg/apiserver/apiserver.go
+++ b/pkg/apiserver/apiserver.go
@@ -20,9 +20,10 @@ import (
 	"bytes"
 	"context"
 	"fmt"
+	"kubesphere.io/devops/pkg/kapis/common"
 	kapisv1alpha1 "kubesphere.io/devops/pkg/kapis/devops/v1alpha1"
-	"kubesphere.io/devops/pkg/kapis/devops/v1alpha1/common"
 	"kubesphere.io/devops/pkg/kapis/doc"
+	gitops "kubesphere.io/devops/pkg/kapis/gitops/v1alpha1"
 	"net/http"
 	rt "runtime"
 	"time"
@@ -162,6 +163,9 @@ func (s *APIServer) installKubeSphereAPIs() {
 	wss = append(wss, kapisv1alpha1.AddToContainer(s.container, &common.Options{
 		GenericClient: s.Client,
 	})...)
+	wss = append(wss, gitops.AddToContainer(s.container, &common.Options{
+		GenericClient: s.Client,
+	})...)
 	doc.AddSwaggerService(wss, s.container)
 }
 
diff --git a/pkg/kapis/devops/v1alpha1/common/options.go b/pkg/kapis/common/options.go
similarity index 61%
rename from pkg/kapis/devops/v1alpha1/common/options.go
rename to pkg/kapis/common/options.go
index 126fffa..e31253b 100644
--- a/pkg/kapis/devops/v1alpha1/common/options.go
+++ b/pkg/kapis/common/options.go
@@ -17,6 +17,7 @@ package common
 
 import (
 	"github.com/emicklei/go-restful"
+	"kubesphere.io/devops/pkg/kapis"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 )
 
@@ -28,4 +29,20 @@ type Options struct {
 var (
 	// DevopsPathParameter is a path parameter definition for devops.
 	DevopsPathParameter = restful.PathParameter("devops", "DevOps project name")
+	// NamespacePathParameter is a path parameter definition for namespace
+	NamespacePathParameter = restful.PathParameter("namespace", "The namespace name")
 )
+
+// GetPathParameter returns the parameter value from a request
+func GetPathParameter(req *restful.Request, param *restful.Parameter) string {
+	return req.PathParameter(param.Data().Name)
+}
+
+// Response is a common response method
+func Response(req *restful.Request, res *restful.Response, object interface{}, err error) {
+	if err != nil {
+		kapis.HandleError(req, res, err)
+	} else {
+		_ = res.WriteEntity(object)
+	}
+}
diff --git a/pkg/kapis/devops/v1alpha1/register.go b/pkg/kapis/devops/v1alpha1/register.go
index 7381f57..2ecdf81 100644
--- a/pkg/kapis/devops/v1alpha1/register.go
+++ b/pkg/kapis/devops/v1alpha1/register.go
@@ -19,8 +19,7 @@ import (
 	"github.com/emicklei/go-restful"
 	"kubesphere.io/devops/pkg/api/devops/v1alpha1"
 	"kubesphere.io/devops/pkg/apiserver/runtime"
-	"kubesphere.io/devops/pkg/kapis/devops/v1alpha1/argocd"
-	"kubesphere.io/devops/pkg/kapis/devops/v1alpha1/common"
+	"kubesphere.io/devops/pkg/kapis/common"
 	"kubesphere.io/devops/pkg/kapis/devops/v1alpha1/template"
 )
 
@@ -32,7 +31,6 @@ func AddToContainer(container *restful.Container, options *common.Options) []*re
 	}
 	for _, service := range services {
 		template.RegisterRoutes(service, options)
-		argocd.RegisterRoutes(service, options)
 		container.Add(service)
 	}
 	return services
diff --git a/pkg/kapis/devops/v1alpha1/template/handler.go b/pkg/kapis/devops/v1alpha1/template/handler.go
index 6436bf1..1c161b4 100644
--- a/pkg/kapis/devops/v1alpha1/template/handler.go
+++ b/pkg/kapis/devops/v1alpha1/template/handler.go
@@ -16,7 +16,7 @@
 package template
 
 import (
-	kapisv1alpha1 "kubesphere.io/devops/pkg/kapis/devops/v1alpha1/common"
+	kapisv1alpha1 "kubesphere.io/devops/pkg/kapis/common"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 )
 
diff --git a/pkg/kapis/devops/v1alpha1/template/route.go b/pkg/kapis/devops/v1alpha1/template/route.go
index eb37a71..3d5ac72 100644
--- a/pkg/kapis/devops/v1alpha1/template/route.go
+++ b/pkg/kapis/devops/v1alpha1/template/route.go
@@ -23,7 +23,7 @@ import (
 	"kubesphere.io/devops/pkg/api/devops"
 	"kubesphere.io/devops/pkg/api/devops/v1alpha1"
 	"kubesphere.io/devops/pkg/constants"
-	kapisv1alpha1 "kubesphere.io/devops/pkg/kapis/devops/v1alpha1/common"
+	kapisv1alpha1 "kubesphere.io/devops/pkg/kapis/common"
 	"net/http"
 )
 
diff --git a/pkg/kapis/devops/v1alpha1/template/template_handler.go b/pkg/kapis/devops/v1alpha1/template/template_handler.go
index 82030d2..f156c53 100644
--- a/pkg/kapis/devops/v1alpha1/template/template_handler.go
+++ b/pkg/kapis/devops/v1alpha1/template/template_handler.go
@@ -23,7 +23,7 @@ import (
 	"kubesphere.io/devops/pkg/api/devops/v1alpha1"
 	"kubesphere.io/devops/pkg/apiserver/query"
 	"kubesphere.io/devops/pkg/kapis"
-	kapisv1alpha1 "kubesphere.io/devops/pkg/kapis/devops/v1alpha1/common"
+	kapisv1alpha1 "kubesphere.io/devops/pkg/kapis/common"
 	"kubesphere.io/devops/pkg/models/resources/v1alpha3"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 )
diff --git a/pkg/kapis/devops/v1alpha1/argocd/handler.go b/pkg/kapis/gitops/v1alpha1/argocd/handler.go
similarity index 69%
rename from pkg/kapis/devops/v1alpha1/argocd/handler.go
rename to pkg/kapis/gitops/v1alpha1/argocd/handler.go
index 5aff249..a6738d5 100644
--- a/pkg/kapis/devops/v1alpha1/argocd/handler.go
+++ b/pkg/kapis/gitops/v1alpha1/argocd/handler.go
@@ -20,35 +20,34 @@ import (
 	"github.com/emicklei/go-restful"
 	v1 "k8s.io/api/core/v1"
 	"k8s.io/apimachinery/pkg/types"
-	"kubesphere.io/devops/pkg/api/devops/v1alpha1"
-	"kubesphere.io/devops/pkg/kapis"
-	kapisv1alpha1 "kubesphere.io/devops/pkg/kapis/devops/v1alpha1/common"
+	"kubesphere.io/devops/pkg/api/gitops/v1alpha1"
+	"kubesphere.io/devops/pkg/kapis/common"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 )
 
 func (h *handler) applicationList(req *restful.Request, res *restful.Response) {
-	namespace := getPathParameter(req, kapisv1alpha1.DevopsPathParameter)
+	namespace := common.GetPathParameter(req, common.NamespacePathParameter)
 
 	applicationList := &v1alpha1.ApplicationList{}
 	err := h.List(context.Background(), applicationList, client.InNamespace(namespace))
-	response(req, res, applicationList, err)
+	common.Response(req, res, applicationList, err)
 }
 
 func (h *handler) getApplication(req *restful.Request, res *restful.Response) {
-	namespace := getPathParameter(req, kapisv1alpha1.DevopsPathParameter)
-	name := getPathParameter(req, pathParameterApplication)
+	namespace := common.GetPathParameter(req, common.NamespacePathParameter)
+	name := common.GetPathParameter(req, pathParameterApplication)
 
 	application := &v1alpha1.Application{}
 	err := h.Get(context.Background(), types.NamespacedName{
 		Namespace: namespace,
 		Name:      name,
 	}, application)
-	response(req, res, application, err)
+	common.Response(req, res, application, err)
 }
 
 func (h *handler) delApplication(req *restful.Request, res *restful.Response) {
-	namespace := getPathParameter(req, kapisv1alpha1.DevopsPathParameter)
-	name := getPathParameter(req, pathParameterApplication)
+	namespace := common.GetPathParameter(req, common.NamespacePathParameter)
+	name := common.GetPathParameter(req, pathParameterApplication)
 
 	application := &v1alpha1.Application{}
 	err := h.Get(context.Background(), types.NamespacedName{
@@ -58,12 +57,12 @@ func (h *handler) delApplication(req *restful.Request, res *restful.Response) {
 	if err == nil {
 		err = h.Delete(context.Background(), application)
 	}
-	response(req, res, application, err)
+	common.Response(req, res, application, err)
 }
 
 func (h *handler) createApplication(req *restful.Request, res *restful.Response) {
 	var err error
-	namespace := getPathParameter(req, kapisv1alpha1.DevopsPathParameter)
+	namespace := common.GetPathParameter(req, common.NamespacePathParameter)
 
 	application := &v1alpha1.Application{}
 	if err = req.ReadEntity(application); err == nil {
@@ -71,12 +70,12 @@ func (h *handler) createApplication(req *restful.Request, res *restful.Response)
 		err = h.Create(context.Background(), application)
 	}
 
-	response(req, res, application, err)
+	common.Response(req, res, application, err)
 }
 
 func (h *handler) updateApplication(req *restful.Request, res *restful.Response) {
-	namespace := getPathParameter(req, kapisv1alpha1.DevopsPathParameter)
-	name := getPathParameter(req, pathParameterApplication)
+	namespace := common.GetPathParameter(req, common.NamespacePathParameter)
+	name := common.GetPathParameter(req, pathParameterApplication)
 
 	application := &v1alpha1.Application{}
 	err := h.Get(context.Background(), types.NamespacedName{
@@ -88,7 +87,7 @@ func (h *handler) updateApplication(req *restful.Request, res *restful.Response)
 			err = h.Update(context.Background(), application)
 		}
 	}
-	response(req, res, application, err)
+	common.Response(req, res, application, err)
 }
 
 func (h *handler) getClusters(req *restful.Request, res *restful.Response) {
@@ -115,26 +114,14 @@ func (h *handler) getClusters(req *restful.Request, res *restful.Response) {
 			}
 		}
 	}
-	response(req, res, argoClusters, err)
-}
-
-func getPathParameter(req *restful.Request, param *restful.Parameter) string {
-	return req.PathParameter(param.Data().Name)
-}
-
-func response(req *restful.Request, res *restful.Response, object interface{}, err error) {
-	if err != nil {
-		kapis.HandleError(req, res, err)
-	} else {
-		_ = res.WriteEntity(object)
-	}
+	common.Response(req, res, argoClusters, err)
 }
 
 type handler struct {
 	client.Client
 }
 
-func newHandler(options *kapisv1alpha1.Options) *handler {
+func newHandler(options *common.Options) *handler {
 	return &handler{
 		Client: options.GenericClient,
 	}
diff --git a/pkg/kapis/devops/v1alpha1/argocd/route.go b/pkg/kapis/gitops/v1alpha1/argocd/route.go
similarity index 74%
rename from pkg/kapis/devops/v1alpha1/argocd/route.go
rename to pkg/kapis/gitops/v1alpha1/argocd/route.go
index 3bca682..044e436 100644
--- a/pkg/kapis/devops/v1alpha1/argocd/route.go
+++ b/pkg/kapis/gitops/v1alpha1/argocd/route.go
@@ -18,8 +18,8 @@ package argocd
 import (
 	"github.com/emicklei/go-restful"
 	"kubesphere.io/devops/pkg/api"
-	"kubesphere.io/devops/pkg/api/devops/v1alpha1"
-	kapisv1alpha1 "kubesphere.io/devops/pkg/kapis/devops/v1alpha1/common"
+	"kubesphere.io/devops/pkg/api/gitops/v1alpha1"
+	kapisv1alpha1 "kubesphere.io/devops/pkg/kapis/common"
 	"net/http"
 )
 
@@ -31,36 +31,36 @@ var (
 // RegisterRoutes is for registering Argo CD Application routes into WebService.
 func RegisterRoutes(service *restful.WebService, options *kapisv1alpha1.Options) {
 	handler := newHandler(options)
-	service.Route(service.GET("/devops/{devops}/applications").
+	service.Route(service.GET("/namespaces/{namespace}/applications").
 		To(handler.applicationList).
-		Param(kapisv1alpha1.DevopsPathParameter).
+		Param(kapisv1alpha1.NamespacePathParameter).
 		Doc("Get the application list").
 		Returns(http.StatusOK, api.StatusOK, v1alpha1.ApplicationList{}))
 
-	service.Route(service.POST("/devops/{devops}/applications").
+	service.Route(service.POST("/namespaces/{namespace}/applications").
 		To(handler.createApplication).
-		Param(kapisv1alpha1.DevopsPathParameter).
+		Param(kapisv1alpha1.NamespacePathParameter).
 		Reads(v1alpha1.Application{}).
 		Doc("Create an application").
 		Returns(http.StatusOK, api.StatusOK, v1alpha1.Application{}))
 
-	service.Route(service.GET("/devops/{devops}/applications/{application}").
+	service.Route(service.GET("/namespaces/{namespace}/applications/{application}").
 		To(handler.getApplication).
-		Param(kapisv1alpha1.DevopsPathParameter).
+		Param(kapisv1alpha1.NamespacePathParameter).
 		Param(pathParameterApplication).
 		Doc("Get a particular application").
 		Returns(http.StatusOK, api.StatusOK, v1alpha1.Application{}))
 
-	service.Route(service.DELETE("/devops/{devops}/applications/{application}").
+	service.Route(service.DELETE("/namespaces/{namespace}/applications/{application}").
 		To(handler.delApplication).
-		Param(kapisv1alpha1.DevopsPathParameter).
+		Param(kapisv1alpha1.NamespacePathParameter).
 		Param(pathParameterApplication).
 		Doc("Delete a particular application").
 		Returns(http.StatusOK, api.StatusOK, v1alpha1.Application{}))
 
-	service.Route(service.PUT("/devops/{devops}/applications/{application}").
+	service.Route(service.PUT("/namespaces/{namespace}/applications/{application}").
 		To(handler.updateApplication).
-		Param(kapisv1alpha1.DevopsPathParameter).
+		Param(kapisv1alpha1.NamespacePathParameter).
 		Param(pathParameterApplication).
 		Reads(v1alpha1.Application{}).
 		Doc("Update a particular application").
diff --git a/pkg/kapis/gitops/v1alpha1/registery.go b/pkg/kapis/gitops/v1alpha1/registery.go
new file mode 100644
index 0000000..e394b6b
--- /dev/null
+++ b/pkg/kapis/gitops/v1alpha1/registery.go
@@ -0,0 +1,38 @@
+/*
+Copyright 2022 The KubeSphere Authors.
+
+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.
+*/
+
+package v1alpha1
+
+import (
+	"github.com/emicklei/go-restful"
+	"kubesphere.io/devops/pkg/api/gitops/v1alpha1"
+	"kubesphere.io/devops/pkg/apiserver/runtime"
+	"kubesphere.io/devops/pkg/kapis/common"
+	"kubesphere.io/devops/pkg/kapis/gitops/v1alpha1/argocd"
+)
+
+// AddToContainer adds web services into web service container.
+func AddToContainer(container *restful.Container, options *common.Options) []*restful.WebService {
+	services := []*restful.WebService{
+		runtime.NewWebService(v1alpha1.GroupVersion),
+		runtime.NewWebServiceWithoutGroup(v1alpha1.GroupVersion),
+	}
+	for _, service := range services {
+		argocd.RegisterRoutes(service, options)
+		container.Add(service)
+	}
+	return services
+}


Test patch:
diff --git a/controllers/argocd/application_controller_test.go b/controllers/argocd/application_controller_test.go
index a063422..31a9f7f 100644
--- a/controllers/argocd/application_controller_test.go
+++ b/controllers/argocd/application_controller_test.go
@@ -24,8 +24,8 @@ import (
 	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
 	"k8s.io/apimachinery/pkg/types"
 	"k8s.io/client-go/tools/record"
-	"kubesphere.io/devops/pkg/api/devops/v1alpha1"
 	"kubesphere.io/devops/pkg/api/devops/v1alpha3"
+	"kubesphere.io/devops/pkg/api/gitops/v1alpha1"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 	"sigs.k8s.io/controller-runtime/pkg/client/fake"
 	"testing"
diff --git a/pkg/api/gitops/v1alpha1/groupversion_info_test.go b/pkg/api/gitops/v1alpha1/groupversion_info_test.go
new file mode 100644
index 0000000..3fa79b3
--- /dev/null
+++ b/pkg/api/gitops/v1alpha1/groupversion_info_test.go
@@ -0,0 +1,45 @@
+/*
+Copyright 2022 The KubeSphere Authors.
+
+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.
+*/
+
+package v1alpha1
+
+import (
+	"github.com/stretchr/testify/assert"
+	"k8s.io/apimachinery/pkg/runtime/schema"
+	"testing"
+)
+
+func TestResource(t *testing.T) {
+	type args struct {
+		resource string
+	}
+	tests := []struct {
+		name string
+		args args
+		want schema.GroupResource
+	}{{
+		name: "normal case",
+		args: args{
+			resource: "application",
+		},
+		want: Resource("application"),
+	}}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			assert.Equalf(t, tt.want, Resource(tt.args.resource), "Resource(%v)", tt.args.resource)
+		})
+	}
+}
diff --git a/pkg/kapis/devops/v1alpha1/register_test.go b/pkg/kapis/devops/v1alpha1/register_test.go
index 5d6a8fa..d72842a 100644
--- a/pkg/kapis/devops/v1alpha1/register_test.go
+++ b/pkg/kapis/devops/v1alpha1/register_test.go
@@ -21,7 +21,7 @@ import (
 	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
 	"k8s.io/client-go/kubernetes/scheme"
 	"kubesphere.io/devops/pkg/api/devops/v1alpha1"
-	"kubesphere.io/devops/pkg/kapis/devops/v1alpha1/common"
+	"kubesphere.io/devops/pkg/kapis/common"
 	"net/http"
 	"net/http/httptest"
 	"sigs.k8s.io/controller-runtime/pkg/client/fake"
diff --git a/pkg/kapis/devops/v1alpha1/template/handler_test.go b/pkg/kapis/devops/v1alpha1/template/handler_test.go
index 2223430..7af182d 100644
--- a/pkg/kapis/devops/v1alpha1/template/handler_test.go
+++ b/pkg/kapis/devops/v1alpha1/template/handler_test.go
@@ -16,7 +16,7 @@ package template
 
 import (
 	"k8s.io/client-go/kubernetes/scheme"
-	kapisv1alpha1 "kubesphere.io/devops/pkg/kapis/devops/v1alpha1/common"
+	kapisv1alpha1 "kubesphere.io/devops/pkg/kapis/common"
 	"reflect"
 	"sigs.k8s.io/controller-runtime/pkg/client/fake"
 	"testing"
diff --git a/pkg/kapis/devops/v1alpha1/template/template_handler_test.go b/pkg/kapis/devops/v1alpha1/template/template_handler_test.go
index 52480e4..d1a130d 100644
--- a/pkg/kapis/devops/v1alpha1/template/template_handler_test.go
+++ b/pkg/kapis/devops/v1alpha1/template/template_handler_test.go
@@ -27,7 +27,7 @@ import (
 	"kubesphere.io/devops/pkg/api/devops"
 	"kubesphere.io/devops/pkg/api/devops/v1alpha1"
 	"kubesphere.io/devops/pkg/api/devops/v1alpha3"
-	kapisv1alpha1 "kubesphere.io/devops/pkg/kapis/devops/v1alpha1/common"
+	kapisv1alpha1 "kubesphere.io/devops/pkg/kapis/common"
 	"net/http"
 	"net/http/httptest"
 	"reflect"
diff --git a/pkg/kapis/devops/v1alpha1/argocd/handler_test.go b/pkg/kapis/gitops/v1alpha1/argocd/handler_test.go
similarity index 89%
rename from pkg/kapis/devops/v1alpha1/argocd/handler_test.go
rename to pkg/kapis/gitops/v1alpha1/argocd/handler_test.go
index 644c067..8e02c37 100644
--- a/pkg/kapis/devops/v1alpha1/argocd/handler_test.go
+++ b/pkg/kapis/gitops/v1alpha1/argocd/handler_test.go
@@ -18,6 +18,7 @@ package argocd
 import (
 	"github.com/emicklei/go-restful"
 	"github.com/stretchr/testify/assert"
+	"kubesphere.io/devops/pkg/kapis/common"
 	"net/http"
 	"testing"
 )
@@ -56,7 +57,7 @@ func Test_getPathParameter(t *testing.T) {
 	}}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			assert.Equalf(t, tt.want, getPathParameter(tt.args.req(), tt.args.param), "getPathParameter(%v, %v)", tt.args.req, tt.args.param)
+			assert.Equalf(t, tt.want, common.GetPathParameter(tt.args.req(), tt.args.param), "getPathParameter(%v, %v)", tt.args.req, tt.args.param)
 		})
 	}
 }
diff --git a/pkg/kapis/devops/v1alpha1/argocd/route_test.go b/pkg/kapis/gitops/v1alpha1/argocd/route_test.go
similarity index 91%
rename from pkg/kapis/devops/v1alpha1/argocd/route_test.go
rename to pkg/kapis/gitops/v1alpha1/argocd/route_test.go
index eae8de9..9437072 100644
--- a/pkg/kapis/devops/v1alpha1/argocd/route_test.go
+++ b/pkg/kapis/gitops/v1alpha1/argocd/route_test.go
@@ -24,10 +24,9 @@ import (
 	v1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
-	"kubesphere.io/devops/pkg/api/devops/v1alpha1"
-	"kubesphere.io/devops/pkg/api/devops/v1alpha3"
+	"kubesphere.io/devops/pkg/api/gitops/v1alpha1"
 	"kubesphere.io/devops/pkg/apiserver/runtime"
-	kapisv1alpha1 "kubesphere.io/devops/pkg/kapis/devops/v1alpha1/common"
+	"kubesphere.io/devops/pkg/kapis/common"
 	"net/http"
 	"net/http/httptest"
 	"sigs.k8s.io/controller-runtime/pkg/client"
@@ -37,12 +36,12 @@ import (
 )
 
 func TestRegisterRoutes(t *testing.T) {
-	schema, err := v1alpha3.SchemeBuilder.Register().Build()
+	schema, err := v1alpha1.SchemeBuilder.Register().Build()
 	assert.Nil(t, err)
 
 	type args struct {
 		service *restful.WebService
-		options *kapisv1alpha1.Options
+		options *common.Options
 	}
 	tests := []struct {
 		name   string
@@ -52,7 +51,7 @@ func TestRegisterRoutes(t *testing.T) {
 		name: "normal case",
 		args: args{
 			service: runtime.NewWebService(v1alpha1.GroupVersion),
-			options: &kapisv1alpha1.Options{GenericClient: fake.NewFakeClientWithScheme(schema)},
+			options: &common.Options{GenericClient: fake.NewFakeClientWithScheme(schema)},
 		},
 		verify: func(t *testing.T, service *restful.WebService) {
 			assert.Equal(t, 6, len(service.Routes()))
@@ -126,7 +125,7 @@ func TestAPIs(t *testing.T) {
 		name: "get an empty list of the applications",
 		request: request{
 			method: http.MethodGet,
-			uri:    "/devops/fake/applications",
+			uri:    "/namespaces/fake/applications",
 		},
 		k8sclient:    fake.NewFakeClientWithScheme(schema),
 		responseCode: http.StatusOK,
@@ -143,7 +142,7 @@ func TestAPIs(t *testing.T) {
 		name: "get a normal list of the applications",
 		request: request{
 			method: http.MethodGet,
-			uri:    "/devops/ns/applications",
+			uri:    "/namespaces/ns/applications",
 		},
 		k8sclient:    fake.NewFakeClientWithScheme(schema, app.DeepCopy()),
 		responseCode: http.StatusOK,
@@ -160,7 +159,7 @@ func TestAPIs(t *testing.T) {
 		name: "get a normal application",
 		request: request{
 			method: http.MethodGet,
-			uri:    "/devops/ns/applications/app",
+			uri:    "/namespaces/ns/applications/app",
 		},
 		k8sclient:    fake.NewFakeClientWithScheme(schema, app.DeepCopy()),
 		responseCode: http.StatusOK,
@@ -177,7 +176,7 @@ func TestAPIs(t *testing.T) {
 		name: "delete an application",
 		request: request{
 			method: http.MethodDelete,
-			uri:    "/devops/ns/applications/app",
+			uri:    "/namespaces/ns/applications/app",
 		},
 		k8sclient:    fake.NewFakeClientWithScheme(schema, app.DeepCopy()),
 		responseCode: http.StatusOK,
@@ -194,7 +193,7 @@ func TestAPIs(t *testing.T) {
 		name: "create an application",
 		request: request{
 			method: http.MethodPost,
-			uri:    "/devops/ns/applications",
+			uri:    "/namespaces/ns/applications",
 			body: func() io.Reader {
 				return bytes.NewBuffer([]byte(`{
   "apiVersion": "devops.kubesphere.io/v1alpha1",
@@ -225,7 +224,7 @@ func TestAPIs(t *testing.T) {
 		name: "create an application, invalid payload",
 		request: request{
 			method: http.MethodPost,
-			uri:    "/devops/ns/applications",
+			uri:    "/namespaces/ns/applications",
 			body: func() io.Reader {
 				return bytes.NewBuffer([]byte(`fake`))
 			},
@@ -236,7 +235,7 @@ func TestAPIs(t *testing.T) {
 		name: "update an application",
 		request: request{
 			method: http.MethodPut,
-			uri:    "/devops/ns/applications/app",
+			uri:    "/namespaces/ns/applications/app",
 			body: func() io.Reader {
 				return bytes.NewBuffer([]byte(`{
   "apiVersion": "devops.kubesphere.io/v1alpha1",
@@ -306,12 +305,12 @@ func TestAPIs(t *testing.T) {
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			wsWithGroup := runtime.NewWebService(v1alpha1.GroupVersion)
-			RegisterRoutes(wsWithGroup, &kapisv1alpha1.Options{GenericClient: tt.k8sclient})
+			RegisterRoutes(wsWithGroup, &common.Options{GenericClient: tt.k8sclient})
 
 			container := restful.NewContainer()
 			container.Add(wsWithGroup)
 
-			api := fmt.Sprintf("http://fake.com/kapis/devops.kubesphere.io/%s%s", v1alpha1.GroupVersion.Version, tt.request.uri)
+			api := fmt.Sprintf("http://fake.com/kapis/gitops.kubesphere.io/%s%s", v1alpha1.GroupVersion.Version, tt.request.uri)
 			var body io.Reader
 			if tt.request.body != nil {
 				body = tt.request.body()