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
- 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>
165 lines
4.8 KiB
Go
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)
|
|
}
|