drone_plugin/config_handler/config_handler.go

192 lines
4.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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(cfg.Name, getDeployEnv(req), cfg.toServiceEnv())
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(cfg.Name, getDeployEnv(req), cfg.toServiceEnv())
if err != nil {
logrus.Error(err)
return nil, err
}
if len(modifiedApiList) == 0 && len(modifiedServiceList) == 0 {
// 返回 nil 按照 204 处理
return nil, nil
}
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 {
if "api-"+a.Name == strings.TrimSpace(app) {
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 {
if "service-"+s.Name == strings.TrimSpace(app) {
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([]string{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{}
}