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

Commit b334dde

Browse files
author
Noah Hanjun Lee
authored
Fix deployment patch API (#208)
* Fix the deployment patch API
1 parent 281434c commit b334dde

File tree

9 files changed

+83
-63
lines changed

9 files changed

+83
-63
lines changed

internal/interactor/deployment.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,14 @@ func (i *Interactor) IsApproved(ctx context.Context, d *ent.Deployment) bool {
121121

122122
// DeployToRemote create a new remote deployment after the deployment was approved.
123123
func (i *Interactor) DeployToRemote(ctx context.Context, u *ent.User, r *ent.Repo, d *ent.Deployment, env *vo.Env) (*ent.Deployment, error) {
124+
if d.Status != deployment.StatusWaiting {
125+
return nil, e.NewErrorWithMessage(
126+
e.ErrorCodeDeploymentStatusInvalid,
127+
"The deployment status is not waiting.",
128+
nil,
129+
)
130+
}
131+
124132
if locked, err := i.Store.HasLockOfRepoForEnv(ctx, r, d.Env); locked {
125133
return nil, e.NewError(
126134
e.ErrorCodeDeploymentLocked,

internal/interactor/deployment_test.go

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@ import (
55
"reflect"
66
"testing"
77

8+
"github.com/golang/mock/gomock"
9+
"go.uber.org/zap"
10+
811
"github.com/gitploy-io/gitploy/ent"
912
"github.com/gitploy-io/gitploy/ent/deployment"
1013
"github.com/gitploy-io/gitploy/ent/review"
1114
"github.com/gitploy-io/gitploy/internal/interactor/mock"
15+
"github.com/gitploy-io/gitploy/pkg/e"
1216
"github.com/gitploy-io/gitploy/vo"
13-
"github.com/golang/mock/gomock"
14-
"go.uber.org/zap"
1517
)
1618

1719
func newMockInteractor(store Store, scm SCM) *Interactor {
@@ -193,7 +195,7 @@ func TestInteractor_Deploy(t *testing.T) {
193195
func TestInteractor_DeployToRemote(t *testing.T) {
194196
ctx := gomock.Any()
195197

196-
t.Run("create a new remote deployment and update the deployment.", func(t *testing.T) {
198+
t.Run("Return an error when the deployment status is not waiting.", func(t *testing.T) {
197199
input := struct {
198200
d *ent.Deployment
199201
e *vo.Env
@@ -206,6 +208,29 @@ func TestInteractor_DeployToRemote(t *testing.T) {
206208
store := mock.NewMockStore(ctrl)
207209
scm := mock.NewMockSCM(ctrl)
208210

211+
i := newMockInteractor(store, scm)
212+
213+
_, err := i.DeployToRemote(context.Background(), &ent.User{}, &ent.Repo{}, input.d, input.e)
214+
if !e.HasErrorCode(err, e.ErrorCodeDeploymentStatusInvalid) {
215+
t.Fatalf("CreateRemoteDeployment error = %v, wanted ErrorCodeDeploymentStatusInvalid", err)
216+
}
217+
})
218+
219+
t.Run("create a new remote deployment and update the deployment.", func(t *testing.T) {
220+
input := struct {
221+
d *ent.Deployment
222+
e *vo.Env
223+
}{
224+
d: &ent.Deployment{
225+
Status: deployment.StatusWaiting,
226+
},
227+
e: &vo.Env{},
228+
}
229+
230+
ctrl := gomock.NewController(t)
231+
store := mock.NewMockStore(ctrl)
232+
scm := mock.NewMockSCM(ctrl)
233+
209234
const (
210235
UID = 1000
211236
)

internal/server/api/v1/repos/deployment.go

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -207,20 +207,18 @@ func (r *Repo) UpdateDeployment(c *gin.Context) {
207207
return
208208
}
209209

210-
if p.Status == string(deployment.StatusCreated) && d.Status == deployment.StatusWaiting {
211-
if d, err = r.i.DeployToRemote(ctx, u, re, d, env); err != nil {
212-
r.log.Check(gb.GetZapLogLevel(err), "It has failed to deploy to the remote.").Write(zap.Error(err))
213-
gb.ResponseWithError(c, err)
214-
return
215-
}
210+
if d, err = r.i.DeployToRemote(ctx, u, re, d, env); err != nil {
211+
r.log.Check(gb.GetZapLogLevel(err), "It has failed to deploy to the remote.").Write(zap.Error(err))
212+
gb.ResponseWithError(c, err)
213+
return
214+
}
216215

217-
if _, err := r.i.CreateEvent(ctx, &ent.Event{
218-
Kind: event.KindDeployment,
219-
Type: event.TypeUpdated,
220-
DeploymentID: d.ID,
221-
}); err != nil {
222-
r.log.Error("It has failed to create an event.", zap.Error(err))
223-
}
216+
if _, err := r.i.CreateEvent(ctx, &ent.Event{
217+
Kind: event.KindDeployment,
218+
Type: event.TypeUpdated,
219+
DeploymentID: d.ID,
220+
}); err != nil {
221+
r.log.Error("It has failed to create an event.", zap.Error(err))
224222
}
225223

226224
// Get the deployment with edges.

openapi/v1.yaml

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -591,7 +591,7 @@ paths:
591591
patch:
592592
tags:
593593
- Repo
594-
summary: Deploy to SCM if a status of the deployment is waiting.
594+
summary: Create a remote deployment when the status of the deployment is 'waiting'.
595595
parameters:
596596
- in: path
597597
name: namespace
@@ -609,17 +609,6 @@ paths:
609609
schema:
610610
type: integer
611611
description: The deployment number.
612-
requestBody:
613-
content:
614-
application/json:
615-
schema:
616-
type: object
617-
properties:
618-
status:
619-
type: string
620-
default: created
621-
required:
622-
- status
623612
responses:
624613
'200':
625614
description: Deployment

pkg/e/code.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ const (
1717
ErrorCodeDeploymentLocked ErrorCode = "deployment_locked"
1818
// ErrorCodeDeploymentUnapproved is when the deployment is not approved.
1919
ErrorCodeDeploymentNotApproved ErrorCode = "deployment_not_approved"
20+
// ErrorCodeDeploymentStatusNotWaiting is the status must be 'waiting' to create a remote deployment.
21+
ErrorCodeDeploymentStatusInvalid ErrorCode = "deployment_status_invalid"
2022
// ErrorCodeDeploymentUndeployable is that the merge conflict occurs or a commit status has failed.
2123
ErrorCodeDeploymentUndeployable ErrorCode = "deployment_undeployable"
2224

pkg/e/trans.go

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,20 @@ package e
33
import "net/http"
44

55
var messages = map[ErrorCode]string{
6-
ErrorCodeConfigParseError: "The configuration is invalid.",
7-
ErrorCodeDeploymentConflict: "The conflict occurs, please retry.",
8-
ErrorCodeDeploymentInvalid: "The validation has failed.",
9-
ErrorCodeDeploymentLocked: "The environment is locked.",
10-
ErrorCodeDeploymentNotApproved: "The deployment is not approved",
11-
ErrorCodeDeploymentUndeployable: "There is merge conflict or a commit status check failed.",
12-
ErrorCodeLicenseDecode: "Decoding the license is failed.",
13-
ErrorCodeLicenseRequired: "The license is required.",
14-
ErrorCodeInvalidRequest: "Invalid request parameter.",
15-
ErrorPermissionRequired: "The permission is required",
16-
ErrorCodeNotFound: "It is not found.",
17-
ErrorCodeUnprocessableEntity: "Invalid request payload.",
18-
ErrorCodeInternalError: "Server internal error.",
6+
ErrorCodeConfigParseError: "The configuration is invalid.",
7+
ErrorCodeDeploymentConflict: "The conflict occurs, please retry.",
8+
ErrorCodeDeploymentInvalid: "The validation has failed.",
9+
ErrorCodeDeploymentLocked: "The environment is locked.",
10+
ErrorCodeDeploymentNotApproved: "The deployment is not approved",
11+
ErrorCodeDeploymentStatusInvalid: "The deployment status is invalid",
12+
ErrorCodeDeploymentUndeployable: "There is merge conflict or a commit status check failed.",
13+
ErrorCodeLicenseDecode: "Decoding the license is failed.",
14+
ErrorCodeLicenseRequired: "The license is required.",
15+
ErrorCodeInvalidRequest: "Invalid request parameter.",
16+
ErrorPermissionRequired: "The permission is required",
17+
ErrorCodeNotFound: "It is not found.",
18+
ErrorCodeUnprocessableEntity: "Invalid request payload.",
19+
ErrorCodeInternalError: "Server internal error.",
1920
}
2021

2122
func GetMessage(code ErrorCode) string {
@@ -28,19 +29,20 @@ func GetMessage(code ErrorCode) string {
2829
}
2930

3031
var httpCodes = map[ErrorCode]int{
31-
ErrorCodeConfigParseError: http.StatusUnprocessableEntity,
32-
ErrorCodeDeploymentConflict: http.StatusUnprocessableEntity,
33-
ErrorCodeDeploymentInvalid: http.StatusUnprocessableEntity,
34-
ErrorCodeDeploymentLocked: http.StatusUnprocessableEntity,
35-
ErrorCodeDeploymentNotApproved: http.StatusUnprocessableEntity,
36-
ErrorCodeDeploymentUndeployable: http.StatusUnprocessableEntity,
37-
ErrorCodeLicenseDecode: http.StatusUnprocessableEntity,
38-
ErrorCodeLicenseRequired: http.StatusPaymentRequired,
39-
ErrorCodeInvalidRequest: http.StatusBadRequest,
40-
ErrorCodeNotFound: http.StatusNotFound,
41-
ErrorPermissionRequired: http.StatusForbidden,
42-
ErrorCodeUnprocessableEntity: http.StatusUnprocessableEntity,
43-
ErrorCodeInternalError: http.StatusInternalServerError,
32+
ErrorCodeConfigParseError: http.StatusUnprocessableEntity,
33+
ErrorCodeDeploymentConflict: http.StatusUnprocessableEntity,
34+
ErrorCodeDeploymentInvalid: http.StatusUnprocessableEntity,
35+
ErrorCodeDeploymentLocked: http.StatusUnprocessableEntity,
36+
ErrorCodeDeploymentNotApproved: http.StatusUnprocessableEntity,
37+
ErrorCodeDeploymentStatusInvalid: http.StatusUnprocessableEntity,
38+
ErrorCodeDeploymentUndeployable: http.StatusUnprocessableEntity,
39+
ErrorCodeLicenseDecode: http.StatusUnprocessableEntity,
40+
ErrorCodeLicenseRequired: http.StatusPaymentRequired,
41+
ErrorCodeInvalidRequest: http.StatusBadRequest,
42+
ErrorCodeNotFound: http.StatusNotFound,
43+
ErrorPermissionRequired: http.StatusForbidden,
44+
ErrorCodeUnprocessableEntity: http.StatusUnprocessableEntity,
45+
ErrorCodeInternalError: http.StatusInternalServerError,
4446
}
4547

4648
func GetHttpCode(code ErrorCode) int {

ui/src/apis/deployment.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -216,15 +216,11 @@ export const createDeployment = async (namespace: string, name: string, type: De
216216
return deployment
217217
}
218218

219-
export const updateDeploymentStatusCreated = async (namespace: string, name: string, number: number): Promise<Deployment> => {
220-
const body = JSON.stringify({
221-
status: "created"
222-
})
219+
export const createRemoteDeployment = async (namespace: string, name: string, number: number): Promise<Deployment> => {
223220
const response = await _fetch(`${instance}/api/v1/repos/${namespace}/${name}/deployments/${number}`, {
224221
headers,
225222
credentials: 'same-origin',
226223
method: "PATCH",
227-
body: body,
228224
})
229225
if (response.status === StatusCodes.FORBIDDEN) {
230226
const message = await response.json().then(data => data.message)

ui/src/apis/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
listDeployments,
1515
getDeployment,
1616
createDeployment,
17-
updateDeploymentStatusCreated,
17+
createRemoteDeployment,
1818
rollbackDeployment,
1919
listDeploymentChanges
2020
} from './deployment'
@@ -54,7 +54,7 @@ export {
5454
listDeployments,
5555
getDeployment,
5656
createDeployment,
57-
updateDeploymentStatusCreated,
57+
createRemoteDeployment,
5858
rollbackDeployment,
5959
listDeploymentChanges,
6060
getConfig,

ui/src/redux/deployment.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
} from "../models"
1414
import {
1515
getDeployment,
16-
updateDeploymentStatusCreated,
16+
createRemoteDeployment,
1717
listReviews,
1818
getUserReview,
1919
approveReview,
@@ -83,7 +83,7 @@ export const deployToSCM = createAsyncThunk<Deployment, void, { state: {deployme
8383
}
8484

8585
try {
86-
const deployment = await updateDeploymentStatusCreated(namespace, name, number)
86+
const deployment = await createRemoteDeployment(namespace, name, number)
8787
message.info("It starts to deploy.", 3)
8888

8989
return deployment

0 commit comments

Comments
 (0)