gitea/routers/api/v2/health.go
logikonline dfc94f6408
Some checks failed
Build and Release / Build Binaries (amd64, darwin) (push) Blocked by required conditions
Build and Release / Build Binaries (amd64, linux) (push) Blocked by required conditions
Build and Release / Build Binaries (amd64, windows) (push) Blocked by required conditions
Build and Release / Build Binaries (arm64, darwin) (push) Blocked by required conditions
Build and Release / Build Binaries (arm64, linux) (push) Blocked by required conditions
Build and Release / Build Docker Image (push) Blocked by required conditions
Build and Release / Create Release (push) Blocked by required conditions
Build and Release / Lint and Test (push) Has been cancelled
fix: resolve all golangci-lint errors in v2 API
- Replace encoding/json with modules/json (depguard)
- Add error handling for json.Unmarshal and WriteItem calls (errcheck)
- Use slices.Contains instead of manual loops (modernize)
- Use any instead of interface{} (modernize)
- Use min/max built-in functions (modernize)
- Use strings.FieldsSeq and strings.SplitSeq (modernize)
- Use range over int for loops (modernize)
- Use http.MethodOptions constant (usestdlibvars)
- Use tagged switch statements (staticcheck)
- Use += and /= operators (gocritic)
- Fix gofumpt formatting issues
- Remove unused streamLargeFile function
- Remove unused primaryLang parameter

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-09 15:49:52 -05:00

165 lines
4.8 KiB
Go

// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package v2
import (
"net/http"
"code.gitea.io/gitea/modules/health"
"code.gitea.io/gitea/services/context"
)
// HealthCheckResponse represents the health check response
type HealthCheckResponse struct {
Status string `json:"status"`
Version string `json:"version"`
Uptime float64 `json:"uptime_seconds"`
Timestamp string `json:"timestamp"`
Components map[string]*ComponentStatus `json:"components"`
System *health.SystemInfo `json:"system,omitempty"`
}
// ComponentStatus represents a component's health status
type ComponentStatus struct {
Name string `json:"name"`
Status string `json:"status"`
Message string `json:"message,omitempty"`
DurationMs float64 `json:"duration_ms"`
LastChecked string `json:"last_checked"`
Metadata map[string]any `json:"metadata,omitempty"`
}
// HealthCheck performs a comprehensive health check
// @Summary Health check
// @Description Returns the health status of all components
// @Tags health
// @Produce json
// @Param detailed query bool false "Include system information"
// @Success 200 {object} HealthCheckResponse
// @Router /health [get]
func HealthCheck(ctx *context.APIContext) {
includeSystem := ctx.FormBool("detailed")
manager := health.GetManager()
result := manager.Check(ctx.Req.Context(), includeSystem)
// Convert to response format
components := make(map[string]*ComponentStatus)
for name, check := range result.Components {
components[name] = &ComponentStatus{
Name: check.Name,
Status: string(check.Status),
Message: check.Message,
DurationMs: float64(check.Duration.Milliseconds()),
LastChecked: check.LastChecked.Format("2006-01-02T15:04:05Z07:00"),
Metadata: check.Metadata,
}
}
response := HealthCheckResponse{
Status: string(result.Status),
Version: result.Version,
Uptime: result.Uptime.Seconds(),
Timestamp: result.Timestamp.Format("2006-01-02T15:04:05Z07:00"),
Components: components,
System: result.System,
}
// Set status code based on health
var statusCode int
switch result.Status {
case health.StatusUnhealthy:
statusCode = http.StatusServiceUnavailable
case health.StatusDegraded:
statusCode = http.StatusOK // Still OK but degraded
default:
statusCode = http.StatusOK
}
ctx.JSON(statusCode, response)
}
// LivenessCheck performs a simple liveness check
// @Summary Liveness probe
// @Description Returns OK if the service is running
// @Tags health
// @Produce json
// @Success 200 {object} map[string]any
// @Router /health/live [get]
func LivenessCheck(ctx *context.APIContext) {
manager := health.GetManager()
check := manager.LivenessCheck()
ctx.JSON(http.StatusOK, map[string]any{
"status": string(check.Status),
"message": check.Message,
})
}
// ReadinessCheck performs a readiness check
// @Summary Readiness probe
// @Description Returns OK if the service is ready to handle requests
// @Tags health
// @Produce json
// @Success 200 {object} map[string]any
// @Success 503 {object} map[string]any
// @Router /health/ready [get]
func ReadinessCheck(ctx *context.APIContext) {
manager := health.GetManager()
result := manager.ReadinessCheck(ctx.Req.Context())
response := map[string]any{
"status": string(result.Status),
"timestamp": result.Timestamp.Format("2006-01-02T15:04:05Z07:00"),
}
if result.Status == health.StatusUnhealthy {
ctx.JSON(http.StatusServiceUnavailable, response)
return
}
ctx.JSON(http.StatusOK, response)
}
// ComponentHealthCheck checks a specific component
// @Summary Component health check
// @Description Returns the health status of a specific component
// @Tags health
// @Produce json
// @Param component path string true "Component name"
// @Success 200 {object} ComponentStatus
// @Failure 404 {object} map[string]any
// @Router /health/component/{component} [get]
func ComponentHealthCheck(ctx *context.APIContext) {
component := ctx.PathParam("component")
manager := health.GetManager()
check, found := manager.CheckSingle(ctx.Req.Context(), component)
if !found {
ctx.JSON(http.StatusNotFound, map[string]any{
"code": "COMPONENT_NOT_FOUND",
"message": "Health check component not found",
"component": component,
})
return
}
response := ComponentStatus{
Name: check.Name,
Status: string(check.Status),
Message: check.Message,
DurationMs: float64(check.Duration.Milliseconds()),
LastChecked: check.LastChecked.Format("2006-01-02T15:04:05Z07:00"),
Metadata: check.Metadata,
}
statusCode := http.StatusOK
if check.Status == health.StatusUnhealthy {
statusCode = http.StatusServiceUnavailable
}
ctx.JSON(statusCode, response)
}