From 8bee73da7e894486d2a4e8ac02005eb7bc0791f5 Mon Sep 17 00:00:00 2001 From: noah Date: Tue, 23 Nov 2021 21:24:47 +0900 Subject: [PATCH 1/4] Add a method Eval to Config --- vo/config.go | 70 +++++++++++++++++++++++++++++++++++-------- vo/config_test.go | 76 +++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 128 insertions(+), 18 deletions(-) diff --git a/vo/config.go b/vo/config.go index f2d0d055..f2495867 100644 --- a/vo/config.go +++ b/vo/config.go @@ -14,6 +14,10 @@ import ( type ( Config struct { Envs []*Env `json:"envs" yaml:"envs"` + + // save the content of the configuration file + // when it is unmarshalled. + source []byte } Env struct { @@ -48,21 +52,61 @@ type ( ) const ( - varnameDeployTask = "GITPLOY_DEPLOY_TASK" - varnameRollbackTask = "GITPLOY_ROLLBACK_TASK" - varnameIsRollback = "GITPLOY_IS_ROLLBACK" + VarnameDeployTask = "GITPLOY_DEPLOY_TASK" + VarnameRollbackTask = "GITPLOY_ROLLBACK_TASK" + VarnameIsRollback = "GITPLOY_IS_ROLLBACK" ) const ( - // defaultDeployTask is the value of the 'GITPLOY_DEPLOY_TASK' variable. - defaultDeployTask = "deploy" - // defaultRollbackTask is the value of the 'GITPLOY_ROLLBACK_TASK' variable. - defaultRollbackTask = "rollback" + // DefaultDeployTask is the value of the 'GITPLOY_DEPLOY_TASK' variable. + DefaultDeployTask = "deploy" + // DefaultRollbackTask is the value of the 'GITPLOY_ROLLBACK_TASK' variable. + DefaultRollbackTask = "rollback" ) func UnmarshalYAML(content []byte, c *Config) error { if err := yaml.Unmarshal([]byte(content), c); err != nil { - return err + return eutil.NewError(eutil.ErrorCodeConfigParseError, err) + } + + c.source = content + + return nil +} + +func (c *Config) Eval(v *EvalValues) error { + // Evaluates variables + mapper := func(vn string) string { + if vn == VarnameDeployTask { + if !v.IsRollback { + return DefaultDeployTask + } else { + return "" + } + } + + if vn == VarnameRollbackTask { + if v.IsRollback { + return DefaultRollbackTask + } else { + return "" + } + } + + if vn == VarnameIsRollback { + return strconv.FormatBool(v.IsRollback) + } + + return "ERR_NOT_IMPLEMENTED" + } + + evalued, err := envsubst.Eval(string(c.source), mapper) + if err != nil { + return eutil.NewError(eutil.ErrorCodeConfigParseError, err) + } + + if err := yaml.Unmarshal([]byte(evalued), c); err != nil { + return eutil.NewError(eutil.ErrorCodeConfigParseError, err) } return nil @@ -134,23 +178,23 @@ func (e *Env) Eval(v *EvalValues) error { // Evaluates variables mapper := func(vn string) string { - if vn == varnameDeployTask { + if vn == VarnameDeployTask { if !v.IsRollback { - return defaultDeployTask + return DefaultDeployTask } else { return "" } } - if vn == varnameRollbackTask { + if vn == VarnameRollbackTask { if v.IsRollback { - return defaultRollbackTask + return DefaultRollbackTask } else { return "" } } - if vn == varnameIsRollback { + if vn == VarnameIsRollback { return strconv.FormatBool(v.IsRollback) } diff --git a/vo/config_test.go b/vo/config_test.go index cd8a6cf6..6c834377 100644 --- a/vo/config_test.go +++ b/vo/config_test.go @@ -31,6 +31,7 @@ envs: RequiredContexts: &[]string{"github-action"}, }, }, + source: []byte(s), } if !reflect.DeepEqual(c, e) { tt.Errorf("Config = %s, expected %s", spew.Sdump(c), spew.Sdump(e)) @@ -57,6 +58,7 @@ envs: AutoMerge: pointer.ToBool(false), }, }, + source: []byte(s), } if !reflect.DeepEqual(c, e) { tt.Errorf("Config = %s, expected %s", spew.Sdump(c), spew.Sdump(e)) @@ -72,8 +74,7 @@ envs: err := UnmarshalYAML([]byte(s), c) if err != nil { - tt.Errorf("failed to parse: %s", err) - tt.FailNow() + tt.Fatalf("failed to parse: %s", err) } e := &Config{ @@ -83,6 +84,7 @@ envs: AutoMerge: pointer.ToBool(true), }, }, + source: []byte(s), } if !reflect.DeepEqual(c, e) { tt.Errorf("Config = %s, expected %s", spew.Sdump(c), spew.Sdump(e)) @@ -90,6 +92,70 @@ envs: }) } +func TestConfig_Eval(t *testing.T) { + t.Run("Evaluate the configuration.", func(t *testing.T) { + s := ` +envs: + - name: dev + task: ${GITPLOY_DEPLOY_TASK}:kubernetes` + + c := &Config{} + if err := UnmarshalYAML([]byte(s), c); err != nil { + t.Fatalf("Failed to parse the configuration file: %v", err) + } + + err := c.Eval(&EvalValues{}) + if err != nil { + t.Fatalf("Eval returns an error: %v", err) + } + + e := &Config{ + Envs: []*Env{ + { + Name: "dev", + Task: pointer.ToString("deploy:kubernetes"), + }, + }, + source: []byte(s), + } + if !reflect.DeepEqual(c, e) { + t.Errorf("Config = %v expected %v", spew.Sdump(c), spew.Sdump(e)) + } + }) + + t.Run("Evaluate the configuration with the regexp.", func(t *testing.T) { + s := ` +envs: + - name: dev + task: ${GITPLOY_DEPLOY_TASK}:kubernetes + deployable_ref: 'v.*\..*\..*'` + + c := &Config{} + if err := UnmarshalYAML([]byte(s), c); err != nil { + t.Fatalf("Failed to parse the configuration file: %v", err) + } + + err := c.Eval(&EvalValues{}) + if err != nil { + t.Fatalf("Eval returns an error: %v", err) + } + + e := &Config{ + Envs: []*Env{ + { + Name: "dev", + Task: pointer.ToString("deploy:kubernetes"), + DeployableRef: pointer.ToString(`v.*\..*\..*`), + }, + }, + source: []byte(s), + } + if !reflect.DeepEqual(c, e) { + t.Errorf("Config = %v expected %v", spew.Sdump(c), spew.Sdump(e)) + } + }) +} + func TestEnv_IsProductionEnvironment(t *testing.T) { t.Run("Reutrn false when the production environment is nil", func(t *testing.T) { e := &Env{} @@ -171,7 +237,7 @@ func TestEnv_Eval(t *testing.T) { Task: pointer.ToString("${GITPLOY_DEPLOY_TASK}"), }, want: &Env{ - Task: pointer.ToString(defaultDeployTask), + Task: pointer.ToString(DefaultDeployTask), }, }, { @@ -179,7 +245,7 @@ func TestEnv_Eval(t *testing.T) { Task: pointer.ToString("${GITPLOY_DEPLOY_TASK}:kubernetes"), }, want: &Env{ - Task: pointer.ToString(fmt.Sprintf("%s:kubernetes", defaultDeployTask)), + Task: pointer.ToString(fmt.Sprintf("%s:kubernetes", DefaultDeployTask)), }, }, { @@ -187,7 +253,7 @@ func TestEnv_Eval(t *testing.T) { Task: pointer.ToString("${GITPLOY_DEPLOY_TASK}${GITPLOY_ROLLBACK_TASK}"), }, want: &Env{ - Task: pointer.ToString(defaultDeployTask), + Task: pointer.ToString(DefaultDeployTask), }, }, } From 2910061c46c84a4a43fa8d79965d382deb0d5727 Mon Sep 17 00:00:00 2001 From: noah Date: Tue, 23 Nov 2021 22:00:39 +0900 Subject: [PATCH 2/4] Fix to evaluate the configuration in the server --- internal/interactor/deployment.go | 8 --- internal/server/api/v1/repos/deployment.go | 64 +++++++++++++------ .../server/api/v1/repos/deployment_test.go | 12 ++-- internal/server/api/v1/repos/interface.go | 1 - internal/server/api/v1/repos/lock.go | 15 +++-- internal/server/api/v1/repos/lock_test.go | 15 +++-- .../server/api/v1/repos/mock/interactor.go | 15 ----- internal/server/slack/deploy.go | 10 ++- internal/server/slack/rollback.go | 10 ++- 9 files changed, 85 insertions(+), 65 deletions(-) diff --git a/internal/interactor/deployment.go b/internal/interactor/deployment.go index 343f9efc..37d6a7e8 100644 --- a/internal/interactor/deployment.go +++ b/internal/interactor/deployment.go @@ -37,10 +37,6 @@ func (i *Interactor) Deploy(ctx context.Context, u *ent.User, r *ent.Repo, d *en return nil, err } - if err := env.Eval(&vo.EvalValues{IsRollback: d.IsRollback}); err != nil { - return nil, err - } - number, err := i.Store.GetNextDeploymentNumberOfRepo(ctx, r) if err != nil { return nil, e.NewError( @@ -128,10 +124,6 @@ func (i *Interactor) DeployToRemote(ctx context.Context, u *ent.User, r *ent.Rep ) } - if ok, err := i.isDeployable(ctx, u, r, d, env); !ok { - return nil, err - } - if !i.IsApproved(ctx, d) { return nil, e.NewError( e.ErrorCodeDeploymentNotApproved, diff --git a/internal/server/api/v1/repos/deployment.go b/internal/server/api/v1/repos/deployment.go index 354aaf67..0aa854f0 100644 --- a/internal/server/api/v1/repos/deployment.go +++ b/internal/server/api/v1/repos/deployment.go @@ -85,15 +85,23 @@ func (r *Repo) CreateDeployment(c *gin.Context) { vr, _ := c.Get(KeyRepo) re := vr.(*ent.Repo) - env, err := r.i.GetEnv(ctx, u, re, p.Env) + config, err := r.i.GetConfig(ctx, u, re) if e.HasErrorCode(err, e.ErrorCodeEntityNotFound) { - r.log.Check(gb.GetZapLogLevel(err), "The configuration file is not found.").Write(zap.Error(err)) - // To override the HTTP status 422. + r.log.Check(gb.GetZapLogLevel(err), "Failed to get the configuration.").Write(zap.Error(err)) gb.ResponseWithStatusAndError(c, http.StatusUnprocessableEntity, err) return - } else if err != nil { - r.log.Check(gb.GetZapLogLevel(err), "It has failed to get the configuration.").Write(zap.Error(err)) - gb.ResponseWithError(c, err) + } + + if err := config.Eval(&vo.EvalValues{}); err != nil { + r.log.Check(gb.GetZapLogLevel(err), "Failed to evaluate the configuration.").Write(zap.Error(err)) + gb.ResponseWithStatusAndError(c, http.StatusUnprocessableEntity, err) + return + } + + var env *vo.Env + if env = config.GetEnv(p.Env); env == nil { + r.log.Warn("The environment is not found.", zap.String("env", p.Env)) + gb.ResponseWithStatusAndError(c, http.StatusUnprocessableEntity, e.NewError(e.ErrorCodeConfigUndefinedEnv, nil)) return } @@ -110,7 +118,6 @@ func (r *Repo) CreateDeployment(c *gin.Context) { return } - // TODO: Migrate the event logic into the interactor. if _, err := r.i.CreateEvent(ctx, &ent.Event{ Kind: event.KindDeployment, Type: event.TypeCreated, @@ -124,6 +131,7 @@ func (r *Repo) CreateDeployment(c *gin.Context) { d = de } + r.log.Info("Start to deploy.", zap.String("repo", re.GetFullName()), zap.String("env", p.Env)) gb.Response(c, http.StatusCreated, d) } @@ -149,15 +157,23 @@ func (r *Repo) UpdateDeployment(c *gin.Context) { return } - env, err := r.i.GetEnv(ctx, u, re, d.Env) + config, err := r.i.GetConfig(ctx, u, re) if e.HasErrorCode(err, e.ErrorCodeEntityNotFound) { - r.log.Check(gb.GetZapLogLevel(err), "The configuration file is not found.").Write(zap.Error(err)) - // To override the HTTP status 422. + r.log.Check(gb.GetZapLogLevel(err), "Failed to get the configuration.").Write(zap.Error(err)) gb.ResponseWithStatusAndError(c, http.StatusUnprocessableEntity, err) return - } else if err != nil { - r.log.Check(gb.GetZapLogLevel(err), "It has failed to get the configuration.").Write(zap.Error(err)) - gb.ResponseWithError(c, err) + } + + if err := config.Eval(&vo.EvalValues{IsRollback: d.IsRollback}); err != nil { + r.log.Check(gb.GetZapLogLevel(err), "Failed to evaludate the configuration.").Write(zap.Error(err)) + gb.ResponseWithStatusAndError(c, http.StatusUnprocessableEntity, err) + return + } + + var env *vo.Env + if env = config.GetEnv(d.Env); env == nil { + r.log.Warn("The environment is not found.", zap.String("env", d.Env)) + gb.ResponseWithStatusAndError(c, http.StatusUnprocessableEntity, e.NewError(e.ErrorCodeConfigUndefinedEnv, nil)) return } @@ -180,6 +196,7 @@ func (r *Repo) UpdateDeployment(c *gin.Context) { d = de } + r.log.Info("Start to deploy.", zap.String("repo", re.GetFullName()), zap.Int("number", d.Number)) gb.Response(c, http.StatusOK, d) } @@ -203,15 +220,23 @@ func (r *Repo) RollbackDeployment(c *gin.Context) { return } - env, err := r.i.GetEnv(ctx, u, re, d.Env) + config, err := r.i.GetConfig(ctx, u, re) if e.HasErrorCode(err, e.ErrorCodeEntityNotFound) { - r.log.Check(gb.GetZapLogLevel(err), "The configuration file is not found.").Write(zap.Error(err)) - // To override the HTTP status 422. + r.log.Check(gb.GetZapLogLevel(err), "Failed to get the configuration.").Write(zap.Error(err)) gb.ResponseWithStatusAndError(c, http.StatusUnprocessableEntity, err) return - } else if err != nil { - r.log.Check(gb.GetZapLogLevel(err), "It has failed to get the configuration.").Write(zap.Error(err)) - gb.ResponseWithError(c, err) + } + + if err := config.Eval(&vo.EvalValues{IsRollback: true}); err != nil { + r.log.Check(gb.GetZapLogLevel(err), "Failed to evaludate the configuration.").Write(zap.Error(err)) + gb.ResponseWithStatusAndError(c, http.StatusUnprocessableEntity, err) + return + } + + var env *vo.Env + if env = config.GetEnv(d.Env); env == nil { + r.log.Warn("The environment is not found.", zap.String("env", d.Env)) + gb.ResponseWithStatusAndError(c, http.StatusUnprocessableEntity, e.NewError(e.ErrorCodeConfigUndefinedEnv, nil)) return } @@ -242,6 +267,7 @@ func (r *Repo) RollbackDeployment(c *gin.Context) { d = de } + r.log.Info("Start to rollback.", zap.String("repo", re.GetFullName()), zap.Int("number", d.Number)) gb.Response(c, http.StatusCreated, d) } diff --git a/internal/server/api/v1/repos/deployment_test.go b/internal/server/api/v1/repos/deployment_test.go index 4ef33b70..8ccd7f4b 100644 --- a/internal/server/api/v1/repos/deployment_test.go +++ b/internal/server/api/v1/repos/deployment_test.go @@ -120,13 +120,15 @@ func TestRepo_CreateDeployment(t *testing.T) { ctrl := gomock.NewController(t) m := mock.NewMockInteractor(ctrl) - t.Log("Read the config file.") m. EXPECT(). - GetEnv(gomock.Any(), gomock.AssignableToTypeOf(&ent.User{}), gomock.AssignableToTypeOf(&ent.Repo{}), gomock.Any()). - Return(&vo.Env{ - Name: "prod", - }, nil) + GetConfig(gomock.Any(), gomock.AssignableToTypeOf(&ent.User{}), gomock.AssignableToTypeOf(&ent.Repo{})). + Return(&vo.Config{ + Envs: []*vo.Env{ + { + Name: "prod", + }, + }}, nil) t.Log("Deploy with the payload successfully.") m. diff --git a/internal/server/api/v1/repos/interface.go b/internal/server/api/v1/repos/interface.go index d690ccff..c1d281a5 100644 --- a/internal/server/api/v1/repos/interface.go +++ b/internal/server/api/v1/repos/interface.go @@ -31,7 +31,6 @@ type ( Deploy(ctx context.Context, u *ent.User, re *ent.Repo, d *ent.Deployment, env *vo.Env) (*ent.Deployment, error) DeployToRemote(ctx context.Context, u *ent.User, r *ent.Repo, d *ent.Deployment, env *vo.Env) (*ent.Deployment, error) GetConfig(ctx context.Context, u *ent.User, r *ent.Repo) (*vo.Config, error) - GetEnv(ctx context.Context, u *ent.User, r *ent.Repo, env string) (*vo.Env, error) ListReviews(ctx context.Context, d *ent.Deployment) ([]*ent.Review, error) FindReviewOfUser(ctx context.Context, u *ent.User, d *ent.Deployment) (*ent.Review, error) diff --git a/internal/server/api/v1/repos/lock.go b/internal/server/api/v1/repos/lock.go index fb1002d1..755d1230 100644 --- a/internal/server/api/v1/repos/lock.go +++ b/internal/server/api/v1/repos/lock.go @@ -20,6 +20,7 @@ import ( "github.com/gitploy-io/gitploy/internal/server/global" gb "github.com/gitploy-io/gitploy/internal/server/global" "github.com/gitploy-io/gitploy/pkg/e" + "github.com/gitploy-io/gitploy/vo" ) type ( @@ -84,15 +85,17 @@ func (r *Repo) CreateLock(c *gin.Context) { vu, _ := c.Get(global.KeyUser) u := vu.(*ent.User) - env, err := r.i.GetEnv(ctx, u, re, p.Env) + config, err := r.i.GetConfig(ctx, u, re) if e.HasErrorCode(err, e.ErrorCodeEntityNotFound) { - r.log.Check(gb.GetZapLogLevel(err), "The configuration file is not found.").Write(zap.Error(err)) - // To override the HTTP status 422. + r.log.Check(gb.GetZapLogLevel(err), "Failed to get the configuration.").Write(zap.Error(err)) gb.ResponseWithStatusAndError(c, http.StatusUnprocessableEntity, err) return - } else if err != nil { - r.log.Check(gb.GetZapLogLevel(err), "It has failed to get the configuration.").Write(zap.Error(err)) - gb.ResponseWithError(c, err) + } + + var env *vo.Env + if env = config.GetEnv(p.Env); env == nil { + r.log.Warn("The environment is not found.", zap.String("env", p.Env)) + gb.ResponseWithStatusAndError(c, http.StatusUnprocessableEntity, e.NewError(e.ErrorCodeConfigUndefinedEnv, nil)) return } diff --git a/internal/server/api/v1/repos/lock_test.go b/internal/server/api/v1/repos/lock_test.go index 3ce07ca3..c76527ad 100644 --- a/internal/server/api/v1/repos/lock_test.go +++ b/internal/server/api/v1/repos/lock_test.go @@ -34,10 +34,9 @@ func TestRepo_CreateLock(t *testing.T) { ctrl := gomock.NewController(t) m := mock.NewMockInteractor(ctrl) - t.Log("Read deploy.yml and check the env.") m. EXPECT(). - GetEnv(gomock.Any(), gomock.AssignableToTypeOf(&ent.User{}), gomock.AssignableToTypeOf(&ent.Repo{}), gomock.Any()). + GetConfig(gomock.Any(), gomock.AssignableToTypeOf(&ent.User{}), gomock.AssignableToTypeOf(&ent.Repo{})). Return(nil, e.NewError(e.ErrorCodeConfigUndefinedEnv, nil)) r := NewRepo(RepoConfig{}, m) @@ -72,13 +71,15 @@ func TestRepo_CreateLock(t *testing.T) { ctrl := gomock.NewController(t) m := mock.NewMockInteractor(ctrl) - t.Log("Read deploy.yml and check the env.") m. EXPECT(). - GetEnv(gomock.Any(), gomock.AssignableToTypeOf(&ent.User{}), gomock.AssignableToTypeOf(&ent.Repo{}), gomock.Any()). - Return(&vo.Env{ - Name: "production", - }, nil) + GetConfig(gomock.Any(), gomock.AssignableToTypeOf(&ent.User{}), gomock.AssignableToTypeOf(&ent.Repo{})). + Return(&vo.Config{ + Envs: []*vo.Env{ + { + Name: "production", + }, + }}, nil) t.Log("Lock the env.") m. diff --git a/internal/server/api/v1/repos/mock/interactor.go b/internal/server/api/v1/repos/mock/interactor.go index c2696428..9bc3df33 100644 --- a/internal/server/api/v1/repos/mock/interactor.go +++ b/internal/server/api/v1/repos/mock/interactor.go @@ -336,21 +336,6 @@ func (mr *MockInteractorMockRecorder) GetConfig(ctx, u, r interface{}) *gomock.C return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetConfig", reflect.TypeOf((*MockInteractor)(nil).GetConfig), ctx, u, r) } -// GetEnv mocks base method. -func (m *MockInteractor) GetEnv(ctx context.Context, u *ent.User, r *ent.Repo, env string) (*vo.Env, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetEnv", ctx, u, r, env) - ret0, _ := ret[0].(*vo.Env) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetEnv indicates an expected call of GetEnv. -func (mr *MockInteractorMockRecorder) GetEnv(ctx, u, r, env interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEnv", reflect.TypeOf((*MockInteractor)(nil).GetEnv), ctx, u, r, env) -} - // GetTag mocks base method. func (m *MockInteractor) GetTag(ctx context.Context, u *ent.User, r *ent.Repo, tag string) (*vo.Tag, error) { m.ctrl.T.Helper() diff --git a/internal/server/slack/deploy.go b/internal/server/slack/deploy.go index 685e2432..28509955 100644 --- a/internal/server/slack/deploy.go +++ b/internal/server/slack/deploy.go @@ -273,15 +273,21 @@ func (s *Slack) interactDeploy(c *gin.Context) { return } - cfg, err := s.i.GetConfig(ctx, cu.Edges.User, cb.Edges.Repo) + config, err := s.i.GetConfig(ctx, cu.Edges.User, cb.Edges.Repo) if err != nil { postMessageWithError(cu, err) c.Status(http.StatusOK) return } + if err := config.Eval(&vo.EvalValues{}); err != nil { + postMessageWithError(cu, err) + c.Status(http.StatusOK) + return + } + var env *vo.Env - if env = cfg.GetEnv(sm.Env); env == nil { + if env = config.GetEnv(sm.Env); env == nil { postBotMessage(cu, "The env is not defined in the config.") c.Status(http.StatusOK) return diff --git a/internal/server/slack/rollback.go b/internal/server/slack/rollback.go index ef378823..7327e181 100644 --- a/internal/server/slack/rollback.go +++ b/internal/server/slack/rollback.go @@ -212,15 +212,21 @@ func (s *Slack) interactRollback(c *gin.Context) { return } - cfg, err := s.i.GetConfig(ctx, cu.Edges.User, cb.Edges.Repo) + config, err := s.i.GetConfig(ctx, cu.Edges.User, cb.Edges.Repo) if err != nil { postMessageWithError(cu, err) c.Status(http.StatusOK) return } + if err := config.Eval(&vo.EvalValues{}); err != nil { + postMessageWithError(cu, err) + c.Status(http.StatusOK) + return + } + var env *vo.Env - if env = cfg.GetEnv(d.Env); env == nil { + if env = config.GetEnv(d.Env); env == nil { postBotMessage(cu, "The env is not defined in the config.") c.Status(http.StatusOK) return From 9c4fa717bf6066c0f92a1b4dd958fd5626e8a51e Mon Sep 17 00:00:00 2001 From: noah Date: Tue, 23 Nov 2021 22:02:05 +0900 Subject: [PATCH 3/4] Remove unused methods --- internal/interactor/config.go | 22 --------- internal/interactor/config_test.go | 57 ---------------------- internal/interactor/deployment.go | 4 -- vo/config.go | 44 ----------------- vo/config_test.go | 77 ------------------------------ 5 files changed, 204 deletions(-) delete mode 100644 internal/interactor/config.go delete mode 100644 internal/interactor/config_test.go diff --git a/internal/interactor/config.go b/internal/interactor/config.go deleted file mode 100644 index 68517b29..00000000 --- a/internal/interactor/config.go +++ /dev/null @@ -1,22 +0,0 @@ -package interactor - -import ( - "context" - - "github.com/gitploy-io/gitploy/ent" - "github.com/gitploy-io/gitploy/pkg/e" - "github.com/gitploy-io/gitploy/vo" -) - -func (i *Interactor) GetEnv(ctx context.Context, u *ent.User, r *ent.Repo, env string) (*vo.Env, error) { - config, err := i.SCM.GetConfig(ctx, u, r) - if err != nil { - return nil, err - } - - if !config.HasEnv(env) { - return nil, e.NewError(e.ErrorCodeConfigUndefinedEnv, nil) - } - - return config.GetEnv(env), nil -} diff --git a/internal/interactor/config_test.go b/internal/interactor/config_test.go deleted file mode 100644 index 47f63629..00000000 --- a/internal/interactor/config_test.go +++ /dev/null @@ -1,57 +0,0 @@ -package interactor - -import ( - "context" - "testing" - - "github.com/golang/mock/gomock" - - "github.com/gitploy-io/gitploy/ent" - "github.com/gitploy-io/gitploy/internal/interactor/mock" - "github.com/gitploy-io/gitploy/pkg/e" - "github.com/gitploy-io/gitploy/vo" -) - -func TestInteractor_GetEnv(t *testing.T) { - t.Run("Return an error when the environment is not defined.", func(t *testing.T) { - ctrl := gomock.NewController(t) - scm := mock.NewMockSCM(ctrl) - - scm. - EXPECT(). - GetConfig(gomock.Any(), gomock.AssignableToTypeOf(&ent.User{}), gomock.AssignableToTypeOf(&ent.Repo{})). - Return(&vo.Config{ - Envs: []*vo.Env{}, - }, nil) - - i := &Interactor{SCM: scm} - - _, err := i.GetEnv(context.Background(), &ent.User{}, &ent.Repo{}, "production") - if !e.HasErrorCode(err, e.ErrorCodeConfigUndefinedEnv) { - t.Fatalf("GetEnv error = %v, wanted ErrorCodeConfigUndefinedEnv", err) - } - }) - - t.Run("Return the environment.", func(t *testing.T) { - ctrl := gomock.NewController(t) - scm := mock.NewMockSCM(ctrl) - - scm. - EXPECT(). - GetConfig(gomock.Any(), gomock.AssignableToTypeOf(&ent.User{}), gomock.AssignableToTypeOf(&ent.Repo{})). - Return(&vo.Config{ - Envs: []*vo.Env{ - { - Name: "production", - }, - }, - }, nil) - - i := &Interactor{SCM: scm} - - _, err := i.GetEnv(context.Background(), &ent.User{}, &ent.Repo{}, "production") - if err != nil { - t.Fatalf("GetEnv returns an error: %v", err) - } - }) -} diff --git a/internal/interactor/deployment.go b/internal/interactor/deployment.go index 37d6a7e8..a7c80449 100644 --- a/internal/interactor/deployment.go +++ b/internal/interactor/deployment.go @@ -131,10 +131,6 @@ func (i *Interactor) DeployToRemote(ctx context.Context, u *ent.User, r *ent.Rep ) } - if err := env.Eval(&vo.EvalValues{IsRollback: d.IsRollback}); err != nil { - return nil, err - } - rd, err := i.createRemoteDeployment(ctx, u, r, d, env) if err != nil { return nil, err diff --git a/vo/config.go b/vo/config.go index f2495867..ec1bd590 100644 --- a/vo/config.go +++ b/vo/config.go @@ -1,7 +1,6 @@ package vo import ( - "encoding/json" "regexp" "strconv" @@ -169,46 +168,3 @@ func (e *Env) IsAutoDeployOn(ref string) (bool, error) { func (e *Env) HasReview() bool { return e.Review != nil && e.Review.Enabled } - -func (e *Env) Eval(v *EvalValues) error { - byts, err := json.Marshal(e) - if err != nil { - return eutil.NewError(eutil.ErrorCodeConfigParseError, err) - } - - // Evaluates variables - mapper := func(vn string) string { - if vn == VarnameDeployTask { - if !v.IsRollback { - return DefaultDeployTask - } else { - return "" - } - } - - if vn == VarnameRollbackTask { - if v.IsRollback { - return DefaultRollbackTask - } else { - return "" - } - } - - if vn == VarnameIsRollback { - return strconv.FormatBool(v.IsRollback) - } - - return "ERR_NOT_IMPLEMENTED" - } - - evalued, err := envsubst.Eval(string(byts), mapper) - if err != nil { - return eutil.NewError(eutil.ErrorCodeConfigParseError, err) - } - - if err := json.Unmarshal([]byte(evalued), e); err != nil { - return eutil.NewError(eutil.ErrorCodeConfigParseError, err) - } - - return nil -} diff --git a/vo/config_test.go b/vo/config_test.go index 6c834377..5ec69884 100644 --- a/vo/config_test.go +++ b/vo/config_test.go @@ -1,7 +1,6 @@ package vo import ( - "fmt" "reflect" "testing" @@ -225,79 +224,3 @@ func TestEnv_IsDeployableRef(t *testing.T) { } }) } - -func TestEnv_Eval(t *testing.T) { - t.Run("eval the task.", func(t *testing.T) { - cs := []struct { - env *Env - want *Env - }{ - { - env: &Env{ - Task: pointer.ToString("${GITPLOY_DEPLOY_TASK}"), - }, - want: &Env{ - Task: pointer.ToString(DefaultDeployTask), - }, - }, - { - env: &Env{ - Task: pointer.ToString("${GITPLOY_DEPLOY_TASK}:kubernetes"), - }, - want: &Env{ - Task: pointer.ToString(fmt.Sprintf("%s:kubernetes", DefaultDeployTask)), - }, - }, - { - env: &Env{ - Task: pointer.ToString("${GITPLOY_DEPLOY_TASK}${GITPLOY_ROLLBACK_TASK}"), - }, - want: &Env{ - Task: pointer.ToString(DefaultDeployTask), - }, - }, - } - - for _, c := range cs { - err := c.env.Eval(&EvalValues{}) - if err != nil { - t.Fatalf("Eval returns an error: %s", err) - } - if !reflect.DeepEqual(c.env, c.want) { - t.Fatalf("Eval = %v, wanted %v", *c.env.Task, *c.want.Task) - } - } - }) - - t.Run("eval the is_rollback.", func(t *testing.T) { - const ( - isRollback = true - ) - - cs := []struct { - env *Env - want *Env - }{ - { - env: &Env{ - Payload: pointer.ToString("{\"is_rollback\": ${GITPLOY_IS_ROLLBACK}}"), - }, - want: &Env{ - Payload: pointer.ToString("{\"is_rollback\": true}"), - }, - }, - } - - for _, c := range cs { - err := c.env.Eval(&EvalValues{ - IsRollback: isRollback, - }) - if err != nil { - t.Fatalf("Eval returns an error: %s", err) - } - if !reflect.DeepEqual(c.env, c.want) { - t.Fatalf("Eval = %v, wanted %v", c.env, c.want) - } - } - }) -} From 6e1e0fa57ad77ed9302e59c3151039fb497216e4 Mon Sep 17 00:00:00 2001 From: noah Date: Tue, 23 Nov 2021 22:11:03 +0900 Subject: [PATCH 4/4] Fix test --- internal/interactor/deployment.go | 4 ++++ internal/interactor/deployment_test.go | 2 +- internal/server/api/v1/repos/lock_test.go | 8 ++++++-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/internal/interactor/deployment.go b/internal/interactor/deployment.go index a7c80449..6515f9ed 100644 --- a/internal/interactor/deployment.go +++ b/internal/interactor/deployment.go @@ -124,6 +124,10 @@ func (i *Interactor) DeployToRemote(ctx context.Context, u *ent.User, r *ent.Rep ) } + if ok, err := i.isDeployable(ctx, u, r, d, env); !ok { + return nil, err + } + if !i.IsApproved(ctx, d) { return nil, e.NewError( e.ErrorCodeDeploymentNotApproved, diff --git a/internal/interactor/deployment_test.go b/internal/interactor/deployment_test.go index fca2d386..2de6d565 100644 --- a/internal/interactor/deployment_test.go +++ b/internal/interactor/deployment_test.go @@ -289,7 +289,7 @@ func TestInteractor_DeployToRemote(t *testing.T) { } }) - t.Run("create a new remote deployment and update the deployment.", func(t *testing.T) { + t.Run("Create a new remote deployment and update the deployment.", func(t *testing.T) { input := struct { d *ent.Deployment e *vo.Env diff --git a/internal/server/api/v1/repos/lock_test.go b/internal/server/api/v1/repos/lock_test.go index c76527ad..23a2547e 100644 --- a/internal/server/api/v1/repos/lock_test.go +++ b/internal/server/api/v1/repos/lock_test.go @@ -17,7 +17,6 @@ import ( "github.com/gitploy-io/gitploy/ent" "github.com/gitploy-io/gitploy/internal/server/api/v1/repos/mock" "github.com/gitploy-io/gitploy/internal/server/global" - "github.com/gitploy-io/gitploy/pkg/e" "github.com/gitploy-io/gitploy/vo" ) @@ -37,7 +36,12 @@ func TestRepo_CreateLock(t *testing.T) { m. EXPECT(). GetConfig(gomock.Any(), gomock.AssignableToTypeOf(&ent.User{}), gomock.AssignableToTypeOf(&ent.Repo{})). - Return(nil, e.NewError(e.ErrorCodeConfigUndefinedEnv, nil)) + Return(&vo.Config{ + Envs: []*vo.Env{ + { + Name: "dev", + }, + }}, nil) r := NewRepo(RepoConfig{}, m)