mirror of
https://gitee.com/goploy/goploy.git
synced 2024-11-29 18:57:59 +08:00
Added: custom variable
This commit is contained in:
parent
68b5d2082e
commit
e2cf9c6b11
1
.gitignore
vendored
1
.gitignore
vendored
@ -15,6 +15,7 @@ tmp
|
||||
|
||||
goploy
|
||||
goploy_arm64
|
||||
goploy_arm64.mac
|
||||
goploy.exe*
|
||||
goploy.mac
|
||||
goploy.pid
|
||||
|
14
CHANGELOG.md
14
CHANGELOG.md
@ -4,6 +4,20 @@ All notable changes to the "goploy" extension will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||
|
||||
## [1.17.0] - 2024-05-14
|
||||
|
||||
### Added
|
||||
- [custom variable](https://github.com/zhenorzz/goploy/issues/101)
|
||||
- custom login lock time
|
||||
|
||||
### Changed
|
||||
|
||||
- change deploy dialog ui
|
||||
|
||||
### Bug fixed
|
||||
- [fix quote in rsync remote shell](https://github.com/zhenorzz/goploy/pull/107)
|
||||
|
||||
|
||||
## [1.16.3] - 2024-03-29
|
||||
|
||||
### Bug fixed
|
||||
|
2
build.sh
2
build.sh
@ -29,6 +29,8 @@ env GOOS=linux go build -o goploy cmd/server/main.go
|
||||
|
||||
env GOOS=linux GOARCH=arm64 go build -o goploy_arm64 cmd/server/main.go
|
||||
|
||||
env GOOS=darwin GOARCH=arm64 go build -o goploy_arm64.mac cmd/server/main.go
|
||||
|
||||
env GOOS=darwin go build -o goploy.mac cmd/server/main.go
|
||||
|
||||
env GOOS=windows go build -o goploy.exe cmd/server/main.go
|
||||
|
@ -539,9 +539,11 @@ func (Deploy) ManageProcess(gp *server.Goploy) server.Response {
|
||||
// @Router /deploy/publish [post]
|
||||
func (Deploy) Publish(gp *server.Goploy) server.Response {
|
||||
type ReqData struct {
|
||||
ProjectID int64 `json:"projectId" validate:"required,gt=0"`
|
||||
Commit string `json:"commit"`
|
||||
Branch string `json:"branch"`
|
||||
ProjectID int64 `json:"projectId" validate:"required,gt=0"`
|
||||
Commit string `json:"commit"`
|
||||
Branch string `json:"branch"`
|
||||
ServerIDs []int64 `json:"serverIds"`
|
||||
CustomVariables []model.ProjectScriptCustomVariable `json:"customVariables"`
|
||||
}
|
||||
var reqData ReqData
|
||||
if err := gp.Decode(&reqData); err != nil {
|
||||
@ -554,11 +556,11 @@ func (Deploy) Publish(gp *server.Goploy) server.Response {
|
||||
|
||||
token := ""
|
||||
if project.DeployState == model.ProjectNotDeploy {
|
||||
token, err = projectDeploy(gp, project, "", "")
|
||||
token, err = projectDeploy(gp, project, "", "", reqData.ServerIDs, reqData.CustomVariables)
|
||||
} else if project.Review == model.Enable {
|
||||
err = projectReview(gp, project, reqData.Commit, reqData.Branch)
|
||||
} else {
|
||||
token, err = projectDeploy(gp, project, reqData.Commit, reqData.Branch)
|
||||
token, err = projectDeploy(gp, project, reqData.Commit, reqData.Branch, reqData.ServerIDs, reqData.CustomVariables)
|
||||
}
|
||||
if err != nil {
|
||||
return response.JSON{Code: response.Error, Message: err.Error()}
|
||||
@ -617,7 +619,17 @@ func (Deploy) Rebuild(gp *server.Goploy) server.Response {
|
||||
break
|
||||
}
|
||||
|
||||
if publishTrace.Type == model.Pull {
|
||||
if publishTrace.Type == model.Queue {
|
||||
var queueExt model.PublishTraceQueueExt
|
||||
if publishTrace.Ext != "" {
|
||||
err := json.Unmarshal([]byte(publishTrace.Ext), &queueExt)
|
||||
if err != nil {
|
||||
return response.JSON{Code: response.Error, Message: err.Error()}
|
||||
}
|
||||
// set the token script
|
||||
project.Script = queueExt.Script
|
||||
}
|
||||
} else if publishTrace.Type == model.Pull {
|
||||
err := json.Unmarshal([]byte(publishTrace.Ext), &commitInfo)
|
||||
if err != nil {
|
||||
return response.JSON{Code: response.Error, Message: err.Error()}
|
||||
@ -647,6 +659,7 @@ func (Deploy) Rebuild(gp *server.Goploy) server.Response {
|
||||
|
||||
if project.Script.AfterDeploy.Content != "" {
|
||||
scriptContent := project.ReplaceVars(project.Script.AfterDeploy.Content)
|
||||
scriptContent = project.ReplaceCustomVars(scriptContent)
|
||||
scriptContent = projectServer.ReplaceVars(scriptContent)
|
||||
|
||||
if project.Script.AfterDeploy.Mode == "yaml" {
|
||||
@ -815,56 +828,8 @@ func (Deploy) Rebuild(gp *server.Goploy) server.Response {
|
||||
// @Param request body deploy.GreyPublish.ReqData true "body params"
|
||||
// @Success 200 {object} response.JSON
|
||||
// @Router /deploy/greyPublish [post]
|
||||
func (Deploy) GreyPublish(gp *server.Goploy) server.Response {
|
||||
type ReqData struct {
|
||||
ProjectID int64 `json:"projectId" validate:"required,gt=0"`
|
||||
Commit string `json:"commit"`
|
||||
Branch string `json:"branch"`
|
||||
ServerIDs []int64 `json:"serverIds"`
|
||||
}
|
||||
var reqData ReqData
|
||||
if err := gp.Decode(&reqData); err != nil {
|
||||
return response.JSON{Code: response.Error, Message: err.Error()}
|
||||
}
|
||||
project, err := model.Project{ID: reqData.ProjectID}.GetData()
|
||||
|
||||
if err != nil {
|
||||
return response.JSON{Code: response.Error, Message: err.Error()}
|
||||
}
|
||||
|
||||
bindProjectServers, err := model.ProjectServer{ProjectID: project.ID}.GetBindServerListByProjectID()
|
||||
|
||||
if err != nil {
|
||||
return response.JSON{Code: response.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 response.JSON{Code: response.Error, Message: err.Error()}
|
||||
}
|
||||
task.AddDeployTask(task.Gsync{
|
||||
UserInfo: gp.UserInfo,
|
||||
Project: project,
|
||||
ProjectServers: projectServers,
|
||||
CommitID: reqData.Commit,
|
||||
Branch: reqData.Branch,
|
||||
})
|
||||
|
||||
return response.JSON{}
|
||||
func (d Deploy) GreyPublish(gp *server.Goploy) server.Response {
|
||||
return d.Publish(gp)
|
||||
}
|
||||
|
||||
// Review reviews the project
|
||||
@ -906,7 +871,7 @@ func (Deploy) Review(gp *server.Goploy) server.Response {
|
||||
if err != nil {
|
||||
return response.JSON{Code: response.Error, Message: err.Error()}
|
||||
}
|
||||
if _, err := projectDeploy(gp, project, pr.CommitID, pr.Branch); err != nil {
|
||||
if _, err := projectDeploy(gp, project, pr.CommitID, pr.Branch, nil, nil); err != nil {
|
||||
return response.JSON{Code: response.Error, Message: err.Error()}
|
||||
}
|
||||
}
|
||||
@ -1005,7 +970,7 @@ func (Deploy) Callback(gp *server.Goploy) server.Response {
|
||||
if err != nil {
|
||||
return response.JSON{Code: response.Error, Message: err.Error()}
|
||||
}
|
||||
if _, err := projectDeploy(gp, project, pr.CommitID, pr.Branch); err != nil {
|
||||
if _, err := projectDeploy(gp, project, pr.CommitID, pr.Branch, nil, nil); err != nil {
|
||||
return response.JSON{Code: response.Error, Message: err.Error()}
|
||||
}
|
||||
|
||||
@ -1016,11 +981,32 @@ func (Deploy) Callback(gp *server.Goploy) server.Response {
|
||||
return response.JSON{}
|
||||
}
|
||||
|
||||
func projectDeploy(gp *server.Goploy, project model.Project, commitID string, branch string) (string, error) {
|
||||
projectServers, err := model.ProjectServer{ProjectID: project.ID}.GetBindServerListByProjectID()
|
||||
func projectDeploy(gp *server.Goploy, project model.Project, commitID string, branch string, serverIDs []int64, customVariables []model.ProjectScriptCustomVariable) (string, error) {
|
||||
bindProjectServers, err := model.ProjectServer{ProjectID: project.ID}.GetBindServerListByProjectID()
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
projectServers := bindProjectServers
|
||||
|
||||
if len(serverIDs) > 0 {
|
||||
projectServers = model.ProjectServers{}
|
||||
for _, projectServer := range bindProjectServers {
|
||||
for _, serverID := range serverIDs {
|
||||
if projectServer.ServerID == serverID {
|
||||
projectServers = append(projectServers, projectServer)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(customVariables) > 0 {
|
||||
project.Script.CustomVariables = customVariables
|
||||
} else {
|
||||
project.Script.CustomVariables = []model.ProjectScriptCustomVariable{}
|
||||
}
|
||||
|
||||
project.PublisherID = gp.UserInfo.ID
|
||||
project.PublisherName = gp.UserInfo.Name
|
||||
project.DeployState = model.ProjectDeploying
|
||||
|
@ -49,7 +49,7 @@ var (
|
||||
s string
|
||||
)
|
||||
|
||||
const appVersion = "1.16.3"
|
||||
const appVersion = "1.17.0"
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&config.AssetDir, "asset-dir", "", "default: ./")
|
||||
@ -64,7 +64,7 @@ func init() {
|
||||
}
|
||||
|
||||
// @title Goploy
|
||||
// @version 1.16.3
|
||||
// @version 1.17.0
|
||||
// @description A web deployment system tool!
|
||||
// @contact.name zhenorzz
|
||||
// @contact.url https://github.com/zhenorzz/goploy
|
||||
|
@ -117,12 +117,18 @@ func AddDeployTask(gsync Gsync) {
|
||||
}{gsync.Project.LastPublishToken},
|
||||
},
|
||||
})
|
||||
|
||||
queueExt := model.PublishTraceQueueExt{
|
||||
Script: gsync.Project.Script,
|
||||
}
|
||||
ext, _ := json.Marshal(queueExt)
|
||||
gsync.PublishTrace = model.PublishTrace{
|
||||
Token: gsync.Project.LastPublishToken,
|
||||
ProjectID: gsync.Project.ID,
|
||||
ProjectName: gsync.Project.Name,
|
||||
PublisherID: gsync.UserInfo.ID,
|
||||
PublisherName: gsync.UserInfo.Name,
|
||||
Ext: string(ext),
|
||||
InsertTime: time.Now().Format("20060102150405"),
|
||||
Type: model.Queue,
|
||||
State: model.Success,
|
||||
@ -208,9 +214,9 @@ func (gsync *Gsync) repoStage() error {
|
||||
var err error
|
||||
r, _ := repo.GetRepo(gsync.Project.RepoType)
|
||||
if len(gsync.CommitID) == 0 {
|
||||
err = r.Follow(gsync.Project, "origin/"+gsync.Project.Branch)
|
||||
err = r.Follow(gsync.Project.ID, "origin/"+gsync.Project.Branch, gsync.Project.URL, gsync.Project.Branch)
|
||||
} else {
|
||||
err = r.Follow(gsync.Project, gsync.CommitID)
|
||||
err = r.Follow(gsync.Project.ID, gsync.CommitID, gsync.Project.URL, gsync.Project.Branch)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
@ -286,6 +292,7 @@ func (gsync *Gsync) serverStage() error {
|
||||
scriptContent := ""
|
||||
if project.Script.AfterDeploy.Content != "" {
|
||||
scriptContent = project.ReplaceVars(project.Script.AfterDeploy.Content)
|
||||
scriptContent = project.ReplaceCustomVars(scriptContent)
|
||||
scriptContent = projectServer.ReplaceVars(scriptContent)
|
||||
scriptContent = strings.Replace(scriptContent, "${SERVER_TOTAL_NUMBER}", strconv.Itoa(len(gsync.ProjectServers)), -1)
|
||||
scriptContent = strings.Replace(scriptContent, "${SERVER_SERIAL_NUMBER}", strconv.Itoa(index), -1)
|
||||
@ -575,7 +582,9 @@ func (gsync *Gsync) runLocalScript() error {
|
||||
if mode != "" {
|
||||
scriptMode = mode
|
||||
}
|
||||
scriptText := project.ReplaceVars(commitInfo.ReplaceVars(content))
|
||||
scriptText := commitInfo.ReplaceVars(content)
|
||||
scriptText = project.ReplaceVars(scriptText)
|
||||
scriptText = project.ReplaceCustomVars(scriptText)
|
||||
|
||||
// run yaml script by docker
|
||||
if mode == "yaml" {
|
||||
|
@ -392,7 +392,7 @@ CREATE TABLE IF NOT EXISTS `terminal_log` (
|
||||
INSERT IGNORE INTO `user`(`id`, `account`, `password`, `name`, `contact`, `state`, `super_manager`) VALUES (1, 'admin', '$2a$10$89ZJ2xeJj35GOw11Qiucr.phaEZP4.kBX6aKTs7oWFp1xcGBBgijm', '超管', '', 1, 1);
|
||||
INSERT IGNORE INTO `namespace`(`id`, `name`) VALUES (1, 'goploy');
|
||||
INSERT IGNORE INTO `namespace_user`(`id`, `namespace_id`, `user_id`, `role_id`) VALUES (1, 1, 1, 0);
|
||||
INSERT IGNORE INTO `system_config` (`id`, `key`, `value`) VALUES (1, 'version', '1.16.3');
|
||||
INSERT IGNORE INTO `system_config` (`id`, `key`, `value`) VALUES (1, 'version', '1.17.0');
|
||||
INSERT IGNORE INTO `role`(`id`, `name`, `description`) VALUES (1, 'manager', '');
|
||||
INSERT IGNORE INTO `role`(`id`, `name`, `description`) VALUES (2, 'member', '');
|
||||
INSERT IGNORE INTO `permission`(`id`, `pid`, `name`, `sort`, `description`) VALUES (1, 0, 'Log', 0, '');
|
||||
@ -457,7 +457,6 @@ INSERT IGNORE INTO `permission`(`id`, `pid`, `name`, `sort`, `description`) VALU
|
||||
INSERT IGNORE INTO `permission`(`id`, `pid`, `name`, `sort`, `description`) VALUES (60, 56, 'DeployDetail', 0, '');
|
||||
INSERT IGNORE INTO `permission`(`id`, `pid`, `name`, `sort`, `description`) VALUES (61, 56, 'DeployProject', 0, '');
|
||||
INSERT IGNORE INTO `permission`(`id`, `pid`, `name`, `sort`, `description`) VALUES (62, 56, 'DeployResetState', 0, '');
|
||||
INSERT IGNORE INTO `permission`(`id`, `pid`, `name`, `sort`, `description`) VALUES (63, 56, 'GreyDeploy', 0, '');
|
||||
INSERT IGNORE INTO `permission`(`id`, `pid`, `name`, `sort`, `description`) VALUES (64, 56, 'DeployRollback', 0, '');
|
||||
INSERT IGNORE INTO `permission`(`id`, `pid`, `name`, `sort`, `description`) VALUES (65, 56, 'DeployReview', 0, '');
|
||||
INSERT IGNORE INTO `permission`(`id`, `pid`, `name`, `sort`, `description`) VALUES (66, 56, 'DeployTask', 0, '');
|
||||
@ -525,7 +524,6 @@ INSERT IGNORE INTO `role_permission`(`role_id`, `permission_id`) VALUES (1, 59);
|
||||
INSERT IGNORE INTO `role_permission`(`role_id`, `permission_id`) VALUES (1, 60);
|
||||
INSERT IGNORE INTO `role_permission`(`role_id`, `permission_id`) VALUES (1, 61);
|
||||
INSERT IGNORE INTO `role_permission`(`role_id`, `permission_id`) VALUES (1, 62);
|
||||
INSERT IGNORE INTO `role_permission`(`role_id`, `permission_id`) VALUES (1, 63);
|
||||
INSERT IGNORE INTO `role_permission`(`role_id`, `permission_id`) VALUES (1, 64);
|
||||
INSERT IGNORE INTO `role_permission`(`role_id`, `permission_id`) VALUES (1, 65);
|
||||
INSERT IGNORE INTO `role_permission`(`role_id`, `permission_id`) VALUES (1, 66);
|
||||
|
@ -1,7 +1,7 @@
|
||||
# Import sql manually https://github.com/zhenorzz/goploy/blob/master/model/sql/goploy.sql
|
||||
FROM alpine
|
||||
LABEL maintainer="zhenorzz@gmail.com"
|
||||
ARG GOPLOY_VER=v1.16.3
|
||||
ARG GOPLOY_VER=v1.17.0
|
||||
ENV GOPLOY_VER=${GOPLOY_VER}
|
||||
|
||||
RUN echo "https://mirrors.aliyun.com/alpine/latest-stable/main/" > /etc/apk/repositories
|
||||
|
@ -30,6 +30,13 @@ type ProjectScript struct {
|
||||
Mode string `json:"mode"`
|
||||
Content string `json:"content"`
|
||||
} `json:"deployFinish"`
|
||||
CustomVariables []ProjectScriptCustomVariable `json:"customVariables"`
|
||||
}
|
||||
|
||||
type ProjectScriptCustomVariable struct {
|
||||
Name string `json:"name"`
|
||||
Value string `json:"value"`
|
||||
Type string `json:"type"`
|
||||
}
|
||||
|
||||
type Project struct {
|
||||
@ -588,3 +595,11 @@ func (p Project) ReplaceVars(script string) string {
|
||||
}
|
||||
return script
|
||||
}
|
||||
|
||||
func (p Project) ReplaceCustomVars(script string) string {
|
||||
for _, variable := range p.Script.CustomVariables {
|
||||
key := fmt.Sprintf("${%s}", variable.Name)
|
||||
script = strings.Replace(script, key, variable.Value, -1)
|
||||
}
|
||||
return script
|
||||
}
|
||||
|
@ -28,6 +28,10 @@ type PublishTrace struct {
|
||||
UpdateTime string `json:"updateTime"`
|
||||
}
|
||||
|
||||
type PublishTraceQueueExt struct {
|
||||
Script ProjectScript `json:"script"`
|
||||
}
|
||||
|
||||
// PublishTraces -
|
||||
type PublishTraces []PublishTrace
|
||||
|
||||
|
@ -13,10 +13,8 @@ import (
|
||||
|
||||
type Repo interface {
|
||||
Ping(url string) error
|
||||
// Create one repository
|
||||
Create(projectID int64) error
|
||||
// Follow the repository code and update to latest
|
||||
Follow(project model.Project, target string) error
|
||||
Follow(projectID int64, target string, url string, branch string) error
|
||||
// RemoteBranchList list remote branches in the url
|
||||
RemoteBranchList(url string) ([]string, error)
|
||||
// BranchList list the local repository's branches
|
||||
|
@ -10,7 +10,6 @@ import (
|
||||
"github.com/jlaffaye/ftp"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/zhenorzz/goploy/config"
|
||||
"github.com/zhenorzz/goploy/internal/model"
|
||||
"io"
|
||||
"net/url"
|
||||
"os"
|
||||
@ -34,18 +33,7 @@ func (ftpRepo FtpRepo) Ping(url string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create -
|
||||
func (ftpRepo FtpRepo) Create(projectID int64) error {
|
||||
project, err := model.Project{ID: projectID}.GetData()
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("The project does not exist, projectID:%d", projectID))
|
||||
return err
|
||||
}
|
||||
return ftpRepo.Follow(project, "")
|
||||
}
|
||||
|
||||
func (ftpRepo FtpRepo) Follow(project model.Project, _ string) error {
|
||||
projectID := project.ID
|
||||
func (ftpRepo FtpRepo) Follow(projectID int64, _ string, projectURL string, _ string) error {
|
||||
srcPath := config.GetProjectPath(projectID)
|
||||
_ = os.RemoveAll(srcPath)
|
||||
if err := os.MkdirAll(srcPath, 0755); err != nil {
|
||||
@ -53,7 +41,7 @@ func (ftpRepo FtpRepo) Follow(project model.Project, _ string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
c, err := ftpRepo.dial(project.URL)
|
||||
c, err := ftpRepo.dial(projectURL)
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("The project fail to connect ftp, projectID:%d, error:%s", projectID, err.Error()))
|
||||
return err
|
||||
|
@ -9,7 +9,6 @@ import (
|
||||
"fmt"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/zhenorzz/goploy/config"
|
||||
"github.com/zhenorzz/goploy/internal/model"
|
||||
"github.com/zhenorzz/goploy/internal/pkg"
|
||||
"os"
|
||||
"strconv"
|
||||
@ -31,22 +30,18 @@ func (GitRepo) Ping(url string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (GitRepo) Create(projectID int64) error {
|
||||
func (GitRepo) create(projectID int64, url string, branch string) error {
|
||||
srcPath := config.GetProjectPath(projectID)
|
||||
if _, err := os.Stat(srcPath); err == nil {
|
||||
return nil
|
||||
}
|
||||
project, err := model.Project{ID: projectID}.GetData()
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("The project does not exist, projectID:%d", projectID))
|
||||
return err
|
||||
}
|
||||
|
||||
if err := os.RemoveAll(srcPath); err != nil {
|
||||
log.Error(fmt.Sprintf("The project fail to remove, projectID:%d, error: %s", projectID, err.Error()))
|
||||
return err
|
||||
}
|
||||
git := pkg.GIT{}
|
||||
if err := git.Clone(project.URL, srcPath); err != nil {
|
||||
if err := git.Clone(url, srcPath); err != nil {
|
||||
log.Error(fmt.Sprintf("The project fail to initialize, projectID:%d, error:%s, detail:%s", projectID, err.Error(), git.Err.String()))
|
||||
return err
|
||||
}
|
||||
@ -57,30 +52,30 @@ func (GitRepo) Create(projectID int64) error {
|
||||
return err
|
||||
}
|
||||
|
||||
currentBranch := pkg.ClearNewline(git.Output.String())
|
||||
if project.Branch != currentBranch {
|
||||
if err := git.Checkout("-b", project.Branch, "origin/"+project.Branch); err != nil {
|
||||
log.Error(fmt.Sprintf("The project fail to switch branch, projectID:%d, error:%s, detail:%s", projectID, err.Error(), git.Err.String()))
|
||||
_ = os.RemoveAll(srcPath)
|
||||
return err
|
||||
}
|
||||
}
|
||||
//currentBranch := pkg.ClearNewline(git.Output.String())
|
||||
//if branch != currentBranch {
|
||||
// if err := git.Checkout("-b", branch, "origin/"+branch); err != nil {
|
||||
// log.Error(fmt.Sprintf("The project fail to switch branch, projectID:%d, error:%s, detail:%s", projectID, err.Error(), git.Err.String()))
|
||||
// _ = os.RemoveAll(srcPath)
|
||||
// return err
|
||||
// }
|
||||
//}
|
||||
log.Trace(fmt.Sprintf("The project success to initialize, projectID:%d", projectID))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (gitRepo GitRepo) Follow(project model.Project, target string) error {
|
||||
if err := gitRepo.Create(project.ID); err != nil {
|
||||
func (gitRepo GitRepo) Follow(projectID int64, target string, url string, branch string) error {
|
||||
if err := gitRepo.create(projectID, url, branch); err != nil {
|
||||
return err
|
||||
}
|
||||
git := pkg.GIT{Dir: config.GetProjectPath(project.ID)}
|
||||
log.Trace("projectID: " + strconv.FormatInt(project.ID, 10) + " git add .")
|
||||
git := pkg.GIT{Dir: config.GetProjectPath(projectID)}
|
||||
log.Trace("projectID: " + strconv.FormatInt(projectID, 10) + " git add .")
|
||||
if err := git.Add("."); err != nil {
|
||||
log.Error(err.Error() + ", detail: " + git.Err.String())
|
||||
return err
|
||||
}
|
||||
|
||||
log.Trace("projectID: " + strconv.FormatInt(project.ID, 10) + " git reset --hard")
|
||||
log.Trace("projectID: " + strconv.FormatInt(projectID, 10) + " git reset --hard")
|
||||
if err := git.Reset("--hard"); err != nil {
|
||||
log.Error(err.Error() + ", detail: " + git.Err.String())
|
||||
return err
|
||||
@ -88,14 +83,14 @@ func (gitRepo GitRepo) Follow(project model.Project, target string) error {
|
||||
|
||||
// the length of commit id is 40
|
||||
if len(target) != 40 {
|
||||
log.Trace("projectID: " + strconv.FormatInt(project.ID, 10) + " git fetch")
|
||||
log.Trace("projectID: " + strconv.FormatInt(projectID, 10) + " git fetch")
|
||||
if err := git.Fetch(); err != nil {
|
||||
log.Error(err.Error() + ", detail: " + git.Err.String())
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
log.Trace("projectID: " + strconv.FormatInt(project.ID, 10) + " git checkout -B goploy " + target)
|
||||
log.Trace("projectID: " + strconv.FormatInt(projectID, 10) + " git checkout -B goploy " + target)
|
||||
if err := git.Checkout("-B", "goploy", target); err != nil {
|
||||
log.Error(err.Error() + ", detail: " + git.Err.String())
|
||||
return err
|
||||
|
@ -9,7 +9,6 @@ import (
|
||||
"github.com/pkg/sftp"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/zhenorzz/goploy/config"
|
||||
"github.com/zhenorzz/goploy/internal/model"
|
||||
"github.com/zhenorzz/goploy/internal/pkg"
|
||||
"golang.org/x/crypto/ssh"
|
||||
"io"
|
||||
@ -36,17 +35,7 @@ func (sftpRepo SftpRepo) Ping(url string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sftpRepo SftpRepo) Create(projectID int64) error {
|
||||
project, err := model.Project{ID: projectID}.GetData()
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("The project does not exist, projectID:%d", projectID))
|
||||
return err
|
||||
}
|
||||
return sftpRepo.Follow(project, "")
|
||||
}
|
||||
|
||||
func (sftpRepo SftpRepo) Follow(project model.Project, _ string) error {
|
||||
projectID := project.ID
|
||||
func (sftpRepo SftpRepo) Follow(projectID int64, _ string, projectURL string, _ string) error {
|
||||
srcPath := config.GetProjectPath(projectID)
|
||||
_ = os.RemoveAll(srcPath)
|
||||
if err := os.MkdirAll(srcPath, 0755); err != nil {
|
||||
@ -54,7 +43,7 @@ func (sftpRepo SftpRepo) Follow(project model.Project, _ string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
sshClient, err := sftpRepo.dial(project.URL)
|
||||
sshClient, err := sftpRepo.dial(projectURL)
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("The project fail to connect ftp, projectID:%d, error:%s", projectID, err.Error()))
|
||||
return err
|
||||
@ -110,7 +99,7 @@ func (sftpRepo SftpRepo) Follow(project model.Project, _ string) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
_url, _, _ := sftpRepo.parseURL(project.URL)
|
||||
_url, _, _ := sftpRepo.parseURL(projectURL)
|
||||
u, err := url.Parse(_url)
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("The project fail to parse url, projectID:%d, error:%s", projectID, err.Error()))
|
||||
|
@ -10,7 +10,6 @@ import (
|
||||
"fmt"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/zhenorzz/goploy/config"
|
||||
"github.com/zhenorzz/goploy/internal/model"
|
||||
"github.com/zhenorzz/goploy/internal/pkg"
|
||||
"os"
|
||||
"strconv"
|
||||
@ -33,40 +32,35 @@ func (SvnRepo) Ping(url string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create -
|
||||
func (SvnRepo) Create(projectID int64) error {
|
||||
func (SvnRepo) create(projectID int64, url string) error {
|
||||
srcPath := config.GetProjectPath(projectID)
|
||||
if _, err := os.Stat(srcPath); err == nil {
|
||||
return nil
|
||||
}
|
||||
project, err := model.Project{ID: projectID}.GetData()
|
||||
if err != nil {
|
||||
log.Trace("The project does not exist, projectID:" + strconv.FormatInt(projectID, 10))
|
||||
return err
|
||||
}
|
||||
|
||||
if err := os.RemoveAll(srcPath); err != nil {
|
||||
log.Trace("The project fail to remove, projectID:" + strconv.FormatInt(project.ID, 10) + " ,error: " + err.Error())
|
||||
log.Trace("The project fail to remove, projectID:" + strconv.FormatInt(projectID, 10) + " ,error: " + err.Error())
|
||||
return err
|
||||
}
|
||||
svn := pkg.SVN{}
|
||||
options := strings.Split(project.URL, " ")
|
||||
options := strings.Split(url, " ")
|
||||
options = append(options, srcPath)
|
||||
if err := svn.Clone(options...); err != nil {
|
||||
log.Error("The project fail to initialize, projectID:" + strconv.FormatInt(project.ID, 10) + " ,error: " + err.Error() + ", detail: " + svn.Err.String())
|
||||
log.Error("The project fail to initialize, projectID:" + strconv.FormatInt(projectID, 10) + " ,error: " + err.Error() + ", detail: " + svn.Err.String())
|
||||
return err
|
||||
}
|
||||
log.Trace("The project success to initialize, projectID:" + strconv.FormatInt(project.ID, 10))
|
||||
log.Trace("The project success to initialize, projectID:" + strconv.FormatInt(projectID, 10))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (svnRepo SvnRepo) Follow(project model.Project, target string) error {
|
||||
if err := svnRepo.Create(project.ID); err != nil {
|
||||
func (svnRepo SvnRepo) Follow(projectID int64, target string, url string, _ string) error {
|
||||
if err := svnRepo.create(projectID, url); err != nil {
|
||||
return err
|
||||
}
|
||||
svn := pkg.SVN{Dir: config.GetProjectPath(project.ID)}
|
||||
svn := pkg.SVN{Dir: config.GetProjectPath(projectID)}
|
||||
|
||||
// the length of commit id is 40
|
||||
log.Trace("projectID:" + strconv.FormatInt(project.ID, 10) + " svn up")
|
||||
log.Trace("projectID:" + strconv.FormatInt(projectID, 10) + " svn up")
|
||||
if strings.Index(target, "r") == 0 {
|
||||
if err := svn.Pull("-r", target); err != nil {
|
||||
log.Error(err.Error() + ", detail: " + svn.Err.String())
|
||||
|
1
web/components.d.ts
vendored
1
web/components.d.ts
vendored
@ -39,6 +39,7 @@ declare module '@vue/runtime-core' {
|
||||
ElPagination: typeof import('element-plus/es')['ElPagination']
|
||||
ElPopover: typeof import('element-plus/es')['ElPopover']
|
||||
ElRadio: typeof import('element-plus/es')['ElRadio']
|
||||
ElRadioButton: typeof import('element-plus/es')['ElRadioButton']
|
||||
ElRadioGroup: typeof import('element-plus/es')['ElRadioGroup']
|
||||
ElRow: typeof import('element-plus/es')['ElRow']
|
||||
ElScrollbar: typeof import('element-plus/es')['ElScrollbar']
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "goploy",
|
||||
"version": "1.16.3",
|
||||
"version": "1.17.0",
|
||||
"license": "GPL-3.0-or-later",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
@ -138,6 +138,8 @@ export class DeployPublish extends Request {
|
||||
projectId: number
|
||||
branch: string
|
||||
commit: string
|
||||
serverIds?: number[]
|
||||
customVariables?: { name: string; value: string; type: string }[]
|
||||
}
|
||||
constructor(param: DeployPublish['param']) {
|
||||
super()
|
||||
|
@ -6,6 +6,7 @@ export interface ProjectScript {
|
||||
afterPull: { mode: string; content: string }
|
||||
afterDeploy: { mode: string; content: string }
|
||||
deployFinish: { mode: string; content: string }
|
||||
customVariables: { name: string; value: string; type: string }[]
|
||||
}
|
||||
|
||||
export interface ProjectData {
|
||||
@ -25,10 +26,6 @@ export interface ProjectData {
|
||||
review: number
|
||||
reviewURL: string
|
||||
script: ProjectScript
|
||||
afterPullScriptMode: string
|
||||
afterPullScript: string
|
||||
afterDeployScriptMode: string
|
||||
afterDeployScript: string
|
||||
transferType: string
|
||||
transferOption: string
|
||||
deployServerMode: string
|
||||
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"default": "Default",
|
||||
"select": "Select",
|
||||
"name": "Name",
|
||||
"signIn": "Sign in",
|
||||
"tag": "Tag",
|
||||
@ -408,7 +409,7 @@
|
||||
"Rejected"
|
||||
],
|
||||
"removeProjectTaskTips": "This action will delete the crontab task in {projectName}, continue?",
|
||||
"publishCommitTips": "This action will rebuild {commit}, continue?"
|
||||
"publishCommitTips": "This action will publish {commit}, continue?"
|
||||
},
|
||||
"loginPage": {
|
||||
"captchaDefault": "Click on the button for check captcha",
|
||||
|
@ -1,5 +1,6 @@
|
||||
{
|
||||
"default": "默认",
|
||||
"select": "选择",
|
||||
"name": "名称",
|
||||
"signIn": "登录",
|
||||
"tag": "标签",
|
||||
@ -354,6 +355,8 @@
|
||||
"afterDeployScriptTips": "部署后在目标服务器运行的脚本\n运行方式:打包成一份脚本文件\n如需重启服务,请注意是否需要nohup",
|
||||
"deployFinishScriptLabel": "部署完成运行脚本",
|
||||
"deployFinishScriptTips": "部署完成后在宿主服务器运行的脚本\n运行方式:打包成一份脚本文件\n检查服务器是否安装该脚本类型(默认以bash运行)",
|
||||
"customVariableLabel": "自定义变量",
|
||||
"customVariableTips": "可用在每个脚本中,构建时可选择传入参数",
|
||||
"predefinedVar": "预定义变量",
|
||||
"autoDeployTitle": "构建触发器:达成某种条件后自动构建发布项目",
|
||||
"autoDeployGitTips": "填入连接http(s)://域名(IP)/deploy/webhook?project_id={projectId}\n勾选push event即可, (Gitlab可以选对应的分支)",
|
||||
@ -379,7 +382,7 @@
|
||||
"reviewTips": "此操作将通过该次提交, 是否继续?",
|
||||
"reviewStateOption": ["待审", "已审", "拒审"],
|
||||
"removeProjectTaskTips": "此操作删除{projectName}的定时任务, 是否继续?",
|
||||
"publishCommitTips": "此操作将重新构建{commit}, 是否继续?"
|
||||
"publishCommitTips": "此操作将发布\n{commit}"
|
||||
},
|
||||
"loginPage": {
|
||||
"captchaDefault": "点击按键进行人机验证",
|
||||
|
@ -3,8 +3,19 @@
|
||||
v-model="dialogVisible"
|
||||
title="Commit"
|
||||
:fullscreen="$store.state.app.device === 'mobile'"
|
||||
:show-close="false"
|
||||
:close-on-press-escape="false"
|
||||
:close-on-click-modal="false"
|
||||
class="commit-dialog"
|
||||
>
|
||||
<el-row type="flex" justify="end" @change="handleChangeType">
|
||||
<el-radio-group v-model="type" style="margin-bottom: 10px">
|
||||
<el-radio-button label="Commit" value="Commit" />
|
||||
<el-radio-button label="Tag" value="Tag" />
|
||||
</el-radio-group>
|
||||
</el-row>
|
||||
<el-select
|
||||
v-if="type == 'Commit'"
|
||||
v-model="branch"
|
||||
v-loading="branchLoading"
|
||||
filterable
|
||||
@ -36,6 +47,17 @@
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="type == 'Tag'" prop="tag" label="tag">
|
||||
<template #default="scope">
|
||||
<RepoURL
|
||||
style="font-size: 12px"
|
||||
:url="projectRow.url"
|
||||
:suffix="'/tree/' + scope.row.tag"
|
||||
:text="scope.row.tag"
|
||||
>
|
||||
</RepoURL>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="message"
|
||||
width="155"
|
||||
@ -77,7 +99,7 @@
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<template #footer>
|
||||
<el-button @click="dialogVisible = false">
|
||||
<el-button @click="cancel">
|
||||
{{ $t('cancel') }}
|
||||
</el-button>
|
||||
</template>
|
||||
@ -85,7 +107,11 @@
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import RepoURL from '@/components/RepoURL/index.vue'
|
||||
import { RepositoryBranchList, RepositoryCommitList } from '@/api/repository'
|
||||
import {
|
||||
RepositoryBranchList,
|
||||
RepositoryCommitList,
|
||||
RepositoryTagList,
|
||||
} from '@/api/repository'
|
||||
import { ProjectData } from '@/api/project'
|
||||
import { parseTime } from '@/utils'
|
||||
import { PropType, computed, watch, ref } from 'vue'
|
||||
@ -99,13 +125,16 @@ const props = defineProps({
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const emit = defineEmits(['update:modelValue', 'cancel'])
|
||||
const dialogVisible = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (val) => {
|
||||
emit('update:modelValue', val)
|
||||
},
|
||||
})
|
||||
|
||||
const type = ref('Commit')
|
||||
|
||||
const branchLoading = ref(false)
|
||||
const branchOption = ref<RepositoryBranchList['datagram']['list']>([])
|
||||
const branch = ref('')
|
||||
@ -152,4 +181,35 @@ const getCommitList = () => {
|
||||
tableLoading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
const getTagList = () => {
|
||||
tableLoading.value = true
|
||||
new RepositoryTagList({ id: props.projectRow.id })
|
||||
.request()
|
||||
.then((response) => {
|
||||
tableData.value = response.data.list
|
||||
})
|
||||
.finally(() => {
|
||||
tableLoading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
function handleChangeType() {
|
||||
tableData.value = []
|
||||
if (type.value == 'Tag') {
|
||||
getTagList()
|
||||
}
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
emit('cancel')
|
||||
dialogVisible.value = false
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.commit-dialog {
|
||||
.el-dialog__header {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -3,6 +3,9 @@
|
||||
v-model="dialogVisible"
|
||||
title="Tag"
|
||||
:fullscreen="$store.state.app.device === 'mobile'"
|
||||
:show-close="false"
|
||||
:close-on-press-escape="false"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-table
|
||||
v-loading="tableLoading"
|
||||
@ -76,7 +79,7 @@
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<template #footer>
|
||||
<el-button @click="dialogVisible = false">
|
||||
<el-button @click="cancel">
|
||||
{{ $t('cancel') }}
|
||||
</el-button>
|
||||
</template>
|
||||
@ -97,7 +100,7 @@ const props = defineProps({
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
const emit = defineEmits(['update:modelValue'])
|
||||
const emit = defineEmits(['update:modelValue', 'cancel'])
|
||||
const dialogVisible = computed({
|
||||
get: () => props.modelValue,
|
||||
set: (val) => {
|
||||
@ -122,4 +125,9 @@ watch(
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
function cancel() {
|
||||
emit('cancel')
|
||||
dialogVisible.value = false
|
||||
}
|
||||
</script>
|
||||
|
@ -170,16 +170,7 @@
|
||||
<el-row style="margin-top: 10px" justify="space-between">
|
||||
<div>
|
||||
<Button
|
||||
v-if="row.deployState === DeployState.Uninitialized"
|
||||
:permissions="[pms.DeployProject]"
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="publish(row)"
|
||||
>
|
||||
{{ $t('initial') }}
|
||||
</Button>
|
||||
<Button
|
||||
v-else-if="row.deployState === DeployState.Deploying"
|
||||
v-if="row.deployState === DeployState.Deploying"
|
||||
:permissions="[pms.DeployResetState]"
|
||||
type="primary"
|
||||
size="small"
|
||||
@ -187,38 +178,15 @@
|
||||
>
|
||||
{{ $t('deployPage.resetState') }}
|
||||
</Button>
|
||||
<Dropdown
|
||||
<Button
|
||||
v-else
|
||||
:permissions="[pms.DeployProject]"
|
||||
:split-button="row.review === 1 ? false : true"
|
||||
trigger="click"
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="publish(row)"
|
||||
@command="(funcName: string) => commandFunc[funcName](row)"
|
||||
>
|
||||
<el-button
|
||||
v-if="row.review === 1"
|
||||
size="small"
|
||||
type="primary"
|
||||
>
|
||||
{{ $t('submit') }}
|
||||
<el-icon class="el-icon--right">
|
||||
<arrow-down />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
<span v-else>{{ $t('deploy') }}</span>
|
||||
<template #dropdown>
|
||||
<el-dropdown-menu>
|
||||
<el-dropdown-item :command="'handleCommitCommand'">
|
||||
Commit list
|
||||
</el-dropdown-item>
|
||||
<el-dropdown-item :command="'handleTagCommand'">
|
||||
Tag list
|
||||
</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</template>
|
||||
</Dropdown>
|
||||
{{ $t('deploy') }}
|
||||
</Button>
|
||||
<el-dropdown
|
||||
trigger="click"
|
||||
style="margin-left: 5px"
|
||||
@ -296,72 +264,110 @@
|
||||
<TheCommitListDialog
|
||||
v-model="commitDialogVisible"
|
||||
:project-row="selectedItem"
|
||||
@cancel="handleCancelSelectCommit"
|
||||
>
|
||||
<template #tableOP="scope">
|
||||
<Button
|
||||
type="primary"
|
||||
:permissions="[pms.DeployProject]"
|
||||
@click="publishByCommit(scope.row)"
|
||||
@click="selectCommit(scope.row)"
|
||||
>
|
||||
{{ $t('deploy') }}
|
||||
</Button>
|
||||
<Button
|
||||
type="warning"
|
||||
:permissions="[pms.GreyDeploy]"
|
||||
@click="handleGreyPublish(scope.row)"
|
||||
>
|
||||
{{ $t('grey') }}
|
||||
{{ $t('select') }}
|
||||
</Button>
|
||||
</template>
|
||||
</TheCommitListDialog>
|
||||
<TheTagListDialog v-model="tagDialogVisible" :project-row="selectedItem">
|
||||
<template #tableOP="scope">
|
||||
<Button
|
||||
type="primary"
|
||||
:permissions="[pms.DeployProject]"
|
||||
@click="publishByCommit(scope.row)"
|
||||
>
|
||||
{{ $t('deploy') }}
|
||||
</Button>
|
||||
<Button
|
||||
type="warning"
|
||||
:permissions="[pms.GreyDeploy]"
|
||||
@click="handleGreyPublish(scope.row)"
|
||||
>
|
||||
{{ $t('grey') }}
|
||||
</Button>
|
||||
</template>
|
||||
</TheTagListDialog>
|
||||
<TheTaskListDialog
|
||||
v-model="taskListDialogVisible"
|
||||
:project-row="selectedItem"
|
||||
/>
|
||||
<el-dialog v-model="greyServerDialogVisible" :title="$t('deploy')">
|
||||
<el-form
|
||||
ref="greyServerForm"
|
||||
:rules="greyServerFormRules"
|
||||
:model="greyServerFormData"
|
||||
>
|
||||
<el-form-item :label="$t('server')" label-width="80px" prop="serverIds">
|
||||
<el-checkbox-group v-model="greyServerFormData.serverIds">
|
||||
<el-checkbox
|
||||
v-for="(item, index) in greyServerFormProps.serverOption"
|
||||
:key="index"
|
||||
:label="item.serverId"
|
||||
>
|
||||
{{ item.server.name + '(' + item.server.description + ')' }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-dialog
|
||||
v-model="publishDialogVisible"
|
||||
:title="publishFormProps.title"
|
||||
class="publish-dialog"
|
||||
align-center
|
||||
width="450px"
|
||||
:fullscreen="$store.state.app.device === 'mobile'"
|
||||
>
|
||||
<template #header>
|
||||
<el-row style="white-space: pre-wrap" v-html="publishFormProps.title" />
|
||||
</template>
|
||||
<el-row>
|
||||
<el-row
|
||||
v-for="(variable, index) in publishFormProps.customVariables"
|
||||
:key="index"
|
||||
type="flex"
|
||||
align="middle"
|
||||
style="width: 100%; margin-bottom: 10px"
|
||||
>
|
||||
<el-row style="margin-right: 10px">
|
||||
<span>${</span>{{ variable.name }}<span>}</span>
|
||||
</el-row>
|
||||
<el-select
|
||||
v-if="variable.type == 'list'"
|
||||
v-model="variable.value"
|
||||
style="flex: 1"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in selectedItem.script.customVariables[index].value.split(',')"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
<el-input
|
||||
v-else
|
||||
v-model.trim="variable.value"
|
||||
style="flex: 1"
|
||||
autocomplete="off"
|
||||
placeholder="variable value"
|
||||
>
|
||||
</el-input>
|
||||
</el-row>
|
||||
<el-row style="width: 100%">
|
||||
<el-checkbox
|
||||
v-model="publishFormProps.selectCommit"
|
||||
:label="`Select Commit (default lastest ${selectedItem.branch})`"
|
||||
:disabled="publishFormProps.selectTag"
|
||||
@change="handleSelectCommit"
|
||||
/>
|
||||
<el-row
|
||||
v-show="publishFormProps.selectCommit"
|
||||
style="width: 100%; padding-left: 20px"
|
||||
>
|
||||
{{ publishFormProps.branch }}
|
||||
{{ publishFormProps.commit }}
|
||||
</el-row>
|
||||
</el-row>
|
||||
<el-row style="width: 100%; margin-top: 10px">
|
||||
<el-checkbox
|
||||
v-model="publishFormProps.selectServer"
|
||||
:label="`Select Server (default all)`"
|
||||
@change="handleSelectServer"
|
||||
/>
|
||||
<el-row
|
||||
v-show="publishFormProps.selectServer"
|
||||
style="width: 100%; padding-left: 20px"
|
||||
>
|
||||
<el-checkbox-group v-model="publishFormProps.serverIds">
|
||||
<el-checkbox
|
||||
v-for="(item, index) in publishFormProps.serverOption"
|
||||
:key="index"
|
||||
:label="item.serverId"
|
||||
>
|
||||
{{ item.server.name + '(' + item.server.description + ')' }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-row>
|
||||
</el-row>
|
||||
</el-row>
|
||||
<template #footer>
|
||||
<el-button @click="greyServerDialogVisible = false">
|
||||
<el-button @click="publishDialogVisible = false">
|
||||
{{ $t('cancel') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
:disabled="greyServerFormProps.disabled"
|
||||
:disabled="publishFormProps.disabled"
|
||||
type="primary"
|
||||
@click="greyPublish"
|
||||
@click="publishFormProps.func"
|
||||
>
|
||||
{{ $t('confirm') }}
|
||||
</el-button>
|
||||
@ -397,20 +403,17 @@ import {
|
||||
DeployList,
|
||||
DeployPublish,
|
||||
DeployResetState,
|
||||
DeployGreyPublish,
|
||||
} from '@/api/deploy'
|
||||
import { ProjectServerList, ProjectData, LabelList } from '@/api/project'
|
||||
import RepoURL from '@/components/RepoURL/index.vue'
|
||||
import { isLink, parseTime } from '@/utils'
|
||||
import { isLink, parseTime, deepClone } from '@/utils'
|
||||
import TheDetailDialog from './TheDetailDialog.vue'
|
||||
import TheCommitListDialog from './TheCommitListDialog.vue'
|
||||
import TheTagListDialog from './TheTagListDialog.vue'
|
||||
import TheTaskListDialog from './TheTaskListDialog.vue'
|
||||
import TheReviewListDialog from './TheReviewListDialog.vue'
|
||||
import TheProcessManagerDialog from './TheProcessManagerDialog.vue'
|
||||
import TheFileCompareDialog from './TheFileCompareDialog.vue'
|
||||
import TheFileSyncDialog from './TheFileSyncDialog.vue'
|
||||
import type { ElForm } from 'element-plus'
|
||||
import { computed, watch, h, ref } from 'vue'
|
||||
import { CommitData } from '@/api/repository'
|
||||
import { useStore } from 'vuex'
|
||||
@ -418,13 +421,12 @@ import { useI18n } from 'vue-i18n'
|
||||
const { t } = useI18n()
|
||||
const store = useStore()
|
||||
const commitDialogVisible = ref(false)
|
||||
const tagDialogVisible = ref(false)
|
||||
const greyServerDialogVisible = ref(false)
|
||||
const taskListDialogVisible = ref(false)
|
||||
const fileSyncDialogVisible = ref(false)
|
||||
const fileCompareDialogVisible = ref(false)
|
||||
const processManagerDialogVisible = ref(false)
|
||||
const reviewListDialogVisible = ref(false)
|
||||
const publishDialogVisible = ref(false)
|
||||
const dialogVisible = ref(false)
|
||||
const stickList = ref(getStick())
|
||||
const searchProject = ref({
|
||||
@ -459,26 +461,23 @@ const disabled = computed(() => noMore.value)
|
||||
const tableData = ref<any[]>([])
|
||||
const labelList = ref<string[]>([])
|
||||
const pagination = ref({ page: 0, rows: 24 })
|
||||
const greyServerForm = ref<InstanceType<typeof ElForm>>()
|
||||
const greyServerFormProps = ref({
|
||||
|
||||
const tempPublishFormProps = {
|
||||
disabled: false,
|
||||
serverOption: [] as ProjectServerList['datagram']['list'],
|
||||
})
|
||||
const greyServerFormData = ref({
|
||||
projectId: 0,
|
||||
title: '',
|
||||
customVariables: [],
|
||||
commit: '',
|
||||
branch: '',
|
||||
serverIds: [],
|
||||
})
|
||||
const greyServerFormRules: InstanceType<typeof ElForm>['rules'] = {
|
||||
serverIds: [
|
||||
{
|
||||
type: 'array',
|
||||
required: true,
|
||||
message: 'Server required',
|
||||
trigger: 'change',
|
||||
},
|
||||
],
|
||||
selectCommit: false,
|
||||
selectServer: false,
|
||||
serverOption: [] as ProjectServerList['datagram']['list'],
|
||||
func: () => {
|
||||
ElMessage.error('Undefined function')
|
||||
},
|
||||
}
|
||||
const publishFormProps = ref(tempPublishFormProps)
|
||||
|
||||
const tablePage = computed(() => {
|
||||
let _tableData = tableData.value
|
||||
if (searchProject.value.name !== '') {
|
||||
@ -663,16 +662,27 @@ function handleRebuilt() {
|
||||
tableData.value[projectIndex].deployState = 1
|
||||
}
|
||||
|
||||
function handleGreyPublish(data: CommitData) {
|
||||
function handleSelectCommit(state) {
|
||||
if (state == false) {
|
||||
publishFormProps.value.branch = ''
|
||||
publishFormProps.value.commit = ''
|
||||
return
|
||||
}
|
||||
commitDialogVisible.value = true
|
||||
}
|
||||
|
||||
function handleSelectServer() {
|
||||
new ProjectServerList({ id: selectedItem.value.id })
|
||||
.request()
|
||||
.then((response) => {
|
||||
greyServerFormProps.value.serverOption = response.data.list
|
||||
publishFormProps.value.serverOption = response.data.list
|
||||
})
|
||||
// add projectID to server form
|
||||
greyServerFormData.value.projectId = selectedItem.value.id
|
||||
greyServerFormData.value.commit = data.commit
|
||||
greyServerDialogVisible.value = true
|
||||
}
|
||||
|
||||
function handleCancelSelectCommit(state) {
|
||||
publishFormProps.value.branch = ''
|
||||
publishFormProps.value.commit = ''
|
||||
publishFormProps.value.selectCommit = false
|
||||
}
|
||||
|
||||
const cardMoreFunc: { [K: string]: (data: ProjectData) => void } = {
|
||||
@ -696,8 +706,6 @@ function handleUnpinCard(data: ProjectData) {
|
||||
}
|
||||
|
||||
const commandFunc: { [K: string]: (data: ProjectData) => void } = {
|
||||
handleCommitCommand,
|
||||
handleTagCommand,
|
||||
handleTaskCommand,
|
||||
handleFileCompareCommand,
|
||||
handleFileSyncCommand,
|
||||
@ -705,16 +713,6 @@ const commandFunc: { [K: string]: (data: ProjectData) => void } = {
|
||||
handleReviewCommand,
|
||||
}
|
||||
|
||||
function handleCommitCommand(data: ProjectData) {
|
||||
selectedItem.value = data
|
||||
commitDialogVisible.value = true
|
||||
}
|
||||
|
||||
function handleTagCommand(data: ProjectData) {
|
||||
selectedItem.value = data
|
||||
tagDialogVisible.value = true
|
||||
}
|
||||
|
||||
function handleTaskCommand(data: ProjectData) {
|
||||
selectedItem.value = data
|
||||
taskListDialogVisible.value = true
|
||||
@ -740,8 +738,14 @@ function handleReviewCommand(data: ProjectData) {
|
||||
reviewListDialogVisible.value = true
|
||||
}
|
||||
|
||||
function selectCommit(data: CommitData) {
|
||||
publishFormProps.value.branch = data.branch
|
||||
publishFormProps.value.commit = data.commit
|
||||
commitDialogVisible.value = false
|
||||
}
|
||||
|
||||
function publish(data: ProjectData) {
|
||||
const id = data.id
|
||||
restorePublishForm()
|
||||
let color = ''
|
||||
if (data.environment === 1) {
|
||||
color = 'color: var(--el-color-danger)'
|
||||
@ -750,63 +754,41 @@ function publish(data: ProjectData) {
|
||||
} else {
|
||||
color = 'color: var(--el-color-info)'
|
||||
}
|
||||
ElMessageBox.confirm('', t('tips'), {
|
||||
message: h('p', null, [
|
||||
h('span', null, 'Deploy: '),
|
||||
h(
|
||||
'b',
|
||||
{ style: color },
|
||||
data.name + ' - ' + t(`envOption[${data.environment}]`)
|
||||
),
|
||||
]),
|
||||
confirmButtonText: t('confirm'),
|
||||
cancelButtonText: t('cancel'),
|
||||
type: 'warning',
|
||||
})
|
||||
.then(() => {
|
||||
new DeployPublish({ projectId: id, commit: '', branch: '' })
|
||||
.request()
|
||||
.then(() => {
|
||||
const projectIndex = tableData.value.findIndex(
|
||||
(element) => element.id === id
|
||||
)
|
||||
tableData.value[projectIndex].deployState = 1
|
||||
})
|
||||
selectedItem.value = deepClone(data)
|
||||
const customVariables = deepClone(data.script.customVariables)
|
||||
publishFormProps.value.customVariables =
|
||||
customVariables &&
|
||||
customVariables.map((item) => {
|
||||
if (item.type == 'list') {
|
||||
item.value = ''
|
||||
}
|
||||
return item
|
||||
})
|
||||
.catch(() => {
|
||||
ElMessage.info('Cancel')
|
||||
})
|
||||
}
|
||||
publishDialogVisible.value = true
|
||||
|
||||
function publishByCommit(data: CommitData) {
|
||||
ElMessageBox.confirm(
|
||||
t('deployPage.publishCommitTips', { commit: data.commit }),
|
||||
t('tips'),
|
||||
{
|
||||
confirmButtonText: t('confirm'),
|
||||
cancelButtonText: t('cancel'),
|
||||
type: 'warning',
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
new DeployPublish({
|
||||
projectId: selectedItem.value.id,
|
||||
branch: data.branch,
|
||||
commit: data.commit,
|
||||
let env = t(`envOption[${data.environment}]`)
|
||||
publishFormProps.value.title = `<span style="${color}; font-weight: 600; font-size: 15px">${data.name} - ${env}</span>`
|
||||
publishFormProps.value.func = () => {
|
||||
publishFormProps.value.disabled = true
|
||||
new DeployPublish({
|
||||
projectId: data.id,
|
||||
commit: publishFormProps.value.commit,
|
||||
branch: publishFormProps.value.branch,
|
||||
customVariables: publishFormProps.value.customVariables,
|
||||
serverIds: publishFormProps.value.serverIds,
|
||||
})
|
||||
.request()
|
||||
.then(() => {
|
||||
publishDialogVisible.value = false
|
||||
const projectIndex = tableData.value.findIndex(
|
||||
(element) => element.id === data.id
|
||||
)
|
||||
tableData.value[projectIndex].deployState = 1
|
||||
})
|
||||
.request()
|
||||
.then(() => {
|
||||
const projectIndex = tableData.value.findIndex(
|
||||
(element) => element.id === selectedItem.value.id
|
||||
)
|
||||
tableData.value[projectIndex].deployState = 1
|
||||
commitDialogVisible.value = false
|
||||
tagDialogVisible.value = false
|
||||
})
|
||||
})
|
||||
.catch(() => {
|
||||
ElMessage.info('Cancel')
|
||||
})
|
||||
.finally(() => {
|
||||
publishFormProps.value.disabled = false
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function resetState(data: ProjectData) {
|
||||
@ -831,48 +813,6 @@ function resetState(data: ProjectData) {
|
||||
})
|
||||
}
|
||||
|
||||
function greyPublish() {
|
||||
greyServerForm.value?.validate((valid) => {
|
||||
if (valid) {
|
||||
const data = greyServerFormData.value
|
||||
ElMessageBox.confirm(
|
||||
t('deployPage.publishCommitTips', {
|
||||
commit: data.commit,
|
||||
}),
|
||||
t('tips'),
|
||||
{
|
||||
confirmButtonText: t('confirm'),
|
||||
cancelButtonText: t('cancel'),
|
||||
type: 'warning',
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
new DeployGreyPublish({
|
||||
projectId: data.projectId,
|
||||
commit: data.commit,
|
||||
serverIds: data.serverIds,
|
||||
})
|
||||
.request()
|
||||
.then(() => {
|
||||
const projectIndex = tableData.value.findIndex(
|
||||
(element) => element.id === data.projectId
|
||||
)
|
||||
tableData.value[projectIndex].deployState = 1
|
||||
commitDialogVisible.value = false
|
||||
tagDialogVisible.value = false
|
||||
greyServerDialogVisible.value = false
|
||||
})
|
||||
})
|
||||
.catch(() => {
|
||||
ElMessage.info('Cancel')
|
||||
})
|
||||
return Promise.resolve(true)
|
||||
} else {
|
||||
return Promise.reject(false)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function enterToBR(detail: string) {
|
||||
return detail ? detail.replace(/\n|(\r\n)/g, '<br>') : ''
|
||||
}
|
||||
@ -900,8 +840,28 @@ function getStick(): number[] {
|
||||
function setStick(value: string) {
|
||||
localStorage.setItem('deploy-stick', value)
|
||||
}
|
||||
</script>
|
||||
|
||||
function restorePublishForm() {
|
||||
publishFormProps.value = { ...tempPublishFormProps }
|
||||
console.log(publishFormProps.value)
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.publish-dialog {
|
||||
.el-dialog__header {
|
||||
padding: 20px 15px 10px 15px;
|
||||
margin-right: 0px;
|
||||
}
|
||||
.el-dialog__body {
|
||||
padding-top: 10px;
|
||||
padding-left: 15px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
.el-dialog__footer {
|
||||
padding: 10px 15px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style lang="scss" scoped>
|
||||
.card {
|
||||
border: none;
|
||||
|
@ -1096,6 +1096,72 @@
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane name="customVariable">
|
||||
<template #label>
|
||||
<span style="vertical-align: middle; padding-right: 4px">
|
||||
{{ $t('projectPage.customVariableLabel') }}
|
||||
</span>
|
||||
<el-tooltip class="item" effect="dark" placement="bottom">
|
||||
<template #content>
|
||||
<div style="white-space: pre-line">
|
||||
{{ $t('projectPage.customVariableTips') }}
|
||||
</div>
|
||||
</template>
|
||||
<el-icon style="vertical-align: middle" :size="16">
|
||||
<question-filled />
|
||||
</el-icon>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
<el-row type="flex" justify="end" style="margin-bottom: 10px">
|
||||
<el-button
|
||||
type="primary"
|
||||
:icon="Plus"
|
||||
@click="handleCusotmVariableAdd"
|
||||
/>
|
||||
</el-row>
|
||||
<el-form-item prop="customVariableScript" label-width="0px">
|
||||
<el-row
|
||||
v-for="(variable, index) in formData.script.customVariables"
|
||||
:key="index"
|
||||
type="flex"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-input
|
||||
v-model.trim="variable.name"
|
||||
style="flex: 1"
|
||||
autocomplete="off"
|
||||
placeholder="variable name"
|
||||
>
|
||||
<template #prepend>${</template>
|
||||
<template #append>}</template>
|
||||
</el-input>
|
||||
<el-select v-model="variable.type" style="width: 200px">
|
||||
<el-option
|
||||
v-for="item in formProps.customVariablesType"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
</el-select>
|
||||
<el-input
|
||||
v-model.trim="variable.value"
|
||||
style="flex: 1"
|
||||
autocomplete="off"
|
||||
:placeholder="
|
||||
variable.type == 'list'
|
||||
? 'value split by comma'
|
||||
: 'default value'
|
||||
"
|
||||
/>
|
||||
<el-button
|
||||
type="warning"
|
||||
:icon="Minus"
|
||||
plain
|
||||
@click="handleCusotmVariableDelete(index)"
|
||||
/>
|
||||
</el-row>
|
||||
</el-form-item>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
@ -1208,6 +1274,7 @@ import {
|
||||
View,
|
||||
Link,
|
||||
Plus,
|
||||
Minus,
|
||||
Edit,
|
||||
QuestionFilled,
|
||||
Files,
|
||||
@ -1315,6 +1382,7 @@ const formProps = ref({
|
||||
pinging: false,
|
||||
lsBranchLoading: false,
|
||||
tab: 'base',
|
||||
customVariablesType: ['string', 'list'],
|
||||
})
|
||||
const tempFormData = {
|
||||
id: 0,
|
||||
@ -1329,6 +1397,7 @@ const tempFormData = {
|
||||
afterPull: { mode: '', content: '' },
|
||||
afterDeploy: { mode: '', content: '' },
|
||||
deployFinish: { mode: '', content: '' },
|
||||
customVariables: [] as { name: string; value: string; type: string }[],
|
||||
},
|
||||
environment: 1,
|
||||
branch: '',
|
||||
@ -1509,6 +1578,21 @@ function handleAutoDeploy(data: ProjectData) {
|
||||
autoDeployFormData.value.autoDeploy = data.autoDeploy
|
||||
}
|
||||
|
||||
function handleCusotmVariableAdd() {
|
||||
if (!formData.value.script.customVariables) {
|
||||
formData.value.script.customVariables = []
|
||||
}
|
||||
formData.value.script.customVariables.push({
|
||||
name: '',
|
||||
value: '',
|
||||
type: 'string',
|
||||
})
|
||||
}
|
||||
|
||||
function handleCusotmVariableDelete(index: number) {
|
||||
formData.value.script.customVariables.splice(index, 1)
|
||||
}
|
||||
|
||||
enum ScriptKey {
|
||||
AfterPull = 'afterPull',
|
||||
AfterDeploy = 'afterDeploy',
|
||||
|
Loading…
Reference in New Issue
Block a user