mirror of
https://gitee.com/goploy/goploy.git
synced 2024-11-29 18:57:59 +08:00
A review
This commit is contained in:
parent
b5d77dce93
commit
eec45897b8
@ -2,12 +2,16 @@ package controller
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"github.com/zhenorzz/goploy/core"
|
||||
"github.com/zhenorzz/goploy/model"
|
||||
"github.com/zhenorzz/goploy/service"
|
||||
"github.com/zhenorzz/goploy/utils"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
@ -16,7 +20,7 @@ import (
|
||||
type Deploy Controller
|
||||
|
||||
// GetList -
|
||||
func (deploy Deploy) GetList(gp *core.Goploy) *core.Response {
|
||||
func (Deploy) GetList(gp *core.Goploy) *core.Response {
|
||||
type RespData struct {
|
||||
Project model.Projects `json:"list"`
|
||||
}
|
||||
@ -34,7 +38,7 @@ func (deploy Deploy) GetList(gp *core.Goploy) *core.Response {
|
||||
}
|
||||
|
||||
// GetPreview deploy detail
|
||||
func (deploy Deploy) GetPreview(gp *core.Goploy) *core.Response {
|
||||
func (Deploy) GetPreview(gp *core.Goploy) *core.Response {
|
||||
type RespData struct {
|
||||
GitTraceList model.PublishTraces `json:"gitTraceList"`
|
||||
Pagination model.Pagination `json:"pagination"`
|
||||
@ -70,7 +74,7 @@ func (deploy Deploy) GetPreview(gp *core.Goploy) *core.Response {
|
||||
}
|
||||
|
||||
// GetDetail deploy detail
|
||||
func (deploy Deploy) GetDetail(gp *core.Goploy) *core.Response {
|
||||
func (Deploy) GetDetail(gp *core.Goploy) *core.Response {
|
||||
type RespData struct {
|
||||
PublishTraceList model.PublishTraces `json:"publishTraceList"`
|
||||
}
|
||||
@ -87,7 +91,7 @@ func (deploy Deploy) GetDetail(gp *core.Goploy) *core.Response {
|
||||
}
|
||||
|
||||
// GetCommitList get latest 10 commit list
|
||||
func (deploy Deploy) GetCommitList(gp *core.Goploy) *core.Response {
|
||||
func (Deploy) GetCommitList(gp *core.Goploy) *core.Response {
|
||||
type RespData struct {
|
||||
CommitList []utils.Commit `json:"commitList"`
|
||||
}
|
||||
@ -103,19 +107,19 @@ func (deploy Deploy) GetCommitList(gp *core.Goploy) *core.Response {
|
||||
}
|
||||
srcPath := core.GetProjectPath(project.ID)
|
||||
git := utils.GIT{Dir: srcPath}
|
||||
if err := git.Clean([]string{"-f"}); err != nil {
|
||||
if err := git.Clean("-f"); err != nil {
|
||||
return &core.Response{Code: core.Error, Message: err.Error() + ", detail: " + git.Err.String()}
|
||||
}
|
||||
|
||||
if err := git.Checkout([]string{"--", "."}); err != nil {
|
||||
if err := git.Checkout("--", "."); err != nil {
|
||||
return &core.Response{Code: core.Error, Message: err.Error() + ", detail: " + git.Err.String()}
|
||||
}
|
||||
|
||||
if err := git.Pull([]string{}); err != nil {
|
||||
if err := git.Pull(); err != nil {
|
||||
return &core.Response{Code: core.Error, Message: err.Error() + ", detail: " + git.Err.String()}
|
||||
}
|
||||
|
||||
if err := git.Log([]string{"--stat", "--pretty=format:`start`%H`%an`%at`%s`", "-n", "10"}); err != nil {
|
||||
if err := git.Log("--stat", "--pretty=format:`start`%H`%an`%at`%s`", "-n", "10"); err != nil {
|
||||
return &core.Response{Code: core.Error, Message: err.Error() + ", detail: " + git.Err.String()}
|
||||
}
|
||||
|
||||
@ -125,7 +129,7 @@ func (deploy Deploy) GetCommitList(gp *core.Goploy) *core.Response {
|
||||
}
|
||||
|
||||
// Publish the project
|
||||
func (deploy Deploy) Publish(gp *core.Goploy) *core.Response {
|
||||
func (Deploy) Publish(gp *core.Goploy) *core.Response {
|
||||
type ReqData struct {
|
||||
ProjectID int64 `json:"projectId" validate:"gt=0"`
|
||||
Commit string `json:"commit"`
|
||||
@ -134,41 +138,65 @@ func (deploy Deploy) Publish(gp *core.Goploy) *core.Response {
|
||||
if err := verify(gp.Body, &reqData); err != nil {
|
||||
return &core.Response{Code: core.Error, Message: err.Error()}
|
||||
}
|
||||
|
||||
var 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.Deny, Message: "Project is being build by other"}
|
||||
if project.Review == model.Enable && gp.Namespace.Role == core.RoleMember {
|
||||
err = projectReview(gp, project, reqData.Commit)
|
||||
} else {
|
||||
err = projectDeploy(gp, project, reqData.Commit)
|
||||
}
|
||||
|
||||
projectServers, err := model.ProjectServer{ProjectID: reqData.ProjectID}.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()
|
||||
return &core.Response{}
|
||||
}
|
||||
|
||||
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"`
|
||||
}
|
||||
|
||||
var reqData ReqData
|
||||
if err := verify(gp.Body, &reqData); err != nil {
|
||||
return &core.Response{Code: core.Error, Message: err.Error()}
|
||||
}
|
||||
|
||||
projectReviewModel := model.ProjectReview{
|
||||
ID: reqData.ProjectReviewID,
|
||||
State: reqData.State,
|
||||
Editor: gp.UserInfo.Name,
|
||||
EditorID: gp.UserInfo.ID,
|
||||
}
|
||||
projectReview, err := projectReviewModel.GetData()
|
||||
if err != nil {
|
||||
return &core.Response{Code: core.Error, Message: err.Error()}
|
||||
}
|
||||
go service.Sync{
|
||||
UserInfo: gp.UserInfo,
|
||||
Project: project,
|
||||
ProjectServers: projectServers,
|
||||
CommitID: reqData.Commit,
|
||||
}.Exec()
|
||||
return &core.Response{Message: "deploying"}
|
||||
|
||||
if projectReview.State != model.PENDING {
|
||||
return &core.Response{Code: core.Error, Message: "Project review state is invalid"}
|
||||
}
|
||||
|
||||
// Webhook connect
|
||||
func (deploy Deploy) Webhook(gp *core.Goploy) *core.Response {
|
||||
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()}
|
||||
}
|
||||
if err := projectDeploy(gp, project, projectReview.CommitID); err != nil {
|
||||
return &core.Response{Code: core.Error, Message: err.Error()}
|
||||
}
|
||||
}
|
||||
projectReviewModel.EditRow()
|
||||
|
||||
return &core.Response{}
|
||||
}
|
||||
|
||||
// Webhook -
|
||||
func (Deploy) Webhook(gp *core.Goploy) *core.Response {
|
||||
projectID, err := strconv.ParseInt(gp.URLQuery.Get("project_id"), 10, 64)
|
||||
if err != nil {
|
||||
return &core.Response{Code: core.Error, Message: err.Error()}
|
||||
@ -228,3 +256,109 @@ func (deploy Deploy) Webhook(gp *core.Goploy) *core.Response {
|
||||
}.Exec()
|
||||
return &core.Response{Message: "receive push signal"}
|
||||
}
|
||||
|
||||
// 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()}
|
||||
}
|
||||
if err := projectDeploy(gp, project, projectReview.CommitID); err != nil {
|
||||
return &core.Response{Code: core.Error, Message: err.Error()}
|
||||
}
|
||||
projectReviewModel.EditRow()
|
||||
|
||||
return &core.Response{}
|
||||
}
|
||||
|
||||
func projectDeploy(gp *core.Goploy, project model.Project, commitID string) error {
|
||||
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
|
||||
}
|
||||
go service.Sync{
|
||||
UserInfo: gp.UserInfo,
|
||||
Project: project,
|
||||
ProjectServers: projectServers,
|
||||
CommitID: commitID,
|
||||
}.Exec()
|
||||
return nil
|
||||
}
|
||||
|
||||
func projectReview(gp *core.Goploy, project model.Project, commitID string) error {
|
||||
if len(commitID) == 0 {
|
||||
return errors.New("commit id is required")
|
||||
}
|
||||
projectReviewModel := model.ProjectReview{
|
||||
ProjectID: project.ID,
|
||||
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)
|
||||
reviewURL = strings.Replace(reviewURL, "__BRANCH__", project.Branch, 1)
|
||||
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
|
||||
}
|
||||
|
@ -114,6 +114,8 @@ func (project Project) Add(gp *core.Goploy) *core.Response {
|
||||
Environment uint8 `json:"Environment" validate:"required"`
|
||||
Branch string `json:"branch" validate:"required"`
|
||||
SymlinkPath string `json:"symlinkPath"`
|
||||
Review uint8 `json:"review"`
|
||||
ReviewURL string `json:"reviewURL"`
|
||||
AfterPullScriptMode string `json:"afterPullScriptMode"`
|
||||
AfterPullScript string `json:"afterPullScript"`
|
||||
AfterDeployScriptMode string `json:"afterDeployScriptMode"`
|
||||
@ -138,9 +140,11 @@ func (project Project) Add(gp *core.Goploy) *core.Response {
|
||||
Name: reqData.Name,
|
||||
URL: reqData.URL,
|
||||
Path: reqData.Path,
|
||||
SymlinkPath: reqData.SymlinkPath,
|
||||
Environment: reqData.Environment,
|
||||
Branch: reqData.Branch,
|
||||
SymlinkPath: reqData.SymlinkPath,
|
||||
Review: reqData.Review,
|
||||
ReviewURL: reqData.ReviewURL,
|
||||
AfterPullScriptMode: reqData.AfterPullScriptMode,
|
||||
AfterPullScript: reqData.AfterPullScript,
|
||||
AfterDeployScriptMode: reqData.AfterDeployScriptMode,
|
||||
@ -201,6 +205,8 @@ func (project Project) Edit(gp *core.Goploy) *core.Response {
|
||||
URL string `json:"url"`
|
||||
Path string `json:"path"`
|
||||
SymlinkPath string `json:"symlinkPath"`
|
||||
Review uint8 `json:"review"`
|
||||
ReviewURL string `json:"reviewURL"`
|
||||
Environment uint8 `json:"Environment"`
|
||||
Branch string `json:"branch"`
|
||||
AfterPullScriptMode string `json:"afterPullScriptMode"`
|
||||
@ -230,9 +236,11 @@ func (project Project) Edit(gp *core.Goploy) *core.Response {
|
||||
Name: reqData.Name,
|
||||
URL: reqData.URL,
|
||||
Path: reqData.Path,
|
||||
SymlinkPath: reqData.SymlinkPath,
|
||||
Environment: reqData.Environment,
|
||||
Branch: reqData.Branch,
|
||||
SymlinkPath: reqData.SymlinkPath,
|
||||
Review: reqData.Review,
|
||||
ReviewURL: reqData.ReviewURL,
|
||||
AfterPullScriptMode: reqData.AfterPullScriptMode,
|
||||
AfterPullScript: reqData.AfterPullScript,
|
||||
AfterDeployScriptMode: reqData.AfterDeployScriptMode,
|
||||
@ -413,7 +421,7 @@ func (project Project) RemoveUser(gp *core.Goploy) *core.Response {
|
||||
// GetTaskList -
|
||||
func (project Project) GetTaskList(gp *core.Goploy) *core.Response {
|
||||
type RespData struct {
|
||||
ProjectTask model.ProjectTasks `json:"projectTaskList"`
|
||||
ProjectTasks model.ProjectTasks `json:"list"`
|
||||
Pagination model.Pagination `json:"pagination"`
|
||||
}
|
||||
pagination, err := model.PaginationFrom(gp.URLQuery)
|
||||
@ -429,7 +437,29 @@ func (project Project) GetTaskList(gp *core.Goploy) *core.Response {
|
||||
if err != nil {
|
||||
return &core.Response{Code: core.Error, Message: err.Error()}
|
||||
}
|
||||
return &core.Response{Data: RespData{ProjectTask: projectTaskList, Pagination: pagination}}
|
||||
return &core.Response{Data: RespData{ProjectTasks: projectTaskList, Pagination: pagination}}
|
||||
}
|
||||
|
||||
// GetReviewList -
|
||||
func (project Project) GetReviewList(gp *core.Goploy) *core.Response {
|
||||
type RespData struct {
|
||||
ProjectReviews model.ProjectReviews `json:"list"`
|
||||
Pagination model.Pagination `json:"pagination"`
|
||||
}
|
||||
pagination, err := model.PaginationFrom(gp.URLQuery)
|
||||
if err != nil {
|
||||
return &core.Response{Code: core.Error, Message: err.Error()}
|
||||
}
|
||||
id, err := strconv.ParseInt(gp.URLQuery.Get("id"), 10, 64)
|
||||
if err != nil {
|
||||
return &core.Response{Code: core.Error, Message: err.Error()}
|
||||
}
|
||||
ProjectReviews, pagination, err := model.ProjectReview{ProjectID: id}.GetListByProjectID(pagination)
|
||||
|
||||
if err != nil {
|
||||
return &core.Response{Code: core.Error, Message: err.Error()}
|
||||
}
|
||||
return &core.Response{Data: RespData{ProjectReviews: ProjectReviews, Pagination: pagination}}
|
||||
}
|
||||
|
||||
// AddTask to project
|
||||
@ -454,7 +484,6 @@ func (project Project) AddTask(gp *core.Goploy) *core.Response {
|
||||
|
||||
if err != nil {
|
||||
return &core.Response{Code: core.Error, Message: err.Error()}
|
||||
|
||||
}
|
||||
type RespData struct {
|
||||
ID int64 `json:"id"`
|
||||
|
97
goploy.sql
97
goploy.sql
@ -4,7 +4,7 @@ CREATE TABLE IF NOT EXISTS `goploy`.`log` (
|
||||
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`type` tinyint(3) UNSIGNED NOT NULL DEFAULT 1 COMMENT 'log type',
|
||||
`ip` int(10) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`desc` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'description',
|
||||
`desc` varchar(30) NOT NULL DEFAULT '' COMMENT 'description',
|
||||
`user_id` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '',
|
||||
`create_time` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '',
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
@ -14,25 +14,27 @@ CREATE TABLE IF NOT EXISTS `goploy`.`log` (
|
||||
CREATE TABLE IF NOT EXISTS `goploy`.`project` (
|
||||
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`namespace_id` int(10) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'project name',
|
||||
`url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'repository url',
|
||||
`path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'project deploy path',
|
||||
`symlink_path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '(ln -sfn symlink_path/uuid project_path)',
|
||||
`name` varchar(255) NOT NULL DEFAULT '' COMMENT 'project name',
|
||||
`url` varchar(255) NOT NULL DEFAULT '' COMMENT 'repository url',
|
||||
`path` varchar(255) NOT NULL DEFAULT '' COMMENT 'project deploy path',
|
||||
`symlink_path` varchar(255) NOT NULL DEFAULT '' COMMENT '(ln -sfn symlink_path/uuid project_path)',
|
||||
`environment` tinyint(4) UNSIGNED NOT NULL DEFAULT 0 COMMENT '1.production 2.pre-release 3.test 4.development',
|
||||
`branch` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT 'master' COMMENT 'repository branch',
|
||||
`after_pull_script_mode` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'sh|php|py|...',
|
||||
`after_pull_script` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '',
|
||||
`after_deploy_script_mode` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'sh|php|py|...',
|
||||
`after_deploy_script` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '',
|
||||
`rsync_option` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'rsync options',
|
||||
`branch` varchar(255) NOT NULL DEFAULT 'master' COMMENT 'repository branch',
|
||||
`review` tinyint(4) unsigned NOT NULL DEFAULT '0' COMMENT '0.disable 1.enable',
|
||||
`review_url` varchar(1000) NOT NULL DEFAULT '' COMMENT 'review notification link',
|
||||
`after_pull_script_mode` varchar(20) NOT NULL DEFAULT '' COMMENT 'sh|php|py|...',
|
||||
`after_pull_script` text NOT NULL COMMENT '',
|
||||
`after_deploy_script_mode` varchar(20) NOT NULL DEFAULT '' COMMENT 'sh|php|py|...',
|
||||
`after_deploy_script` text NOT NULL COMMENT '',
|
||||
`rsync_option` varchar(255) NOT NULL DEFAULT '' COMMENT 'rsync options',
|
||||
`auto_deploy` tinyint(4) UNSIGNED NOT NULL DEFAULT 1 COMMENT '0.disable 1.webhook',
|
||||
`state` tinyint(4) UNSIGNED NOT NULL DEFAULT 1 COMMENT '0.disable 1.enable',
|
||||
`deploy_state` tinyint(4) UNSIGNED NOT NULL DEFAULT 0 COMMENT '0.not deploy 1.deploying 2.success 3.fail',
|
||||
`publisher_id` int(10) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`publisher_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
|
||||
`publisher_name` varchar(255) NOT NULL DEFAULT '',
|
||||
`last_publish_token` char(36) CHARACTER SET utf8mb4 NOT NULL DEFAULT '',
|
||||
`notify_type` tinyint(4) UNSIGNED NOT NULL DEFAULT 0 COMMENT '1.weixin 2.ding talk 3.feishu 255.custom',
|
||||
`notify_target` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '',
|
||||
`notify_target` varchar(255) NOT NULL DEFAULT '' COMMENT '',
|
||||
`insert_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
@ -75,6 +77,21 @@ CREATE TABLE IF NOT EXISTS `goploy`.`project_task` (
|
||||
KEY `index_project_update` (`project_id`,`update_time`) USING BTREE COMMENT 'project_id,update_time'
|
||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `goploy`.`project_review` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`project_id` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`commit_id` char(40) NOT NULL DEFAULT '',
|
||||
`review_url` varchar(1000) NOT NULL DEFAULT '' COMMENT 'review notification link',
|
||||
`state` tinyint(4) unsigned NOT NULL DEFAULT '0' COMMENT '0.Pending 1.Approve 2.Deny',
|
||||
`creator_id` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`creator` varchar(255) NOT NULL DEFAULT '',
|
||||
`editor_id` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`editor` varchar(255) NOT NULL DEFAULT '',
|
||||
`insert_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `goploy`.`publish_trace` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`token` char(36) CHARACTER SET utf8mb4 NOT NULL DEFAULT '',
|
||||
@ -96,17 +113,17 @@ CREATE TABLE IF NOT EXISTS `goploy`.`publish_trace` (
|
||||
CREATE TABLE IF NOT EXISTS `goploy`.`monitor` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`namespace_id` int(10) unsigned NOT NULL,
|
||||
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
|
||||
`domain` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
|
||||
`name` varchar(255) NOT NULL,
|
||||
`domain` varchar(50) NOT NULL,
|
||||
`port` smallint(5) unsigned NOT NULL DEFAULT '80',
|
||||
`second` int(10) unsigned NOT NULL DEFAULT '1' COMMENT 'How many seconds to run',
|
||||
`times` smallint(5) unsigned NOT NULL DEFAULT '1' COMMENT 'How many times of failures',
|
||||
`description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
|
||||
`description` varchar(255) NOT NULL DEFAULT '',
|
||||
`notify_type` tinyint(4) unsigned NOT NULL DEFAULT '0' COMMENT '1.weixin 2.ding talk 3.feishu 255.custom',
|
||||
`notify_target` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
|
||||
`notify_target` varchar(255) NOT NULL DEFAULT '',
|
||||
`notify_times` smallint(5) unsigned NOT NULL DEFAULT '1' COMMENT 'Notify times',
|
||||
`state` tinyint(4) unsigned NOT NULL DEFAULT '1' COMMENT '0.disable 1.enable',
|
||||
`error_content` text COLLATE utf8mb4_general_ci NOT NULL,
|
||||
`error_content` varchar(1000) NOT NULL DEFAULT '',
|
||||
`insert_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
@ -115,12 +132,12 @@ CREATE TABLE IF NOT EXISTS `goploy`.`monitor` (
|
||||
CREATE TABLE IF NOT EXISTS `goploy`.`server` (
|
||||
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`namespace_id` int(10) UNSIGNED NOT NULL DEFAULT 0,
|
||||
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
|
||||
`ip` varchar(15) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
|
||||
`name` varchar(255) NOT NULL DEFAULT '',
|
||||
`ip` varchar(15) NOT NULL DEFAULT '',
|
||||
`port` smallint(10) UNSIGNED NOT NULL DEFAULT 22,
|
||||
`owner` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
|
||||
`description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
|
||||
`last_publish_token` char(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
|
||||
`owner` varchar(255) NOT NULL DEFAULT '',
|
||||
`description` varchar(255) NOT NULL DEFAULT '',
|
||||
`last_publish_token` char(36) NOT NULL DEFAULT '',
|
||||
`insert_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
`state` tinyint(4) UNSIGNED NOT NULL DEFAULT 1 COMMENT '0.disable 1.enable',
|
||||
@ -131,12 +148,12 @@ CREATE TABLE IF NOT EXISTS `goploy`.`server` (
|
||||
CREATE TABLE IF NOT EXISTS `goploy`.`crontab` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`namespace_id` int(10) unsigned NOT NULL DEFAULT 0,
|
||||
`command` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
|
||||
`command_md5` char(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'command md5 for replace',
|
||||
`command` varchar(255) NOT NULL DEFAULT '',
|
||||
`command_md5` char(32) NOT NULL DEFAULT '' COMMENT 'command md5 for replace',
|
||||
`creator_id` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`creator` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
|
||||
`creator` varchar(255) NOT NULL DEFAULT '',
|
||||
`editor_id` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`editor` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
|
||||
`editor` varchar(255) NOT NULL DEFAULT '',
|
||||
`insert_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
@ -155,10 +172,10 @@ CREATE TABLE IF NOT EXISTS `goploy`.`crontab_server` (
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `goploy`.`template` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
|
||||
`package_id_str` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
|
||||
`script` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
|
||||
`remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
|
||||
`name` varchar(255) NOT NULL DEFAULT '',
|
||||
`package_id_str` text NOT NULL,
|
||||
`script` text NOT NULL,
|
||||
`remark` varchar(255) NOT NULL DEFAULT '',
|
||||
`insert_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`) USING BTREE
|
||||
@ -166,7 +183,7 @@ CREATE TABLE IF NOT EXISTS `goploy`.`template` (
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `goploy`.`package` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
|
||||
`name` varchar(255) NOT NULL DEFAULT '',
|
||||
`size` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`insert_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
@ -175,13 +192,13 @@ CREATE TABLE IF NOT EXISTS `goploy`.`package` (
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `goploy`.`install_trace` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`token` char(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
|
||||
`token` char(36) NOT NULL DEFAULT '',
|
||||
`server_id` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`server_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
|
||||
`server_name` varchar(255) NOT NULL DEFAULT '',
|
||||
`detail` longtext NOT NULL,
|
||||
`state` tinyint(4) unsigned NOT NULL DEFAULT '1',
|
||||
`operator_id` int(10) unsigned NOT NULL DEFAULT '0',
|
||||
`operator_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
|
||||
`operator_name` varchar(255) NOT NULL DEFAULT '',
|
||||
`type` tinyint(4) unsigned NOT NULL DEFAULT '0' COMMENT '1.rsync 2.ssh 3.script',
|
||||
`insert_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
@ -192,10 +209,10 @@ CREATE TABLE IF NOT EXISTS `goploy`.`install_trace` (
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `goploy`.`user` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`account` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
|
||||
`password` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
|
||||
`name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
|
||||
`contact` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
|
||||
`account` varchar(30) NOT NULL DEFAULT '',
|
||||
`password` varchar(60) NOT NULL DEFAULT '',
|
||||
`name` varchar(30) NOT NULL DEFAULT '',
|
||||
`contact` varchar(255) NOT NULL DEFAULT '',
|
||||
`state` tinyint(1) NOT NULL DEFAULT '1' COMMENT '0.disable 1.enable',
|
||||
`insert_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
@ -206,7 +223,7 @@ CREATE TABLE IF NOT EXISTS `goploy`.`user` (
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `goploy`.`namespace` (
|
||||
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
|
||||
`name` varchar(20) NOT NULL DEFAULT '',
|
||||
`insert_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`id`) USING BTREE,
|
||||
|
16
main.go
16
main.go
@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"github.com/joho/godotenv"
|
||||
@ -14,6 +15,7 @@ import (
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/exec"
|
||||
"time"
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
@ -49,6 +51,20 @@ func install() {
|
||||
println("The configuration file already exists, no need to reinstall (if you need to reinstall, please back up the database goploy first, delete the .env file)")
|
||||
return
|
||||
}
|
||||
var stdout bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
cmd := exec.Command("rsync", "--version")
|
||||
cmd.Stdout = &stdout
|
||||
cmd.Stderr = &stderr
|
||||
if err := cmd.Run(); err != nil {
|
||||
println(err.Error() + ", detail: " + stderr.String())
|
||||
panic("Please check if rsync is installed correctly, see https://rsync.samba.org/download.html")
|
||||
}
|
||||
git := utils.GIT{}
|
||||
if err := git.Run("--version"); err != nil {
|
||||
println(err.Error() + ", detail: " + git.Err.String())
|
||||
panic("Please check if git is installed correctly, see https://git-scm.com/downloads")
|
||||
}
|
||||
inputReader := bufio.NewReader(os.Stdin)
|
||||
println("Installation guidelines (Enter to confirm input)")
|
||||
println("Please enter the mysql user:")
|
||||
|
File diff suppressed because one or more lines are too long
@ -148,8 +148,8 @@ func (m Monitor) GetAllByState() (Monitors, error) {
|
||||
func (m Monitor) AddRow() (int64, error) {
|
||||
result, err := sq.
|
||||
Insert(monitorTable).
|
||||
Columns("namespace_id", "name", "domain", "port", "second", "times", "notify_type", "notify_target", "notify_times", "description").
|
||||
Values(m.NamespaceID, m.Name, m.Domain, m.Port, m.Second, m.Times, m.NotifyType, m.NotifyTarget, m.NotifyTimes, m.Description).
|
||||
Columns("namespace_id", "name", "domain", "port", "second", "times", "notify_type", "notify_target", "notify_times", "description", "error_content").
|
||||
Values(m.NamespaceID, m.Name, m.Domain, m.Port, m.Second, m.Times, m.NotifyType, m.NotifyTarget, m.NotifyTimes, m.Description, "").
|
||||
RunWith(DB).
|
||||
Exec()
|
||||
if err != nil {
|
||||
|
@ -15,9 +15,11 @@ type Project struct {
|
||||
Name string `json:"name"`
|
||||
URL string `json:"url"`
|
||||
Path string `json:"path"`
|
||||
SymlinkPath string `json:"symlinkPath"`
|
||||
Environment uint8 `json:"environment"`
|
||||
Branch string `json:"branch"`
|
||||
SymlinkPath string `json:"symlinkPath"`
|
||||
Review uint8 `json:"review"`
|
||||
ReviewURL string `json:"reviewURL"`
|
||||
AfterPullScriptMode string `json:"afterPullScriptMode"`
|
||||
AfterPullScript string `json:"afterPullScript"`
|
||||
AfterDeployScriptMode string `json:"afterDeployScriptMode"`
|
||||
@ -65,8 +67,42 @@ type Projects []Project
|
||||
func (p Project) AddRow() (int64, error) {
|
||||
result, err := sq.
|
||||
Insert(projectTable).
|
||||
Columns("namespace_id", "name", "url", "path", "symlink_path", "environment", "branch", "after_pull_script_mode", "after_pull_script", "after_deploy_script_mode", "after_deploy_script", "rsync_option", "notify_type", "notify_target").
|
||||
Values(p.NamespaceID, p.Name, p.URL, p.Path, p.SymlinkPath, p.Environment, p.Branch, p.AfterPullScriptMode, p.AfterPullScript, p.AfterDeployScriptMode, p.AfterDeployScript, p.RsyncOption, p.NotifyType, p.NotifyTarget).
|
||||
Columns(
|
||||
"namespace_id",
|
||||
"name",
|
||||
"url",
|
||||
"path",
|
||||
"environment",
|
||||
"branch",
|
||||
"symlink_path",
|
||||
"review",
|
||||
"review_url",
|
||||
"after_pull_script_mode",
|
||||
"after_pull_script",
|
||||
"after_deploy_script_mode",
|
||||
"after_deploy_script",
|
||||
"rsync_option",
|
||||
"notify_type",
|
||||
"notify_target",
|
||||
).
|
||||
Values(
|
||||
p.NamespaceID,
|
||||
p.Name,
|
||||
p.URL,
|
||||
p.Path,
|
||||
p.Environment,
|
||||
p.Branch,
|
||||
p.SymlinkPath,
|
||||
p.Review,
|
||||
p.ReviewURL,
|
||||
p.AfterPullScriptMode,
|
||||
p.AfterPullScript,
|
||||
p.AfterDeployScriptMode,
|
||||
p.AfterDeployScript,
|
||||
p.RsyncOption,
|
||||
p.NotifyType,
|
||||
p.NotifyTarget,
|
||||
).
|
||||
RunWith(DB).
|
||||
Exec()
|
||||
if err != nil {
|
||||
@ -84,9 +120,11 @@ func (p Project) EditRow() error {
|
||||
"name": p.Name,
|
||||
"url": p.URL,
|
||||
"path": p.Path,
|
||||
"symlink_path": p.SymlinkPath,
|
||||
"environment": p.Environment,
|
||||
"branch": p.Branch,
|
||||
"symlink_path": p.SymlinkPath,
|
||||
"review": p.Review,
|
||||
"review_url": p.ReviewURL,
|
||||
"after_pull_script_mode": p.AfterPullScriptMode,
|
||||
"after_pull_script": p.AfterPullScript,
|
||||
"after_deploy_script_mode": p.AfterDeployScriptMode,
|
||||
@ -175,7 +213,27 @@ func (p Project) DeployFail() error {
|
||||
// GetList -
|
||||
func (p Project) GetList(pagination Pagination) (Projects, error) {
|
||||
builder := sq.
|
||||
Select("project.id, name, url, path, symlink_path, environment, branch, after_pull_script_mode, after_pull_script, after_deploy_script_mode, after_deploy_script, rsync_option, auto_deploy, notify_type, notify_target, project.insert_time, project.update_time").
|
||||
Select(`
|
||||
project.id,
|
||||
name,
|
||||
url,
|
||||
path,
|
||||
environment,
|
||||
branch,
|
||||
symlink_path,
|
||||
review,
|
||||
review_url,
|
||||
after_pull_script_mode,
|
||||
after_pull_script,
|
||||
after_deploy_script_mode,
|
||||
after_deploy_script,
|
||||
rsync_option,
|
||||
auto_deploy,
|
||||
notify_type,
|
||||
notify_target,
|
||||
project.insert_time,
|
||||
project.update_time
|
||||
`).
|
||||
From(projectTable).
|
||||
Join(projectUserTable + " ON project_user.project_id = project.id").
|
||||
Where(sq.Eq{
|
||||
@ -206,9 +264,11 @@ func (p Project) GetList(pagination Pagination) (Projects, error) {
|
||||
&project.Name,
|
||||
&project.URL,
|
||||
&project.Path,
|
||||
&project.SymlinkPath,
|
||||
&project.Environment,
|
||||
&project.Branch,
|
||||
&project.SymlinkPath,
|
||||
&project.Review,
|
||||
&project.ReviewURL,
|
||||
&project.AfterPullScriptMode,
|
||||
&project.AfterPullScript,
|
||||
&project.AfterDeployScriptMode,
|
||||
@ -265,6 +325,7 @@ func (p Project) GetUserProjectList() (Projects, error) {
|
||||
IFNULL(publish_trace.ext, '{}'),
|
||||
project.environment,
|
||||
project.branch,
|
||||
project.review,
|
||||
project.last_publish_token,
|
||||
project.deploy_state,
|
||||
project.update_time`).
|
||||
@ -299,6 +360,7 @@ func (p Project) GetUserProjectList() (Projects, error) {
|
||||
&project.PublishExt,
|
||||
&project.Environment,
|
||||
&project.Branch,
|
||||
&project.Review,
|
||||
&project.LastPublishToken,
|
||||
&project.DeployState,
|
||||
&project.UpdateTime); err != nil {
|
||||
@ -315,7 +377,7 @@ func (p Project) GetUserProjectList() (Projects, error) {
|
||||
func (p Project) GetData() (Project, error) {
|
||||
var project Project
|
||||
err := sq.
|
||||
Select("id, namespace_id, name, url, path, symlink_path, environment, branch, after_pull_script_mode, after_pull_script, after_deploy_script_mode, after_deploy_script, rsync_option, auto_deploy, deploy_state, notify_type, notify_target, insert_time, update_time").
|
||||
Select("id, namespace_id, name, url, path, environment, branch, symlink_path, review, review_url, after_pull_script_mode, after_pull_script, after_deploy_script_mode, after_deploy_script, rsync_option, auto_deploy, deploy_state, notify_type, notify_target, insert_time, update_time").
|
||||
From(projectTable).
|
||||
Where(sq.Eq{"id": p.ID}).
|
||||
RunWith(DB).
|
||||
@ -326,9 +388,11 @@ func (p Project) GetData() (Project, error) {
|
||||
&project.Name,
|
||||
&project.URL,
|
||||
&project.Path,
|
||||
&project.SymlinkPath,
|
||||
&project.Environment,
|
||||
&project.Branch,
|
||||
&project.SymlinkPath,
|
||||
&project.Review,
|
||||
&project.ReviewURL,
|
||||
&project.AfterPullScriptMode,
|
||||
&project.AfterPullScript,
|
||||
&project.AfterDeployScriptMode,
|
||||
|
125
model/ProjectReviewModel.go
Normal file
125
model/ProjectReviewModel.go
Normal file
@ -0,0 +1,125 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
sq "github.com/Masterminds/squirrel"
|
||||
)
|
||||
|
||||
const projectReviewTable = "`project_review`"
|
||||
|
||||
// ProjectReview -
|
||||
type ProjectReview struct {
|
||||
ID int64 `json:"id"`
|
||||
ProjectID int64 `json:"projectId"`
|
||||
CommitID string `json:"commitId"`
|
||||
ReviewURL string `json:"reviewURL"`
|
||||
State uint8 `json:"state"`
|
||||
Creator string `json:"creator"`
|
||||
CreatorID int64 `json:"creatorId"`
|
||||
Editor string `json:"editor"`
|
||||
EditorID int64 `json:"editorId"`
|
||||
InsertTime string `json:"insertTime"`
|
||||
UpdateTime string `json:"updateTime"`
|
||||
}
|
||||
|
||||
// ProjectReviews -
|
||||
type ProjectReviews []ProjectReview
|
||||
|
||||
// GetListByProjectID -
|
||||
func (pr ProjectReview) GetListByProjectID(pagination Pagination) (ProjectReviews, Pagination, error) {
|
||||
rows, err := sq.
|
||||
Select("id, project_id, commit_id, state, creator, creator_id, editor, editor_id, insert_time, update_time").
|
||||
From(projectReviewTable).
|
||||
Where(sq.Eq{"project_id": pr.ProjectID}).
|
||||
Limit(pagination.Rows).
|
||||
Offset((pagination.Page - 1) * pagination.Rows).
|
||||
OrderBy("id DESC").
|
||||
RunWith(DB).
|
||||
Query()
|
||||
|
||||
if err != nil {
|
||||
return nil, pagination, err
|
||||
}
|
||||
projectReviews := ProjectReviews{}
|
||||
for rows.Next() {
|
||||
var projectReview ProjectReview
|
||||
|
||||
if err := rows.Scan(
|
||||
&projectReview.ID,
|
||||
&projectReview.ProjectID,
|
||||
&projectReview.CommitID,
|
||||
&projectReview.State,
|
||||
&projectReview.Creator,
|
||||
&projectReview.CreatorID,
|
||||
&projectReview.Editor,
|
||||
&projectReview.EditorID,
|
||||
&projectReview.InsertTime,
|
||||
&projectReview.UpdateTime,
|
||||
); err != nil {
|
||||
return projectReviews, pagination, err
|
||||
}
|
||||
projectReviews = append(projectReviews, projectReview)
|
||||
}
|
||||
err = sq.
|
||||
Select("COUNT(*) AS count").
|
||||
From(projectReviewTable).
|
||||
Where(sq.Eq{"project_id": pr.ProjectID}).
|
||||
RunWith(DB).
|
||||
QueryRow().
|
||||
Scan(&pagination.Total)
|
||||
if err != nil {
|
||||
return projectReviews, pagination, err
|
||||
}
|
||||
return projectReviews, pagination, nil
|
||||
}
|
||||
|
||||
// GetData -
|
||||
func (pr ProjectReview) GetData() (ProjectReview, error) {
|
||||
var projectReview ProjectReview
|
||||
err := sq.
|
||||
Select("id, project_id, commit_id, state, insert_time, update_time").
|
||||
From(projectReviewTable).
|
||||
Where(sq.Eq{"id": pr.ID}).
|
||||
RunWith(DB).
|
||||
QueryRow().
|
||||
Scan(
|
||||
&projectReview.ID,
|
||||
&projectReview.ProjectID,
|
||||
&projectReview.CommitID,
|
||||
&projectReview.State,
|
||||
&projectReview.InsertTime,
|
||||
&projectReview.UpdateTime)
|
||||
if err != nil {
|
||||
return projectReview, err
|
||||
}
|
||||
return projectReview, nil
|
||||
}
|
||||
|
||||
// AddRow -
|
||||
func (pr ProjectReview) AddRow() (int64, error) {
|
||||
result, err := sq.
|
||||
Insert(projectReviewTable).
|
||||
Columns("project_id", "commit_id", "review_url", "creator", "creator_id").
|
||||
Values(pr.ProjectID, pr.CommitID, pr.ReviewURL, pr.Creator, pr.CreatorID).
|
||||
RunWith(DB).
|
||||
Exec()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
id, err := result.LastInsertId()
|
||||
return id, err
|
||||
}
|
||||
|
||||
// EditRow -
|
||||
func (pr ProjectReview) EditRow() error {
|
||||
_, err := sq.
|
||||
Update(projectReviewTable).
|
||||
SetMap(sq.Eq{
|
||||
"state": pr.State,
|
||||
"editor": pr.Editor,
|
||||
"editor_id": pr.EditorID,
|
||||
}).
|
||||
Where(sq.Eq{"id": pr.ID}).
|
||||
RunWith(DB).
|
||||
Exec()
|
||||
return err
|
||||
}
|
@ -64,7 +64,7 @@ func (pt ProjectTask) GetListByProjectID(pagination Pagination) (ProjectTasks, P
|
||||
&projectTask.InsertTime,
|
||||
&projectTask.UpdateTime,
|
||||
); err != nil {
|
||||
return nil, pagination, err
|
||||
return projectTasks, pagination, err
|
||||
}
|
||||
projectTasks = append(projectTasks, projectTask)
|
||||
}
|
||||
@ -76,7 +76,7 @@ func (pt ProjectTask) GetListByProjectID(pagination Pagination) (ProjectTasks, P
|
||||
QueryRow().
|
||||
Scan(&pagination.Total)
|
||||
if err != nil {
|
||||
return nil, pagination, err
|
||||
return projectTasks, pagination, err
|
||||
}
|
||||
return projectTasks, pagination, nil
|
||||
}
|
||||
|
@ -16,8 +16,8 @@ func Init() *router.Router {
|
||||
// no need to check login
|
||||
rt.RegisterWhiteList(map[string]struct{}{
|
||||
"/user/login": {},
|
||||
"/user/isShowPhrase": {},
|
||||
"/deploy/webhook": {},
|
||||
"/deploy/callback": {},
|
||||
})
|
||||
// websocket route
|
||||
rt.Add("/ws/connect", http.MethodGet, ws.GetHub().Connect)
|
||||
@ -61,6 +61,7 @@ func Init() *router.Router {
|
||||
rt.Add("/project/editTask", http.MethodPost, controller.Project{}.EditTask).Roles([]string{core.RoleAdmin, core.RoleManager, core.RoleGroupManager})
|
||||
rt.Add("/project/removeTask", http.MethodPost, controller.Project{}.RemoveTask).Roles([]string{core.RoleAdmin, core.RoleManager, core.RoleGroupManager})
|
||||
rt.Add("/project/getTaskList", http.MethodGet, controller.Project{}.GetTaskList).Roles([]string{core.RoleAdmin, core.RoleManager, core.RoleGroupManager})
|
||||
rt.Add("/project/getReviewList", http.MethodGet, controller.Project{}.GetReviewList)
|
||||
|
||||
// monitor route
|
||||
rt.Add("/monitor/getList", http.MethodGet, controller.Monitor{}.GetList)
|
||||
@ -76,8 +77,10 @@ func Init() *router.Router {
|
||||
rt.Add("/deploy/getDetail", http.MethodGet, controller.Deploy{}.GetDetail)
|
||||
rt.Add("/deploy/getCommitList", http.MethodGet, controller.Deploy{}.GetCommitList)
|
||||
rt.Add("/deploy/getPreview", http.MethodGet, controller.Deploy{}.GetPreview)
|
||||
rt.Add("/deploy/review", http.MethodPost, controller.Deploy{}.Review).Roles([]string{core.RoleAdmin, core.RoleManager, core.RoleGroupManager})
|
||||
rt.Add("/deploy/publish", http.MethodPost, controller.Deploy{}.Publish, middleware.HasPublishAuth)
|
||||
rt.Add("/deploy/webhook", http.MethodPost, controller.Deploy{}.Webhook, middleware.FilterEvent)
|
||||
rt.Add("/deploy/callback", http.MethodGet, controller.Deploy{}.Callback)
|
||||
|
||||
// server route
|
||||
rt.Add("/server/getList", http.MethodGet, controller.Server{}.GetList)
|
||||
|
@ -29,12 +29,12 @@ func (repository Repository) Create() error {
|
||||
return err
|
||||
}
|
||||
git := utils.GIT{}
|
||||
if err := git.Clone([]string{project.URL, srcPath}); err != nil {
|
||||
if err := git.Clone(project.URL, srcPath); err != nil {
|
||||
core.Log(core.ERROR, "The project fail to initialize, projectID:"+strconv.FormatInt(project.ID, 10)+" ,error: "+err.Error()+", detail: "+git.Err.String())
|
||||
return err
|
||||
}
|
||||
if project.Branch != "master" {
|
||||
if err := git.Checkout([]string{"-b", project.Branch, "origin/" + project.Branch}); err != nil {
|
||||
if err := git.Checkout("-b", project.Branch, "origin/" + project.Branch); err != nil {
|
||||
core.Log(core.ERROR, "The project fail to switch branch, projectID:"+strconv.FormatInt(project.ID, 10)+" ,error: "+err.Error()+", detail: "+git.Err.String())
|
||||
os.RemoveAll(srcPath)
|
||||
return err
|
||||
|
@ -210,7 +210,7 @@ func gitPull(project model.Project) error {
|
||||
Message: ws.ProjectMessage{ProjectID: project.ID, ProjectName: project.Name, State: ws.GitClean, Message: "git clean"},
|
||||
}
|
||||
core.Log(core.TRACE, "projectID:"+strconv.FormatInt(project.ID, 10)+" git clean -f")
|
||||
if err := git.Clean([]string{"-f"}); err != nil {
|
||||
if err := git.Clean("-f"); err != nil {
|
||||
core.Log(core.ERROR, err.Error()+", detail: "+git.Err.String())
|
||||
return errors.New(git.Err.String())
|
||||
}
|
||||
@ -221,7 +221,7 @@ func gitPull(project model.Project) error {
|
||||
Message: ws.ProjectMessage{ProjectID: project.ID, ProjectName: project.Name, State: ws.GitCheckout, Message: "git checkout"},
|
||||
}
|
||||
core.Log(core.TRACE, "projectID:"+strconv.FormatInt(project.ID, 10)+" git checkout -- .")
|
||||
if err := git.Checkout([]string{"--", "."}); err != nil {
|
||||
if err := git.Checkout("--", "."); err != nil {
|
||||
core.Log(core.ERROR, err.Error()+", detail: "+git.Err.String())
|
||||
return errors.New(git.Err.String())
|
||||
}
|
||||
@ -231,7 +231,7 @@ func gitPull(project model.Project) error {
|
||||
Message: ws.ProjectMessage{ProjectID: project.ID, ProjectName: project.Name, State: ws.GitPull, Message: "git pull"},
|
||||
}
|
||||
core.Log(core.TRACE, "projectID:"+strconv.FormatInt(project.ID, 10)+" git pull")
|
||||
if err := git.Pull([]string{}); err != nil {
|
||||
if err := git.Pull(); err != nil {
|
||||
core.Log(core.ERROR, err.Error()+", detail: "+git.Err.String())
|
||||
return errors.New(git.Err.String())
|
||||
}
|
||||
@ -262,7 +262,7 @@ func gitReset(commit string, project model.Project) error {
|
||||
func gitCommitLog(project model.Project) (utils.Commit, error) {
|
||||
git := utils.GIT{Dir: core.GetProjectPath(project.ID)}
|
||||
|
||||
if err := git.Log([]string{"--stat", "--pretty=format:`start`%H`%an`%at`%s`", "-n", "1"}); err != nil {
|
||||
if err := git.Log("--stat", "--pretty=format:`start`%H`%an`%at`%s`", "-n", "1"); err != nil {
|
||||
core.Log(core.ERROR, err.Error()+", detail: "+git.Err.String())
|
||||
return utils.Commit{}, errors.New(git.Err.String())
|
||||
}
|
||||
|
25
utils/Git.go
25
utils/Git.go
@ -13,7 +13,7 @@ type GIT struct {
|
||||
Err bytes.Buffer
|
||||
}
|
||||
|
||||
func (git *GIT) Run(operator string,options []string) error {
|
||||
func (git *GIT) Run(operator string, options ...string) error {
|
||||
git.Output.Reset()
|
||||
git.Err.Reset()
|
||||
cmd := exec.Command("git", append([]string{operator}, options...)...)
|
||||
@ -28,44 +28,41 @@ func (git *GIT) Run(operator string,options []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (git *GIT) Clone(options []string) error {
|
||||
if err := git.Run("clone", options); err != nil {
|
||||
func (git *GIT) Clone(options ...string) error {
|
||||
if err := git.Run("clone", options...); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
func (git *GIT) Clean(options []string) error {
|
||||
if err := git.Run("clean", options); err != nil {
|
||||
func (git *GIT) Clean(options ...string) error {
|
||||
if err := git.Run("clean", options...); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (git *GIT) Checkout(options []string) error {
|
||||
if err := git.Run("checkout", options); err != nil {
|
||||
func (git *GIT) Checkout(options ...string) error {
|
||||
if err := git.Run("checkout", options...); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (git *GIT) Pull(options []string) error {
|
||||
if err := git.Run("pull", options); err != nil {
|
||||
func (git *GIT) Pull(options ...string) error {
|
||||
if err := git.Run("pull", options...); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
func (git *GIT) Log(options []string) error {
|
||||
if err := git.Run("log", options); err != nil {
|
||||
func (git *GIT) Log(options ...string) error {
|
||||
if err := git.Run("log", options...); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
type Commit struct {
|
||||
Commit string `json:"commit"`
|
||||
Author string `json:"author"`
|
||||
|
@ -1,3 +1,3 @@
|
||||
ALTER TABLE `goploy`.`monitor`
|
||||
ADD COLUMN `notify_times` smallint(5) UNSIGNED NOT NULL DEFAULT 1 AFTER `notify_target`,
|
||||
ADD COLUMN `error_content` text NOT NULL AFTER `notify_times`;
|
||||
ADD COLUMN `error_content` varchar(1000) NOT NULL DEFAULT '' AFTER `notify_times`;
|
3
v1.0.4.sql
Normal file
3
v1.0.4.sql
Normal file
@ -0,0 +1,3 @@
|
||||
ALTER TABLE `goploy`.`project`
|
||||
ADD COLUMN `review` tinyint(4) UNSIGNED NOT NULL DEFAULT 0 COMMENT '0.disable 1.enable' AFTER `symlink_path`,
|
||||
ADD COLUMN `review_url` varchar(1000) NOT NULL DEFAULT '' COMMENT 'review notification link' AFTER `review`;
|
@ -64,6 +64,18 @@ export function publish(projectId, commit) {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {int} id
|
||||
* @return {Promise}
|
||||
*/
|
||||
export function review(projectReviewId, state) {
|
||||
return request({
|
||||
url: '/deploy/review',
|
||||
method: 'post',
|
||||
data: { projectReviewId, state }
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {int} id
|
||||
* @return {Promise}
|
||||
|
@ -175,3 +175,15 @@ export function getTaskList({ page, rows }, id) {
|
||||
params: { page, rows, id }
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {id} id
|
||||
* @return {Promise}
|
||||
*/
|
||||
export function getReviewList({ page, rows }, id) {
|
||||
return request({
|
||||
url: '/project/getReviewList',
|
||||
method: 'get',
|
||||
params: { page, rows, id }
|
||||
})
|
||||
}
|
||||
|
@ -25,11 +25,15 @@ export default {
|
||||
crontab: 'Crontab',
|
||||
command: 'Command',
|
||||
directory: 'Directory',
|
||||
func: 'Func',
|
||||
param: 'Param',
|
||||
deploy: 'Deploy',
|
||||
search: 'Search',
|
||||
tips: 'Tips',
|
||||
view: 'View',
|
||||
detail: 'Detail',
|
||||
review: 'Review',
|
||||
reject: 'Reject',
|
||||
manage: 'Manage',
|
||||
interval: 'Interval',
|
||||
desc: 'Description',
|
||||
@ -38,7 +42,6 @@ export default {
|
||||
branch: 'Branch',
|
||||
setting: 'Setting',
|
||||
baseSetting: 'Base setting',
|
||||
advancedSetting: 'Advanced setting',
|
||||
notice: 'Notice',
|
||||
task: 'Task',
|
||||
date: 'Date',
|
||||
@ -52,9 +55,12 @@ export default {
|
||||
creator: 'Creator',
|
||||
editor: 'Editor',
|
||||
op: 'Operation',
|
||||
submit: 'Submit',
|
||||
add: 'Add',
|
||||
edit: 'Edit',
|
||||
copy: 'Copy',
|
||||
approve: 'Approve',
|
||||
deny: 'Deny',
|
||||
upload: 'Upload',
|
||||
uploading: 'Uploading',
|
||||
reUpload: 'Reupload',
|
||||
@ -166,6 +172,10 @@ export default {
|
||||
removeUserTips: `This action will delete the user's({userName}) binding relationship, continue?`
|
||||
},
|
||||
deployPage: {
|
||||
taskDeploy: 'Crontab deploy',
|
||||
reviewDeploy: 'Review deploy',
|
||||
reviewTips: 'This action will approve commit, continue?',
|
||||
reviewStateOption: ['Wait', 'Reviewed', 'Rejected'],
|
||||
removeProjectTaskTips: 'This action will delete the crontab task in {projectName}, continue?',
|
||||
rollbackTips: 'This action will rebuild {commit}, continue?'
|
||||
}
|
||||
|
@ -25,11 +25,15 @@ export default {
|
||||
crontab: '定时',
|
||||
command: '命令',
|
||||
directory: '目录',
|
||||
func: '功能',
|
||||
param: '参数',
|
||||
deploy: '构建',
|
||||
search: '搜索',
|
||||
tips: '提示',
|
||||
view: '查看',
|
||||
detail: '详情',
|
||||
review: '审核',
|
||||
reject: '拒绝',
|
||||
manage: '管理',
|
||||
interval: '间隔',
|
||||
desc: '描述',
|
||||
@ -38,7 +42,6 @@ export default {
|
||||
branch: '分支',
|
||||
setting: '设置',
|
||||
baseSetting: '基本配置',
|
||||
advancedSetting: '高级配置',
|
||||
notice: '通知',
|
||||
task: '任务',
|
||||
date: '日期',
|
||||
@ -46,14 +49,18 @@ export default {
|
||||
today: '今天',
|
||||
m1d: '减一天',
|
||||
p1d: '加一天',
|
||||
time: '时间',
|
||||
insertTime: '创建时间',
|
||||
updateTime: '更新时间',
|
||||
creator: '创建人',
|
||||
editor: '修改人',
|
||||
op: '操作',
|
||||
submit: '提交',
|
||||
add: '添加',
|
||||
edit: '编辑',
|
||||
copy: '复制',
|
||||
approve: '同意',
|
||||
deny: '拒绝',
|
||||
upload: '上传',
|
||||
uploading: '上传中',
|
||||
reUpload: '重传',
|
||||
@ -143,6 +150,15 @@ export default {
|
||||
lishBranch: '列出分支',
|
||||
scriptMode: '脚本类型',
|
||||
deployNotice: '构建通知',
|
||||
publishReview: '发布审核',
|
||||
reviewFooterTips: `
|
||||
<p>只有成员构建项目才会触发审核</p>
|
||||
审核方式:
|
||||
<p>1. 前往构建发布页面进行审核</p>
|
||||
<p>2. 推送到URL:http(s)://domain?custom-param=1&callback=***</p>
|
||||
<p> http get callback的值即可完成审核</p>
|
||||
<p> 重复访问callback只会发布一次,并且发布过不会再次发布</p>
|
||||
`,
|
||||
symlinkLabel: '软链部署(推荐)',
|
||||
symlinkHeaderTips: `<p>项目先同步到指定目录(rsync 软链目录),然后ln -s 部署路径 软链目录</p>
|
||||
<p>可以避免项目在同步传输文件的过程中,外部访问到部分正在同步的文件</p>
|
||||
@ -167,6 +183,10 @@ export default {
|
||||
removeUserTips: '此操作将永久删除用户({userName})的绑定关系, 是否继续?'
|
||||
},
|
||||
deployPage: {
|
||||
taskDeploy: '定时构建',
|
||||
reviewDeploy: '审核构建',
|
||||
reviewTips: '此操作将通过该次提交, 是否继续?',
|
||||
reviewStateOption: ['待审', '已审', '拒审'],
|
||||
removeProjectTaskTips: '此操作删除{projectName}的定时任务, 是否继续?',
|
||||
rollbackTips: '此操作将重新构建{commit}, 是否继续?'
|
||||
}
|
||||
|
@ -11,6 +11,9 @@ const mixin = {
|
||||
},
|
||||
hasGroupManagerPermission() {
|
||||
return [this.$global.Admin, this.$global.Manager, this.$global.GroupManager].indexOf(getNamespace()['role']) !== -1
|
||||
},
|
||||
isMember() {
|
||||
return this.$global.member === getNamespace()['role']
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -59,30 +59,32 @@
|
||||
<template slot-scope="scope">
|
||||
<el-row class="operation-btn">
|
||||
<el-dropdown
|
||||
v-if="hasGroupManagerPermission() || scope.row.review === 0"
|
||||
split-button
|
||||
trigger="click"
|
||||
:disabled="scope.row.deployState === 1"
|
||||
type="primary"
|
||||
@click="publish(scope.row)"
|
||||
@command="handlePublishCommand"
|
||||
@command="(commandFunc) => commandFunc(scope.row)"
|
||||
>
|
||||
{{ $t('deploy') }}
|
||||
{{ isMember() && scope.row.review === 1 ? $t('submit') : $t('deploy') }}
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item :command="scope.row">List commit</el-dropdown-item>
|
||||
<el-dropdown-item :command="getCommitList">Commit list</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
<el-button v-else type="primary" @click="getCommitList(scope.row)">{{ $t('deploy') }}</el-button>
|
||||
<el-dropdown
|
||||
v-if="hasGroupManagerPermission()"
|
||||
split-button
|
||||
trigger="click"
|
||||
v-if="hasGroupManagerPermission() || scope.row.review === 1"
|
||||
:disabled="scope.row.deployState === 1"
|
||||
type="warning"
|
||||
@click="handleAddProjectTask(scope.row)"
|
||||
@command="handleProjectTaskCommand"
|
||||
trigger="click"
|
||||
@command="(commandFunc) => commandFunc(scope.row)"
|
||||
>
|
||||
{{ $t('crontab') }}
|
||||
<el-button type="warning">
|
||||
{{ $t('func') }}<i class="el-icon-arrow-down el-icon--right" />
|
||||
</el-button>
|
||||
<el-dropdown-menu slot="dropdown" style="min-width:84px;text-align:center;">
|
||||
<el-dropdown-item :command="scope.row">{{ $t('manage') }}</el-dropdown-item>
|
||||
<el-dropdown-item v-if="hasGroupManagerPermission()" :command="handleTaskCommand">{{ $t('deployPage.taskDeploy') }}</el-dropdown-item>
|
||||
<el-dropdown-item v-if="scope.row.review === 1" :command="handleReviewCommand">{{ $t('deployPage.reviewDeploy') }}</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
<el-button type="success" @click="handleDetail(scope.row)">{{ $t('detail') }}</el-button>
|
||||
@ -262,6 +264,9 @@
|
||||
</div>
|
||||
</el-dialog>
|
||||
<el-dialog :title="$t('manage')" :visible.sync="taskListDialogVisible">
|
||||
<el-row class="app-bar" type="flex" justify="end">
|
||||
<el-button type="primary" icon="el-icon-plus" @click="handleAddProjectTask(selectedItem)" />
|
||||
</el-row>
|
||||
<el-table
|
||||
v-loading="taskTableLoading"
|
||||
border
|
||||
@ -272,7 +277,19 @@
|
||||
>
|
||||
<el-table-column prop="id" label="ID" width="80" />
|
||||
<el-table-column prop="projectName" :label="$t('projectName')" width="150" />
|
||||
<el-table-column prop="commitId" label="commit" width="290" />
|
||||
<el-table-column prop="commitId" label="commit" width="290">
|
||||
<template slot-scope="scope">
|
||||
<el-link
|
||||
type="primary"
|
||||
style="font-size: 12px"
|
||||
:underline="false"
|
||||
:href="parseGitURL(selectedItem.url) + '/commit/' + scope.row.commitId"
|
||||
target="_blank"
|
||||
>
|
||||
{{ scope.row.commitId }}
|
||||
</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="date" :label="$t('date')" width="150" />
|
||||
<el-table-column prop="isRun" :label="$t('task')" width="60">
|
||||
<template slot-scope="scope">
|
||||
@ -284,8 +301,8 @@
|
||||
{{ $t(`stateOption[${scope.row.state}]`) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="creator" :label="$t('creator')" />
|
||||
<el-table-column prop="editor" :label="$t('editor')" />
|
||||
<el-table-column prop="creator" :label="$t('creator')" align="center" />
|
||||
<el-table-column prop="editor" :label="$t('editor')" align="center" />
|
||||
<el-table-column prop="insertTime" :label="$t('insertTime')" width="135" align="center" />
|
||||
<el-table-column prop="updateTime" :label="$t('updateTime')" width="135" align="center" />
|
||||
<el-table-column prop="operation" :label="$t('op')" width="150" align="center" fixed="right">
|
||||
@ -295,10 +312,74 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
hide-on-single-page
|
||||
:total="taskPagination.total"
|
||||
:page-size="taskPagination.rows"
|
||||
:current-page.sync="taskPagination.page"
|
||||
style="margin-top:10px; text-align:right;"
|
||||
background
|
||||
layout="sizes, total, prev, pager, next"
|
||||
@current-change="handleTaskPageChange"
|
||||
/>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="taskListDialogVisible = false">{{ $t('cancel') }}</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<el-dialog :title="$t('review')" :visible.sync="reviewListDialogVisible">
|
||||
<el-table
|
||||
v-loading="reviewTableLoading"
|
||||
border
|
||||
stripe
|
||||
highlight-current-row
|
||||
max-height="447px"
|
||||
:data="reviewTableData"
|
||||
>
|
||||
<el-table-column prop="id" label="ID" width="80" />
|
||||
<el-table-column prop="projectName" :label="$t('projectName')" width="150" />
|
||||
<el-table-column prop="commitId" label="commit" width="290">
|
||||
<template slot-scope="scope">
|
||||
<el-link
|
||||
type="primary"
|
||||
style="font-size: 12px"
|
||||
:underline="false"
|
||||
:href="parseGitURL(selectedItem.url) + '/commit/' + scope.row.commitId"
|
||||
target="_blank"
|
||||
>
|
||||
{{ scope.row.commitId }}
|
||||
</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="state" :label="$t('state')" width="50">
|
||||
<template slot-scope="scope">
|
||||
{{ $t(`deployPage.reviewStateOption[${scope.row.state}]`) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="creator" :label="$t('creator')" align="center" />
|
||||
<el-table-column prop="editor" :label="$t('editor')" align="center" />
|
||||
<el-table-column prop="insertTime" :label="$t('insertTime')" width="135" align="center" />
|
||||
<el-table-column prop="updateTime" :label="$t('updateTime')" width="135" align="center" />
|
||||
<el-table-column prop="operation" :label="$t('op')" width="150" align="center" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="success" :disabled="scope.row.state !== 0" @click="handleProjectReview(scope.row, 1)">{{ $t('approve') }}</el-button>
|
||||
<el-button type="danger" :disabled="scope.row.state !== 0" @click="handleProjectReview(scope.row, 2)">{{ $t('deny') }}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination
|
||||
hide-on-single-page
|
||||
:total="reviewPagination.total"
|
||||
:page-size="reviewPagination.rows"
|
||||
:current-page.sync="reviewPagination.page"
|
||||
style="margin-top:10px; text-align:right;"
|
||||
background
|
||||
layout="sizes, total, prev, pager, next"
|
||||
@current-change="handleReviewPageChange"
|
||||
/>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
<el-button @click="reviewListDialogVisible = false">{{ $t('cancel') }}</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<el-dialog :title="$t('setting')" :visible.sync="taskDialogVisible" width="600px">
|
||||
<el-form ref="taskForm" :rules="taskFormRules" :model="taskFormData" label-width="120px">
|
||||
<el-form-item :label="$t('projectName')">
|
||||
@ -333,8 +414,8 @@
|
||||
</template>
|
||||
<script>
|
||||
import tableHeight from '@/mixin/tableHeight'
|
||||
import { getList, getDetail, getPreview, getCommitList, publish } from '@/api/deploy'
|
||||
import { addTask, editTask, removeTask, getTaskList } from '@/api/project'
|
||||
import { getList, getDetail, getPreview, getCommitList, publish, review } from '@/api/deploy'
|
||||
import { addTask, editTask, removeTask, getTaskList, getReviewList } from '@/api/project'
|
||||
import { getUserOption } from '@/api/namespace'
|
||||
import { parseTime, parseGitURL } from '@/utils'
|
||||
|
||||
@ -350,6 +431,8 @@ export default {
|
||||
commitDialogVisible: false,
|
||||
taskDialogVisible: false,
|
||||
taskListDialogVisible: false,
|
||||
reviewDialogVisible: false,
|
||||
reviewListDialogVisible: false,
|
||||
dialogVisible: false,
|
||||
tableloading: false,
|
||||
tableData: [],
|
||||
@ -389,6 +472,13 @@ export default {
|
||||
{ required: true, message: 'Date required', trigger: 'change' }
|
||||
]
|
||||
},
|
||||
reviewTableLoading: false,
|
||||
reviewTableData: [],
|
||||
reviewPagination: {
|
||||
total: 0,
|
||||
page: 1,
|
||||
rows: 20
|
||||
},
|
||||
searchPreview: {
|
||||
loading: false,
|
||||
projectId: '',
|
||||
@ -608,7 +698,7 @@ export default {
|
||||
this.getDetail()
|
||||
},
|
||||
|
||||
handlePublishCommand(data) {
|
||||
getCommitList(data) {
|
||||
const id = data.id
|
||||
this.commitDialogVisible = true
|
||||
this.commitTableLoading = true
|
||||
@ -652,18 +742,29 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
handleProjectTaskCommand(data) {
|
||||
this.taskListDialogVisible = true
|
||||
getTaskList() {
|
||||
this.taskTableLoading = true
|
||||
getTaskList(this.taskPagination, data.id).then(response => {
|
||||
const projectTaskList = response.data.projectTaskList || []
|
||||
getTaskList(this.taskPagination, this.selectedItem.id).then(response => {
|
||||
const projectTaskList = response.data.list
|
||||
this.taskTableData = projectTaskList.map(element => {
|
||||
return Object.assign(element, { projectId: data.id, projectName: data.name })
|
||||
return Object.assign(element, { projectId: this.selectedItem.id, projectName: this.selectedItem.name })
|
||||
})
|
||||
this.taskPagination.total = response.data.pagination.total
|
||||
}).finally(() => { this.taskTableLoading = false })
|
||||
},
|
||||
|
||||
handleTaskCommand(data) {
|
||||
this.selectedItem = data
|
||||
this.taskPagination.page = 1
|
||||
this.taskListDialogVisible = true
|
||||
this.getTaskList()
|
||||
},
|
||||
|
||||
handleTaskPageChange(page) {
|
||||
this.taskPagination.page = page
|
||||
this.getTaskList()
|
||||
},
|
||||
|
||||
submitTask() {
|
||||
this.$refs.taskForm.validate((valid) => {
|
||||
if (valid) {
|
||||
@ -713,6 +814,53 @@ export default {
|
||||
})
|
||||
},
|
||||
|
||||
getReviewList() {
|
||||
this.reviewTableLoading = true
|
||||
getReviewList(this.reviewPagination, this.selectedItem.id).then(response => {
|
||||
const projectTaskList = response.data.list
|
||||
this.reviewTableData = projectTaskList.map(element => {
|
||||
return Object.assign(element, { projectId: this.selectedItem.id, projectName: this.selectedItem.name })
|
||||
})
|
||||
this.reviewPagination.total = response.data.pagination.total
|
||||
}).finally(() => { this.reviewTableLoading = false })
|
||||
},
|
||||
|
||||
handleReviewCommand(data) {
|
||||
this.selectedItem = data
|
||||
this.reviewPagination.page = 1
|
||||
this.reviewListDialogVisible = true
|
||||
this.getReviewList()
|
||||
},
|
||||
|
||||
handleReviewPageChange(page) {
|
||||
this.reviewPagination.page = page
|
||||
this.getReviewList()
|
||||
},
|
||||
|
||||
handleProjectReview(data, state) {
|
||||
if (state === 1) {
|
||||
this.$confirm(this.$i18n.t('deployPage.reviewTips'), this.$i18n.t('tips'), {
|
||||
confirmButtonText: this.$i18n.t('confirm'),
|
||||
cancelButtonText: this.$i18n.t('cancel'),
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
review(data.id, state).then((response) => {
|
||||
const projectIndex = this.tableData.findIndex(element => element.id === data.projectId)
|
||||
this.tableData[projectIndex].state = state
|
||||
this.reviewListDialogVisible = false
|
||||
})
|
||||
}).catch(() => {
|
||||
this.$message.info('Cancel')
|
||||
})
|
||||
} else {
|
||||
review(data.id, state).then((response) => {
|
||||
const projectIndex = this.tableData.findIndex(element => element.id === data.projectId)
|
||||
this.tableData[projectIndex].state = state
|
||||
this.reviewListDialogVisible = false
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
rollback(data) {
|
||||
this.$confirm(this.$i18n.t('deployPage.rollbackTips', { commit: data.commit }), this.$i18n.t('tips'), {
|
||||
confirmButtonText: this.$i18n.t('confirm'),
|
||||
|
@ -46,6 +46,12 @@
|
||||
<el-button type="text" icon="el-icon-edit" @click="handleAutoDeploy(scope.row)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column width="60" :label="$t('review')" align="center">
|
||||
<template slot-scope="scope">
|
||||
<span v-if="scope.row.review === 0">{{ $t('close') }}</span>
|
||||
<span v-else>{{ $t('open') }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="server" width="80" :label="$t('server')" align="center">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" @click="handleServer(scope.row)">{{ $t('view') }}</el-button>
|
||||
@ -131,6 +137,18 @@
|
||||
<span slot="label">Rsync<br> [OPTION...]</span>
|
||||
<el-input v-model.trim="formData.rsyncOption" type="textarea" :rows="3" autocomplete="off" placeholder="-rtv --exclude .git --delete-after" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('projectPage.deployNotice')" prop="notifyTarget">
|
||||
<el-row type="flex">
|
||||
<el-select v-model="formData.notifyType" clearable>
|
||||
<el-option :label="$t('webhookOption[0]')" :value="0" />
|
||||
<el-option :label="$t('webhookOption[1]')" :value="1" />
|
||||
<el-option :label="$t('webhookOption[2]')" :value="2" />
|
||||
<el-option :label="$t('webhookOption[3]')" :value="3" />
|
||||
<el-option :label="$t('webhookOption[255]')" :value="255" />
|
||||
</el-select>
|
||||
<el-input v-model.trim="formData.notifyTarget" autocomplete="off" placeholder="webhook" />
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
<el-form-item v-show="formProps.showServers" :label="$t('server')" prop="serverIds">
|
||||
<el-select v-model="formData.serverIds" multiple style="width:100%">
|
||||
<el-option
|
||||
@ -152,6 +170,28 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('projectPage.publishReview')" name="review">
|
||||
<el-form-item label="" label-width="10px">
|
||||
<el-radio-group v-model="formData.review">
|
||||
<el-radio :label="0">{{ $t('close') }}</el-radio>
|
||||
<el-radio :label="1">{{ $t('open') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-show="formData.review" label="URL" label-width="50px">
|
||||
<el-input v-model.trim="formProps.reviewURL" autocomplete="off" placeholder="http(s)://domain?custom-param=1" />
|
||||
</el-form-item>
|
||||
<el-form-item v-show="formData.review" :label="$t('param')" label-width="50px">
|
||||
<el-checkbox-group v-model="formProps.reviewURLParam">
|
||||
<el-checkbox
|
||||
v-for="(item, key) in formProps.reviewURLParamOption"
|
||||
:key="key"
|
||||
:label="item.value"
|
||||
:disabled="item['disabled']"
|
||||
>{{ item.label }}</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
<el-row v-show="formData.review" style="margin: 0 10px" v-html="$t('projectPage.reviewFooterTips')" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('projectPage.symlinkLabel')" name="symlink">
|
||||
<el-row style="margin: 0 10px" v-html="$t('projectPage.symlinkHeaderTips')" />
|
||||
<el-form-item label="" label-width="10px">
|
||||
@ -209,20 +249,6 @@
|
||||
<codemirror ref="afterDeployScript" v-model="formData.afterDeployScript" :options="cmOption" />
|
||||
</el-form-item>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('advancedSetting')" name="advance">
|
||||
<el-form-item :label="$t('projectPage.deployNotice')" prop="notifyTarget">
|
||||
<el-row type="flex">
|
||||
<el-select v-model="formData.notifyType" clearable>
|
||||
<el-option :label="$t('webhookOption[0]')" :value="0" />
|
||||
<el-option :label="$t('webhookOption[1]')" :value="1" />
|
||||
<el-option :label="$t('webhookOption[2]')" :value="2" />
|
||||
<el-option :label="$t('webhookOption[3]')" :value="3" />
|
||||
<el-option :label="$t('webhookOption[255]')" :value="255" />
|
||||
</el-select>
|
||||
<el-input v-model.trim="formData.notifyTarget" autocomplete="off" placeholder="webhook" />
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-form>
|
||||
<div slot="footer" class="dialog-footer">
|
||||
@ -415,6 +441,47 @@ export default {
|
||||
tableServerData: [],
|
||||
tableUserData: [],
|
||||
formProps: {
|
||||
reviewURLParamOption: [
|
||||
{
|
||||
label: 'project_id',
|
||||
value: 'project_id=__PROJECT_ID__'
|
||||
},
|
||||
{
|
||||
label: 'project_name',
|
||||
value: 'project_name=__PROJECT_NAME__'
|
||||
},
|
||||
{
|
||||
label: 'branch',
|
||||
value: 'branch=__BRANCH__'
|
||||
},
|
||||
{
|
||||
label: 'environment',
|
||||
value: 'environment=__ENVIRONMENT__'
|
||||
},
|
||||
{
|
||||
label: 'commit_id',
|
||||
value: 'commit_id=__COMMIT_ID__'
|
||||
},
|
||||
{
|
||||
label: 'publish_time',
|
||||
value: 'publish_time=__PUBLISH_TIME__'
|
||||
},
|
||||
{
|
||||
label: 'publisher_id',
|
||||
value: 'publisher_id=__PUBLISHER_ID__'
|
||||
},
|
||||
{
|
||||
label: 'publisher_name',
|
||||
value: 'publisher_name=__PUBLISHER_NAME__'
|
||||
},
|
||||
{
|
||||
label: 'callback',
|
||||
value: 'callback=__CALLBACK__',
|
||||
disabled: true
|
||||
}
|
||||
],
|
||||
reviewURL: '',
|
||||
reviewURLParam: ['callback=__CALLBACK__'],
|
||||
symlink: false,
|
||||
disabled: false,
|
||||
branch: [],
|
||||
@ -439,6 +506,8 @@ export default {
|
||||
rsyncOption: '-rtv --exclude .git --delete-after',
|
||||
serverIds: [],
|
||||
userIds: [],
|
||||
review: 0,
|
||||
reviewURL: '',
|
||||
notifyType: 0,
|
||||
notifyTarget: ''
|
||||
},
|
||||
@ -447,7 +516,7 @@ export default {
|
||||
{ required: true, message: 'Name required', trigger: ['blur'] }
|
||||
],
|
||||
url: [
|
||||
{ required: true, message: 'Repository url required', trigger: ['blur'] }
|
||||
{ required: true, type: 'url', message: 'Repository url required', trigger: ['blur'] }
|
||||
],
|
||||
path: [
|
||||
{ required: true, message: 'Path required', trigger: ['blur'] }
|
||||
@ -517,18 +586,24 @@ export default {
|
||||
this.formProps.symlink = this.formData.symlinkPath !== ''
|
||||
this.formProps.showServers = this.formProps.showUsers = false
|
||||
this.formProps.branch = []
|
||||
this.formProps.reviewURL = ''
|
||||
this.formProps.reviewURLParam = []
|
||||
if (this.formData.review === 1 && this.formData.reviewURL.length > 0) {
|
||||
const url = new URL(this.formData.reviewURL)
|
||||
this.formProps.reviewURLParamOption.forEach(item => {
|
||||
if (url.searchParams.has(item.value.split('=')[0])) {
|
||||
url.searchParams.delete(item.value.split('=')[0])
|
||||
this.formProps.reviewURLParam.push(item.value)
|
||||
}
|
||||
})
|
||||
this.formProps.reviewURL = url.href
|
||||
}
|
||||
this.dialogVisible = true
|
||||
},
|
||||
|
||||
handleCopy(data) {
|
||||
this.formData = Object.assign({}, data)
|
||||
this.handleEdit(data)
|
||||
this.formData.id = 0
|
||||
this.formData.serverIds = []
|
||||
this.formData.userIds = []
|
||||
this.formProps.symlink = this.formData.symlinkPath !== ''
|
||||
this.formProps.showServers = this.formProps.showUsers = false
|
||||
this.formProps.branch = []
|
||||
this.dialogVisible = true
|
||||
},
|
||||
|
||||
handleRemove(data) {
|
||||
@ -602,6 +677,15 @@ export default {
|
||||
if (this.formProps.symlink === false) {
|
||||
this.formData.symlinkPath = ''
|
||||
}
|
||||
if (this.formData.review === 1 && this.formProps.reviewURL.length > 0) {
|
||||
const url = new URL(this.formProps.reviewURL)
|
||||
this.formProps.reviewURLParam.forEach(param => {
|
||||
url.searchParams.set(...param.split('='))
|
||||
})
|
||||
this.formData.reviewURL = url.href
|
||||
} else {
|
||||
this.formData.reviewURL = ''
|
||||
}
|
||||
if (this.formData.id === 0) {
|
||||
this.add()
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user