From 9543d09d6bbf5011df6319a0cc92b1cb3f389776 Mon Sep 17 00:00:00 2001
From: Daniel Hu <tao.hu@merico.dev>
Date: Thu, 29 Sep 2022 11:49:46 +0800
Subject: [PATCH 1/6] feat: update plugin templates with new scaffolding

Signed-off-by: Daniel Hu <tao.hu@merico.dev>
---
 .../{NAME_plugin.md.tpl => NAME.md.tpl}       |  0
 .../{NAME_plugin.zh.md.tpl => NAME.zh.md.tpl} |  0
 .../{NAME_plugin.md.go => NAME_md.go}         |  2 +-
 .../{NAME_plugin.zh.md.go => NAME_zh_md.go}   |  2 +-
 .../pkg/develop/plugin/template/create.go     | 39 +++++++++++--------
 .../pkg/develop/plugin/template/delete.go     | 31 +++++++--------
 .../pkg/develop/plugin/template/options.go    | 15 +++++++
 internal/pkg/develop/plugin/template/read.go  | 33 ++++++++--------
 .../pkg/develop/plugin/template/update.go     | 39 +++++++++++--------
 .../pkg/develop/plugin/template/validate.go   | 24 ++++++++++--
 10 files changed, 115 insertions(+), 70 deletions(-)
 rename internal/pkg/develop/plugin/template/{NAME_plugin.md.tpl => NAME.md.tpl} (100%)
 rename internal/pkg/develop/plugin/template/{NAME_plugin.zh.md.tpl => NAME.zh.md.tpl} (100%)
 rename internal/pkg/develop/plugin/template/{NAME_plugin.md.go => NAME_md.go} (91%)
 rename internal/pkg/develop/plugin/template/{NAME_plugin.zh.md.go => NAME_zh_md.go} (91%)

diff --git a/internal/pkg/develop/plugin/template/NAME_plugin.md.tpl b/internal/pkg/develop/plugin/template/NAME.md.tpl
similarity index 100%
rename from internal/pkg/develop/plugin/template/NAME_plugin.md.tpl
rename to internal/pkg/develop/plugin/template/NAME.md.tpl
diff --git a/internal/pkg/develop/plugin/template/NAME_plugin.zh.md.tpl b/internal/pkg/develop/plugin/template/NAME.zh.md.tpl
similarity index 100%
rename from internal/pkg/develop/plugin/template/NAME_plugin.zh.md.tpl
rename to internal/pkg/develop/plugin/template/NAME.zh.md.tpl
diff --git a/internal/pkg/develop/plugin/template/NAME_plugin.md.go b/internal/pkg/develop/plugin/template/NAME_md.go
similarity index 91%
rename from internal/pkg/develop/plugin/template/NAME_plugin.md.go
rename to internal/pkg/develop/plugin/template/NAME_md.go
index 1b2f4c6c0..60ca9e3b5 100644
--- a/internal/pkg/develop/plugin/template/NAME_plugin.md.go
+++ b/internal/pkg/develop/plugin/template/NAME_md.go
@@ -5,7 +5,7 @@ import _ "embed"
 var NamePluginMdNameTpl = "[[ .Name ]].md"
 var NamePluginMdDirTpl = "docs/plugins/"
 
