mirror of
https://gitee.com/goploy/goploy.git
synced 2024-12-02 04:07:33 +08:00
commit
018c54daf1
@ -20,11 +20,14 @@ import (
|
||||
"github.com/zhenorzz/goploy/cmd/server/task"
|
||||
"github.com/zhenorzz/goploy/config"
|
||||
"github.com/zhenorzz/goploy/internal/model"
|
||||
"github.com/zhenorzz/goploy/internal/pipeline/docker"
|
||||
"github.com/zhenorzz/goploy/internal/pkg"
|
||||
"github.com/zhenorzz/goploy/internal/pkg/cmd"
|
||||
"github.com/zhenorzz/goploy/internal/repo"
|
||||
"github.com/zhenorzz/goploy/internal/server"
|
||||
"github.com/zhenorzz/goploy/internal/server/response"
|
||||
"github.com/zhenorzz/goploy/internal/transmitter"
|
||||
"gopkg.in/yaml.v3"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@ -628,23 +631,51 @@ func (Deploy) Rebuild(gp *server.Goploy) server.Response {
|
||||
ch := make(chan bool, len(projectServers))
|
||||
for _, projectServer := range projectServers {
|
||||
go func(projectServer model.ProjectServer) {
|
||||
var dockerScript docker.Script
|
||||
destDir := path.Join(project.SymlinkPath, project.LastPublishToken)
|
||||
cmdEntity := cmd.New(projectServer.Server.OS)
|
||||
afterDeployCommands := []string{cmdEntity.Symlink(destDir, project.Path), cmdEntity.ChangeDirTime(destDir)}
|
||||
if project.Script.AfterDeploy.Content != "" {
|
||||
scriptName := fmt.Sprintf("goploy-after-deploy-p%d-s%d.%s", project.ID, projectServer.ServerID, pkg.GetScriptExt(project.Script.AfterDeploy.Mode))
|
||||
|
||||
if project.Script.AfterDeploy.Content != "" {
|
||||
scriptContent := project.ReplaceVars(project.Script.AfterDeploy.Content)
|
||||
scriptContent = projectServer.ReplaceVars(scriptContent)
|
||||
err = os.WriteFile(path.Join(config.GetProjectPath(project.ID), scriptName), []byte(project.ReplaceVars(project.Script.AfterDeploy.Content)), 0755)
|
||||
|
||||
if project.Script.AfterDeploy.Mode == "yaml" {
|
||||
if err := yaml.Unmarshal([]byte(scriptContent), &dockerScript); err != nil {
|
||||
log.Error("projectID:" + strconv.FormatInt(project.ID, 10) + " unmarshal yaml script fail err: " + err.Error())
|
||||
ch <- false
|
||||
return
|
||||
}
|
||||
|
||||
for stepIndex, step := range dockerScript.Steps {
|
||||
scriptName = fmt.Sprintf("goploy-after-deploy-p%d-s%d-y%d", project.ID, projectServer.ServerID, stepIndex)
|
||||
// delete the script
|
||||
step.Commands = append(step.Commands, fmt.Sprintf("rm -f %s", docker.GetDockerProjectScriptPath(project.ID, scriptName)))
|
||||
scriptContent = strings.Join(step.Commands, "\n")
|
||||
err = os.WriteFile(path.Join(config.GetProjectPath(project.ID), scriptName), []byte(scriptContent), 0755)
|
||||
if err != nil {
|
||||
log.Error("projectID:" + strconv.FormatInt(project.ID, 10) + " write file err: " + err.Error())
|
||||
ch <- false
|
||||
return
|
||||
}
|
||||
afterDeployScriptPath := path.Join(project.Path, scriptName)
|
||||
afterDeployCommands = append(afterDeployCommands, cmdEntity.Script(project.Script.AfterDeploy.Mode, afterDeployScriptPath))
|
||||
afterDeployCommands = append(afterDeployCommands, cmdEntity.Remove(afterDeployScriptPath))
|
||||
}
|
||||
} else {
|
||||
err = os.WriteFile(path.Join(config.GetProjectPath(project.ID), scriptName), []byte(scriptContent), 0755)
|
||||
if err != nil {
|
||||
log.Error("projectID:" + strconv.FormatInt(project.ID, 10) + " write file err: " + err.Error())
|
||||
ch <- false
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
transmitterEntity := transmitter.New(project, projectServer)
|
||||
if transmitterOutput, err := transmitterEntity.Exec(); err != nil {
|
||||
log.Error("projectID:" + strconv.FormatInt(project.ID, 10) + " transmit exec err: " + err.Error() + ", output: " + transmitterOutput)
|
||||
ch <- false
|
||||
return
|
||||
}
|
||||
|
||||
client, err := projectServer.ToSSHConfig().Dial()
|
||||
if err != nil {
|
||||
log.Error("projectID:" + strconv.FormatInt(project.ID, 10) + " dial err: " + err.Error())
|
||||
@ -652,12 +683,14 @@ func (Deploy) Rebuild(gp *server.Goploy) server.Response {
|
||||
return
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
session, err := client.NewSession()
|
||||
if err != nil {
|
||||
log.Error("projectID:" + strconv.FormatInt(project.ID, 10) + " new session err: " + err.Error())
|
||||
ch <- false
|
||||
return
|
||||
}
|
||||
defer session.Close()
|
||||
|
||||
// check if the path is existed or not
|
||||
if output, err := session.CombinedOutput("cd " + destDir); err != nil {
|
||||
@ -665,7 +698,41 @@ func (Deploy) Rebuild(gp *server.Goploy) server.Response {
|
||||
ch <- false
|
||||
return
|
||||
}
|
||||
|
||||
if project.Script.AfterDeploy.Mode == "yaml" && len(dockerScript.Steps) > 0 {
|
||||
dockerConfig := docker.Config{
|
||||
ProjectID: project.ID,
|
||||
ProjectPath: project.Path,
|
||||
Server: projectServer.Server,
|
||||
}
|
||||
|
||||
if err := dockerConfig.Setup(); err != nil {
|
||||
log.Error("projectID:" + strconv.FormatInt(project.ID, 10) + " setup docker err: " + err.Error())
|
||||
ch <- false
|
||||
return
|
||||
}
|
||||
|
||||
for stepIndex, step := range dockerScript.Steps {
|
||||
step.ScriptName = fmt.Sprintf("goploy-after-deploy-p%d-s%d-y%d", project.ID, projectServer.ServerID, stepIndex)
|
||||
dockerOutput, dockerErr := dockerConfig.Run(step)
|
||||
|
||||
scriptFullName := path.Join(config.GetProjectPath(project.ID), step.ScriptName)
|
||||
_ = os.Remove(scriptFullName)
|
||||
|
||||
if dockerErr != "" {
|
||||
log.Error("projectID:" + strconv.FormatInt(project.ID, 10) + " run docker script err: " + err.Error() + ", detail: " + string(dockerOutput))
|
||||
ch <- false
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
afterDeployCommands := []string{cmdEntity.Symlink(destDir, project.Path), cmdEntity.ChangeDirTime(destDir)}
|
||||
afterDeployScriptPath := path.Join(project.Path, scriptName)
|
||||
afterDeployCommands = append(afterDeployCommands, cmdEntity.Script(project.Script.AfterDeploy.Mode, afterDeployScriptPath))
|
||||
afterDeployCommands = append(afterDeployCommands, cmdEntity.Remove(afterDeployScriptPath))
|
||||
|
||||
session, err = client.NewSession()
|
||||
defer session.Close()
|
||||
if err != nil {
|
||||
log.Error("projectID:" + strconv.FormatInt(project.ID, 10) + " new session err: " + err.Error())
|
||||
ch <- false
|
||||
@ -678,6 +745,8 @@ func (Deploy) Rebuild(gp *server.Goploy) server.Response {
|
||||
ch <- false
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
ch <- true
|
||||
}(projectServer)
|
||||
}
|
||||
|
@ -597,7 +597,7 @@ func (Project) Edit(gp *server.Goploy) server.Response {
|
||||
func (Project) SetAutoDeploy(gp *server.Goploy) server.Response {
|
||||
type ReqData struct {
|
||||
ID int64 `json:"id" validate:"required,gt=0"`
|
||||
AutoDeploy uint8 `json:"autoDeploy" validate:"required,gte=0"`
|
||||
AutoDeploy uint8 `json:"autoDeploy" validate:"oneof=0 1"`
|
||||
}
|
||||
var reqData ReqData
|
||||
if err := gp.Decode(&reqData); err != nil {
|
||||
|
@ -14,10 +14,12 @@ import (
|
||||
"github.com/zhenorzz/goploy/cmd/server/ws"
|
||||
"github.com/zhenorzz/goploy/config"
|
||||
"github.com/zhenorzz/goploy/internal/model"
|
||||
"github.com/zhenorzz/goploy/internal/pipeline/docker"
|
||||
"github.com/zhenorzz/goploy/internal/pkg"
|
||||
"github.com/zhenorzz/goploy/internal/pkg/cmd"
|
||||
"github.com/zhenorzz/goploy/internal/repo"
|
||||
"github.com/zhenorzz/goploy/internal/transmitter"
|
||||
"gopkg.in/yaml.v3"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
@ -261,10 +263,6 @@ func (gsync *Gsync) afterPullScriptStage() error {
|
||||
}
|
||||
|
||||
gsync.PublishTrace.Type = model.AfterPull
|
||||
ext, _ := json.Marshal(struct {
|
||||
Script string `json:"script"`
|
||||
}{gsync.Project.Script.AfterPull.Content})
|
||||
gsync.PublishTrace.Ext = string(ext)
|
||||
return gsync.runLocalScript()
|
||||
}
|
||||
|
||||
@ -279,14 +277,46 @@ func (gsync *Gsync) serverStage() error {
|
||||
project := gsync.Project
|
||||
publishTraceModel := gsync.PublishTrace
|
||||
// write after deploy script for rsync
|
||||
var dockerScript docker.Script
|
||||
scriptName := fmt.Sprintf("goploy-after-deploy-p%d-s%d.%s", project.ID, projectServer.ServerID, pkg.GetScriptExt(project.Script.AfterDeploy.Mode))
|
||||
scriptContent := ""
|
||||
if project.Script.AfterDeploy.Content != "" {
|
||||
scriptContent := project.ReplaceVars(project.Script.AfterDeploy.Content)
|
||||
scriptContent = project.ReplaceVars(project.Script.AfterDeploy.Content)
|
||||
scriptContent = projectServer.ReplaceVars(scriptContent)
|
||||
scriptContent = strings.Replace(scriptContent, "${SERVER_TOTAL_NUMBER}", strconv.Itoa(len(gsync.ProjectServers)), -1)
|
||||
scriptContent = strings.Replace(scriptContent, "${SERVER_SERIAL_NUMBER}", strconv.Itoa(index), -1)
|
||||
|
||||
if project.Script.AfterDeploy.Mode == "yaml" {
|
||||
if err := yaml.Unmarshal([]byte(scriptContent), &dockerScript); err != nil {
|
||||
log.Error(fmt.Sprintf("projectID: %d unmarshal yaml script fail err: %s", project.ID, err))
|
||||
publishTraceModel.Detail = fmt.Sprintf("err: %s", err)
|
||||
publishTraceModel.State = model.Fail
|
||||
if _, err := publishTraceModel.AddRow(); err != nil {
|
||||
log.Errorf(projectLogFormat, project.ID, err)
|
||||
}
|
||||
|
||||
ch <- syncMessage{
|
||||
serverName: projectServer.Server.Name,
|
||||
projectID: project.ID,
|
||||
detail: err.Error(),
|
||||
state: model.ProjectFail,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
for stepIndex, step := range dockerScript.Steps {
|
||||
scriptName = fmt.Sprintf("goploy-after-deploy-p%d-s%d-y%d", project.ID, projectServer.ServerID, stepIndex)
|
||||
// delete the script
|
||||
step.Commands = append(step.Commands, fmt.Sprintf("rm -f %s", docker.GetDockerProjectScriptPath(project.ID, scriptName)))
|
||||
scriptContent = strings.Join(step.Commands, "\n")
|
||||
project.Script.AfterDeploy.ScriptNames = append(project.Script.AfterDeploy.ScriptNames, scriptName)
|
||||
_ = os.WriteFile(path.Join(config.GetProjectPath(project.ID), scriptName), []byte(scriptContent), 0755)
|
||||
}
|
||||
} else {
|
||||
project.Script.AfterDeploy.ScriptNames = append(project.Script.AfterDeploy.ScriptNames, scriptName)
|
||||
_ = os.WriteFile(path.Join(config.GetProjectPath(project.ID), scriptName), []byte(scriptContent), 0755)
|
||||
}
|
||||
}
|
||||
|
||||
transmitterEntity := transmitter.New(project, projectServer)
|
||||
logCmd := transmitterEntity.String()
|
||||
@ -321,6 +351,69 @@ func (gsync *Gsync) serverStage() error {
|
||||
}
|
||||
}
|
||||
|
||||
if project.Script.AfterDeploy.Mode == "yaml" && len(dockerScript.Steps) > 0 {
|
||||
dockerConfig := docker.Config{
|
||||
ProjectID: project.ID,
|
||||
ProjectPath: project.Path,
|
||||
Server: projectServer.Server,
|
||||
}
|
||||
|
||||
if err := dockerConfig.Setup(); err != nil {
|
||||
log.Error(fmt.Sprintf("projectID: %d err: %s", project.ID, err))
|
||||
publishTraceModel.Detail = err.Error()
|
||||
publishTraceModel.State = model.Fail
|
||||
if _, err := publishTraceModel.AddRow(); err != nil {
|
||||
log.Errorf(projectLogFormat, project.ID, err)
|
||||
}
|
||||
ch <- syncMessage{
|
||||
serverName: projectServer.Server.Name,
|
||||
projectID: project.ID,
|
||||
detail: err.Error(),
|
||||
state: model.ProjectFail,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
for stepIndex, step := range dockerScript.Steps {
|
||||
step.ScriptName = fmt.Sprintf("goploy-after-deploy-p%d-s%d-y%d", project.ID, projectServer.ServerID, stepIndex)
|
||||
dockerOutput, dockerErr := dockerConfig.Run(step)
|
||||
|
||||
scriptContent = strings.Join(step.Commands, "\n")
|
||||
publishTraceModel.Type = model.AfterDeploy
|
||||
ext, _ = json.Marshal(struct {
|
||||
ServerID int64 `json:"serverId"`
|
||||
ServerName string `json:"serverName"`
|
||||
Script string `json:"script"`
|
||||
Step string `json:"step"`
|
||||
}{projectServer.ServerID, projectServer.Server.Name, scriptContent, step.Name})
|
||||
publishTraceModel.Ext = string(ext)
|
||||
|
||||
scriptFullName := path.Join(config.GetProjectPath(project.ID), step.ScriptName)
|
||||
_ = os.Remove(scriptFullName)
|
||||
|
||||
if dockerErr != "" {
|
||||
log.Error(fmt.Sprintf("projectID: %d run docker script err: %s", project.ID, dockerErr))
|
||||
publishTraceModel.Detail = fmt.Sprintf("err: %s\noutput: %s", dockerErr, dockerOutput)
|
||||
publishTraceModel.State = model.Fail
|
||||
if _, err := publishTraceModel.AddRow(); err != nil {
|
||||
log.Errorf(projectLogFormat, project.ID, err)
|
||||
}
|
||||
ch <- syncMessage{
|
||||
serverName: projectServer.Server.Name,
|
||||
projectID: project.ID,
|
||||
detail: fmt.Sprintf("err: %s\noutput: %s", dockerErr, dockerOutput),
|
||||
state: model.ProjectFail,
|
||||
}
|
||||
return
|
||||
} else {
|
||||
publishTraceModel.Detail = dockerOutput
|
||||
publishTraceModel.State = model.Success
|
||||
if _, err := publishTraceModel.AddRow(); err != nil {
|
||||
log.Error("projectID: " + strconv.FormatInt(project.ID, 10) + " " + err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var afterDeployCommands []string
|
||||
cmdEntity := cmd.New(projectServer.Server.OS)
|
||||
if len(project.SymlinkPath) != 0 {
|
||||
@ -349,7 +442,7 @@ func (gsync *Gsync) serverStage() error {
|
||||
ServerID int64 `json:"serverId"`
|
||||
ServerName string `json:"serverName"`
|
||||
Script string `json:"script"`
|
||||
}{projectServer.ServerID, projectServer.Server.Name, completeAfterDeployCmd})
|
||||
}{projectServer.ServerID, projectServer.Server.Name, scriptContent})
|
||||
publishTraceModel.Ext = string(ext)
|
||||
|
||||
client, err := projectServer.ToSSHConfig().Dial()
|
||||
@ -387,7 +480,9 @@ func (gsync *Gsync) serverStage() error {
|
||||
return
|
||||
}
|
||||
defer session.Close()
|
||||
|
||||
log.Trace(fmt.Sprintf("projectID: %d ssh exec: %s", project.ID, completeAfterDeployCmd))
|
||||
|
||||
output, err := session.CombinedOutput(completeAfterDeployCmd)
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("projectID: %d ssh exec err: %s, output: %s", project.ID, err, output))
|
||||
@ -410,6 +505,8 @@ func (gsync *Gsync) serverStage() error {
|
||||
if _, err := publishTraceModel.AddRow(); err != nil {
|
||||
log.Error("projectID: " + strconv.FormatInt(project.ID, 10) + " " + err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
ch <- syncMessage{
|
||||
serverName: projectServer.Server.Name,
|
||||
projectID: project.ID,
|
||||
@ -446,11 +543,6 @@ func (gsync *Gsync) deployFinishScriptStage() error {
|
||||
}
|
||||
|
||||
gsync.PublishTrace.Type = model.DeployFinish
|
||||
ext, _ := json.Marshal(struct {
|
||||
Script string `json:"script"`
|
||||
}{gsync.Project.Script.DeployFinish.Content})
|
||||
gsync.PublishTrace.Ext = string(ext)
|
||||
|
||||
return gsync.runLocalScript()
|
||||
}
|
||||
|
||||
@ -467,7 +559,7 @@ func (gsync *Gsync) runLocalScript() error {
|
||||
})
|
||||
mode = project.Script.AfterPull.Mode
|
||||
content = project.Script.AfterPull.Content
|
||||
scriptName = "goploy-after-pull." + pkg.GetScriptExt(project.Script.AfterPull.Mode)
|
||||
scriptName = "goploy-after-pull"
|
||||
|
||||
case model.DeployFinish:
|
||||
ws.Send(ws.Data{
|
||||
@ -476,7 +568,7 @@ func (gsync *Gsync) runLocalScript() error {
|
||||
})
|
||||
mode = project.Script.DeployFinish.Mode
|
||||
content = project.Script.DeployFinish.Content
|
||||
scriptName = "goploy-deploy-finish." + pkg.GetScriptExt(project.Script.DeployFinish.Mode)
|
||||
scriptName = "goploy-deploy-finish"
|
||||
|
||||
default:
|
||||
return errors.New("not support stage")
|
||||
@ -486,13 +578,76 @@ func (gsync *Gsync) runLocalScript() error {
|
||||
|
||||
commitInfo := gsync.CommitInfo
|
||||
srcPath := config.GetProjectPath(project.ID)
|
||||
scriptFullName := path.Join(srcPath, scriptName)
|
||||
scriptMode := "bash"
|
||||
if mode != "" {
|
||||
scriptMode = mode
|
||||
}
|
||||
scriptText := project.ReplaceVars(commitInfo.ReplaceVars(content))
|
||||
|
||||
// run yaml script by docker
|
||||
if mode == "yaml" {
|
||||
var dockerScript docker.Script
|
||||
err := yaml.Unmarshal([]byte(scriptText), &dockerScript)
|
||||
if err != nil {
|
||||
return errors.New("unmarshal yaml script fail")
|
||||
}
|
||||
|
||||
projectPath, err := filepath.Abs(config.GetProjectPath(project.ID))
|
||||
if err != nil {
|
||||
return fmt.Errorf("get repository abs path err: %s", err)
|
||||
}
|
||||
|
||||
if len(dockerScript.Steps) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
dockerConfig := docker.Config{
|
||||
ProjectID: project.ID,
|
||||
ProjectPath: projectPath,
|
||||
}
|
||||
|
||||
if err = dockerConfig.Setup(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for stepIndex, step := range dockerScript.Steps {
|
||||
scriptText = strings.Join(step.Commands, "\n")
|
||||
tmpScriptName := scriptName + fmt.Sprintf("-y%d", stepIndex)
|
||||
scriptFullName := path.Join(srcPath, tmpScriptName)
|
||||
step.ScriptName = tmpScriptName
|
||||
|
||||
_ = os.WriteFile(scriptFullName, []byte(scriptText), 0755)
|
||||
|
||||
dockerOutput, dockerErr := dockerConfig.Run(step)
|
||||
|
||||
ext, _ := json.Marshal(struct {
|
||||
Script string `json:"script"`
|
||||
Step string `json:"step"`
|
||||
}{scriptText, step.Name})
|
||||
gsync.PublishTrace.Ext = string(ext)
|
||||
|
||||
_ = os.Remove(scriptFullName)
|
||||
|
||||
if dockerErr != "" {
|
||||
gsync.PublishTrace.Detail = dockerErr
|
||||
gsync.PublishTrace.State = model.Fail
|
||||
if _, err := gsync.PublishTrace.AddRow(); err != nil {
|
||||
log.Errorf(projectLogFormat, gsync.Project.ID, err)
|
||||
}
|
||||
return fmt.Errorf("run docker script err: %s", dockerErr)
|
||||
} else {
|
||||
gsync.PublishTrace.Detail = dockerOutput
|
||||
gsync.PublishTrace.State = model.Success
|
||||
if _, err := gsync.PublishTrace.AddRow(); err != nil {
|
||||
log.Errorf(projectLogFormat, gsync.Project.ID, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
scriptName += fmt.Sprintf(".%s", pkg.GetScriptExt(mode))
|
||||
scriptFullName := path.Join(srcPath, scriptName)
|
||||
_ = os.WriteFile(scriptFullName, []byte(scriptText), 0755)
|
||||
|
||||
var commandOptions []string
|
||||
if scriptMode == "cmd" {
|
||||
commandOptions = append(commandOptions, "/C")
|
||||
@ -500,6 +655,11 @@ func (gsync *Gsync) runLocalScript() error {
|
||||
}
|
||||
commandOptions = append(commandOptions, scriptFullName)
|
||||
|
||||
ext, _ := json.Marshal(struct {
|
||||
Script string `json:"script"`
|
||||
}{Script: scriptText})
|
||||
gsync.PublishTrace.Ext = string(ext)
|
||||
|
||||
handler := exec.Command(scriptMode, commandOptions...)
|
||||
handler.Dir = srcPath
|
||||
|
||||
@ -517,8 +677,10 @@ func (gsync *Gsync) runLocalScript() error {
|
||||
if _, err := gsync.PublishTrace.AddRow(); err != nil {
|
||||
log.Errorf(projectLogFormat, gsync.Project.ID, err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// commit id
|
||||
|
28
go.mod
28
go.mod
@ -4,12 +4,13 @@ go 1.18
|
||||
|
||||
require (
|
||||
github.com/Masterminds/squirrel v1.4.0
|
||||
github.com/docker/docker v24.0.7+incompatible
|
||||
github.com/go-ldap/ldap/v3 v3.4.1
|
||||
github.com/go-playground/locales v0.13.0
|
||||
github.com/go-playground/universal-translator v0.17.0
|
||||
github.com/go-sql-driver/mysql v1.5.0
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible
|
||||
github.com/google/uuid v1.1.1
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/gorilla/schema v1.2.0
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/hashicorp/go-version v1.3.0
|
||||
@ -19,22 +20,43 @@ require (
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/vearutop/statigz v1.1.8
|
||||
github.com/wenlng/go-captcha v1.2.5
|
||||
golang.org/x/crypto v0.1.0
|
||||
golang.org/x/crypto v0.14.0
|
||||
gopkg.in/go-playground/validator.v9 v9.31.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20211209120228-48547f28849e // indirect
|
||||
github.com/Microsoft/go-winio v0.6.1 // indirect
|
||||
github.com/containerd/containerd v1.7.9 // indirect
|
||||
github.com/distribution/reference v0.5.0 // indirect
|
||||
github.com/docker/distribution v2.8.3+incompatible // indirect
|
||||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.3 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/klauspost/compress v1.17.3 // indirect
|
||||
github.com/kr/fs v0.1.0 // indirect
|
||||
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect
|
||||
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect
|
||||
github.com/leodido/go-urn v1.2.0 // indirect
|
||||
github.com/moby/patternmatcher v0.6.0 // indirect
|
||||
github.com/moby/sys/sequential v0.5.0 // indirect
|
||||
github.com/moby/term v0.5.0 // indirect
|
||||
github.com/morikuni/aec v1.0.0 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b // indirect
|
||||
github.com/opencontainers/runc v1.1.10 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
golang.org/x/image v0.10.0 // indirect
|
||||
golang.org/x/sys v0.5.0 // indirect
|
||||
golang.org/x/mod v0.11.0 // indirect
|
||||
golang.org/x/net v0.17.0 // indirect
|
||||
golang.org/x/sys v0.13.0 // indirect
|
||||
golang.org/x/time v0.4.0 // indirect
|
||||
golang.org/x/tools v0.10.0 // indirect
|
||||
gopkg.in/go-playground/assert.v1 v1.2.1 // indirect
|
||||
gotest.tools/v3 v3.5.1 // indirect
|
||||
)
|
||||
|
84
go.sum
84
go.sum
@ -1,13 +1,30 @@
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20211209120228-48547f28849e h1:ZU22z/2YRFLyf/P4ZwUYSdNCWsMEI0VeyrFoI2rAhJQ=
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20211209120228-48547f28849e/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
|
||||
github.com/Masterminds/squirrel v1.4.0 h1:he5i/EXixZxrBUWcxzDYMiju9WZ3ld/l7QBNuo/eN3w=
|
||||
github.com/Masterminds/squirrel v1.4.0/go.mod h1:yaPeOnPG5ZRwL9oKdTsO/prlkPbXWZlRVMQ/gGlzIuA=
|
||||
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
|
||||
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
|
||||
github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8=
|
||||
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
|
||||
github.com/bool64/dev v0.2.9 h1:efyGf5pgx4CYWQpCzPEX8a1PgewaCGaEexXa+IYHT/8=
|
||||
github.com/containerd/containerd v1.7.9 h1:KOhK01szQbM80YfW1H6RZKh85PHGqY/9OcEZ35Je8sc=
|
||||
github.com/containerd/containerd v1.7.9/go.mod h1:0/W44LWEYfSHoxBtsHIiNU/duEkgpMokemafHVCpq9Y=
|
||||
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/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0=
|
||||
github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
|
||||
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM=
|
||||
github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.3 h1:u7utq56RUFiynqUzgVMFDymapcOtQ/MZkh3H4QYkxag=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.3/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
@ -19,12 +36,15 @@ github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD87
|
||||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/schema v1.2.0 h1:YufUaxZYCKGFuAq3c96BOhjgd5nmXiOY9NGzF247Tsc=
|
||||
github.com/gorilla/schema v1.2.0/go.mod h1:kgLaKoK1FELgZqMAVxx/5cbj0kT+57qxUrAlIO2eleU=
|
||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||
@ -38,6 +58,10 @@ github.com/hashicorp/go-version v1.3.0 h1:McDWVJIU/y+u1BRV06dPaLfLCaT7fUTJLp5r04
|
||||
github.com/hashicorp/go-version v1.3.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/jlaffaye/ftp v0.0.0-20220301181425-a81b090061fa h1:Cv45cONl1gg0QBv5rvDBrZycQtJtEJlEloN4IIeVhxg=
|
||||
github.com/jlaffaye/ftp v0.0.0-20220301181425-a81b090061fa/go.mod h1:oZaomI+9/et52UBjvNU9LCIqmgt816+7ljXCx0EIPzo=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.17.3 h1:qkRjuerhUU1EmXLYGkSH6EZL+vPSxIrYjLNAK4slzwA=
|
||||
github.com/klauspost/compress v1.17.3/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
|
||||
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw=
|
||||
@ -46,6 +70,20 @@ github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhR
|
||||
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw=
|
||||
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||
github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
|
||||
github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
|
||||
github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
|
||||
github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo=
|
||||
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
|
||||
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
|
||||
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
||||
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b h1:YWuSjZCQAPM8UUBLkYUk1e+rZcvWHJmFb6i6rM44Xs8=
|
||||
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b/go.mod h1:3OVijpioIKYWTqjiG0zfF6wvoJ4fAXGbjdZuI2NgsRQ=
|
||||
github.com/opencontainers/runc v1.1.10 h1:EaL5WeO9lv9wmS6SASjszOeQdSctvpbu0DdBQBizE40=
|
||||
github.com/opencontainers/runc v1.1.10/go.mod h1:+/R6+KmDlh+hOO8NkjmgkG9Qzvypzk0yXxAPYYR65+M=
|
||||
github.com/pelletier/go-toml/v2 v2.0.0-beta.4 h1:GCs8ebsDtEH3RiO78+BvhHqj65d/I6tjESitJZc07Rc=
|
||||
github.com/pelletier/go-toml/v2 v2.0.0-beta.4/go.mod h1:ke6xncR3W76Ba8xnVxkrZG0js6Rd2BsQEAYrfgJ6eQA=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
@ -60,47 +98,64 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1-0.20210427113832-6241f9ab9942 h1:t0lM6y/M5IiUZyvbBTcngso8SZEZICH7is9B6g/obVU=
|
||||
github.com/stretchr/testify v1.7.1-0.20210427113832-6241f9ab9942/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/vearutop/statigz v1.1.8 h1:IJgQHx6EomuYOYd2TzFt3haP+BIzV471zn7aepRiLHA=
|
||||
github.com/vearutop/statigz v1.1.8/go.mod h1:pfzrpvgLRnFeSVZd9iUYrpYDLqbV+RgeCfizr3ZFf44=
|
||||
github.com/wenlng/go-captcha v1.2.5 h1:zA0/fovEl9oAhSg+KwHBwmq99GeeAXknWx6wYKjhjTg=
|
||||
github.com/wenlng/go-captcha v1.2.5/go.mod h1:QgPgpEURSa37gF3GtojNoNRwbMwuatSBx5NXrzASOb0=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
|
||||
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
||||
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
|
||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
|
||||
golang.org/x/image v0.10.0 h1:gXjUUtwtx5yOE0VKWq1CH4IJAClq4UGgUA3i+rpON9M=
|
||||
golang.org/x/image v0.10.0/go.mod h1:jtrku+n79PfroUbvDdeUWMAI+heR786BofxrbiSF+J0=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
|
||||
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
@ -108,16 +163,29 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/time v0.4.0 h1:Z81tqI5ddIoXDPvVQ7/7CC9TnLM7ubaFG2qXYd5BbYY=
|
||||
golang.org/x/time v0.4.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.10.0 h1:tvDr/iQoUqNdohiYm0LmmKcBk+q86lb9EprIUFhHHGg=
|
||||
golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM=
|
||||
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
|
||||
gopkg.in/go-playground/validator.v9 v9.31.0 h1:bmXmP2RSNtFES+bn4uYuHT7iJFJv7Vj+an+ZQdDaD1M=
|
||||
gopkg.in/go-playground/validator.v9 v9.31.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
|
||||
gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
|
||||
|
@ -24,6 +24,7 @@ type ProjectScript struct {
|
||||
AfterDeploy struct {
|
||||
Mode string `json:"mode"`
|
||||
Content string `json:"content"`
|
||||
ScriptNames []string `json:"scriptNames"`
|
||||
} `json:"afterDeploy"`
|
||||
DeployFinish struct {
|
||||
Mode string `json:"mode"`
|
||||
@ -408,6 +409,7 @@ func (p Project) GetDeployList() (Projects, error) {
|
||||
project.branch,
|
||||
project.symlink_path,
|
||||
project.review,
|
||||
project.script,
|
||||
project.last_publish_token,
|
||||
project.auto_deploy,
|
||||
project.deploy_state,
|
||||
@ -436,7 +438,7 @@ func (p Project) GetDeployList() (Projects, error) {
|
||||
projects := Projects{}
|
||||
for rows.Next() {
|
||||
var project Project
|
||||
|
||||
var script []byte
|
||||
if err := rows.Scan(
|
||||
&project.ID,
|
||||
&project.Name,
|
||||
@ -451,12 +453,18 @@ func (p Project) GetDeployList() (Projects, error) {
|
||||
&project.Branch,
|
||||
&project.SymlinkPath,
|
||||
&project.Review,
|
||||
&script,
|
||||
&project.LastPublishToken,
|
||||
&project.AutoDeploy,
|
||||
&project.DeployState,
|
||||
&project.UpdateTime); err != nil {
|
||||
return projects, err
|
||||
}
|
||||
|
||||
if err = json.Unmarshal(script, &project.Script); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
projects = append(projects, project)
|
||||
}
|
||||
|
||||
|
212
internal/pipeline/docker/docker.go
Normal file
212
internal/pipeline/docker/docker.go
Normal file
@ -0,0 +1,212 @@
|
||||
package docker
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/mount"
|
||||
"github.com/docker/docker/api/types/registry"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
"github.com/docker/docker/pkg/stdcopy"
|
||||
"github.com/google/uuid"
|
||||
"github.com/zhenorzz/goploy/config"
|
||||
"github.com/zhenorzz/goploy/internal/model"
|
||||
"path"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
type Script struct {
|
||||
Steps []Step `yaml:"steps"`
|
||||
}
|
||||
|
||||
type Step struct {
|
||||
Name string `yaml:"name"`
|
||||
Commands []string `yaml:"commands"`
|
||||
Image string `yaml:"image"`
|
||||
ImageOptions struct {
|
||||
Registry string `yaml:"registry"`
|
||||
Username string `yaml:"username"`
|
||||
Password string `yaml:"password"`
|
||||
Dockerfile string `yaml:"dockerfile"`
|
||||
} `yaml:"imageOptions"`
|
||||
ScriptName string
|
||||
ContainerName string
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
ProjectID int64
|
||||
ProjectPath string
|
||||
Server model.Server
|
||||
Client client.APIClient
|
||||
}
|
||||
|
||||
func GetDockerProjectPath(projectID int64) string {
|
||||
return fmt.Sprintf("/data/www/repository/project_%d", projectID)
|
||||
}
|
||||
|
||||
func GetDockerProjectScriptPath(projectID int64, scriptName string) string {
|
||||
return path.Join(GetDockerProjectPath(projectID), scriptName)
|
||||
}
|
||||
|
||||
func (c *Config) Setup() (err error) {
|
||||
if c.Server.IP != "" {
|
||||
c.Client, err = client.NewClientWithOpts(client.WithHost(fmt.Sprintf("tcp://%s:2375", c.Server.IP)), client.WithAPIVersionNegotiation())
|
||||
} else {
|
||||
c.Client, err = client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("connect docker err: %s", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Config) Run(step Step) (outStr string, errStr string) {
|
||||
defer func() {
|
||||
c.Destroy(step)
|
||||
}()
|
||||
|
||||
step.ContainerName = uuid.New().String()
|
||||
ctx := context.Background()
|
||||
pullOptions := types.ImagePullOptions{}
|
||||
|
||||
if step.ImageOptions.Registry != "" {
|
||||
step.Image = fmt.Sprintf("%s%s", step.ImageOptions.Registry, step.Image)
|
||||
}
|
||||
|
||||
// build image by dockerfile
|
||||
if step.ImageOptions.Dockerfile != "" {
|
||||
localProjectPath, err := filepath.Abs(config.GetProjectPath(c.ProjectID))
|
||||
if err != nil {
|
||||
errStr = fmt.Sprintf("get local repository abs path err: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
tar, err := archive.TarWithOptions(filepath.Join(localProjectPath, step.ImageOptions.Dockerfile), &archive.TarOptions{})
|
||||
|
||||
_, err = c.Client.ImageBuild(ctx, tar, types.ImageBuildOptions{
|
||||
Tags: []string{step.Image},
|
||||
Dockerfile: "Dockerfile",
|
||||
Remove: true,
|
||||
ForceRemove: true,
|
||||
})
|
||||
if err != nil {
|
||||
errStr = fmt.Sprintf("build image err: %s", err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// pull image from private registry
|
||||
if step.ImageOptions.Username != "" && step.ImageOptions.Password != "" {
|
||||
authConfig := registry.AuthConfig{
|
||||
Username: step.ImageOptions.Username,
|
||||
Password: step.ImageOptions.Password,
|
||||
}
|
||||
authConfigBytes, _ := json.Marshal(authConfig)
|
||||
authConfigEncoded := base64.URLEncoding.EncodeToString(authConfigBytes)
|
||||
pullOptions.RegistryAuth = authConfigEncoded
|
||||
}
|
||||
|
||||
_, err := c.Client.ImagePull(ctx, step.Image, pullOptions)
|
||||
if err != nil {
|
||||
errStr = fmt.Sprintf("pull docker image err: %s", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
dockerProjectPath := GetDockerProjectPath(c.ProjectID)
|
||||
|
||||
hostConfig := &container.HostConfig{
|
||||
Mounts: []mount.Mount{
|
||||
{
|
||||
Type: mount.TypeBind,
|
||||
Source: c.ProjectPath,
|
||||
Target: dockerProjectPath,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
_, err := c.Client.ContainerCreate(ctx, &container.Config{
|
||||
Image: step.Image,
|
||||
Cmd: []string{GetDockerProjectScriptPath(c.ProjectID, step.ScriptName)},
|
||||
Entrypoint: []string{"/bin/sh"},
|
||||
WorkingDir: dockerProjectPath,
|
||||
AttachStdin: false,
|
||||
AttachStdout: true,
|
||||
AttachStderr: true,
|
||||
}, hostConfig, nil, nil, step.ContainerName)
|
||||
|
||||
// if err is image does not exist, re-pull image and re-create container
|
||||
if client.IsErrNotFound(err) && step.ImageOptions.Dockerfile == "" {
|
||||
_, err = c.Client.ImagePull(ctx, step.Image, pullOptions)
|
||||
if err != nil {
|
||||
errStr = fmt.Sprintf("pull docker image twice err: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = c.Client.ContainerCreate(ctx, &container.Config{
|
||||
Image: step.Image,
|
||||
Cmd: []string{GetDockerProjectScriptPath(c.ProjectID, step.ScriptName)},
|
||||
Entrypoint: []string{"/bin/sh"},
|
||||
WorkingDir: dockerProjectPath,
|
||||
AttachStdin: false,
|
||||
AttachStdout: true,
|
||||
AttachStderr: true,
|
||||
}, hostConfig, nil, nil, step.ContainerName)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
errStr = fmt.Sprintf("create docker container err: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err := c.Client.ContainerStart(ctx, step.ContainerName, types.ContainerStartOptions{}); err != nil {
|
||||
errStr = fmt.Sprintf("start docker container err: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
statusCh, errCh := c.Client.ContainerWait(ctx, step.ContainerName, container.WaitConditionNotRunning)
|
||||
select {
|
||||
case err := <-errCh:
|
||||
if err != nil {
|
||||
errStr = fmt.Sprintf("wait docker container err: %s", err)
|
||||
break
|
||||
}
|
||||
case <-statusCh:
|
||||
}
|
||||
|
||||
if errStr != "" {
|
||||
return
|
||||
}
|
||||
|
||||
out, err := c.Client.ContainerLogs(ctx, step.ContainerName, types.ContainerLogsOptions{ShowStdout: true, ShowStderr: true})
|
||||
if err != nil {
|
||||
errStr = fmt.Sprintf("logs docker container err: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
var dockerOutbuf, dockerErrbuf bytes.Buffer
|
||||
stdcopy.StdCopy(&dockerOutbuf, &dockerErrbuf, out)
|
||||
defer out.Close()
|
||||
|
||||
if dockerErrbuf.Len() > 0 {
|
||||
errStr = fmt.Sprintf("run docker script err: %s", dockerErrbuf.String())
|
||||
return
|
||||
}
|
||||
|
||||
return dockerOutbuf.String(), errStr
|
||||
}
|
||||
|
||||
func (c *Config) Destroy(step Step) {
|
||||
ctx := context.Background()
|
||||
_ = c.Client.ContainerKill(ctx, step.ContainerName, "9")
|
||||
_ = c.Client.ContainerRemove(ctx, step.ContainerName, types.ContainerRemoveOptions{
|
||||
RemoveVolumes: true,
|
||||
RemoveLinks: false,
|
||||
Force: true,
|
||||
})
|
||||
}
|
@ -24,6 +24,9 @@ func (ct customTransmitter) String() string {
|
||||
scriptVars := map[string]string{
|
||||
"${AFTER_DEPLOY_FILENAME}": fmt.Sprintf("goploy-after-deploy-p%d-s%d.%s", project.ID, server.ServerID, pkg.GetScriptExt(project.Script.AfterDeploy.Mode)),
|
||||
}
|
||||
for index, scriptName := range project.Script.AfterDeploy.ScriptNames {
|
||||
scriptVars[fmt.Sprintf("${AFTER_DEPLOY_FILENAME_YAML_%d}", index)] = scriptName
|
||||
}
|
||||
for key, value := range scriptVars {
|
||||
script = strings.Replace(script, key, value, -1)
|
||||
}
|
||||
|
@ -5,7 +5,6 @@
|
||||
package transmitter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/zhenorzz/goploy/config"
|
||||
"github.com/zhenorzz/goploy/internal/model"
|
||||
"github.com/zhenorzz/goploy/internal/pkg"
|
||||
@ -36,10 +35,12 @@ func (rt rsyncTransmitter) args() []string {
|
||||
}
|
||||
|
||||
rsyncOption, _ := pkg.ParseCommandLine(projectServer.ReplaceVars(project.ReplaceVars(project.TransferOption)))
|
||||
rsyncOption = append([]string{
|
||||
"--include",
|
||||
fmt.Sprintf("goploy-after-deploy-p%d-s%d.%s", project.ID, projectServer.ServerID, pkg.GetScriptExt(project.Script.AfterDeploy.Mode)),
|
||||
}, rsyncOption...)
|
||||
var includes []string
|
||||
for _, scriptName := range project.Script.AfterDeploy.ScriptNames {
|
||||
includes = append(includes, "--include", scriptName)
|
||||
}
|
||||
|
||||
rsyncOption = append(includes, rsyncOption...)
|
||||
rsyncOption = append(rsyncOption, "-e", projectServer.ToSSHOption())
|
||||
|
||||
if projectServer.Server.OS == model.ServerOSLinux {
|
||||
|
@ -5,7 +5,6 @@
|
||||
package transmitter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/pkg/sftp"
|
||||
"github.com/zhenorzz/goploy/config"
|
||||
"github.com/zhenorzz/goploy/internal/model"
|
||||
@ -97,7 +96,7 @@ func (st sftpTransmitter) Exec() (string, error) {
|
||||
}
|
||||
nextItem = ""
|
||||
}
|
||||
includes = append(includes, fmt.Sprintf("goploy-after-deploy-p%d-s%d.%s", project.ID, st.ProjectServer.ServerID, pkg.GetScriptExt(project.Script.AfterDeploy.Mode)))
|
||||
includes = append(includes, project.Script.AfterDeploy.ScriptNames...)
|
||||
|
||||
srcPath := config.GetProjectPath(project.ID) + "/"
|
||||
destPath := project.Path
|
||||
|
@ -45,6 +45,7 @@ export interface PublishTraceExt {
|
||||
diff: string
|
||||
script: string
|
||||
command: string
|
||||
step: string
|
||||
}
|
||||
|
||||
export class DeployList extends Request {
|
||||
|
@ -6,6 +6,7 @@ const scriptLang = {
|
||||
{ label: 'python', value: 'python', lang: 'python' },
|
||||
{ label: 'php', value: 'php', lang: 'php' },
|
||||
{ label: 'bat', value: 'cmd', lang: 'batchfile' },
|
||||
{ label: 'yaml', value: 'yaml', lang: 'yaml' },
|
||||
],
|
||||
getScriptLang: function (mode = '') {
|
||||
if (mode !== '') {
|
||||
|
@ -245,7 +245,7 @@
|
||||
{{ projectRow.repoType }}
|
||||
</span>
|
||||
<span
|
||||
v-if="localTraceList[PublishTraceType.Pull].state === 1"
|
||||
v-if="localTraceList[PublishTraceType.Pull][0].state === 1"
|
||||
class="icon-success"
|
||||
></span>
|
||||
<span v-else class="icon-fail"></span>
|
||||
@ -253,51 +253,51 @@
|
||||
</el-row>
|
||||
<el-row>
|
||||
Time:
|
||||
{{ localTraceList[PublishTraceType.Pull].updateTime }}
|
||||
{{ localTraceList[PublishTraceType.Pull][0].updateTime }}
|
||||
</el-row>
|
||||
<template v-if="localTraceList[PublishTraceType.Pull].state !== 0">
|
||||
<template v-if="localTraceList[PublishTraceType.Pull][0].state !== 0">
|
||||
<el-row>
|
||||
Branch:
|
||||
{{ localTraceList[PublishTraceType.Pull]['branch'] }}
|
||||
{{ localTraceList[PublishTraceType.Pull][0]['branch'] }}
|
||||
</el-row>
|
||||
<el-row>
|
||||
Commit:
|
||||
<RepoURL
|
||||
:url="projectRow.url"
|
||||
:suffix="`/commit/${
|
||||
localTraceList[PublishTraceType.Pull]['commit']
|
||||
localTraceList[PublishTraceType.Pull][0]['commit']
|
||||
}`"
|
||||
:text="localTraceList[PublishTraceType.Pull]['commit']"
|
||||
:text="localTraceList[PublishTraceType.Pull][0]['commit']"
|
||||
>
|
||||
</RepoURL>
|
||||
</el-row>
|
||||
<el-row>
|
||||
Message:
|
||||
{{ localTraceList[PublishTraceType.Pull]['message'] }}
|
||||
{{ localTraceList[PublishTraceType.Pull][0]['message'] }}
|
||||
</el-row>
|
||||
<el-row>
|
||||
Author:
|
||||
{{ localTraceList[PublishTraceType.Pull]['author'] }}
|
||||
{{ localTraceList[PublishTraceType.Pull][0]['author'] }}
|
||||
</el-row>
|
||||
<el-row>
|
||||
Datetime:
|
||||
{{
|
||||
localTraceList[PublishTraceType.Pull]['timestamp']
|
||||
localTraceList[PublishTraceType.Pull][0]['timestamp']
|
||||
? parseTime(
|
||||
localTraceList[PublishTraceType.Pull]['timestamp']
|
||||
localTraceList[PublishTraceType.Pull][0]['timestamp']
|
||||
)
|
||||
: ''
|
||||
}}
|
||||
</el-row>
|
||||
<el-row>
|
||||
<span style="white-space: pre-line">
|
||||
{{ localTraceList[PublishTraceType.Pull]['diff'] }}
|
||||
{{ localTraceList[PublishTraceType.Pull][0]['diff'] }}
|
||||
</span>
|
||||
</el-row>
|
||||
</template>
|
||||
<el-row v-else style="margin: 5px 0">
|
||||
<span style="white-space: pre-line; padding: 5px 0">
|
||||
{{ localTraceList[PublishTraceType.Pull].detail }}
|
||||
{{ localTraceList[PublishTraceType.Pull][0].detail }}
|
||||
</span>
|
||||
</el-row>
|
||||
</div>
|
||||
@ -308,47 +308,56 @@
|
||||
<el-row style="margin: 5px 0" class="project-title">
|
||||
<span style="margin-right: 5px">After Pull</span>
|
||||
<span
|
||||
v-if="localTraceList[PublishTraceType.AfterPull].state === 1"
|
||||
v-if="
|
||||
!localTraceList[PublishTraceType.AfterPull]
|
||||
.map((localTrace) => localTrace.state)
|
||||
.includes(0)
|
||||
"
|
||||
class="icon-success"
|
||||
></span>
|
||||
<span v-else class="icon-fail"></span>
|
||||
</el-row>
|
||||
<el-row>
|
||||
Time: {{ localTraceList[PublishTraceType.AfterPull].updateTime }}
|
||||
<div
|
||||
v-for="(trace, traceKey) in localTraceList[
|
||||
PublishTraceType.AfterPull
|
||||
]"
|
||||
:key="traceKey"
|
||||
>
|
||||
<el-divider
|
||||
v-if="traceKey !== 0"
|
||||
border-style="dashed"
|
||||
style="margin: 0"
|
||||
/>
|
||||
<el-row
|
||||
v-if="trace.step && trace.step !== ''"
|
||||
style="margin-top: 5px"
|
||||
>
|
||||
Step: {{ trace.step }}
|
||||
</el-row>
|
||||
<el-row> Time: {{ trace.updateTime }} </el-row>
|
||||
<el-row style="width: 100%">
|
||||
<div>Script:</div>
|
||||
<pre style="white-space: pre-line">
|
||||
{{ localTraceList[PublishTraceType.AfterPull].script }}
|
||||
</pre>
|
||||
</el-row>
|
||||
<div
|
||||
v-loading="
|
||||
traceDetail[localTraceList[PublishTraceType.AfterPull].id] === ''
|
||||
"
|
||||
style="margin: 5px 0"
|
||||
{{ trace.script }}
|
||||
</pre
|
||||
>
|
||||
</el-row>
|
||||
<div v-loading="traceDetail[trace.id] === ''" style="margin: 5px 0">
|
||||
<span>[goploy ~]#</span>
|
||||
<el-button
|
||||
v-if="
|
||||
localTraceList[PublishTraceType.AfterPull].state === 1 &&
|
||||
!(localTraceList[PublishTraceType.AfterPull].id in traceDetail)
|
||||
"
|
||||
v-if="trace.state === 1 && !(trace.id in traceDetail)"
|
||||
type="primary"
|
||||
link
|
||||
@click="
|
||||
getPublishTraceDetail(
|
||||
localTraceList[PublishTraceType.AfterPull]
|
||||
)
|
||||
"
|
||||
@click="getPublishTraceDetail(trace)"
|
||||
>
|
||||
{{ $t('deployPage.showDetail') }}
|
||||
</el-button>
|
||||
<span v-else style="white-space: pre-line; padding: 5px 0">
|
||||
{{ traceDetail[localTraceList[PublishTraceType.AfterPull].id] }}
|
||||
{{ traceDetail[trace.id] }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-tabs v-model="activeRomoteTracePane" style="width: 100%">
|
||||
<el-tab-pane
|
||||
v-for="(item, serverName) in remoteTraceList"
|
||||
@ -356,13 +365,28 @@
|
||||
:label="serverName"
|
||||
:name="serverName"
|
||||
>
|
||||
<div v-for="(trace, key) in item" :key="key">
|
||||
<template v-if="trace.type === PublishTraceType.BeforeDeploy">
|
||||
<div v-for="(traceList, key) in item" :key="key">
|
||||
<template v-if="Number(key) === PublishTraceType.BeforeDeploy">
|
||||
<el-row style="margin: 5px 0" class="project-title">
|
||||
<span style="margin-right: 5px">Before deploy</span>
|
||||
<span v-if="trace.state === 1" class="icon-success"></span>
|
||||
<span
|
||||
v-if="!traceList.map((trace) => trace.state).includes(0)"
|
||||
class="icon-success"
|
||||
></span>
|
||||
<span v-else class="icon-fail"></span>
|
||||
</el-row>
|
||||
<div v-for="(trace, traceKey) in traceList" :key="traceKey">
|
||||
<el-divider
|
||||
v-if="traceKey !== 0"
|
||||
border-style="dashed"
|
||||
style="margin: 0"
|
||||
/>
|
||||
<el-row
|
||||
v-if="trace.step && trace.step !== ''"
|
||||
style="margin-top: 5px"
|
||||
>
|
||||
Step: {{ trace.step }}
|
||||
</el-row>
|
||||
<el-row style="margin: 5px 0">
|
||||
Time: {{ trace.updateTime }}
|
||||
</el-row>
|
||||
@ -384,15 +408,20 @@
|
||||
{{ traceDetail[trace.id] }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="trace.type === PublishTraceType.Deploy">
|
||||
<template v-else-if="Number(key) === PublishTraceType.Deploy">
|
||||
<el-row style="margin: 5px 0" class="project-title">
|
||||
<span style="margin-right: 5px; text-transform: capitalize">
|
||||
{{ projectRow.transferType }}
|
||||
</span>
|
||||
<span v-if="trace.state === 1" class="icon-success"></span>
|
||||
<span
|
||||
v-if="!traceList.map((trace) => trace.state).includes(0)"
|
||||
class="icon-success"
|
||||
></span>
|
||||
<span v-else class="icon-fail"></span>
|
||||
</el-row>
|
||||
<div v-for="(trace, traceKey) in traceList" :key="traceKey">
|
||||
<el-row style="margin: 5px 0">
|
||||
Time: {{ trace.updateTime }}
|
||||
</el-row>
|
||||
@ -411,17 +440,40 @@
|
||||
{{ traceDetail[trace.id] }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="trace.type === PublishTraceType.AfterDeploy">
|
||||
<template
|
||||
v-else-if="Number(key) === PublishTraceType.AfterDeploy"
|
||||
>
|
||||
<el-row style="margin: 5px 0" class="project-title">
|
||||
<span style="margin-right: 5px">After deploy</span>
|
||||
<span v-if="trace.state === 1" class="icon-success"></span>
|
||||
<span
|
||||
v-if="!traceList.map((trace) => trace.state).includes(0)"
|
||||
class="icon-success"
|
||||
></span>
|
||||
<span v-else class="icon-fail"></span>
|
||||
</el-row>
|
||||
<div v-for="(trace, traceKey) in traceList" :key="traceKey">
|
||||
<el-divider
|
||||
v-if="traceKey !== 0"
|
||||
border-style="dashed"
|
||||
style="margin: 0"
|
||||
/>
|
||||
<el-row
|
||||
v-if="trace.step && trace.step !== ''"
|
||||
style="margin-top: 5px"
|
||||
>
|
||||
Step: {{ trace.step }}
|
||||
</el-row>
|
||||
<el-row style="margin: 5px 0">
|
||||
Time: {{ trace.updateTime }}
|
||||
</el-row>
|
||||
<el-row>Script: {{ trace.script }}</el-row>
|
||||
<el-row>
|
||||
Script:
|
||||
<pre style="white-space: pre-line">
|
||||
{{ trace.script }}
|
||||
</pre>
|
||||
</el-row>
|
||||
<div
|
||||
v-loading="traceDetail[trace.id] === ''"
|
||||
style="margin: 5px 0"
|
||||
@ -439,6 +491,7 @@
|
||||
{{ traceDetail[trace.id] }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
@ -450,53 +503,54 @@
|
||||
<el-row style="margin: 5px 0" class="project-title">
|
||||
<span style="margin-right: 5px">Deploy Finish</span>
|
||||
<span
|
||||
v-if="localTraceList[PublishTraceType.DeployFinish].state === 1"
|
||||
v-if="
|
||||
!localTraceList[PublishTraceType.DeployFinish]
|
||||
.map((localTrace) => localTrace.state)
|
||||
.includes(0)
|
||||
"
|
||||
class="icon-success"
|
||||
></span>
|
||||
<span v-else class="icon-fail"></span>
|
||||
</el-row>
|
||||
<div
|
||||
v-for="(trace, traceKey) in localTraceList[
|
||||
PublishTraceType.DeployFinish
|
||||
]"
|
||||
:key="traceKey"
|
||||
>
|
||||
<el-row
|
||||
v-if="trace.step && trace.step !== ''"
|
||||
style="margin-top: 5px"
|
||||
>
|
||||
Step: {{ trace.step }}
|
||||
</el-row>
|
||||
<el-row>
|
||||
Time: {{ localTraceList[PublishTraceType.DeployFinish].updateTime }}
|
||||
Time:
|
||||
{{ trace.updateTime }}
|
||||
</el-row>
|
||||
<el-row style="width: 100%">
|
||||
<div>Script:</div>
|
||||
<pre style="white-space: pre-line">
|
||||
{{ localTraceList[PublishTraceType.DeployFinish].script }}
|
||||
</pre>
|
||||
</el-row>
|
||||
<div
|
||||
v-loading="
|
||||
traceDetail[localTraceList[PublishTraceType.DeployFinish].id] ===
|
||||
''
|
||||
"
|
||||
style="margin: 5px 0"
|
||||
{{ trace.script }}
|
||||
</pre
|
||||
>
|
||||
</el-row>
|
||||
<div v-loading="traceDetail[trace.id] === ''" style="margin: 5px 0">
|
||||
<span>[goploy ~]#</span>
|
||||
<el-button
|
||||
v-if="
|
||||
localTraceList[PublishTraceType.DeployFinish].state === 1 &&
|
||||
!(
|
||||
localTraceList[PublishTraceType.DeployFinish].id in
|
||||
traceDetail
|
||||
)
|
||||
"
|
||||
v-if="trace.state === 1 && !(trace.id in traceDetail)"
|
||||
type="primary"
|
||||
link
|
||||
@click="
|
||||
getPublishTraceDetail(
|
||||
localTraceList[PublishTraceType.DeployFinish]
|
||||
)
|
||||
"
|
||||
@click="getPublishTraceDetail(trace)"
|
||||
>
|
||||
{{ $t('deployPage.showDetail') }}
|
||||
</el-button>
|
||||
<span v-else style="white-space: pre-line; padding: 5px 0">
|
||||
{{
|
||||
traceDetail[localTraceList[PublishTraceType.DeployFinish].id]
|
||||
}}
|
||||
{{ traceDetail[trace.id] }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-row>
|
||||
</el-row>
|
||||
</el-dialog>
|
||||
@ -581,7 +635,7 @@ const shortcuts = [
|
||||
const userOption = ref<NamespaceUserOption['datagram']['list']>([])
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(val: typeof props['modelValue']) => {
|
||||
(val: (typeof props)['modelValue']) => {
|
||||
if (val === true) {
|
||||
clearFilterParams()
|
||||
getPreviewList(props.projectRow.id)
|
||||
@ -607,9 +661,11 @@ const gitTraceList = ref<(PublishTraceData & PublishTraceExt)[]>([])
|
||||
const pagination = reactive({ page: 1, rows: 11, total: 0 })
|
||||
const traceDetail = ref<Record<number, string>>({})
|
||||
const publishToken = ref('')
|
||||
const localTraceList = ref<(PublishTraceData & PublishTraceExt)[]>([])
|
||||
const localTraceList = ref<
|
||||
Record<number, (PublishTraceData & PublishTraceExt)[]>
|
||||
>({})
|
||||
const remoteTraceList = ref<
|
||||
Record<string, (PublishTraceData & PublishTraceExt)[]>
|
||||
Record<string, Record<number, (PublishTraceData & PublishTraceExt)[]>>
|
||||
>({})
|
||||
const filterlength = computed(() => {
|
||||
let number = 0
|
||||
@ -671,7 +727,7 @@ const getPreviewList = (projectId: number) => {
|
||||
publishToken.value = gitTraceList.value[0].token
|
||||
getPublishTrace(publishToken.value)
|
||||
} else {
|
||||
localTraceList.value = []
|
||||
localTraceList.value = {}
|
||||
remoteTraceList.value = {}
|
||||
}
|
||||
pagination.total = response.data.pagination.total
|
||||
@ -705,7 +761,7 @@ function getPublishTrace(publishToken: string) {
|
||||
}
|
||||
return element as PublishTraceData & PublishTraceExt
|
||||
})
|
||||
localTraceList.value = []
|
||||
localTraceList.value = {}
|
||||
remoteTraceList.value = {}
|
||||
for (const trace of publishTraceList) {
|
||||
if (trace.detail !== '') {
|
||||
@ -720,7 +776,10 @@ function getPublishTrace(publishToken: string) {
|
||||
PublishTraceType.DeployFinish,
|
||||
].includes(trace.type)
|
||||
) {
|
||||
localTraceList.value[trace.type] = trace
|
||||
if (!localTraceList.value[trace.type]) {
|
||||
localTraceList.value[trace.type] = []
|
||||
}
|
||||
localTraceList.value[trace.type].push(trace)
|
||||
} else if (
|
||||
[
|
||||
PublishTraceType.BeforeDeploy,
|
||||
@ -729,9 +788,13 @@ function getPublishTrace(publishToken: string) {
|
||||
].includes(trace.type)
|
||||
) {
|
||||
if (!remoteTraceList.value[trace.serverName]) {
|
||||
remoteTraceList.value[trace.serverName] = []
|
||||
remoteTraceList.value[trace.serverName] = {}
|
||||
}
|
||||
remoteTraceList.value[trace.serverName].push(trace)
|
||||
if (!remoteTraceList.value[trace.serverName][trace.type]) {
|
||||
remoteTraceList.value[trace.serverName][trace.type] = []
|
||||
}
|
||||
|
||||
remoteTraceList.value[trace.serverName][trace.type].push(trace)
|
||||
}
|
||||
}
|
||||
activeRomoteTracePane.value = Object.keys(remoteTraceList.value)[0]
|
||||
|
Loading…
Reference in New Issue
Block a user