Skip to content
This repository was archived by the owner on May 30, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ require (
entgo.io/ent v0.9.0
github.com/AlekSi/pointer v1.1.0
github.com/asaskevich/EventBus v0.0.0-20200907212545-49d423059eef
github.com/creasty/defaults v1.5.1
github.com/davecgh/go-spew v1.1.1
github.com/fvbock/endless v0.0.0-20170109170031-447134032cb6 // indirect
github.com/drone/envsubst v1.0.3
github.com/fvbock/endless v0.0.0-20170109170031-447134032cb6
github.com/gin-contrib/cors v1.3.1
github.com/gin-contrib/sse v0.1.0
github.com/gin-gonic/gin v1.7.2
Expand All @@ -33,6 +33,6 @@ require (
go.uber.org/zap v1.13.0
golang.org/x/net v0.0.0-20210525063256-abc453219eb5 // indirect
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c
gopkg.in/h2non/gock.v1 v1.1.2 // indirect
gopkg.in/h2non/gock.v1 v1.1.2
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
)
42 changes: 12 additions & 30 deletions go.sum

Large diffs are not rendered by default.

12 changes: 4 additions & 8 deletions internal/interactor/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,18 @@ import (
"fmt"
"time"

"github.com/AlekSi/pointer"
"github.com/gitploy-io/gitploy/ent"
"github.com/gitploy-io/gitploy/ent/approval"
"github.com/gitploy-io/gitploy/ent/deployment"
"github.com/gitploy-io/gitploy/vo"
"go.uber.org/zap"
)

func (i *Interactor) Deploy(ctx context.Context, u *ent.User, r *ent.Repo, d *ent.Deployment, env *vo.Env) (*ent.Deployment, error) {
func (i *Interactor) Deploy(ctx context.Context, u *ent.User, r *ent.Repo, d *ent.Deployment, e *vo.Env) (*ent.Deployment, error) {
d.UserID = u.ID
d.RepoID = r.ID

return i.deploy(ctx, u, r, d, env)
}

func (i *Interactor) deploy(ctx context.Context, u *ent.User, r *ent.Repo, d *ent.Deployment, e *vo.Env) (*ent.Deployment, error) {
if !e.IsApprovalEabled() {
rd, err := i.SCM.CreateRemoteDeployment(ctx, u, r, d, e)
if err != nil {
Expand Down Expand Up @@ -71,9 +68,8 @@ func (i *Interactor) CreateRemoteDeployment(ctx context.Context, u *ent.User, re
// 1) Set auto_merge false to avoid the merge conflict.
// 2) Set required_contexts empty to skip the verfication.
if d.IsRollback {
e.Task = "rollback"
e.AutoMerge = false
e.RequiredContexts = []string{}
e.AutoMerge = pointer.ToBool(false)
e.RequiredContexts = &[]string{}
}

rd, err := i.SCM.CreateRemoteDeployment(ctx, u, re, d, e)
Expand Down
12 changes: 6 additions & 6 deletions internal/pkg/github/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ func (g *Github) CreateRemoteDeployment(ctx context.Context, u *ent.User, r *ent
CreateDeployment(ctx, r.Namespace, r.Name, &github.DeploymentRequest{
Ref: github.String(d.Ref),
Environment: github.String(e.Name),
Task: github.String(e.Task),
Description: github.String(e.Description),
AutoMerge: github.Bool(e.AutoMerge),
RequiredContexts: &e.RequiredContexts,
Payload: github.String(e.Payload),
ProductionEnvironment: github.Bool(e.ProductionEnvironment),
Task: e.Task,
Description: e.Description,
AutoMerge: e.AutoMerge,
RequiredContexts: e.RequiredContexts,
Payload: e.Payload,
ProductionEnvironment: e.ProductionEnvironment,
})
if res.StatusCode == http.StatusConflict {
return nil, &vo.UnprocessibleDeploymentError{
Expand Down
18 changes: 18 additions & 0 deletions internal/server/api/v1/repos/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,12 @@ func (r *Repo) CreateDeployment(c *gin.Context) {
return
}

if err := cf.GetEnv(p.Env).Eval(&vo.EvalValues{}); err != nil {
r.log.Warn("It has failed to eval the env.", zap.Error(err))
gb.ErrorResponse(c, http.StatusUnprocessableEntity, "It has failed to eval the env in the configuration file.")
return
}

var (
number int
)
Expand Down Expand Up @@ -213,6 +219,12 @@ func (r *Repo) UpdateDeployment(c *gin.Context) {
return
}

if err := cf.GetEnv(d.Env).Eval(&vo.EvalValues{IsRollback: d.IsRollback}); err != nil {
r.log.Warn("It has failed to eval the env.", zap.Error(err))
gb.ErrorResponse(c, http.StatusUnprocessableEntity, "It has failed to eval the env in the configuration file.")
return
}

if p.Status == string(deployment.StatusCreated) && d.Status == deployment.StatusWaiting {
// Check the deployment is approved:
// Approved >= Required Approval Count
Expand Down Expand Up @@ -296,6 +308,12 @@ func (r *Repo) RollbackDeployment(c *gin.Context) {
return
}

if err := cf.GetEnv(d.Env).Eval(&vo.EvalValues{IsRollback: true}); err != nil {
r.log.Warn("It has failed to eval the env.", zap.Error(err))
gb.ErrorResponse(c, http.StatusUnprocessableEntity, "It has failed to eval the env in the configuration file.")
return
}

var (
next int
)
Expand Down
6 changes: 6 additions & 0 deletions internal/server/slack/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,12 @@ func (s *Slack) interactDeploy(c *gin.Context) {

env := cf.GetEnv(sm.Env)

if err := env.Eval(&vo.EvalValues{}); err != nil {
postBotMessage(cu, "The environment is invalid. It has failed to eval the environment.")
c.Status(http.StatusOK)
return
}

number, err := s.i.GetNextDeploymentNumberOfRepo(ctx, cb.Edges.Repo)
if err != nil {
s.log.Error("It has failed to get the next deployment number.", zap.Error(err))
Expand Down
6 changes: 6 additions & 0 deletions internal/server/slack/rollback.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,12 @@ func (s *Slack) interactRollback(c *gin.Context) {
return
}

if err := cf.GetEnv(d.Env).Eval(&vo.EvalValues{IsRollback: true}); err != nil {
postBotMessage(cu, "The environment is invalid. It has failed to eval the environment.")
c.Status(http.StatusOK)
return
}

env := cf.GetEnv(d.Env)

next, err := s.i.GetNextDeploymentNumberOfRepo(ctx, cb.Edges.Repo)
Expand Down
89 changes: 65 additions & 24 deletions vo/config.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package vo

import (
"encoding/json"
"fmt"
"strconv"

"github.com/creasty/defaults"
"github.com/drone/envsubst"
"gopkg.in/yaml.v3"
)

Expand All @@ -16,29 +18,47 @@ type (
Name string `json:"name" yaml:"name"`

// Github parameters of deployment.
Task string `json:"task" yaml:"task" default:"deploy"`
Description string `json:"description" yaml:"description" default:"Gitploy starts to deploy."`
AutoMerge bool `json:"auto_merge" default:"true"`
RequiredContexts []string `json:"required_contexts,omitempty" yaml:"required_contexts"`
Payload string `json:"payload" yaml:"payload"`
ProductionEnvironment bool `json:"production_environment" yaml:"production_environment"`
Task *string `json:"task" yaml:"task"`
Description *string `json:"description" yaml:"description"`
AutoMerge *bool `json:"auto_merge" yaml:"auto_merge"`
RequiredContexts *[]string `json:"required_contexts,omitempty" yaml:"required_contexts"`
Payload *string `json:"payload" yaml:"payload"`
ProductionEnvironment *bool `json:"production_environment" yaml:"production_environment"`
Comment on lines +21 to +26
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change types into a pointer for optional fields.


// Approval is the configuration of Approval,
// It is disabled when it is empty.
Approval *Approval `json:"approval,omitempty" yaml:"approval"`

// The type of auto_merge must be string to avoid
// that the value of auto_merge is always set true
// after processing defaults.Set
StrAutoMerge string `yaml:"auto_merge"`
}

Approval struct {
Enabled bool `json:"enabled" yaml:"enabled"`
RequiredCount int `json:"required_count" yaml:"required_count"`
}

EvalValues struct {
IsRollback bool
}
)

const (
varnameDeployTask = "GITPLOY_DEPLOY_TASK"
varnameRollbackTask = "GITPLOY_ROLLBACK_TASK"
varnameIsRollback = "GITPLOY_IS_ROLLBACK"
)

const (
defaultDeployTask = "deploy"
defaultRollbackTask = "rollback"
)

func UnmarshalYAML(content []byte, c *Config) error {
if err := yaml.Unmarshal([]byte(content), c); err != nil {
return err
}

return nil
}

func (c *Config) HasEnv(name string) bool {
for _, e := range c.Envs {
if e.Name == name {
Expand Down Expand Up @@ -67,23 +87,44 @@ func (e *Env) IsApprovalEabled() bool {
return e.Approval.Enabled
}

func UnmarshalYAML(content []byte, c *Config) error {
if err := yaml.Unmarshal([]byte(content), c); err != nil {
return err
func (e *Env) Eval(v *EvalValues) error {
byts, err := json.Marshal(e)
if err != nil {
return fmt.Errorf("failed to marshal the env: %w", err)
}

if err := defaults.Set(c); err != nil {
return err
}
// Evaluates variables
mapper := func(vn string) string {
if vn == varnameDeployTask {
if !v.IsRollback {
return defaultDeployTask
} else {
return ""
}
}

// Set default value manually.
for _, e := range c.Envs {
am, err := strconv.ParseBool(e.StrAutoMerge)
if err != nil {
continue
if vn == varnameRollbackTask {
if v.IsRollback {
return defaultRollbackTask
} else {
return ""
}
}

if vn == varnameIsRollback {
return strconv.FormatBool(v.IsRollback)
}

e.AutoMerge = am
return "ERR_NOT_IMPLEMENTED"
}

evalued, err := envsubst.Eval(string(byts), mapper)
if err != nil {
return fmt.Errorf("failed to eval variables: %w", err)
}

if err := json.Unmarshal([]byte(evalued), e); err != nil {
return fmt.Errorf("failed to unmarshal to the env: %w", err)
}

return nil
Expand Down
Loading