drone_plugin/config_handler/config_handler.go
icechen e38bf7e1af
All checks were successful
continuous-integration/drone/push Build is passing
feat: 增加namespace
2022-01-10 17:51:52 +08:00

205 lines
5.0 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package config_handler
import (
"context"
"encoding/json"
"errors"
"strings"
"git.icechen.cn/pkg/drone_plugin/consts"
"git.icechen.cn/pkg/drone_plugin/git"
"github.com/drone/drone-go/drone"
"github.com/drone/drone-go/plugin/config"
"github.com/sirupsen/logrus"
)
// New returns a new conversion plugin.
func New() config.Plugin {
return &plugin{}
}
type plugin struct{}
type Handler interface {
ToDestinationConfig() (string, error)
}
func (p *plugin) Find(ctx context.Context, req *config.Request) (*drone.Config, error) {
resp, err := json.Marshal(req)
if err != nil {
logrus.Error(err)
return nil, err
}
logrus.Infof("%s", string(resp))
// 1. 获取原始配置文件信息
cfg, err := getRealConfig(getGitClient(req))
if err != nil {
logrus.Error(err)
return nil, err
}
// 2. 是否部署
// 2.1 非 monorepo 的直接返回
if cfg.Type != TypeMonorepo {
// 返回 nil 按照 204 处理
return nil, nil
}
// 2.2 无部署环境报错返回,阻断部署
if getDeployEnv(req) == consts.EnvNone {
return nil, errors.New("ignore event")
}
// 3. 获取提交文件树
modifiedFileList, err := getGitClient(req).GetCommitModifiedFileList()
if err != nil {
logrus.Error(err)
return nil, err
}
// 4. 根据文件树以及原始配置文件的信息组装需要构建的服务的ci信息
// 4.1 api
modifiedApiList := getModifiedApi(cfg.Api, modifiedFileList, foundAppByMessage(req.Build.Message), foundAppByParams(req.Build.Params))
destinationApi, err := modifiedApiList.toDestinationConfig(getDeployEnv(req))
if err != nil {
logrus.Error(err)
return nil, err
}
// 4.2 service
modifiedServiceList := getModifiedService(cfg.Service, modifiedFileList, foundAppByMessage(req.Build.Message), foundAppByParams(req.Build.Params))
destinationService, err := modifiedServiceList.toDestinationConfig(getDeployEnv(req))
if err != nil {
logrus.Error(err)
return nil, err
}
if len(modifiedApiList) == 0 && len(modifiedServiceList) == 0 {
// 返回空
return &drone.Config{
Data: "",
Kind: "",
}, errors.New("skipping build")
}
retData := destinationApi + "\n\n" + destinationService
n := strings.LastIndex(retData, "---")
if n > 0 {
retData = retData[:n]
}
logrus.Info(retData)
// 5. 组装所有ci信息并输出
return &drone.Config{
Data: retData,
Kind: "pipeline",
}, nil
}
func getGitClient(req *config.Request) git.Client {
return git.New(req.Repo.Namespace, req.Repo.Name, req.Build.After, req.Repo.Config)
}
func getDeployEnv(req *config.Request) consts.Env {
switch req.Build.Event {
case "push":
fallthrough
case "custom":
if req.Build.Target == "master" {
return consts.EnvTest
}
case "tag":
return consts.EnvProduction
}
return consts.EnvNone
}
func getModifiedApi(api ApiList, modifiedFileList []string, appByMessage []string, appByParams []string) ApiList {
ret := make(ApiList, 0)
tempIndex := NewSet()
for i, a := range api {
for _, file := range modifiedFileList {
if strings.HasPrefix(file, a.Root) {
tempIndex.Add(i)
}
}
}
for _, i := range tempIndex.ToSlice() {
ret = append(ret, api[i])
}
ret = append(ret, getDeployApiByAppSlice(api, append(appByMessage, appByParams...))...)
return ret
}
func getDeployApiByAppSlice(api ApiList, appSlice []string) ApiList {
ret := make(ApiList, 0)
for _, app := range appSlice {
for _, a := range api {
appWithNamespace := strings.Split(app, ".")
if len(appWithNamespace) == 2 {
name := appWithNamespace[0]
namespace := appWithNamespace[1]
if a.Namespace == strings.TrimSpace(namespace) && "api-"+a.Name == strings.TrimSpace(name) {
ret = append(ret, a)
}
}
}
}
return ret
}
func getModifiedService(service ServiceList, modifiedFileList []string, appByMessage []string, appByParams []string) ServiceList {
ret := make(ServiceList, 0)
tempIndex := NewSet()
for i, s := range service {
for _, file := range modifiedFileList {
if strings.HasPrefix(file, s.Root) {
tempIndex.Add(i)
}
}
}
for _, i := range tempIndex.ToSlice() {
ret = append(ret, service[i])
}
ret = append(ret, getDeployServiceByAppSlice(service, append(appByMessage, appByParams...))...)
return ret
}
func getDeployServiceByAppSlice(service ServiceList, appSlice []string) ServiceList {
ret := make(ServiceList, 0)
for _, app := range appSlice {
for _, s := range service {
appWithNamespace := strings.Split(app, ".")
if len(appWithNamespace) == 2 {
name := appWithNamespace[0]
namespace := appWithNamespace[1]
if s.Namespace == strings.TrimSpace(namespace) && "service-"+s.Name == strings.TrimSpace(name) {
ret = append(ret, s)
}
}
}
}
return ret
}
func foundAppByMessage(message string) []string {
i := strings.Index(message, "[")
if i >= 0 {
j := strings.Index(message[i:], "]")
if j >= 0 {
return append(strings.Split(message[i+1:j+i], ","), foundAppByMessage(message[j+i:])...)
}
}
return []string{}
}
func foundAppByParams(params map[string]string) []string {
app, has := params["app"]
if has {
return strings.Split(app, ",")
}
return []string{}
}