oto/services/core/internal/httpserver/execution_handlers.go
toki b318da195f refactor(core): httpserver 파일을 핸들러 단위로 분리한다
단일 server.go에 집중되어 있던 HTTP 라우팅 로직을 실행/작업/런너 핸들러 파일로 분리해 책임 경계를 더 선명하게 하며, milestone 기록 파일의 보관 위치도 정리한다.
2026-06-08 20:58:27 +09:00

140 lines
4 KiB
Go

package httpserver
import (
"encoding/json"
"net/http"
"strings"
"github.com/toki/oto/services/core/internal/cicdstate"
)
func handleGetExecution(store *cicdstate.Store) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
execID := r.PathValue("id")
if execID == "" {
parts := strings.Split(r.URL.Path, "/")
if len(parts) >= 5 {
execID = parts[4]
}
}
if execID == "" {
writeResponse(w, http.StatusBadRequest, map[string]string{"error": "missing execution id"})
return
}
exec, err := store.GetExecution(execID)
if err != nil {
writeResponse(w, http.StatusNotFound, map[string]string{"error": "execution not found"})
return
}
writeResponse(w, http.StatusOK, execToJSON(exec))
}
}
func handleAppendLog(store *cicdstate.Store) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
writeResponse(w, http.StatusMethodNotAllowed, map[string]string{"error": "method not allowed"})
return
}
execID := r.PathValue("id")
if execID == "" {
parts := strings.Split(r.URL.Path, "/")
if len(parts) >= 5 {
execID = parts[4]
}
}
if execID == "" {
writeResponse(w, http.StatusBadRequest, map[string]string{"error": "missing execution id"})
return
}
var req struct {
Line string `json:"line"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil || req.Line == "" {
writeResponse(w, http.StatusBadRequest, map[string]string{"error": "line is required"})
return
}
if err := store.AppendLog(execID, req.Line); err != nil {
writeResponse(w, http.StatusNotFound, map[string]string{"error": "execution not found"})
return
}
writeResponse(w, http.StatusCreated, map[string]string{"status": "accepted"})
}
}
func handleGetLogs(store *cicdstate.Store) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
execID := r.PathValue("id")
if execID == "" {
parts := strings.Split(r.URL.Path, "/")
if len(parts) >= 5 {
execID = parts[4]
}
}
if execID == "" {
writeResponse(w, http.StatusBadRequest, map[string]string{"error": "missing execution id"})
return
}
logs, err := store.GetLogs(execID)
if err != nil {
writeResponse(w, http.StatusNotFound, map[string]string{"error": "execution not found"})
return
}
writeResponse(w, http.StatusOK, logsToJSON(logs))
}
}
func handleAppendArtifact(store *cicdstate.Store) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
writeResponse(w, http.StatusMethodNotAllowed, map[string]string{"error": "method not allowed"})
return
}
execID := r.PathValue("id")
if execID == "" {
parts := strings.Split(r.URL.Path, "/")
if len(parts) >= 5 {
execID = parts[4]
}
}
if execID == "" {
writeResponse(w, http.StatusBadRequest, map[string]string{"error": "missing execution id"})
return
}
var req struct {
Name string `json:"name"`
Path string `json:"path"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil || req.Name == "" || req.Path == "" {
writeResponse(w, http.StatusBadRequest, map[string]string{"error": "name and path are required"})
return
}
if err := store.AppendArtifact(execID, req.Name, req.Path); err != nil {
writeResponse(w, http.StatusNotFound, map[string]string{"error": "execution not found"})
return
}
writeResponse(w, http.StatusCreated, map[string]string{"status": "accepted"})
}
}
func handleGetArtifacts(store *cicdstate.Store) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
execID := r.PathValue("id")
if execID == "" {
parts := strings.Split(r.URL.Path, "/")
if len(parts) >= 5 {
execID = parts[4]
}
}
if execID == "" {
writeResponse(w, http.StatusBadRequest, map[string]string{"error": "missing execution id"})
return
}
artifacts, err := store.GetArtifacts(execID)
if err != nil {
writeResponse(w, http.StatusNotFound, map[string]string{"error": "execution not found"})
return
}
writeResponse(w, http.StatusOK, artifactsToJSON(artifacts))
}
}