Skip to content
This repository was archived by the owner on May 30, 2024. It is now read-only.

Commit e672d1a

Browse files
author
Noah Lee
authored
Refactoring validation for deployment (#349)
* Add validators for deployment
1 parent 6222fd2 commit e672d1a

File tree

6 files changed

+317
-359
lines changed

6 files changed

+317
-359
lines changed

internal/interactor/deployment.go

Lines changed: 35 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
"github.com/AlekSi/pointer"
99
"github.com/gitploy-io/gitploy/model/ent"
1010
"github.com/gitploy-io/gitploy/model/ent/deployment"
11-
"github.com/gitploy-io/gitploy/model/ent/review"
1211
"github.com/gitploy-io/gitploy/model/extent"
1312
"github.com/gitploy-io/gitploy/pkg/e"
1413
"go.uber.org/zap"
@@ -71,57 +70,38 @@ type (
7170
}
7271
)
7372

74-
// IsApproved verifies that the request is approved or not.
75-
// It is approved if there is an approval of reviews at least, but
76-
// it is rejected if there is a reject of reviews.
77-
func (i *DeploymentInteractor) IsApproved(ctx context.Context, d *ent.Deployment) bool {
78-
rvs, _ := i.store.ListReviews(ctx, d)
79-
80-
for _, r := range rvs {
81-
if r.Status == review.StatusRejected {
82-
return false
83-
}
84-
}
85-
86-
for _, r := range rvs {
87-
if r.Status == review.StatusApproved {
88-
return true
89-
}
90-
}
91-
92-
return false
93-
}
94-
9573
// Deploy posts a new deployment to SCM with the payload.
96-
// But if it requires a review, it saves the payload on the DB
97-
// and waits until reviewed.
74+
// But if it requires a review, it saves the payload on the store and waits until reviewed.
9875
// It returns an error for a undeployable payload.
9976
func (i *DeploymentInteractor) Deploy(ctx context.Context, u *ent.User, r *ent.Repo, d *ent.Deployment, env *extent.Env) (*ent.Deployment, error) {
100-
if err := i.isDeployable(ctx, u, r, d, env); err != nil {
77+
i.log.Debug("Validate the request.")
78+
v := NewDeploymentValidator([]Validator{
79+
&RefValidator{Env: env},
80+
&FrozenWindowValidator{Env: env},
81+
&LockValidator{Repo: r, Store: i.store},
82+
})
83+
if err := v.Validate(d); err != nil {
10184
return nil, err
10285
}
10386

10487
number, err := i.store.GetNextDeploymentNumberOfRepo(ctx, r)
10588
if err != nil {
106-
return nil, e.NewError(
107-
e.ErrorCodeInternalError,
108-
err,
109-
)
89+
return nil, e.NewError(e.ErrorCodeInternalError, err)
11090
}
11191

112-
if env.HasReview() {
113-
d := &ent.Deployment{
114-
Number: number,
115-
Type: d.Type,
116-
Env: d.Env,
117-
Ref: d.Ref,
118-
Status: deployment.StatusWaiting,
119-
ProductionEnvironment: env.IsProductionEnvironment(),
120-
IsRollback: d.IsRollback,
121-
UserID: u.ID,
122-
RepoID: r.ID,
123-
}
92+
d = &ent.Deployment{
93+
Number: number,
94+
Type: d.Type,
95+
Env: d.Env,
96+
Ref: d.Ref,
97+
Status: deployment.DefaultStatus,
98+
ProductionEnvironment: env.IsProductionEnvironment(),
99+
IsRollback: d.IsRollback,
100+
UserID: u.ID,
101+
RepoID: r.ID,
102+
}
124103

104+
if env.HasReview() {
125105
i.log.Debug("Save the deployment to wait reviews.")
126106
d, err = i.store.CreateDeployment(ctx, d)
127107
if err != nil {
@@ -148,22 +128,12 @@ func (i *DeploymentInteractor) Deploy(ctx context.Context, u *ent.User, r *ent.R
148128
return nil, err
149129
}
150130

151-
d = &ent.Deployment{
152-
Number: number,
153-
Type: d.Type,
154-
Env: d.Env,
155-
Ref: d.Ref,
156-
Status: deployment.StatusCreated,
157-
UID: rd.UID,
158-
Sha: rd.SHA,
159-
HTMLURL: rd.HTLMURL,
160-
ProductionEnvironment: env.IsProductionEnvironment(),
161-
IsRollback: d.IsRollback,
162-
UserID: u.ID,
163-
RepoID: r.ID,
164-
}
131+
d.UID = rd.UID
132+
d.Sha = rd.SHA
133+
d.HTMLURL = rd.HTLMURL
134+
d.Status = deployment.StatusCreated
165135

166-
i.log.Debug("Create a new deployment with the payload.", zap.Any("deployment", d))
136+
i.log.Debug("Create a new deployment with the response.", zap.Any("deployment", d))
167137
d, err = i.store.CreateDeployment(ctx, d)
168138
if err != nil {
169139
return nil, fmt.Errorf("It failed to save a new deployment.: %w", err)
@@ -182,25 +152,18 @@ func (i *DeploymentInteractor) Deploy(ctx context.Context, u *ent.User, r *ent.R
182152
// after review has finished.
183153
// It returns an error for a undeployable payload.
184154
func (i *DeploymentInteractor) DeployToRemote(ctx context.Context, u *ent.User, r *ent.Repo, d *ent.Deployment, env *extent.Env) (*ent.Deployment, error) {
185-
if d.Status != deployment.StatusWaiting {
186-
return nil, e.NewErrorWithMessage(
187-
e.ErrorCodeDeploymentStatusInvalid,
188-
"The deployment status is not waiting.",
189-
nil,
190-
)
191-
}
192-
193-
if err := i.isDeployable(ctx, u, r, d, env); err != nil {
155+
i.log.Debug("Validate the request.")
156+
v := NewDeploymentValidator([]Validator{
157+
&StatusValidator{Status: deployment.StatusWaiting},
158+
&RefValidator{Env: env},
159+
&FrozenWindowValidator{Env: env},
160+
&LockValidator{Repo: r, Store: i.store},
161+
&ReviewValidator{Store: i.store},
162+
})
163+
if err := v.Validate(d); err != nil {
194164
return nil, err
195165
}
196166

197-
if !i.IsApproved(ctx, d) {
198-
return nil, e.NewError(
199-
e.ErrorCodeDeploymentNotApproved,
200-
nil,
201-
)
202-
}
203-
204167
rd, err := i.createRemoteDeployment(ctx, u, r, d, env)
205168
if err != nil {
206169
return nil, err
@@ -237,32 +200,6 @@ func (i *DeploymentInteractor) createRemoteDeployment(ctx context.Context, u *en
237200
return i.scm.CreateRemoteDeployment(ctx, u, r, d, env)
238201
}
239202

240-
func (i *DeploymentInteractor) isDeployable(ctx context.Context, u *ent.User, r *ent.Repo, d *ent.Deployment, env *extent.Env) error {
241-
// Skip verifications for roll back.
242-
if !d.IsRollback {
243-
if ok, err := env.IsDeployableRef(d.Ref); !ok {
244-
return e.NewErrorWithMessage(e.ErrorCodeEntityUnprocessable, "The ref is not matched with 'deployable_ref'.", nil)
245-
} else if err != nil {
246-
return err
247-
}
248-
}
249-
250-
// Check that the environment is locked.
251-
if locked, err := i.store.HasLockOfRepoForEnv(ctx, r, d.Env); locked {
252-
return e.NewError(e.ErrorCodeDeploymentLocked, err)
253-
} else if err != nil {
254-
return err
255-
}
256-
257-
if freezed, err := env.IsFreezed(time.Now().UTC()); freezed {
258-
return e.NewError(e.ErrorCodeDeploymentFrozen, err)
259-
} else if err != nil {
260-
return err
261-
}
262-
263-
return nil
264-
}
265-
266203
func (i *DeploymentInteractor) runClosingInactiveDeployment(stop <-chan struct{}) {
267204
ctx := context.Background()
268205

0 commit comments

Comments
 (0)