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

Commit 12e25a8

Browse files
author
Noah Lee
authored
Support the pipeline serialization (#386)
* Add a validator for serialization * Add `FindPrevRunningDeployment` method to store
1 parent 90fa0cc commit 12e25a8

File tree

10 files changed

+206
-127
lines changed

10 files changed

+206
-127
lines changed

internal/interactor/_mock.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ github.com/gitploy-io/gitploy/internal/interactor=user.go\
77
,github.com/gitploy-io/gitploy/internal/interactor=deploymentstatistics.go\
88
,github.com/gitploy-io/gitploy/internal/interactor=lock.go\
99
,github.com/gitploy-io/gitploy/internal/interactor=event.go\
10+
,github.com/gitploy-io/gitploy/internal/interactor=review.go\
1011
-source ./interface.go \
1112
-package mock \
1213
-destination ./mock/pkg.go

internal/interactor/deployment.go

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ type (
2727
FindDeploymentByID(ctx context.Context, id int) (*ent.Deployment, error)
2828
FindDeploymentByUID(ctx context.Context, uid int64) (*ent.Deployment, error)
2929
FindDeploymentOfRepoByNumber(ctx context.Context, r *ent.Repo, number int) (*ent.Deployment, error)
30+
FindPrevRunningDeployment(ctx context.Context, d *ent.Deployment) (*ent.Deployment, error)
3031
FindPrevSuccessDeployment(ctx context.Context, d *ent.Deployment) (*ent.Deployment, error)
3132
GetNextDeploymentNumberOfRepo(ctx context.Context, r *ent.Repo) (int, error)
3233
CreateDeployment(ctx context.Context, d *ent.Deployment) (*ent.Deployment, error)
@@ -71,21 +72,12 @@ type (
7172
// But if it requires a review, it saves the payload on the store and waits until reviewed.
7273
// It returns an error for a undeployable payload.
7374
func (i *DeploymentInteractor) Deploy(ctx context.Context, u *ent.User, r *ent.Repo, d *ent.Deployment, env *extent.Env) (*ent.Deployment, error) {
74-
i.log.Debug("Validate the request.")
75-
v := NewDeploymentValidator([]Validator{
76-
&RefValidator{Env: env},
77-
&FrozenWindowValidator{Env: env},
78-
&LockValidator{Repo: r, Store: i.store},
79-
})
80-
if err := v.Validate(d); err != nil {
81-
return nil, err
82-
}
83-
8475
number, err := i.store.GetNextDeploymentNumberOfRepo(ctx, r)
8576
if err != nil {
8677
return nil, e.NewError(e.ErrorCodeInternalError, err)
8778
}
8879

80+
i.log.Debug("Get the next number, and build the deployment.")
8981
d = &ent.Deployment{
9082
Number: number,
9183
Type: d.Type,
@@ -98,6 +90,17 @@ func (i *DeploymentInteractor) Deploy(ctx context.Context, u *ent.User, r *ent.R
9890
RepoID: r.ID,
9991
}
10092

93+
i.log.Debug("Validate the deployment before a request.")
94+
v := NewDeploymentValidator([]Validator{
95+
&RefValidator{Env: env},
96+
&FrozenWindowValidator{Env: env},
97+
&LockValidator{Repo: r, Store: i.store},
98+
&SerializationValidator{Env: env, Store: i.store},
99+
})
100+
if err := v.Validate(d); err != nil {
101+
return nil, err
102+
}
103+
101104
if env.HasReview() {
102105
i.log.Debug("Save the deployment to wait reviews.")
103106
d, err = i.store.CreateDeployment(ctx, d)
@@ -199,12 +202,13 @@ func (i *DeploymentInteractor) requestReviews(ctx context.Context, u *ent.User,
199202
// after review has finished.
200203
// It returns an error for a undeployable payload.
201204
func (i *DeploymentInteractor) DeployToRemote(ctx context.Context, u *ent.User, r *ent.Repo, d *ent.Deployment, env *extent.Env) (*ent.Deployment, error) {
202-
i.log.Debug("Validate the request.")
205+
i.log.Debug("Validate the deployment before a request.")
203206
v := NewDeploymentValidator([]Validator{
204207
&StatusValidator{Status: deployment.StatusWaiting},
205208
&RefValidator{Env: env},
206209
&FrozenWindowValidator{Env: env},
207210
&LockValidator{Repo: r, Store: i.store},
211+
&SerializationValidator{Env: env, Store: i.store},
208212
&ReviewValidator{Store: i.store},
209213
})
210214
if err := v.Validate(d); err != nil {

internal/interactor/mock/pkg.go

Lines changed: 15 additions & 113 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/interactor/validator.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/gitploy-io/gitploy/model/ent/review"
1010
"github.com/gitploy-io/gitploy/model/extent"
1111
"github.com/gitploy-io/gitploy/pkg/e"
12+
"go.uber.org/zap"
1213
)
1314

1415
// DeploymentValidator validate that it is deployable.
@@ -137,3 +138,33 @@ func (v *ReviewValidator) Validate(d *ent.Deployment) error {
137138

138139
return e.NewError(e.ErrorCodeDeploymentNotApproved, nil)
139140
}
141+
142+
// SerializationValidator verify if there is currently a running deployment
143+
// for the environment.
144+
type SerializationValidator struct {
145+
Env *extent.Env
146+
Store DeploymentStore
147+
}
148+
149+
func (v *SerializationValidator) Validate(d *ent.Deployment) error {
150+
log := zap.L().Named("serialization-validator")
151+
defer log.Sync()
152+
153+
// Skip if the serialization field is disabled.
154+
if v.Env.Serialization == nil || !*v.Env.Serialization {
155+
log.Debug("Skip the serialization validator.")
156+
return nil
157+
}
158+
159+
d, err := v.Store.FindPrevRunningDeployment(context.Background(), d)
160+
if d != nil {
161+
return e.NewError(e.ErrorCodeDeploymentSerialization, nil)
162+
}
163+
164+
if e.HasErrorCode(err, e.ErrorCodeEntityNotFound) {
165+
log.Debug("There is no running deployment.")
166+
return nil
167+
}
168+
169+
return err
170+
}

internal/interactor/validator_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,39 @@ func TestReviewValidator_Validate(t *testing.T) {
102102
}
103103
})
104104
}
105+
106+
func TestSerializationValidator_Validate(t *testing.T) {
107+
t.Run("Returns nil if the serialization is empty.", func(t *testing.T) {
108+
ctrl := gomock.NewController(t)
109+
store := mock.NewMockStore(ctrl)
110+
111+
v := &i.SerializationValidator{
112+
Env: &extent.Env{},
113+
Store: store,
114+
}
115+
116+
if err := v.Validate(&ent.Deployment{}); err != nil {
117+
t.Fatalf("Validate returns an error: %v", err)
118+
}
119+
})
120+
121+
t.Run("Returns an deployment_serialization error if there is a running deployment.", func(t *testing.T) {
122+
t.Log("Start mocking:")
123+
ctrl := gomock.NewController(t)
124+
store := mock.NewMockStore(ctrl)
125+
126+
t.Log("Return a running deployment.")
127+
store.EXPECT().
128+
FindPrevRunningDeployment(gomock.Any(), gomock.AssignableToTypeOf(&ent.Deployment{})).
129+
Return(&ent.Deployment{}, nil)
130+
131+
v := &i.SerializationValidator{
132+
Env: &extent.Env{Serialization: pointer.ToBool(true)},
133+
Store: store,
134+
}
135+
136+
if err := v.Validate(&ent.Deployment{}); !e.HasErrorCode(err, e.ErrorCodeDeploymentSerialization) {
137+
t.Fatalf("Error is not deployment_serialization: %v", err)
138+
}
139+
})
140+
}

internal/pkg/store/deployment.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,32 @@ func (s *Store) GetNextDeploymentNumberOfRepo(ctx context.Context, r *ent.Repo)
208208
return cnt + 1, nil
209209
}
210210

211+
// FindPrevRunningDeployment find a deployment of which the status is created, queued, or running.
212+
func (s *Store) FindPrevRunningDeployment(ctx context.Context, d *ent.Deployment) (*ent.Deployment, error) {
213+
d, err := s.c.Deployment.
214+
Query().
215+
Where(
216+
deployment.And(
217+
deployment.RepoIDEQ(d.RepoID),
218+
deployment.EnvEQ(d.Env),
219+
deployment.StatusIn(
220+
deployment.StatusCreated,
221+
deployment.StatusQueued,
222+
deployment.StatusRunning,
223+
),
224+
),
225+
).
226+
Order(ent.Desc(deployment.FieldCreatedAt)).
227+
First(ctx)
228+
if ent.IsNotFound(err) {
229+
return nil, e.NewErrorWithMessage(e.ErrorCodeEntityNotFound, "The deployment is not found.", err)
230+
} else if err != nil {
231+
return nil, e.NewError(e.ErrorCodeInternalError, err)
232+
}
233+
234+
return d, nil
235+
}
236+
211237
func (s *Store) FindPrevSuccessDeployment(ctx context.Context, d *ent.Deployment) (*ent.Deployment, error) {
212238
d, err := s.c.Deployment.
213239
Query().

0 commit comments

Comments
 (0)