2020-08-04 14:28:25 +08:00
|
|
|
package controller
|
|
|
|
|
|
|
|
import (
|
2021-02-12 23:05:06 +08:00
|
|
|
"bytes"
|
2020-08-04 14:28:25 +08:00
|
|
|
"database/sql"
|
2021-02-12 23:05:06 +08:00
|
|
|
"encoding/json"
|
2020-09-25 20:05:25 +08:00
|
|
|
"errors"
|
2020-08-04 14:28:25 +08:00
|
|
|
"github.com/zhenorzz/goploy/core"
|
|
|
|
"github.com/zhenorzz/goploy/model"
|
|
|
|
"github.com/zhenorzz/goploy/service"
|
|
|
|
"github.com/zhenorzz/goploy/utils"
|
2021-03-26 17:00:18 +08:00
|
|
|
"io/ioutil"
|
2020-09-25 20:05:25 +08:00
|
|
|
"net/http"
|
|
|
|
"net/url"
|
2021-02-12 23:05:06 +08:00
|
|
|
"path"
|
2020-08-04 14:28:25 +08:00
|
|
|
"strconv"
|
|
|
|
"strings"
|
2020-09-25 20:05:25 +08:00
|
|
|
"time"
|
2020-08-04 14:28:25 +08:00
|
|
|
|
|
|
|
"github.com/google/uuid"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Deploy struct
|
|
|
|
type Deploy Controller
|
|
|
|
|
2020-08-15 13:38:06 +08:00
|
|
|
// GetList -
|
2020-09-25 20:05:25 +08:00
|
|
|
func (Deploy) GetList(gp *core.Goploy) *core.Response {
|
2020-08-04 14:28:25 +08:00
|
|
|
projects, err := model.Project{
|
|
|
|
NamespaceID: gp.Namespace.ID,
|
2020-08-17 18:24:15 +08:00
|
|
|
UserID: gp.UserInfo.ID,
|
|
|
|
}.GetUserProjectList()
|
2020-08-04 14:28:25 +08:00
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
2020-09-26 11:45:44 +08:00
|
|
|
return &core.Response{
|
|
|
|
Data: struct {
|
|
|
|
Project model.Projects `json:"list"`
|
|
|
|
}{Project: projects},
|
|
|
|
}
|
2020-08-04 14:28:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// GetPreview deploy detail
|
2020-09-25 20:05:25 +08:00
|
|
|
func (Deploy) GetPreview(gp *core.Goploy) *core.Response {
|
2020-08-04 14:28:25 +08:00
|
|
|
pagination, err := model.PaginationFrom(gp.URLQuery)
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
projectID, err := strconv.ParseInt(gp.URLQuery.Get("projectId"), 10, 64)
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
|
|
|
|
userID, err := strconv.ParseInt(gp.URLQuery.Get("userId"), 10, 64)
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
|
|
|
|
state, err := strconv.ParseInt(gp.URLQuery.Get("state"), 10, 64)
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
2021-01-08 20:22:35 +08:00
|
|
|
commitDate := strings.Split(gp.URLQuery.Get("commitDate"), ",")
|
|
|
|
for i, date := range commitDate {
|
|
|
|
tm2, _ := time.Parse("2006-01-02 15:04:05", date)
|
|
|
|
commitDate[i] = strconv.FormatInt(tm2.Unix(), 10)
|
|
|
|
}
|
2020-08-04 14:28:25 +08:00
|
|
|
gitTraceList, pagination, err := model.PublishTrace{
|
|
|
|
ProjectID: projectID,
|
|
|
|
PublisherID: userID,
|
|
|
|
PublishState: int(state),
|
2021-01-08 20:22:35 +08:00
|
|
|
}.GetPreview(
|
|
|
|
gp.URLQuery.Get("branch"),
|
|
|
|
gp.URLQuery.Get("commit"),
|
|
|
|
gp.URLQuery.Get("filename"),
|
|
|
|
commitDate,
|
|
|
|
strings.Split(gp.URLQuery.Get("deployDate"), ","),
|
|
|
|
pagination,
|
|
|
|
)
|
2020-08-04 14:28:25 +08:00
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
2020-09-26 11:45:44 +08:00
|
|
|
return &core.Response{
|
|
|
|
Data: struct {
|
|
|
|
GitTraceList model.PublishTraces `json:"gitTraceList"`
|
|
|
|
Pagination model.Pagination `json:"pagination"`
|
|
|
|
}{GitTraceList: gitTraceList, Pagination: pagination},
|
|
|
|
}
|
2020-08-04 14:28:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// GetDetail deploy detail
|
2020-12-23 17:38:39 +08:00
|
|
|
func (Deploy) GetPublishTrace(gp *core.Goploy) *core.Response {
|
2020-08-04 14:28:25 +08:00
|
|
|
lastPublishToken := gp.URLQuery.Get("lastPublishToken")
|
|
|
|
publishTraceList, err := model.PublishTrace{Token: lastPublishToken}.GetListByToken()
|
|
|
|
if err == sql.ErrNoRows {
|
|
|
|
return &core.Response{Code: core.Error, Message: "No deploy record"}
|
|
|
|
} else if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
2020-09-26 11:45:44 +08:00
|
|
|
return &core.Response{
|
|
|
|
Data: struct {
|
|
|
|
PublishTraceList model.PublishTraces `json:"publishTraceList"`
|
|
|
|
}{PublishTraceList: publishTraceList},
|
|
|
|
}
|
2020-08-04 14:28:25 +08:00
|
|
|
}
|
|
|
|
|
2020-12-23 17:38:39 +08:00
|
|
|
// GetDetail deploy detail
|
|
|
|
func (Deploy) GetPublishTraceDetail(gp *core.Goploy) *core.Response {
|
|
|
|
id, err := strconv.ParseInt(gp.URLQuery.Get("publish_trace_id"), 10, 64)
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
detail, err := model.PublishTrace{ID: id}.GetDetail()
|
|
|
|
if err == sql.ErrNoRows {
|
|
|
|
return &core.Response{Code: core.Error, Message: "No deploy record"}
|
|
|
|
} else if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
return &core.Response{
|
|
|
|
Data: struct {
|
|
|
|
Detail string `json:"detail"`
|
|
|
|
}{Detail: detail},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-04 14:28:25 +08:00
|
|
|
// GetCommitList get latest 10 commit list
|
2020-09-25 20:05:25 +08:00
|
|
|
func (Deploy) GetCommitList(gp *core.Goploy) *core.Response {
|
2020-08-04 14:28:25 +08:00
|
|
|
id, err := strconv.ParseInt(gp.URLQuery.Get("id"), 10, 64)
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
|
|
|
|
project, err := model.Project{ID: id}.GetData()
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
2020-09-04 17:19:53 +08:00
|
|
|
srcPath := core.GetProjectPath(project.ID)
|
2020-08-04 14:28:25 +08:00
|
|
|
git := utils.GIT{Dir: srcPath}
|
2020-12-03 17:05:03 +08:00
|
|
|
if err := git.Log(gp.URLQuery.Get("branch"), "--stat", "--pretty=format:`start`%H`%an`%at`%s`%d`", "-n", "10"); err != nil {
|
2020-08-04 14:28:25 +08:00
|
|
|
return &core.Response{Code: core.Error, Message: err.Error() + ", detail: " + git.Err.String()}
|
|
|
|
}
|
|
|
|
|
2020-12-03 17:05:03 +08:00
|
|
|
commitList := utils.ParseGITLog(git.Output.String())
|
|
|
|
|
|
|
|
return &core.Response{
|
|
|
|
Data: struct {
|
|
|
|
CommitList []utils.Commit `json:"commitList"`
|
|
|
|
}{CommitList: commitList},
|
2020-08-04 14:28:25 +08:00
|
|
|
}
|
2020-12-03 17:05:03 +08:00
|
|
|
}
|
2020-08-04 14:28:25 +08:00
|
|
|
|
2020-12-03 17:05:03 +08:00
|
|
|
// GetBranchList get all branch list
|
|
|
|
func (Deploy) GetBranchList(gp *core.Goploy) *core.Response {
|
|
|
|
id, err := strconv.ParseInt(gp.URLQuery.Get("id"), 10, 64)
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
2020-08-04 14:28:25 +08:00
|
|
|
}
|
|
|
|
|
2020-12-03 17:05:03 +08:00
|
|
|
project, err := model.Project{ID: id}.GetData()
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
srcPath := core.GetProjectPath(project.ID)
|
|
|
|
git := utils.GIT{Dir: srcPath}
|
|
|
|
|
|
|
|
if err := git.Fetch(); err != nil {
|
2020-08-04 14:28:25 +08:00
|
|
|
return &core.Response{Code: core.Error, Message: err.Error() + ", detail: " + git.Err.String()}
|
|
|
|
}
|
|
|
|
|
2020-12-03 17:05:03 +08:00
|
|
|
if err := git.Branch("-r", "--sort=-committerdate"); err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error() + ", detail: " + git.Err.String()}
|
|
|
|
}
|
2020-08-04 14:28:25 +08:00
|
|
|
|
2020-12-03 17:05:03 +08:00
|
|
|
unformatBranchList := strings.Split(git.Output.String(), "\n")
|
|
|
|
var branchList []string
|
|
|
|
for _, row := range unformatBranchList {
|
|
|
|
branch := strings.Trim(row, " ")
|
|
|
|
if len(branch) != 0 {
|
|
|
|
branchList = append(branchList, branch)
|
|
|
|
}
|
|
|
|
}
|
2020-09-26 11:45:44 +08:00
|
|
|
return &core.Response{
|
|
|
|
Data: struct {
|
2020-12-03 17:05:03 +08:00
|
|
|
BranchList []string `json:"branchList"`
|
|
|
|
}{BranchList: branchList},
|
2020-09-26 11:45:44 +08:00
|
|
|
}
|
2020-08-04 14:28:25 +08:00
|
|
|
}
|
|
|
|
|
2020-11-04 16:16:15 +08:00
|
|
|
// GetTagList get latest 10 tag list
|
|
|
|
func (Deploy) GetTagList(gp *core.Goploy) *core.Response {
|
|
|
|
id, err := strconv.ParseInt(gp.URLQuery.Get("id"), 10, 64)
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
|
|
|
|
project, err := model.Project{ID: id}.GetData()
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
srcPath := core.GetProjectPath(project.ID)
|
|
|
|
git := utils.GIT{Dir: srcPath}
|
|
|
|
|
2020-12-07 22:17:04 +08:00
|
|
|
if err := git.Add("."); err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error() + ", detail: " + git.Err.String()}
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := git.Reset("--hard"); err != nil {
|
2020-11-04 16:16:15 +08:00
|
|
|
return &core.Response{Code: core.Error, Message: err.Error() + ", detail: " + git.Err.String()}
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := git.Pull(); err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error() + ", detail: " + git.Err.String()}
|
|
|
|
}
|
|
|
|
|
2020-11-05 14:43:03 +08:00
|
|
|
if err := git.Log("--tags", "-n", "10", "--no-walk", "--stat", "--pretty=format:`start`%H`%an`%at`%s`%d`"); err != nil {
|
2020-11-04 16:16:15 +08:00
|
|
|
return &core.Response{Code: core.Error, Message: err.Error() + ", detail: " + git.Err.String()}
|
|
|
|
}
|
|
|
|
|
|
|
|
tagList := utils.ParseGITLog(git.Output.String())
|
|
|
|
|
|
|
|
return &core.Response{
|
|
|
|
Data: struct {
|
|
|
|
TagList []utils.Commit `json:"tagList"`
|
|
|
|
}{TagList: tagList},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-12 23:05:06 +08:00
|
|
|
// ResetState -
|
|
|
|
func (Deploy) ResetState(gp *core.Goploy) *core.Response {
|
|
|
|
type ReqData struct {
|
|
|
|
ProjectID int64 `json:"projectId" validate:"gt=0"`
|
|
|
|
}
|
|
|
|
var reqData ReqData
|
|
|
|
if err := verify(gp.Body, &reqData); err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := (model.Project{ID: reqData.ProjectID}).ResetState(); err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
|
|
|
|
return &core.Response{}
|
|
|
|
}
|
|
|
|
|
2020-08-04 14:28:25 +08:00
|
|
|
// Publish the project
|
2020-09-25 20:05:25 +08:00
|
|
|
func (Deploy) Publish(gp *core.Goploy) *core.Response {
|
2020-08-04 14:28:25 +08:00
|
|
|
type ReqData struct {
|
2020-08-19 10:22:43 +08:00
|
|
|
ProjectID int64 `json:"projectId" validate:"gt=0"`
|
2020-08-04 14:28:25 +08:00
|
|
|
Commit string `json:"commit"`
|
2020-12-03 17:05:03 +08:00
|
|
|
Branch string `json:"branch"`
|
2020-08-04 14:28:25 +08:00
|
|
|
}
|
|
|
|
var reqData ReqData
|
2020-08-19 10:22:43 +08:00
|
|
|
if err := verify(gp.Body, &reqData); err != nil {
|
2020-08-04 14:28:25 +08:00
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
2020-08-21 10:31:36 +08:00
|
|
|
project, err := model.Project{ID: reqData.ProjectID}.GetData()
|
2020-08-04 14:28:25 +08:00
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
2020-09-25 20:05:25 +08:00
|
|
|
if project.Review == model.Enable && gp.Namespace.Role == core.RoleMember {
|
2020-12-03 17:05:03 +08:00
|
|
|
err = projectReview(gp, project, reqData.Commit, reqData.Branch)
|
2020-09-25 20:05:25 +08:00
|
|
|
} else {
|
2020-12-03 17:05:03 +08:00
|
|
|
err = projectDeploy(gp, project, reqData.Commit, reqData.Branch)
|
2020-09-25 20:05:25 +08:00
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
2020-08-04 14:28:25 +08:00
|
|
|
}
|
2020-09-25 20:05:25 +08:00
|
|
|
return &core.Response{}
|
|
|
|
}
|
2020-08-04 14:28:25 +08:00
|
|
|
|
2021-02-12 23:05:06 +08:00
|
|
|
// Publish the project
|
|
|
|
func (Deploy) Rebuild(gp *core.Goploy) *core.Response {
|
2020-11-23 17:49:38 +08:00
|
|
|
type ReqData struct {
|
2021-02-12 23:05:06 +08:00
|
|
|
Token string `json:"token"`
|
2020-11-23 17:49:38 +08:00
|
|
|
}
|
|
|
|
var reqData ReqData
|
|
|
|
if err := verify(gp.Body, &reqData); err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
2021-02-12 23:05:06 +08:00
|
|
|
var err error
|
|
|
|
publishTraceList, err := model.PublishTrace{Token: reqData.Token}.GetListByToken()
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
projectID := publishTraceList[0].ProjectID
|
|
|
|
project, err := model.Project{ID: projectID}.GetData()
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
2020-11-23 17:49:38 +08:00
|
|
|
|
2021-02-12 23:05:06 +08:00
|
|
|
//if reqData.Token == project.LastPublishToken {
|
|
|
|
// return &core.Response{Code: core.Error, Message: "You are in the same position"}
|
|
|
|
//}
|
|
|
|
|
|
|
|
projectServers, err := model.ProjectServer{ProjectID: projectID}.GetBindServerListByProjectID()
|
|
|
|
if err != nil {
|
2020-11-23 17:49:38 +08:00
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
|
2021-02-12 23:05:06 +08:00
|
|
|
needToPublish := project.SymlinkPath == ""
|
|
|
|
var commitInfo utils.Commit
|
|
|
|
publishTraceServerCount := 0
|
|
|
|
for _, publishTrace := range publishTraceList {
|
|
|
|
// publish failed
|
|
|
|
if publishTrace.State == 0 {
|
|
|
|
needToPublish = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
|
|
|
|
if publishTrace.Type == model.Pull {
|
|
|
|
err := json.Unmarshal([]byte(publishTrace.Ext), &commitInfo)
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
} else if publishTrace.Type == model.Deploy {
|
|
|
|
for _, projectServer := range projectServers {
|
|
|
|
if strings.Contains(publishTrace.Ext, projectServer.ServerIP) {
|
|
|
|
publishTraceServerCount++
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// project server has changed
|
|
|
|
if publishTraceServerCount != len(projectServers) {
|
|
|
|
needToPublish = true
|
|
|
|
}
|
|
|
|
if needToPublish == false {
|
2021-03-26 17:00:18 +08:00
|
|
|
if len(project.AfterDeployScript) != 0 {
|
|
|
|
scriptName := path.Join(core.GetProjectPath(project.ID), "goploy-after-deploy."+utils.GetScriptExt(project.AfterDeployScriptMode))
|
|
|
|
ioutil.WriteFile(scriptName, []byte(service.ReplaceScriptVars(project.AfterDeployScript, project)), 0755)
|
|
|
|
}
|
2021-02-12 23:05:06 +08:00
|
|
|
ch := make(chan bool, len(projectServers))
|
|
|
|
for _, projectServer := range projectServers {
|
|
|
|
go func(projectServer model.ProjectServer) {
|
|
|
|
client, err := utils.DialSSH(projectServer.ServerOwner, projectServer.ServerPassword, projectServer.ServerPath, projectServer.ServerIP, projectServer.ServerPort)
|
|
|
|
if err != nil {
|
|
|
|
core.Log(core.ERROR, "projectID:"+strconv.FormatInt(project.ID, 10)+" dial err: "+err.Error())
|
|
|
|
ch <- false
|
|
|
|
return
|
|
|
|
}
|
|
|
|
session, err := client.NewSession()
|
|
|
|
if err != nil {
|
|
|
|
core.Log(core.ERROR, "projectID:"+strconv.FormatInt(project.ID, 10)+" new session err: "+err.Error())
|
|
|
|
ch <- false
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
var sshOutbuf, sshErrbuf bytes.Buffer
|
|
|
|
session.Stdout = &sshOutbuf
|
|
|
|
session.Stderr = &sshErrbuf
|
|
|
|
symlinkPath := path.Join(project.SymlinkPath, project.Name, reqData.Token)
|
|
|
|
|
|
|
|
// check if the path is exist or not
|
|
|
|
if err := session.Run("cd " + symlinkPath); err != nil {
|
|
|
|
core.Log(core.ERROR, "projectID:"+strconv.FormatInt(project.ID, 10)+" check symlink path err: "+err.Error()+", detail: "+sshErrbuf.String())
|
|
|
|
ch <- false
|
|
|
|
return
|
|
|
|
}
|
|
|
|
session.Close()
|
|
|
|
session, err = client.NewSession()
|
|
|
|
if err != nil {
|
|
|
|
core.Log(core.ERROR, "projectID:"+strconv.FormatInt(project.ID, 10)+" new session err: "+err.Error())
|
|
|
|
ch <- false
|
|
|
|
return
|
|
|
|
}
|
2021-03-26 17:00:18 +08:00
|
|
|
afterDeployCommands := []string{"ln -sfn " + symlinkPath + " " + project.Path}
|
|
|
|
if len(project.AfterDeployScript) != 0 {
|
|
|
|
scriptMode := "bash"
|
|
|
|
if len(project.AfterDeployScriptMode) != 0 {
|
|
|
|
scriptMode = project.AfterDeployScriptMode
|
|
|
|
}
|
|
|
|
afterDeployScriptPath := path.Join(project.Path, "goploy-after-deploy."+utils.GetScriptExt(project.AfterDeployScriptMode))
|
|
|
|
afterDeployCommands = append(afterDeployCommands, scriptMode+" "+afterDeployScriptPath)
|
|
|
|
afterDeployCommands = append(afterDeployCommands, "rm -f "+afterDeployScriptPath)
|
|
|
|
}
|
2021-02-12 23:05:06 +08:00
|
|
|
// redirect to project path
|
2021-03-26 17:00:18 +08:00
|
|
|
if err := session.Run(strings.Join(afterDeployCommands, ";")); err != nil {
|
2021-02-12 23:05:06 +08:00
|
|
|
core.Log(core.ERROR, "projectID:"+strconv.FormatInt(project.ID, 10)+" ln -sfn err: "+err.Error()+", detail: "+sshErrbuf.String())
|
|
|
|
ch <- false
|
|
|
|
return
|
|
|
|
}
|
|
|
|
session.Close()
|
|
|
|
ch <- true
|
|
|
|
}(projectServer)
|
|
|
|
}
|
|
|
|
|
|
|
|
for i := 0; i < len(projectServers); i++ {
|
|
|
|
if <-ch == false {
|
|
|
|
needToPublish = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
close(ch)
|
|
|
|
if needToPublish == false {
|
|
|
|
model.PublishTrace{
|
|
|
|
Token: reqData.Token,
|
|
|
|
UpdateTime: time.Now().Format("20060102150405"),
|
|
|
|
}.EditUpdateTimeByToken()
|
|
|
|
project.PublisherID = gp.UserInfo.ID
|
|
|
|
project.PublisherName = gp.UserInfo.Name
|
|
|
|
project.LastPublishToken = reqData.Token
|
|
|
|
project.Publish()
|
|
|
|
return &core.Response{Data: "symlink"}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if needToPublish == true {
|
|
|
|
project.PublisherID = gp.UserInfo.ID
|
|
|
|
project.PublisherName = gp.UserInfo.Name
|
|
|
|
project.DeployState = model.ProjectDeploying
|
|
|
|
project.LastPublishToken = uuid.New().String()
|
|
|
|
err = project.Publish()
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
core.Gwg.Add(1)
|
|
|
|
go func() {
|
|
|
|
defer core.Gwg.Done()
|
|
|
|
service.Gsync{
|
|
|
|
UserInfo: gp.UserInfo,
|
|
|
|
Project: project,
|
|
|
|
ProjectServers: projectServers,
|
|
|
|
CommitID: commitInfo.Commit,
|
|
|
|
Branch: commitInfo.Branch,
|
|
|
|
}.Exec()
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
return &core.Response{Data: "publish"}
|
2020-11-23 17:49:38 +08:00
|
|
|
}
|
|
|
|
|
2020-11-07 17:37:26 +08:00
|
|
|
// GreyPublish the project
|
|
|
|
func (Deploy) GreyPublish(gp *core.Goploy) *core.Response {
|
|
|
|
type ReqData struct {
|
|
|
|
ProjectID int64 `json:"projectId" validate:"gt=0"`
|
|
|
|
Commit string `json:"commit"`
|
2020-12-03 17:05:03 +08:00
|
|
|
Branch string `json:"branch"`
|
2020-11-07 17:37:26 +08:00
|
|
|
ServerIDs []int64 `json:"serverIds"`
|
|
|
|
}
|
|
|
|
var reqData ReqData
|
|
|
|
if err := verify(gp.Body, &reqData); err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
project, err := model.Project{ID: reqData.ProjectID}.GetData()
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
if project.DeployState == model.ProjectDeploying {
|
|
|
|
return &core.Response{Code: core.Error, Message: "project is being build"}
|
|
|
|
}
|
|
|
|
|
|
|
|
bindProjectServers, err := model.ProjectServer{ProjectID: project.ID}.GetBindServerListByProjectID()
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
|
|
|
|
projectServers := model.ProjectServers{}
|
|
|
|
|
|
|
|
for _, projectServer := range bindProjectServers {
|
|
|
|
for _, serverID := range reqData.ServerIDs {
|
|
|
|
if projectServer.ServerID == serverID {
|
|
|
|
projectServers = append(projectServers, projectServer)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
project.PublisherID = gp.UserInfo.ID
|
|
|
|
project.PublisherName = gp.UserInfo.Name
|
|
|
|
project.DeployState = model.ProjectDeploying
|
|
|
|
project.LastPublishToken = uuid.New().String()
|
|
|
|
err = project.Publish()
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
2021-02-12 11:48:36 +08:00
|
|
|
core.Gwg.Add(1)
|
|
|
|
go func() {
|
|
|
|
defer core.Gwg.Done()
|
|
|
|
service.Gsync{
|
|
|
|
UserInfo: gp.UserInfo,
|
|
|
|
Project: project,
|
|
|
|
ProjectServers: projectServers,
|
|
|
|
CommitID: reqData.Commit,
|
|
|
|
Branch: reqData.Branch,
|
|
|
|
}.Exec()
|
|
|
|
}()
|
2020-11-07 17:37:26 +08:00
|
|
|
return &core.Response{}
|
|
|
|
}
|
|
|
|
|
2020-09-25 20:05:25 +08:00
|
|
|
func (Deploy) Review(gp *core.Goploy) *core.Response {
|
|
|
|
type ReqData struct {
|
|
|
|
ProjectReviewID int64 `json:"projectReviewId" validate:"gt=0"`
|
|
|
|
State uint8 `json:"state" validate:"gt=0"`
|
|
|
|
}
|
2020-08-04 14:28:25 +08:00
|
|
|
|
2020-09-25 20:05:25 +08:00
|
|
|
var reqData ReqData
|
|
|
|
if err := verify(gp.Body, &reqData); err != nil {
|
2020-08-04 14:28:25 +08:00
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
2020-09-25 20:05:25 +08:00
|
|
|
|
|
|
|
projectReviewModel := model.ProjectReview{
|
|
|
|
ID: reqData.ProjectReviewID,
|
|
|
|
State: reqData.State,
|
|
|
|
Editor: gp.UserInfo.Name,
|
|
|
|
EditorID: gp.UserInfo.ID,
|
|
|
|
}
|
|
|
|
projectReview, err := projectReviewModel.GetData()
|
2020-08-04 14:28:25 +08:00
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
2020-09-25 20:05:25 +08:00
|
|
|
|
|
|
|
if projectReview.State != model.PENDING {
|
|
|
|
return &core.Response{Code: core.Error, Message: "Project review state is invalid"}
|
|
|
|
}
|
|
|
|
|
|
|
|
if reqData.State == model.APPROVE {
|
|
|
|
project, err := model.Project{ID: projectReview.ProjectID}.GetData()
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
2020-12-03 17:05:03 +08:00
|
|
|
if err := projectDeploy(gp, project, projectReview.CommitID, projectReview.Branch); err != nil {
|
2020-09-25 20:05:25 +08:00
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
projectReviewModel.EditRow()
|
|
|
|
|
|
|
|
return &core.Response{}
|
2020-08-04 14:28:25 +08:00
|
|
|
}
|
|
|
|
|
2020-09-25 20:05:25 +08:00
|
|
|
// Webhook -
|
|
|
|
func (Deploy) Webhook(gp *core.Goploy) *core.Response {
|
2020-08-21 10:31:36 +08:00
|
|
|
projectID, err := strconv.ParseInt(gp.URLQuery.Get("project_id"), 10, 64)
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
2020-08-04 14:28:25 +08:00
|
|
|
// other event is blocked in deployMiddleware
|
|
|
|
type ReqData struct {
|
2020-08-19 10:22:43 +08:00
|
|
|
Ref string `json:"ref" validate:"required"`
|
2020-08-04 14:28:25 +08:00
|
|
|
}
|
|
|
|
var reqData ReqData
|
2020-08-19 10:22:43 +08:00
|
|
|
if err := verify(gp.Body, &reqData); err != nil {
|
2020-08-04 14:28:25 +08:00
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
|
2020-08-21 10:31:36 +08:00
|
|
|
project, err := model.Project{ID: projectID}.GetData()
|
2020-08-04 14:28:25 +08:00
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
|
|
|
|
if project.State != model.Disable {
|
|
|
|
return &core.Response{Code: core.Deny, Message: "Project is disabled"}
|
|
|
|
}
|
|
|
|
|
|
|
|
if project.AutoDeploy != model.ProjectWebhookDeploy {
|
|
|
|
return &core.Response{Code: core.Deny, Message: "Webhook auto deploy turn off, go to project setting turn on"}
|
|
|
|
}
|
|
|
|
|
2020-08-21 10:31:36 +08:00
|
|
|
if branch := strings.Split(reqData.Ref, "/")[2]; project.Branch != branch {
|
2020-08-04 14:28:25 +08:00
|
|
|
return &core.Response{Code: core.Deny, Message: "Receive branch:" + branch + " push event, not equal to current branch"}
|
|
|
|
}
|
|
|
|
|
|
|
|
if project.DeployState == model.ProjectDeploying {
|
|
|
|
return &core.Response{Code: core.Deny, Message: "Project is being build by other"}
|
|
|
|
}
|
|
|
|
|
|
|
|
gp.UserInfo, err = model.User{ID: 1}.GetData()
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
|
|
|
|
projectServers, err := model.ProjectServer{ProjectID: project.ID}.GetBindServerListByProjectID()
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
project.PublisherID = gp.UserInfo.ID
|
|
|
|
project.PublisherName = gp.UserInfo.Name
|
|
|
|
project.DeployState = model.ProjectDeploying
|
|
|
|
project.LastPublishToken = uuid.New().String()
|
|
|
|
err = project.Publish()
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
2021-02-12 11:48:36 +08:00
|
|
|
core.Gwg.Add(1)
|
|
|
|
go func() {
|
|
|
|
defer core.Gwg.Done()
|
|
|
|
service.Gsync{
|
|
|
|
UserInfo: gp.UserInfo,
|
|
|
|
Project: project,
|
|
|
|
ProjectServers: projectServers,
|
|
|
|
}.Exec()
|
|
|
|
}()
|
2020-08-04 14:28:25 +08:00
|
|
|
return &core.Response{Message: "receive push signal"}
|
|
|
|
}
|
2020-09-25 20:05:25 +08:00
|
|
|
|
|
|
|
// Callback -
|
|
|
|
func (Deploy) Callback(gp *core.Goploy) *core.Response {
|
|
|
|
projectReviewID, err := strconv.ParseInt(gp.URLQuery.Get("project_review_id"), 10, 64)
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
|
|
|
|
projectReviewModel := model.ProjectReview{
|
|
|
|
ID: projectReviewID,
|
|
|
|
State: model.APPROVE,
|
|
|
|
Editor: "admin",
|
|
|
|
EditorID: 1,
|
|
|
|
}
|
|
|
|
projectReview, err := projectReviewModel.GetData()
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
|
|
|
|
if projectReview.State != model.PENDING {
|
|
|
|
return &core.Response{Code: core.Error, Message: "Project review state is invalid"}
|
|
|
|
}
|
|
|
|
|
|
|
|
project, err := model.Project{ID: projectReview.ProjectID}.GetData()
|
|
|
|
if err != nil {
|
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
2020-12-03 17:05:03 +08:00
|
|
|
if err := projectDeploy(gp, project, projectReview.CommitID, projectReview.Branch); err != nil {
|
2020-09-25 20:05:25 +08:00
|
|
|
return &core.Response{Code: core.Error, Message: err.Error()}
|
|
|
|
}
|
|
|
|
projectReviewModel.EditRow()
|
|
|
|
|
|
|
|
return &core.Response{}
|
|
|
|
}
|
|
|
|
|
2020-12-03 17:05:03 +08:00
|
|
|
func projectDeploy(gp *core.Goploy, project model.Project, commitID string, branch string) error {
|
2020-09-25 20:05:25 +08:00
|
|
|
if project.DeployState == model.ProjectDeploying {
|
|
|
|
return errors.New("project is being build by other")
|
|
|
|
}
|
|
|
|
|
|
|
|
projectServers, err := model.ProjectServer{ProjectID: project.ID}.GetBindServerListByProjectID()
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
project.PublisherID = gp.UserInfo.ID
|
|
|
|
project.PublisherName = gp.UserInfo.Name
|
|
|
|
project.DeployState = model.ProjectDeploying
|
|
|
|
project.LastPublishToken = uuid.New().String()
|
|
|
|
err = project.Publish()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-02-12 11:48:36 +08:00
|
|
|
core.Gwg.Add(1)
|
|
|
|
go func() {
|
|
|
|
defer core.Gwg.Done()
|
|
|
|
service.Gsync{
|
|
|
|
UserInfo: gp.UserInfo,
|
|
|
|
Project: project,
|
|
|
|
ProjectServers: projectServers,
|
|
|
|
CommitID: commitID,
|
|
|
|
Branch: branch,
|
|
|
|
}.Exec()
|
|
|
|
}()
|
2020-09-25 20:05:25 +08:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-12-03 17:05:03 +08:00
|
|
|
func projectReview(gp *core.Goploy, project model.Project, commitID string, branch string) error {
|
2020-09-25 20:05:25 +08:00
|
|
|
if len(commitID) == 0 {
|
|
|
|
return errors.New("commit id is required")
|
|
|
|
}
|
|
|
|
projectReviewModel := model.ProjectReview{
|
|
|
|
ProjectID: project.ID,
|
2020-12-03 17:05:03 +08:00
|
|
|
Branch: branch,
|
2020-09-25 20:05:25 +08:00
|
|
|
CommitID: commitID,
|
|
|
|
Creator: gp.UserInfo.Name,
|
|
|
|
CreatorID: gp.UserInfo.ID,
|
|
|
|
}
|
|
|
|
reviewURL := project.ReviewURL
|
|
|
|
if len(reviewURL) > 0 {
|
|
|
|
reviewURL = strings.Replace(reviewURL, "__PROJECT_ID__", strconv.FormatInt(project.ID, 10), 1)
|
|
|
|
reviewURL = strings.Replace(reviewURL, "__PROJECT_NAME__", project.Name, 1)
|
2020-12-03 17:05:03 +08:00
|
|
|
reviewURL = strings.Replace(reviewURL, "__BRANCH__", branch, 1)
|
2020-09-25 20:05:25 +08:00
|
|
|
reviewURL = strings.Replace(reviewURL, "__ENVIRONMENT__", strconv.Itoa(int(project.Environment)), 1)
|
|
|
|
reviewURL = strings.Replace(reviewURL, "__COMMIT_ID__", commitID, 1)
|
|
|
|
reviewURL = strings.Replace(reviewURL, "__PUBLISH_TIME__", strconv.FormatInt(time.Now().Unix(), 10), 1)
|
|
|
|
reviewURL = strings.Replace(reviewURL, "__PUBLISHER_ID__", gp.UserInfo.Name, 1)
|
|
|
|
reviewURL = strings.Replace(reviewURL, "__PUBLISHER_NAME__", strconv.FormatInt(gp.UserInfo.ID, 10), 1)
|
|
|
|
|
|
|
|
projectReviewModel.ReviewURL = reviewURL
|
|
|
|
}
|
|
|
|
id, err := projectReviewModel.AddRow()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if len(reviewURL) > 0 {
|
|
|
|
callback := "http://"
|
|
|
|
if gp.Request.TLS != nil {
|
|
|
|
callback = "https://"
|
|
|
|
}
|
|
|
|
callback += gp.Request.Host + "/deploy/callback?project_review_id=" + strconv.FormatInt(id, 10)
|
|
|
|
callback = url.QueryEscape(callback)
|
|
|
|
reviewURL = strings.Replace(reviewURL, "__CALLBACK__", callback, 1)
|
|
|
|
|
|
|
|
resp, err := http.Get(reviewURL)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer resp.Body.Close()
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|