fix: Expose pipeline errors in API response

- Add PipelineErrorResponse struct to handler
- Add Errors field to PipelineResponse struct
- Add mapPipelineErrors helper function
- Include errors in both ListPipelines and GetPipeline responses

Root cause of CI failures: Woodpecker trust level doesn't allow privileged mode
for docker steps. Errors were being returned by Woodpecker but not exposed.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
jordan 2026-01-28 18:36:10 -07:00
parent 823d45f22c
commit a93fe57487

View File

@ -8,9 +8,17 @@ import (
"time" "time"
"github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5"
"github.com/orchard9/rdev/internal/domain"
"github.com/orchard9/rdev/pkg/api" "github.com/orchard9/rdev/pkg/api"
) )
// PipelineErrorResponse is the JSON representation of a pipeline error.
type PipelineErrorResponse struct {
Type string `json:"type"`
Message string `json:"message"`
IsWarning bool `json:"is_warning"`
}
// PipelineResponse is the JSON representation of a CI pipeline. // PipelineResponse is the JSON representation of a CI pipeline.
type PipelineResponse struct { type PipelineResponse struct {
ID int64 `json:"id"` ID int64 `json:"id"`
@ -23,6 +31,7 @@ type PipelineResponse struct {
Author string `json:"author"` Author string `json:"author"`
Started string `json:"started,omitempty"` Started string `json:"started,omitempty"`
Finished string `json:"finished,omitempty"` Finished string `json:"finished,omitempty"`
Errors []PipelineErrorResponse `json:"errors,omitempty"`
} }
// ListPipelines returns recent CI pipeline executions for a project. // ListPipelines returns recent CI pipeline executions for a project.
@ -61,6 +70,7 @@ func (h *InfrastructureHandler) ListPipelines(w http.ResponseWriter, r *http.Req
Author: p.Author, Author: p.Author,
Started: formatTime(p.Started), Started: formatTime(p.Started),
Finished: formatTime(p.Finished), Finished: formatTime(p.Finished),
Errors: mapPipelineErrors(p.Errors),
} }
} }
@ -108,6 +118,7 @@ func (h *InfrastructureHandler) GetPipeline(w http.ResponseWriter, r *http.Reque
Author: p.Author, Author: p.Author,
Started: formatTime(p.Started), Started: formatTime(p.Started),
Finished: formatTime(p.Finished), Finished: formatTime(p.Finished),
Errors: mapPipelineErrors(p.Errors),
}) })
} }
@ -118,3 +129,19 @@ func formatTime(t time.Time) string {
} }
return t.Format(time.RFC3339) return t.Format(time.RFC3339)
} }
// mapPipelineErrors converts domain pipeline errors to response format.
func mapPipelineErrors(errors []domain.CIPipelineError) []PipelineErrorResponse {
if len(errors) == 0 {
return nil
}
resp := make([]PipelineErrorResponse, len(errors))
for i, e := range errors {
resp[i] = PipelineErrorResponse{
Type: e.Type,
Message: e.Message,
IsWarning: e.IsWarning,
}
}
return resp
}