Skip to content

Commit 451a864

Browse files
committed
feat: configure what ip/port server should listen to
1 parent 233e5ec commit 451a864

File tree

4 files changed

+54
-26
lines changed

4 files changed

+54
-26
lines changed

.golangci.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,8 @@ linters-settings:
179179
- i
180180
- id
181181
- ok
182+
- r
183+
- w
182184

183185
tagalign:
184186
# Align and sort can be used together or separately.

cmd/cmd_server.go

+43-26
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,14 @@ type Payload struct {
4040
MergeRequest *MergeRequest `json:"merge_request,omitempty"` // "merge_request" is sent on "note" activity
4141
}
4242

43-
func errHandler(w http.ResponseWriter, code int, err error) {
44-
slog.Error(err.Error())
43+
func errHandler(ctx context.Context, w http.ResponseWriter, code int, err error) {
44+
switch code {
45+
case http.StatusOK:
46+
slogctx.Info(ctx, "Server response", slog.Int("response_code", code), slog.Any("response_message", err))
47+
48+
default:
49+
slogctx.Error(ctx, "Server response", slog.Int("response_code", code), slog.Any("response_message", err))
50+
}
4551

4652
w.WriteHeader(code)
4753
w.Write([]byte(err.Error()))
@@ -50,7 +56,7 @@ func errHandler(w http.ResponseWriter, code int, err error) {
5056
}
5157

5258
func Server(cCtx *cli.Context) error { //nolint:unparam
53-
slogctx.Info(cCtx.Context, "Starting HTTP server")
59+
slogctx.Info(cCtx.Context, "Starting HTTP server", slog.String("listen", cCtx.String(FlagServerListen)))
5460

5561
mux := http.NewServeMux()
5662

@@ -62,42 +68,51 @@ func Server(cCtx *cli.Context) error { //nolint:unparam
6268
return err
6369
}
6470

65-
mux.HandleFunc("POST /gitlab", func(writer http.ResponseWriter, reader *http.Request) {
66-
slogctx.Info(reader.Context(), "Handling /gitlab request")
71+
mux.HandleFunc("POST /gitlab", func(w http.ResponseWriter, r *http.Request) {
72+
ctx := r.Context()
6773

74+
slogctx.Info(ctx, "Handling /gitlab request")
75+
76+
// Check if the webhook secret is set (and if its matching)
6877
if len(ourSecret) > 0 {
69-
theirSecret := reader.Header.Get("X-Gitlab-Token")
78+
theirSecret := r.Header.Get("X-Gitlab-Token")
7079
if ourSecret != theirSecret {
71-
errHandler(writer, http.StatusForbidden, errors.New("Missing or invalid X-Gitlab-Token header"))
80+
errHandler(ctx, w, http.StatusForbidden, errors.New("Missing or invalid X-Gitlab-Token header"))
7281

7382
return
7483
}
7584
}
7685

77-
// Validate headers
78-
if reader.Header.Get("Content-Type") != "application/json" {
79-
errHandler(writer, http.StatusInternalServerError, errors.New("not json"))
86+
// Validate content type
87+
if r.Header.Get("Content-Type") != "application/json" {
88+
errHandler(ctx, w, http.StatusNotAcceptable, errors.New("The request is not using Content-Type: application/json"))
8089

8190
return
8291
}
8392

84-
body, err := io.ReadAll(reader.Body)
93+
// Read the POST body of the request
94+
body, err := io.ReadAll(r.Body)
8595
if err != nil {
86-
errHandler(writer, http.StatusInternalServerError, err)
96+
errHandler(ctx, w, http.StatusBadRequest, err)
8797

8898
return
8999
}
90100

101+
// Ensure we have content in the POST body
102+
if len(body) == 0 {
103+
errHandler(ctx, w, http.StatusBadRequest, errors.New("The POST body is empty; expected a JSON payload"))
104+
}
105+
91106
// Decode request payload
92107
var payload Payload
93108
if err := json.NewDecoder(bytes.NewReader(body)).Decode(&payload); err != nil {
94-
errHandler(writer, http.StatusInternalServerError, err)
109+
errHandler(ctx, w, http.StatusBadRequest, fmt.Errorf("could not decode POST body into Payload struct: %w", err))
95110

96111
return
97112
}
98113

99114
// Initialize context
100-
ctx := state.ContextWithProjectID(reader.Context(), payload.Project.PathWithNamespace)
115+
ctx = state.ContextWithProjectID(ctx, payload.Project.PathWithNamespace)
101116

102117
// Grab event specific information
103118
var (
@@ -115,46 +130,48 @@ func Server(cCtx *cli.Context) error { //nolint:unparam
115130
ref = payload.MergeRequest.LastCommit.ID
116131

117132
default:
118-
errHandler(writer, http.StatusInternalServerError, fmt.Errorf("unknown event: %s", payload.EventType))
133+
errHandler(ctx, w, http.StatusInternalServerError, fmt.Errorf("unknown event type: %s", payload.EventType))
119134
}
120135

136+
ctx = slogctx.With(ctx, slog.String("event_type", payload.EventType), slog.String("merge_request_id", id), slog.String("sha_reference", ref))
137+
121138
// Get the remote config file
122139
file, err := client.MergeRequests().GetRemoteConfig(ctx, cCtx.String(FlagConfigFile), ref)
123140
if err != nil {
124-
errHandler(writer, http.StatusOK, err)
141+
errHandler(ctx, w, http.StatusOK, fmt.Errorf("could not read remote config file: %w", err))
125142

126143
return
127144
}
128145

129146
// Parse the file
130147
cfg, err := config.ParseFile(file)
131148
if err != nil {
132-
errHandler(writer, http.StatusOK, err)
149+
errHandler(ctx, w, http.StatusOK, fmt.Errorf("could not parse config file: %w", err))
133150

134151
return
135152
}
136153

137-
// Decode request payload
138-
var full any
139-
if err := json.NewDecoder(bytes.NewReader(body)).Decode(&full); err != nil {
140-
errHandler(writer, http.StatusInternalServerError, err)
154+
// Decode request payload into 'any' so we have all the details
155+
var fullEventPayload any
156+
if err := json.NewDecoder(bytes.NewReader(body)).Decode(&fullEventPayload); err != nil {
157+
errHandler(ctx, w, http.StatusInternalServerError, err)
141158

142159
return
143160
}
144161

145162
// Process the MR
146-
if err := ProcessMR(ctx, client, cfg, id, full); err != nil {
147-
errHandler(writer, http.StatusOK, err)
163+
if err := ProcessMR(ctx, client, cfg, id, fullEventPayload); err != nil {
164+
errHandler(ctx, w, http.StatusOK, err)
148165

149166
return
150167
}
151168

152-
writer.WriteHeader(http.StatusOK)
153-
writer.Write([]byte("OK"))
169+
w.WriteHeader(http.StatusOK)
170+
w.Write([]byte("OK"))
154171
})
155172

156173
server := &http.Server{
157-
Addr: "0.0.0.0:3000",
174+
Addr: cCtx.String(FlagServerListen),
158175
Handler: http.Handler(mux),
159176
ReadTimeout: 5 * time.Second,
160177
WriteTimeout: 5 * time.Second,

cmd/conventions.go

+1
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ const (
77
FlagSCMBaseURL = "base-url"
88
FlagMergeRequestID = "id"
99
FlagWebhookSecret = "webhook-secret"
10+
FlagServerListen = "listen-port"
1011
)

main.go

+8
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,14 @@ func main() {
100100
"SCM_ENGINE_WEBHOOK_SECRET",
101101
},
102102
},
103+
&cli.StringFlag{
104+
Name: cmd.FlagServerListen,
105+
Usage: "Port the HTTP server should listen on",
106+
Value: "0.0.0.0:3000",
107+
EnvVars: []string{
108+
"SCM_ENGINE_LISTEN",
109+
},
110+
},
103111
},
104112
},
105113
},

0 commit comments

Comments
 (0)