-//go:embed NAME_plugin.md.tpl
+//go:embed NAME.md.tpl
 var NamePluginMdContentTpl string
 
 func init() {
diff --git a/internal/pkg/develop/plugin/template/NAME_plugin.zh.md.go b/internal/pkg/develop/plugin/template/NAME_zh_md.go
similarity index 91%
rename from internal/pkg/develop/plugin/template/NAME_plugin.zh.md.go
rename to internal/pkg/develop/plugin/template/NAME_zh_md.go
index 1b33efadb..6b10cbec9 100644
--- a/internal/pkg/develop/plugin/template/NAME_plugin.zh.md.go
+++ b/internal/pkg/develop/plugin/template/NAME_zh_md.go
@@ -5,7 +5,7 @@ import _ "embed"
 var NamePluginZhMdNameTpl = "[[ .Name ]].zh.md"
 var NamePluginZhMdDirTpl = "docs/plugins/"
 
-//go:embed NAME_plugin.zh.md.tpl
+//go:embed NAME.zh.md.tpl
 var NamePluginZhMdContentTpl string
 
 func init() {
diff --git a/internal/pkg/develop/plugin/template/create.go b/internal/pkg/develop/plugin/template/create.go
index b124699e4..5417ed8e6 100644
--- a/internal/pkg/develop/plugin/template/create.go
+++ b/internal/pkg/develop/plugin/template/create.go
@@ -5,29 +5,36 @@ var createGoDirTpl = "internal/pkg/plugin/[[ .Name | dirFormat ]]/"
 var createGoContentTpl = `package [[ .Name | format ]]
 
 import (
-	"fmt"
-
-	"github.com/mitchellh/mapstructure"
-
+	"github.com/devstream-io/devstream/internal/pkg/plugininstaller"
+	"github.com/devstream-io/devstream/internal/pkg/statemanager"
 	"github.com/devstream-io/devstream/pkg/util/log"
 )
 
 func Create(options map[string]interface{}) (map[string]interface{}, error) {
-	var opts Options
-	if err := mapstructure.Decode(options, &opts); err != nil {
-		return nil, err
+	// Initialize Operator with Operations
+	operator := &plugininstaller.Operator{
+		PreExecuteOperations: plugininstaller.PreExecuteOperations{
+			// TODO(dtm): Add your PreExecuteOperations here.
+		},
+		ExecuteOperations: plugininstaller.ExecuteOperations{
+			// TODO(dtm): Add your ExecuteOperations here.
+		},
+		TerminateOperations: plugininstaller.TerminateOperations{
+			// TODO(dtm): Add your TerminateOperations here.
+		},
+		GetStateOperation: func(options plugininstaller.RawOptions) (statemanager.ResourceState, error) {
+			// TODO(dtm): Add your GetStateOperation here.
+			return nil, nil
+		},
 	}
 
-	if errs := validate(&opts); len(errs) != 0 {
-		for _, e := range errs {
-			log.Errorf("Options error: %s.", e)
-		}
-		return nil, fmt.Errorf("opts are illegal")
+	// Execute all Operations in Operator
+	status, err := operator.Execute(plugininstaller.RawOptions(options))
+	if err != nil {
+		return nil, err
 	}
-
-    // TODO(dtm): Add your logic here.
-
-    return nil, nil
+	log.Debugf("Return map: %v", status)
+	return status, nil
 }
 `
 var create_go_mustExistFlag = true
diff --git a/internal/pkg/develop/plugin/template/delete.go b/internal/pkg/develop/plugin/template/delete.go
index 78c19766b..812c5db21 100644
--- a/internal/pkg/develop/plugin/template/delete.go
+++ b/internal/pkg/develop/plugin/template/delete.go
@@ -5,29 +5,26 @@ var deleteGoDirTpl = "internal/pkg/plugin/[[ .Name | dirFormat ]]/"
 var deleteGoContentTpl = `package [[ .Name | format ]]
 
 import (
-	"fmt"
-
-	"github.com/mitchellh/mapstructure"
-
-	"github.com/devstream-io/devstream/pkg/util/log"
+	"github.com/devstream-io/devstream/internal/pkg/plugininstaller"
 )
 
 func Delete(options map[string]interface{}) (bool, error) {
-	var opts Options
-	if err := mapstructure.Decode(options, &opts); err != nil {
-		return false, err
+	// Initialize Operator with Operations
+	operator := &plugininstaller.Operator{
+		PreExecuteOperations: plugininstaller.PreExecuteOperations{
+			// TODO(dtm): Add your PreExecuteOperations here.
+		},
+		ExecuteOperations: plugininstaller.ExecuteOperations{
+			// TODO(dtm): Add your ExecuteOperations here.
+		},
 	}
-
-	if errs := validate(&opts); len(errs) != 0 {
-		for _, e := range errs {
-			log.Errorf("Options error: %s.", e)
-		}
-		return false, fmt.Errorf("opts are illegal")
+	_, err := operator.Execute(plugininstaller.RawOptions(options))
+	if err != nil {
+		return false, err
 	}
 
-	// TODO(dtm): Add your logic here.
-
-    return false, nil
+	// 2. return ture if all process success
+	return true, nil
 }
 `
 
diff --git a/internal/pkg/develop/plugin/template/options.go b/internal/pkg/develop/plugin/template/options.go
index 2d793d60c..d806592ee 100644
--- a/internal/pkg/develop/plugin/template/options.go
+++ b/internal/pkg/develop/plugin/template/options.go
@@ -4,11 +4,26 @@ var optionsGoNameTpl = "options.go"
 var optionsGoDirTpl = "internal/pkg/plugin/[[ .Name | dirFormat ]]/"
 var optionsGoContentTpl = `package [[ .Name | format ]]
 
+import (
+	"github.com/mitchellh/mapstructure"
+
+	"github.com/devstream-io/devstream/internal/pkg/plugininstaller"
+)
+
 // Options is the struct for configurations of the [[ .Name ]] plugin.
 type Options struct {
     // TODO(dtm): Add your params here.
 	Foo string
 }
+
+// NewOptions create options by raw options
+func NewOptions(options plugininstaller.RawOptions) (Options, error) {
+	var opts Options
+	if err := mapstructure.Decode(options, &opts); err != nil {
+		return opts, err
+	}
+	return opts, nil
+}
 `
 
 func init() {
diff --git a/internal/pkg/develop/plugin/template/read.go b/internal/pkg/develop/plugin/template/read.go
index 64720a72b..bc4905036 100644
--- a/internal/pkg/develop/plugin/template/read.go
+++ b/internal/pkg/develop/plugin/template/read.go
@@ -5,29 +5,30 @@ var readGoDirTpl = "internal/pkg/plugin/[[ .Name | dirFormat ]]/"
 var readGoContentTpl = `package [[ .Name | format ]]
 
 import (
-	"fmt"
-
-	"github.com/mitchellh/mapstructure"
-
+	"github.com/devstream-io/devstream/internal/pkg/plugininstaller"
+	"github.com/devstream-io/devstream/internal/pkg/statemanager"
 	"github.com/devstream-io/devstream/pkg/util/log"
 )
 
 func Read(options map[string]interface{}) (map[string]interface{}, error) {
-	var opts Options
-	if err := mapstructure.Decode(options, &opts); err != nil {
-		return nil, err
+	// Initialize Operator with Operations
+	operator := &plugininstaller.Operator{
+		PreExecuteOperations: plugininstaller.PreExecuteOperations{
+			// TODO(dtm): Add your PreExecuteOperations here.
+		},
+		GetStateOperation: func(options plugininstaller.RawOptions) (statemanager.ResourceState, error) {
+			// TODO(dtm): Add your GetStateOperation here.
+			return nil, nil
+		},
 	}
 
-	if errs := validate(&opts); len(errs) != 0 {
-		for _, e := range errs {
-			log.Errorf("Options error: %s.", e)
-		}
-		return nil, fmt.Errorf("opts are illegal")
+	// Execute all Operations in Operator
+	status, err := operator.Execute(plugininstaller.RawOptions(options))
+	if err != nil {
+		return nil, err
 	}
-
-    // TODO(dtm): Add your logic here.
-
-    return nil, nil
+	log.Debugf("Return map: %v", status)
+	return status, nil
 }
 `
 
diff --git a/internal/pkg/develop/plugin/template/update.go b/internal/pkg/develop/plugin/template/update.go
index 16ce360ff..7f338984b 100644
--- a/internal/pkg/develop/plugin/template/update.go
+++ b/internal/pkg/develop/plugin/template/update.go
@@ -5,29 +5,36 @@ var updateGoDirTpl = "internal/pkg/plugin/[[ .Name | dirFormat ]]/"
 var updateGoContentTpl = `package [[ .Name | format ]]
 
 import (
-	"fmt"
-
-	"github.com/mitchellh/mapstructure"
-
+	"github.com/devstream-io/devstream/internal/pkg/plugininstaller"
+	"github.com/devstream-io/devstream/internal/pkg/statemanager"
 	"github.com/devstream-io/devstream/pkg/util/log"
 )
 
 func Update(options map[string]interface{}) (map[string]interface{}, error) {
-	var opts Options
-	if err := mapstructure.Decode(options, &opts); err != nil {
-		return nil, err
+	// Initialize Operator with Operations
+	operator := &plugininstaller.Operator{
+		PreExecuteOperations: plugininstaller.PreExecuteOperations{
+			// TODO(dtm): Add your PreExecuteOperations here.
+		},
+		ExecuteOperations: plugininstaller.ExecuteOperations{
+			// TODO(dtm): Add your ExecuteOperations here.
+		},
+		TerminateOperations: plugininstaller.TerminateOperations{
+			// TODO(dtm): Add your TerminateOperations here.
+		},
+		GetStateOperation: func(options plugininstaller.RawOptions) (statemanager.ResourceState, error) {
+			// TODO(dtm): Add your GetStateOperation here.
+			return nil, nil
+		},
 	}
 
-	if errs := validate(&opts); len(errs) != 0 {
-		for _, e := range errs {
-			log.Errorf("Options error: %s.", e)
-		}
-		return nil, fmt.Errorf("opts are illegal")
+	// Execute all Operations in Operator
+	status, err := operator.Execute(plugininstaller.RawOptions(options))
+	if err != nil {
+		return nil, err
 	}
-
-    // TODO(dtm): Add your logic here.
-
-    return nil, nil
+	log.Debugf("Return map: %v", status)
+	return status, nil
 }
 `
 
diff --git a/internal/pkg/develop/plugin/template/validate.go b/internal/pkg/develop/plugin/template/validate.go
index ff938e5a1..99ddd5bab 100644
--- a/internal/pkg/develop/plugin/template/validate.go
+++ b/internal/pkg/develop/plugin/template/validate.go
@@ -4,10 +4,28 @@ var validateGoNameTpl = "validate.go"
 var validateGoDirTpl = "internal/pkg/plugin/[[ .Name | dirFormat ]]/"
 var validateGoContentTpl = `package [[ .Name | format ]]
 
+import (
+	"fmt"
+
+	"github.com/devstream-io/devstream/internal/pkg/plugininstaller"
+	"github.com/devstream-io/devstream/pkg/util/log"
+	"github.com/devstream-io/devstream/pkg/util/validator"
+)
+
 // validate validates the options provided by the core.
-func validate(options *Options) []error {
-    // TODO(dtm): Add your logic here.
-	return make([]error, 0)
+func validate(options plugininstaller.RawOptions) (plugininstaller.RawOptions, error) {
+	opts, err := NewOptions(options)
+	if err != nil {
+		return nil, err
+	}
+	errs := validator.Struct(opts)
+	if len(errs) > 0 {
+		for _, e := range errs {
+			log.Errorf("Options error: %s.", e)
+		}
+		return nil, fmt.Errorf("opts are illegal")
+	}
+	return options, nil
 }
 `
 

From 4445334f6ff985822c86d78286f8a58ff19a3f5d Mon Sep 17 00:00:00 2001
From: Daniel Hu <tao.hu@merico.dev>
Date: Thu, 29 Sep 2022 12:13:28 +0800
Subject: [PATCH 2/6] feat: plugin scaffold for apache-devlake

Signed-off-by: Daniel Hu <tao.hu@merico.dev>
---
 cmd/plugin/apache-devlake/main.go             | 39 +++++++++++++++++++
 docs/plugins/apache-devlake.md                |  9 +++++
 docs/plugins/apache-devlake.zh.md             |  9 +++++
 .../pkg/plugin/apachedevlake/apachedevlake.go |  3 ++
 internal/pkg/plugin/apachedevlake/create.go   | 34 ++++++++++++++++
 internal/pkg/plugin/apachedevlake/delete.go   | 24 ++++++++++++
 internal/pkg/plugin/apachedevlake/options.go  | 22 +++++++++++
 internal/pkg/plugin/apachedevlake/read.go     | 28 +++++++++++++
 internal/pkg/plugin/apachedevlake/update.go   | 34 ++++++++++++++++
 internal/pkg/plugin/apachedevlake/validate.go | 25 ++++++++++++
 .../show/config/plugins/apache-devlake.yaml   | 10 +++++
 11 files changed, 237 insertions(+)
 create mode 100644 cmd/plugin/apache-devlake/main.go
 create mode 100644 docs/plugins/apache-devlake.md
 create mode 100644 docs/plugins/apache-devlake.zh.md
 create mode 100644 internal/pkg/plugin/apachedevlake/apachedevlake.go
 create mode 100644 internal/pkg/plugin/apachedevlake/create.go
 create mode 100644 internal/pkg/plugin/apachedevlake/delete.go
 create mode 100644 internal/pkg/plugin/apachedevlake/options.go
 create mode 100644 internal/pkg/plugin/apachedevlake/read.go
 create mode 100644 internal/pkg/plugin/apachedevlake/update.go
 create mode 100644 internal/pkg/plugin/apachedevlake/validate.go
 create mode 100644 internal/pkg/show/config/plugins/apache-devlake.yaml

diff --git a/cmd/plugin/apache-devlake/main.go b/cmd/plugin/apache-devlake/main.go
new file mode 100644
index 000000000..79e99eb54
--- /dev/null
+++ b/cmd/plugin/apache-devlake/main.go
@@ -0,0 +1,39 @@
+package main
+
+import (
+	"github.com/devstream-io/devstream/internal/pkg/plugin/apachedevlake"
+	"github.com/devstream-io/devstream/pkg/util/log"
+)
+
+// NAME is the name of this DevStream plugin.
+const NAME = "apache-devlake"
+
+// Plugin is the type used by DevStream core. It's a string.
+type Plugin string
+
+// Create implements the create of apache-devlake.
+func (p Plugin) Create(options map[string]interface{}) (map[string]interface{}, error) {
+	return apachedevlake.Create(options)
+}
+
+// Update implements the update of apache-devlake.
+func (p Plugin) Update(options map[string]interface{}) (map[string]interface{}, error) {
+	return apachedevlake.Update(options)
+}
+
+// Delete implements the delete of apache-devlake.
+func (p Plugin) Delete(options map[string]interface{}) (bool, error) {
+	return apachedevlake.Delete(options)
+}
+
+// Read implements the read of apache-devlake.
+func (p Plugin) Read(options map[string]interface{}) (map[string]interface{}, error) {
+	return apachedevlake.Read(options)
+}
+
+// DevStreamPlugin is the exported variable used by the DevStream core.
+var DevStreamPlugin Plugin
+
+func main() {
+	log.Infof("%T: %s is a plugin for DevStream. Use it with DevStream.\n", DevStreamPlugin, NAME)
+}
diff --git a/docs/plugins/apache-devlake.md b/docs/plugins/apache-devlake.md
new file mode 100644
index 000000000..a01a29148
--- /dev/null
+++ b/docs/plugins/apache-devlake.md
@@ -0,0 +1,9 @@
+# apache-devlake plugin
+
+TODO(dtm): Add your document here.
+
+## Usage
+
+``` yaml
+--8<-- "apache-devlake.yaml"
+```
diff --git a/docs/plugins/apache-devlake.zh.md b/docs/plugins/apache-devlake.zh.md
new file mode 100644
index 000000000..f093d6104
--- /dev/null
+++ b/docs/plugins/apache-devlake.zh.md
@@ -0,0 +1,9 @@
+# apache-devlake 插件
+
+TODO(dtm): 在这里添加文档.
+
+## 用例
+
+``` yaml
+--8<-- "apache-devlake.yaml"
+```
diff --git a/internal/pkg/plugin/apachedevlake/apachedevlake.go b/internal/pkg/plugin/apachedevlake/apachedevlake.go
new file mode 100644
index 000000000..da0f0ea50
--- /dev/null
+++ b/internal/pkg/plugin/apachedevlake/apachedevlake.go
@@ -0,0 +1,3 @@
+package apachedevlake
+
+// TODO(dtm): Add your logic here.
diff --git a/internal/pkg/plugin/apachedevlake/create.go b/internal/pkg/plugin/apachedevlake/create.go
new file mode 100644
index 000000000..7b966837f
--- /dev/null
+++ b/internal/pkg/plugin/apachedevlake/create.go
@@ -0,0 +1,34 @@
+package apachedevlake
+
+import (
+	"github.com/devstream-io/devstream/internal/pkg/plugininstaller"
+	"github.com/devstream-io/devstream/internal/pkg/statemanager"
+	"github.com/devstream-io/devstream/pkg/util/log"
+)
+
+func Create(options map[string]interface{}) (map[string]interface{}, error) {
+	// Initialize Operator with Operations
+	operator := &plugininstaller.Operator{
+		PreExecuteOperations: plugininstaller.PreExecuteOperations{
+			// TODO(dtm): Add your PreExecuteOperations here.
+		},
+		ExecuteOperations: plugininstaller.ExecuteOperations{
+			// TODO(dtm): Add your ExecuteOperations here.
+		},
+		TerminateOperations: plugininstaller.TerminateOperations{
+			// TODO(dtm): Add your TerminateOperations here.
+		},
+		GetStateOperation: func(options plugininstaller.RawOptions) (statemanager.ResourceState, error) {
+			// TODO(dtm): Add your GetStateOperation here.
+			return nil, nil
+		},
+	}
+
+	// Execute all Operations in Operator
+	status, err := operator.Execute(plugininstaller.RawOptions(options))
+	if err != nil {
+		return nil, err
+	}
+	log.Debugf("Return map: %v", status)
+	return status, nil
+}
diff --git a/internal/pkg/plugin/apachedevlake/delete.go b/internal/pkg/plugin/apachedevlake/delete.go
new file mode 100644
index 000000000..76ad170db
--- /dev/null
+++ b/internal/pkg/plugin/apachedevlake/delete.go
@@ -0,0 +1,24 @@
+package apachedevlake
+
+import (
+	"github.com/devstream-io/devstream/internal/pkg/plugininstaller"
+)
+
+func Delete(options map[string]interface{}) (bool, error) {
+	// Initialize Operator with Operations
+	operator := &plugininstaller.Operator{
+		PreExecuteOperations: plugininstaller.PreExecuteOperations{
+			// TODO(dtm): Add your PreExecuteOperations here.
+		},
+		ExecuteOperations: plugininstaller.ExecuteOperations{
+			// TODO(dtm): Add your ExecuteOperations here.
+		},
+	}
+	_, err := operator.Execute(plugininstaller.RawOptions(options))
+	if err != nil {
+		return false, err
+	}
+
+	// 2. return ture if all process success
+	return true, nil
+}
diff --git a/internal/pkg/plugin/apachedevlake/options.go b/internal/pkg/plugin/apachedevlake/options.go
new file mode 100644
index 000000000..1c199493e
--- /dev/null
+++ b/internal/pkg/plugin/apachedevlake/options.go
@@ -0,0 +1,22 @@
+package apachedevlake
+
+import (
+	"github.com/mitchellh/mapstructure"
+
+	"github.com/devstream-io/devstream/internal/pkg/plugininstaller"
+)
+
+// Options is the struct for configurations of the apache-devlake plugin.
+type Options struct {
+	// TODO(dtm): Add your params here.
+	Foo string
+}
+
+// NewOptions create options by raw options
+func NewOptions(options plugininstaller.RawOptions) (Options, error) {
+	var opts Options
+	if err := mapstructure.Decode(options, &opts); err != nil {
+		return opts, err
+	}
+	return opts, nil
+}
diff --git a/internal/pkg/plugin/apachedevlake/read.go b/internal/pkg/plugin/apachedevlake/read.go
new file mode 100644
index 000000000..5bb7edd14
--- /dev/null
+++ b/internal/pkg/plugin/apachedevlake/read.go
@@ -0,0 +1,28 @@
+package apachedevlake
+
+import (
+	"github.com/devstream-io/devstream/internal/pkg/plugininstaller"
+	"github.com/devstream-io/devstream/internal/pkg/statemanager"
+	"github.com/devstream-io/devstream/pkg/util/log"
+)
+
+func Read(options map[string]interface{}) (map[string]interface{}, error) {
+	// Initialize Operator with Operations
+	operator := &plugininstaller.Operator{
+		PreExecuteOperations: plugininstaller.PreExecuteOperations{
+			// TODO(dtm): Add your PreExecuteOperations here.
+		},
+		GetStateOperation: func(options plugininstaller.RawOptions) (statemanager.ResourceState, error) {
+			// TODO(dtm): Add your GetStateOperation here.
+			return nil, nil
+		},
+	}
+
+	// Execute all Operations in Operator
+	status, err := operator.Execute(plugininstaller.RawOptions(options))
+	if err != nil {
+		return nil, err
+	}
+	log.Debugf("Return map: %v", status)
+	return status, nil
+}
diff --git a/internal/pkg/plugin/apachedevlake/update.go b/internal/pkg/plugin/apachedevlake/update.go
new file mode 100644
index 000000000..e89f3220e
--- /dev/null
+++ b/internal/pkg/plugin/apachedevlake/update.go
@@ -0,0 +1,34 @@
+package apachedevlake
+
+import (
+	"github.com/devstream-io/devstream/internal/pkg/plugininstaller"
+	"github.com/devstream-io/devstream/internal/pkg/statemanager"
+	"github.com/devstream-io/devstream/pkg/util/log"
+)
+
+func Update(options map[string]interface{}) (map[string]interface{}, error) {
+	// Initialize Operator with Operations
+	operator := &plugininstaller.Operator{
+		PreExecuteOperations: plugininstaller.PreExecuteOperations{
+			// TODO(dtm): Add your PreExecuteOperations here.
+		},
+		ExecuteOperations: plugininstaller.ExecuteOperations{
+			// TODO(dtm): Add your ExecuteOperations here.
+		},
+		TerminateOperations: plugininstaller.TerminateOperations{
+			// TODO(dtm): Add your TerminateOperations here.
+		},
+		GetStateOperation: func(options plugininstaller.RawOptions) (statemanager.ResourceState, error) {
+			// TODO(dtm): Add your GetStateOperation here.
+			return nil, nil
+		},
+	}
+
+	// Execute all Operations in Operator
+	status, err := operator.Execute(plugininstaller.RawOptions(options))
+	if err != nil {
+		return nil, err
+	}
+	log.Debugf("Return map: %v", status)
+	return status, nil
+}
diff --git a/internal/pkg/plugin/apachedevlake/validate.go b/internal/pkg/plugin/apachedevlake/validate.go
new file mode 100644
index 000000000..da1f2f387
--- /dev/null
+++ b/internal/pkg/plugin/apachedevlake/validate.go
@@ -0,0 +1,25 @@
+package apachedevlake
+
+import (
+	"fmt"
+
+	"github.com/devstream-io/devstream/internal/pkg/plugininstaller"
+	"github.com/devstream-io/devstream/pkg/util/log"
+	"github.com/devstream-io/devstream/pkg/util/validator"
+)
+
+// validate validates the options provided by the core.
+func validate(options plugininstaller.RawOptions) (plugininstaller.RawOptions, error) {
+	opts, err := NewOptions(options)
+	if err != nil {
+		return nil, err
+	}
+	errs := validator.Struct(opts)
+	if len(errs) > 0 {
+		for _, e := range errs {
+			log.Errorf("Options error: %s.", e)
+		}
+		return nil, fmt.Errorf("opts are illegal")
+	}
+	return options, nil
+}
diff --git a/internal/pkg/show/config/plugins/apache-devlake.yaml b/internal/pkg/show/config/plugins/apache-devlake.yaml
new file mode 100644
index 000000000..f162a0595
--- /dev/null
+++ b/internal/pkg/show/config/plugins/apache-devlake.yaml
@@ -0,0 +1,10 @@
+tools:
+# name of the tool
+- name: apache-devlake
+  # id of the tool instance
+  instanceID: default
+  # format: name.instanceID; If specified, dtm will make sure the dependency is applied first before handling this tool.
+  dependsOn: [ ]
+  # options for the plugin
+  options:
+  # TODO(dtm): Add your default config here.

From 9c95ac786351683715966fa55d351e1ad2001c7e Mon Sep 17 00:00:00 2001
From: Daniel Hu <tao.hu@merico.dev>
Date: Thu, 29 Sep 2022 12:57:07 +0800
Subject: [PATCH 3/6] chore: fix comments in plugin template

Signed-off-by: Daniel Hu <tao.hu@merico.dev>
---
 internal/pkg/develop/plugin/template/delete.go | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/internal/pkg/develop/plugin/template/delete.go b/internal/pkg/develop/plugin/template/delete.go
index 812c5db21..ae1f9f94d 100644
--- a/internal/pkg/develop/plugin/template/delete.go
+++ b/internal/pkg/develop/plugin/template/delete.go
@@ -18,12 +18,13 @@ func Delete(options map[string]interface{}) (bool, error) {
 			// TODO(dtm): Add your ExecuteOperations here.
 		},
 	}
+
+	// Execute all Operations in Operator
 	_, err := operator.Execute(plugininstaller.RawOptions(options))
 	if err != nil {
 		return false, err
 	}
 
-	// 2. return ture if all process success
 	return true, nil
 }
 `

From 6ddc8a6f9bad90a9202f27421cafcfab3c55d59b Mon Sep 17 00:00:00 2001
From: Daniel Hu <tao.hu@merico.dev>
Date: Thu, 29 Sep 2022 13:06:50 +0800
Subject: [PATCH 4/6] feat: implement apache-devlake plugin with helm

Signed-off-by: Daniel Hu <tao.hu@merico.dev>
---
 docs/plugins/apache-devlake.md                |  2 +-
 docs/plugins/apache-devlake.zh.md             |  2 +-
 .../pkg/plugin/apachedevlake/apachedevlake.go | 23 +++++++++++++++-
 internal/pkg/plugin/apachedevlake/create.go   | 18 +++++--------
 internal/pkg/plugin/apachedevlake/delete.go   | 11 ++++----
 internal/pkg/plugin/apachedevlake/options.go  | 22 ----------------
 internal/pkg/plugin/apachedevlake/read.go     | 10 +++----
 internal/pkg/plugin/apachedevlake/update.go   | 17 ++++--------
 internal/pkg/plugin/apachedevlake/validate.go | 25 ------------------
 internal/pkg/show/config/embed_gen.go         |  4 +++
 .../show/config/plugins/apache-devlake.yaml   | 26 ++++++++++++++++++-
 11 files changed, 74 insertions(+), 86 deletions(-)
 delete mode 100644 internal/pkg/plugin/apachedevlake/options.go
 delete mode 100644 internal/pkg/plugin/apachedevlake/validate.go

diff --git a/docs/plugins/apache-devlake.md b/docs/plugins/apache-devlake.md
index a01a29148..3c4325de0 100644
--- a/docs/plugins/apache-devlake.md
+++ b/docs/plugins/apache-devlake.md
@@ -1,6 +1,6 @@
 # apache-devlake plugin
 
-TODO(dtm): Add your document here.
+//TODO(daniel-hutao): add document here after Chinese version be ready.
 
 ## Usage
 
diff --git a/docs/plugins/apache-devlake.zh.md b/docs/plugins/apache-devlake.zh.md
index f093d6104..5f272040c 100644
--- a/docs/plugins/apache-devlake.zh.md
+++ b/docs/plugins/apache-devlake.zh.md
@@ -1,6 +1,6 @@
 # apache-devlake 插件
 
-TODO(dtm): 在这里添加文档.
+//TODO(daniel-hutao): 本插件出于开发中状态。
 
 ## 用例
 
diff --git a/internal/pkg/plugin/apachedevlake/apachedevlake.go b/internal/pkg/plugin/apachedevlake/apachedevlake.go
index da0f0ea50..7178c657e 100644
--- a/internal/pkg/plugin/apachedevlake/apachedevlake.go
+++ b/internal/pkg/plugin/apachedevlake/apachedevlake.go
@@ -1,3 +1,24 @@
 package apachedevlake
 
-// TODO(dtm): Add your logic here.
+import (
+	"github.com/devstream-io/devstream/internal/pkg/plugininstaller/helm"
+	helmCommon "github.com/devstream-io/devstream/pkg/util/helm"
+	"github.com/devstream-io/devstream/pkg/util/types"
+)
+
+// TODO(daniel-hutao): update the config below after devlake chart released.
+var defaultHelmConfig = helm.Options{
+	Chart: helmCommon.Chart{
+		ChartPath:   "",
+		ChartName:   "apache-devlake/devlake",
+		Timeout:     "5m",
+		Wait:        types.Bool(true),
+		UpgradeCRDs: types.Bool(true),
+		ReleaseName: "devlake",
+		Namespace:   "devlake",
+	},
+	Repo: helmCommon.Repo{
+		URL:  "https://apache-devlake.github.io/apache-devlake-helm",
+		Name: "apache-devlake",
+	},
+}
diff --git a/internal/pkg/plugin/apachedevlake/create.go b/internal/pkg/plugin/apachedevlake/create.go
index 7b966837f..8dd084a16 100644
--- a/internal/pkg/plugin/apachedevlake/create.go
+++ b/internal/pkg/plugin/apachedevlake/create.go
@@ -2,7 +2,7 @@ package apachedevlake
 
 import (
 	"github.com/devstream-io/devstream/internal/pkg/plugininstaller"
-	"github.com/devstream-io/devstream/internal/pkg/statemanager"
+	"github.com/devstream-io/devstream/internal/pkg/plugininstaller/helm"
 	"github.com/devstream-io/devstream/pkg/util/log"
 )
 
@@ -10,18 +10,12 @@ func Create(options map[string]interface{}) (map[string]interface{}, error) {
 	// Initialize Operator with Operations
 	operator := &plugininstaller.Operator{
 		PreExecuteOperations: plugininstaller.PreExecuteOperations{
-			// TODO(dtm): Add your PreExecuteOperations here.
-		},
-		ExecuteOperations: plugininstaller.ExecuteOperations{
-			// TODO(dtm): Add your ExecuteOperations here.
-		},
-		TerminateOperations: plugininstaller.TerminateOperations{
-			// TODO(dtm): Add your TerminateOperations here.
-		},
-		GetStateOperation: func(options plugininstaller.RawOptions) (statemanager.ResourceState, error) {
-			// TODO(dtm): Add your GetStateOperation here.
-			return nil, nil
+			helm.SetDefaultConfig(&defaultHelmConfig),
+			helm.Validate,
 		},
+		ExecuteOperations:   helm.DefaultCreateOperations,
+		TerminateOperations: helm.DefaultTerminateOperations,
+		GetStateOperation:   helm.GetPluginAllState,
 	}
 
 	// Execute all Operations in Operator
diff --git a/internal/pkg/plugin/apachedevlake/delete.go b/internal/pkg/plugin/apachedevlake/delete.go
index 76ad170db..332e806c6 100644
--- a/internal/pkg/plugin/apachedevlake/delete.go
+++ b/internal/pkg/plugin/apachedevlake/delete.go
@@ -2,23 +2,24 @@ package apachedevlake
 
 import (
 	"github.com/devstream-io/devstream/internal/pkg/plugininstaller"
+	"github.com/devstream-io/devstream/internal/pkg/plugininstaller/helm"
 )
 
 func Delete(options map[string]interface{}) (bool, error) {
 	// Initialize Operator with Operations
 	operator := &plugininstaller.Operator{
 		PreExecuteOperations: plugininstaller.PreExecuteOperations{
-			// TODO(dtm): Add your PreExecuteOperations here.
-		},
-		ExecuteOperations: plugininstaller.ExecuteOperations{
-			// TODO(dtm): Add your ExecuteOperations here.
+			helm.SetDefaultConfig(&defaultHelmConfig),
+			helm.Validate,
 		},
+		ExecuteOperations: helm.DefaultDeleteOperations,
 	}
+
+	// Execute all Operations in Operator
 	_, err := operator.Execute(plugininstaller.RawOptions(options))
 	if err != nil {
 		return false, err
 	}
 
-	// 2. return ture if all process success
 	return true, nil
 }
diff --git a/internal/pkg/plugin/apachedevlake/options.go b/internal/pkg/plugin/apachedevlake/options.go
deleted file mode 100644
index 1c199493e..000000000
--- a/internal/pkg/plugin/apachedevlake/options.go
+++ /dev/null
@@ -1,22 +0,0 @@
-package apachedevlake
-
-import (
-	"github.com/mitchellh/mapstructure"
-
-	"github.com/devstream-io/devstream/internal/pkg/plugininstaller"
-)
-
-// Options is the struct for configurations of the apache-devlake plugin.
-type Options struct {
-	// TODO(dtm): Add your params here.
-	Foo string
-}
-
-// NewOptions create options by raw options
-func NewOptions(options plugininstaller.RawOptions) (Options, error) {
-	var opts Options
-	if err := mapstructure.Decode(options, &opts); err != nil {
-		return opts, err
-	}
-	return opts, nil
-}
diff --git a/internal/pkg/plugin/apachedevlake/read.go b/internal/pkg/plugin/apachedevlake/read.go
index 5bb7edd14..0db1a95cf 100644
--- a/internal/pkg/plugin/apachedevlake/read.go
+++ b/internal/pkg/plugin/apachedevlake/read.go
@@ -2,7 +2,7 @@ package apachedevlake
 
 import (
 	"github.com/devstream-io/devstream/internal/pkg/plugininstaller"
-	"github.com/devstream-io/devstream/internal/pkg/statemanager"
+	"github.com/devstream-io/devstream/internal/pkg/plugininstaller/helm"
 	"github.com/devstream-io/devstream/pkg/util/log"
 )
 
@@ -10,12 +10,10 @@ func Read(options map[string]interface{}) (map[string]interface{}, error) {
 	// Initialize Operator with Operations
 	operator := &plugininstaller.Operator{
 		PreExecuteOperations: plugininstaller.PreExecuteOperations{
-			// TODO(dtm): Add your PreExecuteOperations here.
-		},
-		GetStateOperation: func(options plugininstaller.RawOptions) (statemanager.ResourceState, error) {
-			// TODO(dtm): Add your GetStateOperation here.
-			return nil, nil
+			helm.SetDefaultConfig(&defaultHelmConfig),
+			helm.Validate,
 		},
+		GetStateOperation: helm.GetPluginAllState,
 	}
 
 	// Execute all Operations in Operator
diff --git a/internal/pkg/plugin/apachedevlake/update.go b/internal/pkg/plugin/apachedevlake/update.go
index e89f3220e..f6f177b94 100644
--- a/internal/pkg/plugin/apachedevlake/update.go
+++ b/internal/pkg/plugin/apachedevlake/update.go
@@ -2,7 +2,7 @@ package apachedevlake
 
 import (
 	"github.com/devstream-io/devstream/internal/pkg/plugininstaller"
-	"github.com/devstream-io/devstream/internal/pkg/statemanager"
+	"github.com/devstream-io/devstream/internal/pkg/plugininstaller/helm"
 	"github.com/devstream-io/devstream/pkg/util/log"
 )
 
@@ -10,18 +10,11 @@ func Update(options map[string]interface{}) (map[string]interface{}, error) {
 	// Initialize Operator with Operations
 	operator := &plugininstaller.Operator{
 		PreExecuteOperations: plugininstaller.PreExecuteOperations{
-			// TODO(dtm): Add your PreExecuteOperations here.
-		},
-		ExecuteOperations: plugininstaller.ExecuteOperations{
-			// TODO(dtm): Add your ExecuteOperations here.
-		},
-		TerminateOperations: plugininstaller.TerminateOperations{
-			// TODO(dtm): Add your TerminateOperations here.
-		},
-		GetStateOperation: func(options plugininstaller.RawOptions) (statemanager.ResourceState, error) {
-			// TODO(dtm): Add your GetStateOperation here.
-			return nil, nil
+			helm.SetDefaultConfig(&defaultHelmConfig),
+			helm.Validate,
 		},
+		ExecuteOperations: helm.DefaultUpdateOperations,
+		GetStateOperation: helm.GetPluginAllState,
 	}
 
 	// Execute all Operations in Operator
diff --git a/internal/pkg/plugin/apachedevlake/validate.go b/internal/pkg/plugin/apachedevlake/validate.go
deleted file mode 100644
index da1f2f387..000000000
--- a/internal/pkg/plugin/apachedevlake/validate.go
+++ /dev/null
@@ -1,25 +0,0 @@
-package apachedevlake
-
-import (
-	"fmt"
-
-	"github.com/devstream-io/devstream/internal/pkg/plugininstaller"
-	"github.com/devstream-io/devstream/pkg/util/log"
-	"github.com/devstream-io/devstream/pkg/util/validator"
-)
-
-// validate validates the options provided by the core.
-func validate(options plugininstaller.RawOptions) (plugininstaller.RawOptions, error) {
-	opts, err := NewOptions(options)
-	if err != nil {
-		return nil, err
-	}
-	errs := validator.Struct(opts)
-	if len(errs) > 0 {
-		for _, e := range errs {
-			log.Errorf("Options error: %s.", e)
-		}
-		return nil, fmt.Errorf("opts are illegal")
-	}
-	return options, nil
-}
diff --git a/internal/pkg/show/config/embed_gen.go b/internal/pkg/show/config/embed_gen.go
index 666e77f0d..cafff9a02 100644
--- a/internal/pkg/show/config/embed_gen.go
+++ b/internal/pkg/show/config/embed_gen.go
@@ -9,6 +9,9 @@ var DefaultConfig string
 // plugin default config
 var (
 
+	//go:embed plugins/apache-devlake.yaml
+	ApacheDevlakeDefaultConfig string
+
 	//go:embed plugins/argocd.yaml
 	ArgocdDefaultConfig string
 
@@ -95,6 +98,7 @@ var (
 )
 
 var pluginDefaultConfigs = map[string]string{
+	"apache-devlake":       ApacheDevlakeDefaultConfig,
 	"argocd":               ArgocdDefaultConfig,
 	"argocdapp":            ArgocdappDefaultConfig,
 	"artifactory":          ArtifactoryDefaultConfig,
diff --git a/internal/pkg/show/config/plugins/apache-devlake.yaml b/internal/pkg/show/config/plugins/apache-devlake.yaml
index f162a0595..7a8abcd48 100644
--- a/internal/pkg/show/config/plugins/apache-devlake.yaml
+++ b/internal/pkg/show/config/plugins/apache-devlake.yaml
@@ -7,4 +7,28 @@ tools:
   dependsOn: [ ]
   # options for the plugin
   options:
-  # TODO(dtm): Add your default config here.
+    # Helm repo information, this section is optional
+    repo:
+      # name of the Helm repo
+      name: apache-devlake
+      # url of the Helm repo
+      url: ""
+    # Helm chart information
+    chart:
+      # local path of the chart; if chartPath != "", repo.name and repo.url will be ignored. e.g. "foo.tgz", "./foo.tgz", "/tmp/foo.tgz"
+      chartPath: ""
+      # name of the chart
+      chartName: apache-devlake/devlake
+      # release name of the chart
+      releaseName: devlake
+      # k8s namespace where Apache DevLake will be installed
+      namespace: devlake
+      # whether to wait for the release to be deployed or not
+      wait: true
+      # the time to wait for any individual Kubernetes operation (like Jobs for hooks). This defaults to 5m0s
+      timeout: 5m
+      # whether to perform a CRD upgrade during installation
+      upgradeCRDs: true
+      # custom configuration (Optional)
+      valuesYaml: |
+        foo: bar

From c2fdefbd2ed953d4d0dc21890a3af5a3bf46943f Mon Sep 17 00:00:00 2001
From: Daniel Hu <tao.hu@merico.dev>
Date: Fri, 30 Sep 2022 18:13:22 +0800
Subject: [PATCH 5/6] feat: sunset old devlake plugin

Signed-off-by: Daniel Hu <tao.hu@merico.dev>
---
 cmd/plugin/devlake/main.go                    | 39 -------------------
 docs/plugins/devlake.md                       | 13 -------
 docs/plugins/devlake.zh.md                    |  3 --
 internal/pkg/plugin/devlake/create.go         | 26 -------------
 internal/pkg/plugin/devlake/delete.go         | 23 -----------
 internal/pkg/plugin/devlake/devlake.go        | 17 --------
 internal/pkg/plugin/devlake/read.go           | 17 --------
 internal/pkg/plugin/devlake/state.go          | 25 ------------
 internal/pkg/plugin/devlake/update.go         |  5 ---
 internal/pkg/show/config/embed_gen.go         |  4 --
 internal/pkg/show/config/plugins/devlake.yaml |  7 ----
 11 files changed, 179 deletions(-)
 delete mode 100644 cmd/plugin/devlake/main.go
 delete mode 100644 docs/plugins/devlake.md
 delete mode 100644 docs/plugins/devlake.zh.md
 delete mode 100644 internal/pkg/plugin/devlake/create.go
 delete mode 100644 internal/pkg/plugin/devlake/delete.go
 delete mode 100644 internal/pkg/plugin/devlake/devlake.go
 delete mode 100644 internal/pkg/plugin/devlake/read.go
 delete mode 100644 internal/pkg/plugin/devlake/state.go
 delete mode 100644 internal/pkg/plugin/devlake/update.go
 delete mode 100644 internal/pkg/show/config/plugins/devlake.yaml

diff --git a/cmd/plugin/devlake/main.go b/cmd/plugin/devlake/main.go
deleted file mode 100644
index 7c4978b65..000000000
--- a/cmd/plugin/devlake/main.go
+++ /dev/null
@@ -1,39 +0,0 @@
-package main
-
-import (
-	"github.com/devstream-io/devstream/internal/pkg/plugin/devlake"
-	"github.com/devstream-io/devstream/pkg/util/log"
-)
-
-// NAME is the name of this DevStream plugin.
-const NAME = "devlake"
-
-// Plugin is the type used by DevStream core. It's a string.
-type Plugin string
-
-// Create implements the installation of DevLake.
-func (p Plugin) Create(options map[string]interface{}) (map[string]interface{}, error) {
-	return devlake.Create(options)
-}
-
-// Update implements the installation of DevLake.
-func (p Plugin) Update(options map[string]interface{}) (map[string]interface{}, error) {
-	return devlake.Update(options)
-}
-
-// Read implements the healthy check of DevLake.
-func (p Plugin) Read(options map[string]interface{}) (map[string]interface{}, error) {
-	return devlake.Read(options)
-}
-
-// Delete Uninstall the installation of DevLake.
-func (p Plugin) Delete(options map[string]interface{}) (bool, error) {
-	return devlake.Delete(options)
-}
-
-// DevStreamPlugin is the exported variable used by the DevStream core.
-var DevStreamPlugin Plugin
-
-func main() {
-	log.Infof("%T: %s is a plugin for DevStream. Use it with DevStream.\n", DevStreamPlugin, NAME)
-}
diff --git a/docs/plugins/devlake.md b/docs/plugins/devlake.md
deleted file mode 100644
index bd588a8bd..000000000
--- a/docs/plugins/devlake.md
+++ /dev/null
@@ -1,13 +0,0 @@
-# devlake Plugin
-
-This plugin installs [DevLake](https://github.com/merico-dev/lake) in an existing K8s cluster.
-
-Note that this isn't a production-ready installation; it's only meant as an alternative for [the original docker-compose installation](https://github.com/merico-dev/lake/blob/main/docker-compose.yml) should you prefer K8s.
-
-## Usage
-
-```yaml
---8<-- "devlake.yaml"
-```
-
-All the parameters in the example above are mandatory.
diff --git a/docs/plugins/devlake.zh.md b/docs/plugins/devlake.zh.md
deleted file mode 100644
index 6a1f9a471..000000000
--- a/docs/plugins/devlake.zh.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# devlake 插件
-
-todo
diff --git a/internal/pkg/plugin/devlake/create.go b/internal/pkg/plugin/devlake/create.go
deleted file mode 100644
index 527c1d529..000000000
--- a/internal/pkg/plugin/devlake/create.go
+++ /dev/null
@@ -1,26 +0,0 @@
-package devlake
-
-import (
-	"github.com/devstream-io/devstream/internal/pkg/plugininstaller"
-	"github.com/devstream-io/devstream/internal/pkg/plugininstaller/kubectl"
-	kubectlUtil "github.com/devstream-io/devstream/pkg/util/kubectl"
-	"github.com/devstream-io/devstream/pkg/util/log"
-)
-
-func Create(options map[string]interface{}) (map[string]interface{}, error) {
-	// Initialize Operator with Operations
-	operator := &plugininstaller.Operator{
-		ExecuteOperations: plugininstaller.ExecuteOperations{
-			kubectl.ProcessByURL(kubectlUtil.Create, devLakeInstallYAMLDownloadURL),
-		},
-		GetStateOperation: getStaticState,
-	}
-
-	// Execute all Operations in Operator
-	status, err := operator.Execute(plugininstaller.RawOptions(options))
-	if err != nil {
-		return nil, err
-	}
-	log.Debugf("Return map: %v", status)
-	return status, nil
-}
diff --git a/internal/pkg/plugin/devlake/delete.go b/internal/pkg/plugin/devlake/delete.go
deleted file mode 100644
index e22938476..000000000
--- a/internal/pkg/plugin/devlake/delete.go
+++ /dev/null
@@ -1,23 +0,0 @@
-package devlake
-
-import (
-	"github.com/devstream-io/devstream/internal/pkg/plugininstaller"
-	"github.com/devstream-io/devstream/internal/pkg/plugininstaller/kubectl"
-	kubectlUtil "github.com/devstream-io/devstream/pkg/util/kubectl"
-)
-
-func Delete(options map[string]interface{}) (bool, error) {
-	// Initialize Operator with Operations
-	operator := &plugininstaller.Operator{
-		ExecuteOperations: plugininstaller.ExecuteOperations{
-			kubectl.ProcessByURL(kubectlUtil.Delete, devLakeInstallYAMLDownloadURL),
-		},
-	}
-
-	// Execute all Operations in Operator
-	_, err := operator.Execute(plugininstaller.RawOptions(options))
-	if err != nil {
-		return false, err
-	}
-	return true, nil
-}
diff --git a/internal/pkg/plugin/devlake/devlake.go b/internal/pkg/plugin/devlake/devlake.go
deleted file mode 100644
index 9da3b07ec..000000000
--- a/internal/pkg/plugin/devlake/devlake.go
+++ /dev/null
@@ -1,17 +0,0 @@
-package devlake
-
-const (
-	devLakeInstallYAMLDownloadURL = "https://raw.githubusercontent.com/merico-dev/lake/main/k8s-deploy.yaml"
-	/// TODO(ironcore864): now the namespace is hard-coded instead of parsed from the YAML file
-	defaultNamespace = "devlake"
-)
-
-// according to devLakeInstallYAMLDownloadURL
-// a successful DevLake installation should have the following deployments
-// (and corresponding services as well)
-var devLakeDeployments = []string{
-	"mysql",
-	"grafana",
-	"config-ui",
-	"devlake",
-}
diff --git a/internal/pkg/plugin/devlake/read.go b/internal/pkg/plugin/devlake/read.go
deleted file mode 100644
index b50dcefea..000000000
--- a/internal/pkg/plugin/devlake/read.go
+++ /dev/null
@@ -1,17 +0,0 @@
-package devlake
-
-import "github.com/devstream-io/devstream/internal/pkg/plugininstaller"
-
-func Read(options map[string]interface{}) (map[string]interface{}, error) {
-	// Initialize Operator with Operations
-	operator := &plugininstaller.Operator{
-		GetStateOperation: getDynamicState,
-	}
-
-	// Execute all Operations in Operator
-	status, err := operator.Execute(plugininstaller.RawOptions(options))
-	if err != nil {
-		return nil, err
-	}
-	return status, nil
-}
diff --git a/internal/pkg/plugin/devlake/state.go b/internal/pkg/plugin/devlake/state.go
deleted file mode 100644
index 2e3837b4b..000000000
--- a/internal/pkg/plugin/devlake/state.go
+++ /dev/null
@@ -1,25 +0,0 @@
-package devlake
-
-import (
-	"github.com/devstream-io/devstream/internal/pkg/plugininstaller"
-	"github.com/devstream-io/devstream/internal/pkg/plugininstaller/common"
-	"github.com/devstream-io/devstream/internal/pkg/statemanager"
-)
-
-func getStaticState(opts plugininstaller.RawOptions) (statemanager.ResourceState, error) {
-	res := make(map[string]interface{})
-	res["deployments"] = make(map[string]interface{})
-	res["services"] = make(map[string]interface{})
-	for _, d := range devLakeDeployments {
-		res["deployments"].(map[string]interface{})[d] = true
-		res["services"].(map[string]interface{})[d] = true
-	}
-	return res, nil
-}
-
-func getDynamicState(opts plugininstaller.RawOptions) (statemanager.ResourceState, error) {
-	labelFilter := map[string]string{
-		"app": "devlake",
-	}
-	return common.GetPluginAllK8sState(defaultNamespace, map[string]string{}, labelFilter)
-}
diff --git a/internal/pkg/plugin/devlake/update.go b/internal/pkg/plugin/devlake/update.go
deleted file mode 100644
index 3d92dc899..000000000
--- a/internal/pkg/plugin/devlake/update.go
+++ /dev/null
@@ -1,5 +0,0 @@
-package devlake
-
-func Update(options map[string]interface{}) (map[string]interface{}, error) {
-	return Create(options)
-}
diff --git a/internal/pkg/show/config/embed_gen.go b/internal/pkg/show/config/embed_gen.go
index cafff9a02..52b0633c3 100644
--- a/internal/pkg/show/config/embed_gen.go
+++ b/internal/pkg/show/config/embed_gen.go
@@ -24,9 +24,6 @@ var (
 	//go:embed plugins/ci-generic.yaml
 	CiGenericDefaultConfig string
 
-	//go:embed plugins/devlake.yaml
-	DevlakeDefaultConfig string
-
 	//go:embed plugins/githubactions-golang.yaml
 	GithubactionsGolangDefaultConfig string
 
@@ -103,7 +100,6 @@ var pluginDefaultConfigs = map[string]string{
 	"argocdapp":            ArgocdappDefaultConfig,
 	"artifactory":          ArtifactoryDefaultConfig,
 	"ci-generic":           CiGenericDefaultConfig,
-	"devlake":              DevlakeDefaultConfig,
 	"githubactions-golang": GithubactionsGolangDefaultConfig,
 	"githubactions-nodejs": GithubactionsNodejsDefaultConfig,
 	"githubactions-python": GithubactionsPythonDefaultConfig,
diff --git a/internal/pkg/show/config/plugins/devlake.yaml b/internal/pkg/show/config/plugins/devlake.yaml
deleted file mode 100644
index c45908843..000000000
--- a/internal/pkg/show/config/plugins/devlake.yaml
+++ /dev/null
@@ -1,7 +0,0 @@
-tools:
-  # name of the tool
-  - name: devlake
-    # id of the tool instance
-    instanceID: default
-    # format: name.instanceID; If specified, dtm will make sure the dependency is applied first before handling this tool.
-    dependsOn: [ ]

From 74bc4c823ec200c32ff38c45ae0a167a1fb61d5a Mon Sep 17 00:00:00 2001
From: Daniel Hu <tao.hu@merico.dev>
Date: Fri, 30 Sep 2022 18:24:20 +0800
Subject: [PATCH 6/6] chore: add chart.version field and unify the indentation
 style of the config files

Signed-off-by: Daniel Hu <tao.hu@merico.dev>
---
 .../{apache-devlake => devlake}/main.go       | 20 +++++++++----------
 .../plugins/{apache-devlake.md => devlake.md} |  4 ++--
 .../{apache-devlake.zh.md => devlake.zh.md}   |  4 ++--
 .../{apachedevlake => devlake}/create.go      |  2 +-
 .../{apachedevlake => devlake}/delete.go      |  2 +-
 .../apachedevlake.go => devlake/devlake.go}   |  8 ++++----
 .../plugin/{apachedevlake => devlake}/read.go |  2 +-
 .../{apachedevlake => devlake}/update.go      |  2 +-
 internal/pkg/show/config/embed_gen.go         |  8 ++++----
 internal/pkg/show/config/plugins/argocd.yaml  |  2 ++
 .../{apache-devlake.yaml => devlake.yaml}     | 12 +++++------
 11 files changed, 34 insertions(+), 32 deletions(-)
 rename cmd/plugin/{apache-devlake => devlake}/main.go (62%)
 rename docs/plugins/{apache-devlake.md => devlake.md} (64%)
 rename docs/plugins/{apache-devlake.zh.md => devlake.zh.md} (60%)
 rename internal/pkg/plugin/{apachedevlake => devlake}/create.go (97%)
 rename internal/pkg/plugin/{apachedevlake => devlake}/delete.go (96%)
 rename internal/pkg/plugin/{apachedevlake/apachedevlake.go => devlake/devlake.go} (77%)
 rename internal/pkg/plugin/{apachedevlake => devlake}/read.go (97%)
 rename internal/pkg/plugin/{apachedevlake => devlake}/update.go (97%)
 rename internal/pkg/show/config/plugins/{apache-devlake.yaml => devlake.yaml} (83%)

diff --git a/cmd/plugin/apache-devlake/main.go b/cmd/plugin/devlake/main.go
similarity index 62%
rename from cmd/plugin/apache-devlake/main.go
rename to cmd/plugin/devlake/main.go
index 79e99eb54..d0044f59a 100644
--- a/cmd/plugin/apache-devlake/main.go
+++ b/cmd/plugin/devlake/main.go
@@ -1,34 +1,34 @@
 package main
 
 import (
-	"github.com/devstream-io/devstream/internal/pkg/plugin/apachedevlake"
+	"github.com/devstream-io/devstream/internal/pkg/plugin/devlake"
 	"github.com/devstream-io/devstream/pkg/util/log"
 )
 
 // NAME is the name of this DevStream plugin.
-const NAME = "apache-devlake"
+const NAME = "devlake"
 
 // Plugin is the type used by DevStream core. It's a string.
 type Plugin string
 
-// Create implements the create of apache-devlake.
+// Create implements the create of devlake.
 func (p Plugin) Create(options map[string]interface{}) (map[string]interface{}, error) {
-	return apachedevlake.Create(options)
+	return devlake.Create(options)
 }
 
-// Update implements the update of apache-devlake.
+// Update implements the update of devlake.
 func (p Plugin) Update(options map[string]interface{}) (map[string]interface{}, error) {
-	return apachedevlake.Update(options)
+	return devlake.Update(options)
 }
 
-// Delete implements the delete of apache-devlake.
+// Delete implements the delete of devlake.
 func (p Plugin) Delete(options map[string]interface{}) (bool, error) {
-	return apachedevlake.Delete(options)
+	return devlake.Delete(options)
 }
 
-// Read implements the read of apache-devlake.
+// Read implements the read of devlake.
 func (p Plugin) Read(options map[string]interface{}) (map[string]interface{}, error) {
-	return apachedevlake.Read(options)
+	return devlake.Read(options)
 }
 
 // DevStreamPlugin is the exported variable used by the DevStream core.
diff --git a/docs/plugins/apache-devlake.md b/docs/plugins/devlake.md
similarity index 64%
rename from docs/plugins/apache-devlake.md
rename to docs/plugins/devlake.md
index 3c4325de0..7d4188e12 100644
--- a/docs/plugins/apache-devlake.md
+++ b/docs/plugins/devlake.md
@@ -1,9 +1,9 @@
-# apache-devlake plugin
+# devlake plugin
 
 //TODO(daniel-hutao): add document here after Chinese version be ready.
 
 ## Usage
 
 ``` yaml
---8<-- "apache-devlake.yaml"
+--8<-- "devlake.yaml"
 ```
diff --git a/docs/plugins/apache-devlake.zh.md b/docs/plugins/devlake.zh.md
similarity index 60%
rename from docs/plugins/apache-devlake.zh.md
rename to docs/plugins/devlake.zh.md
index 5f272040c..823e3dbce 100644
--- a/docs/plugins/apache-devlake.zh.md
+++ b/docs/plugins/devlake.zh.md
@@ -1,9 +1,9 @@
-# apache-devlake 插件
+# devlake 插件
 
 //TODO(daniel-hutao): 本插件出于开发中状态。
 
 ## 用例
 
 ``` yaml
---8<-- "apache-devlake.yaml"
+--8<-- "devlake.yaml"
 ```
diff --git a/internal/pkg/plugin/apachedevlake/create.go b/internal/pkg/plugin/devlake/create.go
similarity index 97%
rename from internal/pkg/plugin/apachedevlake/create.go
rename to internal/pkg/plugin/devlake/create.go
index 8dd084a16..096ca253f 100644
--- a/internal/pkg/plugin/apachedevlake/create.go
+++ b/internal/pkg/plugin/devlake/create.go
@@ -1,4 +1,4 @@
-package apachedevlake
+package devlake
 
 import (
 	"github.com/devstream-io/devstream/internal/pkg/plugininstaller"
diff --git a/internal/pkg/plugin/apachedevlake/delete.go b/internal/pkg/plugin/devlake/delete.go
similarity index 96%
rename from internal/pkg/plugin/apachedevlake/delete.go
rename to internal/pkg/plugin/devlake/delete.go
index 332e806c6..fabe2aef5 100644
--- a/internal/pkg/plugin/apachedevlake/delete.go
+++ b/internal/pkg/plugin/devlake/delete.go
@@ -1,4 +1,4 @@
-package apachedevlake
+package devlake
 
 import (
 	"github.com/devstream-io/devstream/internal/pkg/plugininstaller"
diff --git a/internal/pkg/plugin/apachedevlake/apachedevlake.go b/internal/pkg/plugin/devlake/devlake.go
similarity index 77%
rename from internal/pkg/plugin/apachedevlake/apachedevlake.go
rename to internal/pkg/plugin/devlake/devlake.go
index 7178c657e..086253516 100644
--- a/internal/pkg/plugin/apachedevlake/apachedevlake.go
+++ b/internal/pkg/plugin/devlake/devlake.go
@@ -1,4 +1,4 @@
-package apachedevlake
+package devlake
 
 import (
 	"github.com/devstream-io/devstream/internal/pkg/plugininstaller/helm"
@@ -10,7 +10,7 @@ import (
 var defaultHelmConfig = helm.Options{
 	Chart: helmCommon.Chart{
 		ChartPath:   "",
-		ChartName:   "apache-devlake/devlake",
+		ChartName:   "devlake/devlake",
 		Timeout:     "5m",
 		Wait:        types.Bool(true),
 		UpgradeCRDs: types.Bool(true),
@@ -18,7 +18,7 @@ var defaultHelmConfig = helm.Options{
 		Namespace:   "devlake",
 	},
 	Repo: helmCommon.Repo{
-		URL:  "https://apache-devlake.github.io/apache-devlake-helm",
-		Name: "apache-devlake",
+		URL:  "https://merico-dev.github.io/devlake-helm-chart",
+		Name: "devlake",
 	},
 }
diff --git a/internal/pkg/plugin/apachedevlake/read.go b/internal/pkg/plugin/devlake/read.go
similarity index 97%
rename from internal/pkg/plugin/apachedevlake/read.go
rename to internal/pkg/plugin/devlake/read.go
index 0db1a95cf..abe6a7862 100644
--- a/internal/pkg/plugin/apachedevlake/read.go
+++ b/internal/pkg/plugin/devlake/read.go
@@ -1,4 +1,4 @@
-package apachedevlake
+package devlake
 
 import (
 	"github.com/devstream-io/devstream/internal/pkg/plugininstaller"
diff --git a/internal/pkg/plugin/apachedevlake/update.go b/internal/pkg/plugin/devlake/update.go
similarity index 97%
rename from internal/pkg/plugin/apachedevlake/update.go
rename to internal/pkg/plugin/devlake/update.go
index f6f177b94..84b942832 100644
--- a/internal/pkg/plugin/apachedevlake/update.go
+++ b/internal/pkg/plugin/devlake/update.go
@@ -1,4 +1,4 @@
-package apachedevlake
+package devlake
 
 import (
 	"github.com/devstream-io/devstream/internal/pkg/plugininstaller"
diff --git a/internal/pkg/show/config/embed_gen.go b/internal/pkg/show/config/embed_gen.go
index 52b0633c3..666e77f0d 100644
--- a/internal/pkg/show/config/embed_gen.go
+++ b/internal/pkg/show/config/embed_gen.go
@@ -9,9 +9,6 @@ var DefaultConfig string
 // plugin default config
 var (
 
-	//go:embed plugins/apache-devlake.yaml
-	ApacheDevlakeDefaultConfig string
-
 	//go:embed plugins/argocd.yaml
 	ArgocdDefaultConfig string
 
@@ -24,6 +21,9 @@ var (
 	//go:embed plugins/ci-generic.yaml
 	CiGenericDefaultConfig string
 
+	//go:embed plugins/devlake.yaml
+	DevlakeDefaultConfig string
+
 	//go:embed plugins/githubactions-golang.yaml
 	GithubactionsGolangDefaultConfig string
 
@@ -95,11 +95,11 @@ var (
 )
 
 var pluginDefaultConfigs = map[string]string{
-	"apache-devlake":       ApacheDevlakeDefaultConfig,
 	"argocd":               ArgocdDefaultConfig,
 	"argocdapp":            ArgocdappDefaultConfig,
 	"artifactory":          ArtifactoryDefaultConfig,
 	"ci-generic":           CiGenericDefaultConfig,
+	"devlake":              DevlakeDefaultConfig,
 	"githubactions-golang": GithubactionsGolangDefaultConfig,
 	"githubactions-nodejs": GithubactionsNodejsDefaultConfig,
 	"githubactions-python": GithubactionsPythonDefaultConfig,
diff --git a/internal/pkg/show/config/plugins/argocd.yaml b/internal/pkg/show/config/plugins/argocd.yaml
index 2c00f6aee..a9055bd45 100644
--- a/internal/pkg/show/config/plugins/argocd.yaml
+++ b/internal/pkg/show/config/plugins/argocd.yaml
@@ -19,6 +19,8 @@ tools:
         chartPath: ""
         # name of the chart
         chartName: argo/argo-cd
+        # version of the chart
+        version: ""
         # release name of the chart
         releaseName: argocd
         # k8s namespace where ArgoCD will be installed
diff --git a/internal/pkg/show/config/plugins/apache-devlake.yaml b/internal/pkg/show/config/plugins/devlake.yaml
similarity index 83%
rename from internal/pkg/show/config/plugins/apache-devlake.yaml
rename to internal/pkg/show/config/plugins/devlake.yaml
index 7a8abcd48..ec66fcf7e 100644
--- a/internal/pkg/show/config/plugins/apache-devlake.yaml
+++ b/internal/pkg/show/config/plugins/devlake.yaml
@@ -1,6 +1,6 @@
 tools:
 # name of the tool
-- name: apache-devlake
+- name: devlake
   # id of the tool instance
   instanceID: default
   # format: name.instanceID; If specified, dtm will make sure the dependency is applied first before handling this tool.
@@ -10,18 +10,18 @@ tools:
     # Helm repo information, this section is optional
     repo:
       # name of the Helm repo
-      name: apache-devlake
+      name: devlake
       # url of the Helm repo
-      url: ""
+      url: https://merico-dev.github.io/devlake-helm-chart
     # Helm chart information
     chart:
       # local path of the chart; if chartPath != "", repo.name and repo.url will be ignored. e.g. "foo.tgz", "./foo.tgz", "/tmp/foo.tgz"
       chartPath: ""
       # name of the chart
-      chartName: apache-devlake/devlake
+      chartName: devlake/devlake
       # release name of the chart
       releaseName: devlake
-      # k8s namespace where Apache DevLake will be installed
+      # k8s namespace where DevLake will be installed
       namespace: devlake
       # whether to wait for the release to be deployed or not
       wait: true
@@ -31,4 +31,4 @@ tools:
       upgradeCRDs: true
       # custom configuration (Optional)
       valuesYaml: |
-        foo: bar
+        replicaCount: 1
