feat:新增部署列表接口
This commit is contained in:
parent
cf3714b99a
commit
eaecd00394
|
@ -82,3 +82,22 @@ type UploadReq struct {
|
|||
type UploadRes struct {
|
||||
FileUrl string `json:"fileurl"`
|
||||
}
|
||||
|
||||
// DeployReq 项目部署
|
||||
type DeployReq struct {
|
||||
g.Meta `path:"/project/deploy" method:"post" tags:"项目" summary:"项目部署"`
|
||||
adminin.ProjectDeployInp
|
||||
}
|
||||
|
||||
type DeployRes struct {
|
||||
FileUrl string `json:"fileurl"`
|
||||
}
|
||||
|
||||
type DeployListReq struct {
|
||||
g.Meta `path:"/project/deploy/list" method:"get" tags:"项目" summary:"获取项目列表"`
|
||||
adminin.ProjectDeployListInp
|
||||
}
|
||||
|
||||
type DeployListRes struct {
|
||||
List []*adminin.ProjectDeployListModel `json:"list" dc:"数据列表"`
|
||||
}
|
||||
|
|
2
go.mod
2
go.mod
|
@ -3,10 +3,12 @@ module hotgo
|
|||
go 1.21
|
||||
|
||||
require (
|
||||
github.com/bndr/gojenkins v1.1.0
|
||||
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.6.3
|
||||
github.com/gogf/gf/contrib/nosql/redis/v2 v2.7.2
|
||||
github.com/gogf/gf/v2 v2.7.2
|
||||
github.com/golang-jwt/jwt/v5 v5.2.0
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56
|
||||
)
|
||||
|
||||
require (
|
||||
|
|
12
go.sum
12
go.sum
|
@ -1,5 +1,7 @@
|
|||
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
|
||||
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/bndr/gojenkins v1.1.0 h1:TWyJI6ST1qDAfH33DQb3G4mD8KkrBfyfSUoZBHQAvPI=
|
||||
github.com/bndr/gojenkins v1.1.0/go.mod h1:QeskxN9F/Csz0XV/01IC8y37CapKKWvOHa0UHLLX1fM=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
|
||||
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
|
||||
|
@ -9,6 +11,7 @@ github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL
|
|||
github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME=
|
||||
github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
|
@ -71,6 +74,8 @@ github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUc
|
|||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
|
||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo=
|
||||
|
@ -81,12 +86,18 @@ go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucg
|
|||
go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg=
|
||||
go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI=
|
||||
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
||||
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
|
||||
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
@ -94,5 +105,6 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8
|
|||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
|
|
@ -47,6 +47,12 @@ var (
|
|||
project.NewV1(),
|
||||
)
|
||||
})
|
||||
s.Group("/attachment", func(group *ghttp.RouterGroup) {
|
||||
group.Hook("/*", ghttp.HookBeforeServe, func(r *ghttp.Request) {
|
||||
r.Response.CORSDefault()
|
||||
})
|
||||
|
||||
})
|
||||
s.Run()
|
||||
return nil
|
||||
},
|
||||
|
|
|
@ -2,13 +2,12 @@ package project
|
|||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogf/gf/v2/errors/gcode"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"hotgo/internal/service"
|
||||
|
||||
"hotgo/api/project/v1"
|
||||
)
|
||||
|
||||
func (c *ControllerV1) Delete(ctx context.Context, req *v1.DeleteReq) (res *v1.DeleteRes, err error) {
|
||||
return nil, gerror.NewCode(gcode.CodeNotImplemented)
|
||||
err = service.AdminProject().Delete(ctx, &req.ProjectDeleteInp)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
package project
|
||||
|
||||
import (
|
||||
"context"
|
||||
"hotgo/api/project/v1"
|
||||
"hotgo/internal/service"
|
||||
)
|
||||
|
||||
func (c *ControllerV1) Deploy(ctx context.Context, req *v1.DeployReq) (res *v1.DeployRes, err error) {
|
||||
err = service.AdminProject().Deploy(ctx, &req.ProjectDeployInp)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *ControllerV1) DeployList(ctx context.Context, req *v1.DeployListReq) (res *v1.DeployListRes, err error) {
|
||||
err = service.AdminProject().Deploy(ctx, &req.ProjectDeployInp)
|
||||
return
|
||||
}
|
|
@ -5,18 +5,30 @@ package admin
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/bndr/gojenkins"
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/glog"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"github.com/gogf/gf/v2/util/grand"
|
||||
"github.com/gogf/gf/v2/util/guid"
|
||||
"hotgo/internal/dao"
|
||||
"hotgo/internal/library/contexts"
|
||||
"hotgo/internal/model"
|
||||
"hotgo/internal/model/entity"
|
||||
"hotgo/internal/model/input/adminin"
|
||||
"hotgo/internal/service"
|
||||
"hotgo/internal/utils"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type sAdminProject struct{}
|
||||
|
@ -29,6 +41,21 @@ func init() {
|
|||
service.RegisterAdminProject(NewAdminProject())
|
||||
}
|
||||
|
||||
const (
|
||||
DEPLOY_BUILD_KEY = "deploy.build"
|
||||
DEPLOY_BUILD_URL_KEY = DEPLOY_BUILD_KEY + "." + "url"
|
||||
DEPLOY_BUILD_JOBNAME_KEY = DEPLOY_BUILD_KEY + "." + "jobName"
|
||||
DEPLOY_BUILD_JOBDOWN_KEY = DEPLOY_BUILD_KEY + "." + "jobdown"
|
||||
DEPLOY_BUILD_CALLBACK_KEY = DEPLOY_BUILD_KEY + "." + "callback"
|
||||
DEPLOY_BUILD_MINIOPATH_KEY = DEPLOY_BUILD_KEY + "." + "ossPathPre"
|
||||
DEPLOY_BUILD_UPLOAD_KEY = DEPLOY_BUILD_KEY + "." + "upload"
|
||||
DEPLOY_BUILD_CONFIG_PATH = DEPLOY_BUILD_KEY + "." + "confPath"
|
||||
DEPLOY_BUILD_FRONT_PATH = DEPLOY_BUILD_KEY + "." + "frontPath"
|
||||
DEPLOY_BUILD_JOBTOKEN_KEY = DEPLOY_BUILD_KEY + "." + "jobToken"
|
||||
DEPLOY_BUILD_JOBUSER_KEY = DEPLOY_BUILD_KEY + "." + "jobUser"
|
||||
DEPLOY_BUILD_JOBPASSWORD_KEY = DEPLOY_BUILD_KEY + "." + "jobPassword"
|
||||
)
|
||||
|
||||
// Model ORM模型
|
||||
func (s *sAdminProject) Model(ctx context.Context) *gdb.Model {
|
||||
return dao.AdminProject.Ctx(ctx).Handler(func(m *gdb.Model) *gdb.Model {
|
||||
|
@ -66,6 +93,12 @@ func (s *sAdminProject) Delete(ctx context.Context, in *adminin.ProjectDeleteInp
|
|||
err = gerror.New("没有找到项目!")
|
||||
return err
|
||||
}
|
||||
var project *entity.AdminProject
|
||||
err = s.Model(ctx).WherePri(in.Id).Scan(&project)
|
||||
if project.Status == 1 {
|
||||
err = gerror.New("项目已发布,无法删除!")
|
||||
return err
|
||||
}
|
||||
_, err = s.Model(ctx).WherePri(in.Id).Delete()
|
||||
return
|
||||
}
|
||||
|
@ -165,3 +198,193 @@ func (s *sAdminProject) ExistById(ctx context.Context, id int64) (exists bool, e
|
|||
exists = count > 0
|
||||
return
|
||||
}
|
||||
|
||||
func (s *sAdminProject) Deploy(ctx context.Context, in *adminin.ProjectDeployInp) (err error) {
|
||||
var tempName = guid.S()
|
||||
var basePath = "resource/tmp/" + tempName
|
||||
var project *entity.AdminProject
|
||||
var jsonObj *model.JsonObj
|
||||
err = s.Model(ctx).WherePri(in.Id).Scan(&project)
|
||||
if project == nil {
|
||||
err = gerror.New("项目不存在")
|
||||
return
|
||||
}
|
||||
gconv.Struct(project.Content, &jsonObj)
|
||||
fmt.Println(jsonObj.EditCanvasConfig.BackgroundImage)
|
||||
if jsonObj.EditCanvasConfig.BackgroundImage != "" {
|
||||
backimageUrl := gconv.String(jsonObj.EditCanvasConfig.BackgroundImage)
|
||||
urlarr := strings.Split(backimageUrl, "?")
|
||||
filename := filepath.Base(urlarr[0])
|
||||
DownloadImage(ctx, urlarr[0], basePath+"/data/image/")
|
||||
jsonObj.EditCanvasConfig.BackgroundImage = "/data/image/" + filename + "?" + urlarr[1]
|
||||
}
|
||||
|
||||
componentList := jsonObj.ComponentList
|
||||
for _, component := range componentList {
|
||||
if component.Key == "Image" && component.Option.Dataset != nil {
|
||||
fmt.Println("Image")
|
||||
fmt.Println(component.Option.Dataset)
|
||||
fileUrl := gconv.String(component.Option.Dataset)
|
||||
filename := filepath.Base(fileUrl)
|
||||
DownloadImage(ctx, fileUrl, basePath+"/data/image/")
|
||||
component.Option.Dataset = "/data/image/" + filename
|
||||
}
|
||||
if component.Key == "Video" && component.Option.Dataset != nil {
|
||||
fmt.Println("Video")
|
||||
fmt.Println(component.Option.Dataset)
|
||||
fileUrl := gconv.String(component.Option.Dataset)
|
||||
filename := filepath.Base(fileUrl)
|
||||
DownloadImage(ctx, fileUrl, basePath+"/data/video/")
|
||||
component.Option.Dataset = "/data/video/" + filename
|
||||
}
|
||||
if component.Key == "ImageCarousel" && component.Option.Dataset != nil {
|
||||
fmt.Println("ImageCarousel")
|
||||
fmt.Println(component.Option.Dataset)
|
||||
var datalist = gconv.SliceStr(component.Option.Dataset)
|
||||
for i, fileUrl := range datalist {
|
||||
filename := filepath.Base(fileUrl)
|
||||
DownloadImage(ctx, fileUrl, basePath+"/data/image/")
|
||||
datalist[i] = "/data/image/" + filename
|
||||
}
|
||||
component.Option.Dataset = datalist
|
||||
}
|
||||
|
||||
}
|
||||
jsonstr, err := json.Marshal(jsonObj)
|
||||
os.WriteFile(basePath+"/project.json", jsonstr, 0666)
|
||||
|
||||
err = utils.ZipCompress(basePath, basePath+".zip")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.Log().Debug(ctx, "压缩文件完成")
|
||||
s.BuildTask(ctx, in.Url, basePath+".zip", in.Id)
|
||||
//serverFile := basePath + tempName + ".zip"
|
||||
return nil
|
||||
}
|
||||
|
||||
func DownloadImage(ctx context.Context, url string, path string) error {
|
||||
// 发送 GET 请求获取图片
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
g.Log().Error(ctx, err)
|
||||
return fmt.Errorf("failed to fetch the image: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// 检查响应状态码
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
g.Log().Error(ctx, err)
|
||||
return fmt.Errorf("request returned status code %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
// 获取图片扩展名
|
||||
filename := filepath.Base(url)
|
||||
// 确保目录存在
|
||||
err = os.MkdirAll(path, os.ModePerm)
|
||||
if err != nil {
|
||||
g.Log().Error(ctx, err)
|
||||
return fmt.Errorf("failed to create directory: %w", err)
|
||||
}
|
||||
// 打开或创建文件
|
||||
file, err := os.Create(path + filename)
|
||||
if err != nil {
|
||||
g.Log().Error(ctx, err)
|
||||
return fmt.Errorf("failed to create file: %w", err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// 将图片数据写入文件
|
||||
_, err = io.Copy(file, resp.Body)
|
||||
if err != nil {
|
||||
g.Log().Error(ctx, err)
|
||||
return fmt.Errorf("failed to write data to file: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *sAdminProject) BuildTask(ctx context.Context, options string, resource string, projectId int64) (err error) {
|
||||
|
||||
serviceurl := s.GetCfgEnv(ctx, DEPLOY_BUILD_URL_KEY)
|
||||
jobName := s.GetCfgEnv(ctx, DEPLOY_BUILD_JOBNAME_KEY)
|
||||
callback := s.GetCfgEnv(ctx, DEPLOY_BUILD_CALLBACK_KEY)
|
||||
uploadPath := s.GetCfgEnv(ctx, DEPLOY_BUILD_UPLOAD_KEY)
|
||||
|
||||
last := strings.LastIndex(resource, "/")
|
||||
if last > 0 {
|
||||
filename := resource
|
||||
|
||||
var uploadFile = ""
|
||||
if gstr.ToLower("windows") == "linux" {
|
||||
uploadFile = "bin/linux_amd64/hc-base-gf"
|
||||
} else {
|
||||
uploadFile = "bin/windows_amd64/hc-base-gf.exe"
|
||||
}
|
||||
paras := map[string]string{
|
||||
"jobName": jobName,
|
||||
"remote_path": "obj.ResUrl",
|
||||
"project_id": gconv.String(projectId),
|
||||
// "target_path": "target/project",
|
||||
"target_path": "/projects/1panel/1panel/apps/jenkins/jenkins/data/_data/jenkins_output",
|
||||
"file_name": filename,
|
||||
|
||||
"callback_url": callback, //"http://192.168.10.241:30621/port/getJobBuildBack",
|
||||
"upload_path": uploadPath,
|
||||
"deploy_env": "windows",
|
||||
"auto_open_enable": "true",
|
||||
"upload_file": uploadFile,
|
||||
"front_path": "",
|
||||
}
|
||||
|
||||
num, err, errMsg := s.buildJenkinsJob(ctx, serviceurl, paras, jobName)
|
||||
g.Log().Info(ctx, fmt.Sprintf("构建任务:%s, num:%d, err:%s, errMsg:%s", jobName, num, err, errMsg))
|
||||
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *sAdminProject) GetCfgEnv(ctx context.Context, key string) string {
|
||||
v, _ := g.Cfg().GetWithEnv(ctx, key)
|
||||
|
||||
return v.String()
|
||||
}
|
||||
|
||||
func (s *sAdminProject) buildJenkinsJob(ctx context.Context, baseUrl string, parameters map[string]string, pipelineJobName string) (num int64, err error, errMsg string) {
|
||||
glog.Info(ctx, fmt.Sprintf("开始构建部署任务:baseUrl:%s, parameters:%s,pipelineJobName:%s", baseUrl, parameters, pipelineJobName))
|
||||
// 替换为有效的用户名和 API Token
|
||||
jobuser := s.GetCfgEnv(ctx, DEPLOY_BUILD_JOBUSER_KEY)
|
||||
jobpassword := s.GetCfgEnv(ctx, DEPLOY_BUILD_JOBPASSWORD_KEY)
|
||||
// 创建 HTTP 客户端
|
||||
client := &http.Client{}
|
||||
glog.Info(ctx, fmt.Sprintf("初始化Jenkins客户端:baseUrl:%s,用户:%s", baseUrl, jobuser))
|
||||
jenkins, err := gojenkins.CreateJenkins(client, baseUrl, jobuser, jobpassword).Init(ctx)
|
||||
if err != nil {
|
||||
errMsg = fmt.Sprintf("Jenkins 客户端初始化失败:baseUrl:%s,用户:%s", baseUrl, jobuser)
|
||||
glog.Errorf(ctx, errMsg, err)
|
||||
return 0, err, errMsg
|
||||
}
|
||||
jobarr := strings.Split(pipelineJobName, "/")
|
||||
newjobname := strings.Join(jobarr, "/job/")
|
||||
glog.Info(ctx, fmt.Sprintf("触发流水线执行,任务名:%s", newjobname))
|
||||
queId, err := jenkins.BuildJob(ctx, newjobname, parameters)
|
||||
glog.Debug(ctx, queId)
|
||||
if err != nil {
|
||||
errMsg = fmt.Sprintf("触发流水线执行失败:流水线名:%s, 错误信息:%s", newjobname, err.Error())
|
||||
glog.Error(ctx, errMsg, err)
|
||||
return 0, err, errMsg
|
||||
}
|
||||
//通过队列号获取不到构建,只用来刷新构建号获取值
|
||||
build, err := jenkins.GetBuildFromQueueID(ctx, queId)
|
||||
if build != nil {
|
||||
glog.Debug(ctx, build.GetBuildNumber())
|
||||
} else {
|
||||
glog.Debug(ctx, queId)
|
||||
}
|
||||
job, err := jenkins.GetJob(ctx, newjobname)
|
||||
lastbuild, err := job.GetLastBuild(ctx)
|
||||
glog.Debug(ctx, "流水线执行已触发,构建号:", lastbuild.GetBuildNumber())
|
||||
glog.Info(ctx, "部署任务执行成功,构建号:", lastbuild.GetBuildNumber())
|
||||
return lastbuild.GetBuildNumber(), err, ""
|
||||
}
|
||||
|
|
|
@ -125,3 +125,15 @@ type ProjectPublishModel struct{}
|
|||
type ProjectUploadInp struct {
|
||||
File *ghttp.UploadFile `json:"object" type:"file" dc:"文件"`
|
||||
}
|
||||
|
||||
type ProjectDeployInp struct {
|
||||
Id int64 `json:"id"`
|
||||
Url string `json:"url"`
|
||||
}
|
||||
|
||||
type ProjectDeployListInp struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type ProjectDeployListModel struct {
|
||||
}
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
package model
|
||||
|
||||
type JsonObj struct {
|
||||
EditCanvasConfig *EditCanvasConfig `json:"editCanvasConfig"`
|
||||
ComponentList []*Component `json:"componentList"`
|
||||
RequestGlobalConfig interface{} `json:"requestGlobalConfig"`
|
||||
StaticFile interface{} `json:"staticFile"`
|
||||
GlobalVarList []interface{} `json:"globalVarList"`
|
||||
}
|
||||
|
||||
type Component struct {
|
||||
Id string `json:"id"`
|
||||
IsGroup bool `json:"isGroup"`
|
||||
Attr interface{} `json:"attr"`
|
||||
Styles interface{} `json:"styles"`
|
||||
Preview struct {
|
||||
OverFlowHidden bool `json:"overFlowHidden"`
|
||||
} `json:"preview"`
|
||||
Status struct {
|
||||
Lock bool `json:"lock"`
|
||||
Hide bool `json:"hide"`
|
||||
} `json:"status"`
|
||||
Request interface{} `json:"request"`
|
||||
Filter interface{} `json:"filter"`
|
||||
Events interface{} `json:"events"`
|
||||
Key string `json:"key"`
|
||||
ChartConfig struct {
|
||||
Key string `json:"key"`
|
||||
ChartKey string `json:"chartKey"`
|
||||
ConKey string `json:"conKey"`
|
||||
Title string `json:"title"`
|
||||
Category string `json:"category"`
|
||||
CategoryName string `json:"categoryName"`
|
||||
Package string `json:"package"`
|
||||
ChartFrame string `json:"chartFrame"`
|
||||
Image string `json:"image"`
|
||||
} `json:"chartConfig"`
|
||||
Option struct {
|
||||
Type string `json:"type"`
|
||||
Dataset interface{} `json:"dataset"`
|
||||
Fit string `json:"fit"`
|
||||
BorderRadius int `json:"borderRadius,omitempty"`
|
||||
Loop bool `json:"loop,omitempty"`
|
||||
Muted bool `json:"muted,omitempty"`
|
||||
Autoplay bool `json:"autoplay,omitempty"`
|
||||
Interval int `json:"interval,omitempty"`
|
||||
SlidesPerview int `json:"slidesPerview,omitempty"`
|
||||
Direction string `json:"direction,omitempty"`
|
||||
Draggable bool `json:"draggable,omitempty"`
|
||||
CenteredSlides bool `json:"centeredSlides,omitempty"`
|
||||
Effect string `json:"effect,omitempty"`
|
||||
ShowDots bool `json:"showDots,omitempty"`
|
||||
DotType string `json:"dotType,omitempty"`
|
||||
DotPlacement string `json:"dotPlacement,omitempty"`
|
||||
ShowArrow bool `json:"showArrow,omitempty"`
|
||||
} `json:"option"`
|
||||
}
|
||||
|
||||
type EditCanvasConfig struct {
|
||||
ProjectName string `json:"projectName"`
|
||||
Width int `json:"width"`
|
||||
Height int `json:"height"`
|
||||
FilterShow bool `json:"filterShow"`
|
||||
HueRotate int `json:"hueRotate"`
|
||||
Saturate int `json:"saturate"`
|
||||
Contrast int `json:"contrast"`
|
||||
Brightness int `json:"brightness"`
|
||||
Opacity int `json:"opacity"`
|
||||
RotateZ int `json:"rotateZ"`
|
||||
RotateX int `json:"rotateX"`
|
||||
RotateY int `json:"rotateY"`
|
||||
SkewX int `json:"skewX"`
|
||||
SkewY int `json:"skewY"`
|
||||
BlendMode string `json:"blendMode"`
|
||||
Background interface{} `json:"background"`
|
||||
BackgroundImage string `json:"backgroundImage"`
|
||||
SelectColor bool `json:"selectColor"`
|
||||
ChartThemeColor string `json:"chartThemeColor"`
|
||||
ChartCustomThemeColorInfo interface{} `json:"chartCustomThemeColorInfo"`
|
||||
ChartThemeSetting interface{} `json:"chartThemeSetting"`
|
||||
PreviewScaleType string `json:"previewScaleType"`
|
||||
}
|
||||
|
||||
type RequestObj struct {
|
||||
RequestDataType int `json:"requestDataType"`
|
||||
RequestHttpType string `json:"requestHttpType"`
|
||||
RequestUrl string `json:"requestUrl"`
|
||||
RequestInterval interface{} `json:"requestInterval"`
|
||||
RequestIntervalUnit string `json:"requestIntervalUnit"`
|
||||
RequestContentType int `json:"requestContentType"`
|
||||
RequestParamsBodyType string `json:"requestParamsBodyType"`
|
||||
RequestSQLContent struct {
|
||||
Sql string `json:"sql"`
|
||||
} `json:"requestSQLContent"`
|
||||
RequestParams struct {
|
||||
Body struct {
|
||||
FormData struct {
|
||||
} `json:"form-data"`
|
||||
XWwwFormUrlencoded struct {
|
||||
} `json:"x-www-form-urlencoded"`
|
||||
Json string `json:"json"`
|
||||
Xml string `json:"xml"`
|
||||
} `json:"Body"`
|
||||
Header struct {
|
||||
} `json:"Header"`
|
||||
Params struct {
|
||||
} `json:"Params"`
|
||||
} `json:"requestParams"`
|
||||
}
|
|
@ -27,6 +27,8 @@ type (
|
|||
Publish(ctx context.Context, in *adminin.ProjectPublishInp) (err error)
|
||||
// GetData 获取指定信息
|
||||
GetData(ctx context.Context, in *adminin.ProjectGetDataInp) (res *adminin.ProjectGetDataModel, err error)
|
||||
//项目部署
|
||||
Deploy(ctx context.Context, in *adminin.ProjectDeployInp)(err error)
|
||||
}
|
||||
IAdminSite interface {
|
||||
// Register 账号注册
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
package utils
|
||||
|
||||
import "os"
|
||||
|
||||
func PathExists(path string) (bool, error) {
|
||||
_, err := os.Stat(path)
|
||||
if err == nil{
|
||||
return true, nil
|
||||
}
|
||||
if os.IsNotExist(err) {
|
||||
// 创建文件夹
|
||||
err := os.MkdirAll(path, os.ModePerm)
|
||||
if err != nil {
|
||||
return false, err
|
||||
} else {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, err
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* @Descripttion:
|
||||
* @version:
|
||||
* @Author: lfzxs@qq.com
|
||||
* @Date: 2023-09-20 16:06:07
|
||||
* @LastEditors: lfzxs@qq.com
|
||||
* @LastEditTime: 2023-09-21 16:48:23
|
||||
*/
|
||||
package utils
|
||||
|
||||
import (
|
||||
"archive/zip"
|
||||
"bytes"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"golang.org/x/exp/slog"
|
||||
)
|
||||
|
||||
func ZipCompress(dirPath string, zipPath string) error {
|
||||
|
||||
// 创建一个缓冲区来存储压缩后的数据
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
// 创建一个zip.Writer
|
||||
zipWriter := zip.NewWriter(buf)
|
||||
|
||||
// 遍历目录下的文件和子目录
|
||||
err := filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 构建在zip中的相对路径
|
||||
relPath, err := filepath.Rel(dirPath, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 判断是否为文件
|
||||
if !info.IsDir() {
|
||||
// 将文件添加到zip中
|
||||
zipFile, err := zipWriter.Create(relPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 打开文件并复制到zip中
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
_, err = io.Copy(zipFile, file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
|
||||
|
||||
if err != nil {
|
||||
slog.Error("遍历目录失败:","error",err)
|
||||
return err
|
||||
}
|
||||
|
||||
// 关闭zip写入器
|
||||
err = zipWriter.Close()
|
||||
if err != nil {
|
||||
slog.Error("关闭zip写入器失败:","error",err)
|
||||
return err
|
||||
}
|
||||
|
||||
// 将压缩后的数据写入文件
|
||||
fpath := filepath.Dir(zipPath)
|
||||
_,err = PathExists(fpath)
|
||||
|
||||
if err != nil {
|
||||
slog.Error("创建压缩文件失败:","error",err)
|
||||
return err
|
||||
}
|
||||
|
||||
zipFile, err := os.Create(zipPath)
|
||||
if err != nil {
|
||||
slog.Error("创建压缩文件失败:","error",err)
|
||||
return err
|
||||
}
|
||||
defer zipFile.Close()
|
||||
|
||||
// 将压缩后的数据复制到文件中
|
||||
_, err = io.Copy(zipFile, buf)
|
||||
if err != nil {
|
||||
slog.Error("复制压缩数据到文件失败:","error",err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
|
@ -35,7 +35,7 @@ server:
|
|||
openapiPath: "/api.json" # OpenAPI接口文档地址
|
||||
swaggerPath: "/swagger" # 内置SwaggerUI展示地址
|
||||
serverRoot: "resource/public" # 静态文件服务的目录根路径,配置时自动开启静态文件服务。
|
||||
DumpRouterMap: false # 是否在Server启动时打印所有的路由列表。
|
||||
DumpRouterMap: true # 是否在Server启动时打印所有的路由列表。
|
||||
logPath: "logs/server" # 服务日志保存路径
|
||||
ErrorStack: true # 当Server捕获到异常时是否记录堆栈信息到日志中。默认为true
|
||||
ErrorLogEnabled: true # 是否记录异常日志信息到日志中。默认为true
|
||||
|
@ -43,7 +43,7 @@ server:
|
|||
accessLogEnabled: true # 是否记录访问日志。默认为false
|
||||
accessLogPattern: "access/{Y-m-d}.log" # 访问日志文件格式。默认为"access-{Ymd}.log"
|
||||
maxHeaderBytes: "100KB" # 请求头大小限制,请求头包括客户端提交的Cookie数据,默认设置为100KB
|
||||
clientMaxBodySize: "300MB" # 客户端提交的Body大小限制,同时也影响文件上传大小,默认设置为300MB
|
||||
clientMaxBodySize: "600MB" # 客户端提交的Body大小限制,同时也影响文件上传大小,默认设置为300MB
|
||||
serverAgent: "HG HTTP Server" # 服务端Agent信息。默认为"HG HTTP Server"
|
||||
# PProf配置
|
||||
pprofEnabled: true # 是否开启PProf性能调试特性。默认为false
|
||||
|
@ -73,8 +73,8 @@ token:
|
|||
storager:
|
||||
# 通用配置
|
||||
drive: "local" # 上传驱动。local:本地存储
|
||||
fileSize: "10" # 上传图片大小限制,单位:MB
|
||||
fileType: "doc,docx,pdf,zip,tar,xls,xlsx,rar,jpg,jpeg,gif,npm,png,svg" # 上传文件类型限制,文件上传后缀类型限制
|
||||
fileSize: "1000" # 上传图片大小限制,单位:MB
|
||||
fileType: "doc,docx,pdf,zip,tar,xls,xlsx,rar,jpg,jpeg,gif,npm,png,svg,mp4" # 上传文件类型限制,文件上传后缀类型限制
|
||||
imageSize: "your_image_size_value" # 上传图片大小限制,单位:MB
|
||||
imageType: "jpg,jpeg,gif,npm,png,svg" # 上传图片类型限制,图片上传后缀类型限制
|
||||
localPath: "attachment/" # 本地存储路径,对外访问的相对路径
|
||||
|
@ -101,3 +101,19 @@ database:
|
|||
Prefix: "hg_"
|
||||
|
||||
|
||||
deploy:
|
||||
build:
|
||||
#部署中间层服务地址
|
||||
url: "http://192.168.1.100:8888"
|
||||
#Jenkins任务名称
|
||||
jobName: "local-deploy"
|
||||
#Jenkins任务用户
|
||||
jobUser: "root"
|
||||
#Jenkins任务密码
|
||||
jobPassword: "Gy,.2024"
|
||||
#Jenkins任务token
|
||||
jobToken: ""
|
||||
#部署结果文件上传地址
|
||||
upload: "http://192.168.10.241:30103/trade/deploy/bosavepath"
|
||||
#部署打包中外部打包资源的回调接口的URL地址
|
||||
callBackUrl: "http://192.168.10.241:30103/trade/deploy/packinfocall"
|
Loading…
Reference in New Issue