feat: migrate receiver to Fuego framework with OpenAPI generation
All checks were successful
ci / ci (push) Successful in 2m2s
ci / goreleaser (push) Successful in 2m29s

Replace net/http handlers with Fuego framework for automatic OpenAPI 3.0
spec generation. Add generated Go client package, OpenAPI extraction
script, and update Makefile with separate build/run targets for both
binaries.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Manuel Ganter 2026-02-18 11:12:14 +01:00
parent 479c13f596
commit bc9d0dd8ea
No known key found for this signature in database
11 changed files with 2245 additions and 252 deletions

665
docs/openapi.json Normal file
View file

@ -0,0 +1,665 @@
{
"components": {
"schemas": {
"HTTPError": {
"description": "HTTPError schema",
"properties": {
"detail": {
"description": "Human readable error message",
"nullable": true,
"type": "string"
},
"errors": {
"items": {
"nullable": true,
"properties": {
"more": {
"additionalProperties": {
"description": "Additional information about the error",
"nullable": true
},
"description": "Additional information about the error",
"nullable": true,
"type": "object"
},
"name": {
"description": "For example, name of the parameter that caused the error",
"type": "string"
},
"reason": {
"description": "Human readable error message",
"type": "string"
}
},
"type": "object"
},
"nullable": true,
"type": "array"
},
"instance": {
"nullable": true,
"type": "string"
},
"status": {
"description": "HTTP status code",
"example": 403,
"nullable": true,
"type": "integer"
},
"title": {
"description": "Short title of the error",
"nullable": true,
"type": "string"
},
"type": {
"description": "URL of the error type. Can be used to lookup the error in a documentation",
"nullable": true,
"type": "string"
}
},
"type": "object"
},
"HealthResponse": {
"description": "HealthResponse schema",
"properties": {
"status": {
"type": "string"
}
},
"type": "object"
},
"MetricCreatedResponse": {
"description": "MetricCreatedResponse schema",
"properties": {
"id": {
"minimum": 0,
"type": "integer"
},
"status": {
"type": "string"
}
},
"type": "object"
},
"MetricResponse": {
"description": "MetricResponse schema",
"properties": {
"id": {
"minimum": 0,
"type": "integer"
},
"job": {
"type": "string"
},
"organization": {
"type": "string"
},
"payload": {},
"received_at": {
"format": "date-time",
"type": "string"
},
"repository": {
"type": "string"
},
"run_id": {
"type": "string"
},
"workflow": {
"type": "string"
}
},
"type": "object"
},
"SizingResponse": {
"description": "SizingResponse schema",
"properties": {
"containers": {
"items": {
"properties": {
"cpu": {
"properties": {
"limit": {
"type": "string"
},
"request": {
"type": "string"
}
},
"type": "object"
},
"memory": {
"properties": {
"limit": {
"type": "string"
},
"request": {
"type": "string"
}
},
"type": "object"
},
"name": {
"type": "string"
}
},
"type": "object"
},
"type": "array"
},
"meta": {
"properties": {
"buffer_percent": {
"type": "integer"
},
"cpu_percentile": {
"type": "string"
},
"runs_analyzed": {
"type": "integer"
}
},
"type": "object"
},
"total": {
"properties": {
"cpu": {
"properties": {
"limit": {
"type": "string"
},
"request": {
"type": "string"
}
},
"type": "object"
},
"memory": {
"properties": {
"limit": {
"type": "string"
},
"request": {
"type": "string"
}
},
"type": "object"
}
},
"type": "object"
}
},
"type": "object"
},
"TokenRequest": {
"description": "TokenRequest schema",
"properties": {
"job": {
"type": "string"
},
"organization": {
"type": "string"
},
"repository": {
"type": "string"
},
"workflow": {
"type": "string"
}
},
"type": "object"
},
"TokenResponse": {
"description": "TokenResponse schema",
"properties": {
"token": {
"type": "string"
}
},
"type": "object"
},
"unknown-interface": {
"description": "unknown-interface schema"
}
}
},
"info": {
"contact": {
"name": "API Support",
"url": "https://edp.buildth.ing/DevFW-CICD/forgejo-runner-sizer"
},
"description": "HTTP service that receives and stores CI/CD resource metrics from collectors, providing query and sizing recommendation APIs.",
"license": {
"name": "Apache 2.0",
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
},
"title": "Forgejo Runner Resource Collector API",
"version": "1.0.0"
},
"openapi": "3.1.0",
"paths": {
"/api/v1/metrics": {
"post": {
"description": "#### Controller: \n\n`edp.buildth.ing/DevFW-CICD/forgejo-runner-sizer/internal/receiver.(*Handler).ReceiveMetrics`\n\n#### Middlewares:\n\n- `github.com/go-fuego/fuego.defaultLogger.middleware`\n\n---\n\n",
"operationId": "POST_/api/v1/metrics",
"parameters": [
{
"in": "header",
"name": "Accept",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/MetricCreatedResponse"
}
},
"application/xml": {
"schema": {
"$ref": "#/components/schemas/MetricCreatedResponse"
}
}
},
"description": "OK"
},
"400": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPError"
}
},
"application/xml": {
"schema": {
"$ref": "#/components/schemas/HTTPError"
}
}
},
"description": "Bad Request _(validation or deserialization error)_"
},
"500": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPError"
}
},
"application/xml": {
"schema": {
"$ref": "#/components/schemas/HTTPError"
}
}
},
"description": "Internal Server Error _(panics)_"
},
"default": {
"description": ""
}
},
"summary": "receive metrics",
"tags": [
"api/v1"
]
}
},
"/api/v1/metrics/repo/{org}/{repo}/{workflow}/{job}": {
"get": {
"description": "#### Controller: \n\n`edp.buildth.ing/DevFW-CICD/forgejo-runner-sizer/internal/receiver.(*Handler).GetMetricsByWorkflowJob`\n\n#### Middlewares:\n\n- `github.com/go-fuego/fuego.defaultLogger.middleware`\n- `edp.buildth.ing/DevFW-CICD/forgejo-runner-sizer/internal/receiver.(*Handler).requireReadToken`\n\n---\n\n",
"operationId": "GET_/api/v1/metrics/repo/:org/:repo/:workflow/:job",
"parameters": [
{
"in": "header",
"name": "Accept",
"schema": {
"type": "string"
}
},
{
"in": "path",
"name": "org",
"required": true,
"schema": {
"type": "string"
}
},
{
"in": "path",
"name": "repo",
"required": true,
"schema": {
"type": "string"
}
},
{
"in": "path",
"name": "workflow",
"required": true,
"schema": {
"type": "string"
}
},
{
"in": "path",
"name": "job",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"items": {
"$ref": "#/components/schemas/MetricResponse"
},
"type": "array"
}
},
"application/xml": {
"schema": {
"items": {
"$ref": "#/components/schemas/MetricResponse"
},
"type": "array"
}
}
},
"description": "OK"
},
"400": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPError"
}
},
"application/xml": {
"schema": {
"$ref": "#/components/schemas/HTTPError"
}
}
},
"description": "Bad Request _(validation or deserialization error)_"
},
"500": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPError"
}
},
"application/xml": {
"schema": {
"$ref": "#/components/schemas/HTTPError"
}
}
},
"description": "Internal Server Error _(panics)_"
},
"default": {
"description": ""
}
},
"summary": "get metrics by workflow job",
"tags": [
"api/v1"
]
}
},
"/api/v1/sizing/repo/{org}/{repo}/{workflow}/{job}": {
"get": {
"description": "#### Controller: \n\n`edp.buildth.ing/DevFW-CICD/forgejo-runner-sizer/internal/receiver.(*Handler).GetSizing`\n\n#### Middlewares:\n\n- `github.com/go-fuego/fuego.defaultLogger.middleware`\n- `edp.buildth.ing/DevFW-CICD/forgejo-runner-sizer/internal/receiver.(*Handler).requireReadToken`\n\n---\n\n",
"operationId": "GET_/api/v1/sizing/repo/:org/:repo/:workflow/:job",
"parameters": [
{
"in": "header",
"name": "Accept",
"schema": {
"type": "string"
}
},
{
"in": "path",
"name": "org",
"required": true,
"schema": {
"type": "string"
}
},
{
"in": "path",
"name": "repo",
"required": true,
"schema": {
"type": "string"
}
},
{
"in": "path",
"name": "workflow",
"required": true,
"schema": {
"type": "string"
}
},
{
"in": "path",
"name": "job",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SizingResponse"
}
},
"application/xml": {
"schema": {
"$ref": "#/components/schemas/SizingResponse"
}
}
},
"description": "OK"
},
"400": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPError"
}
},
"application/xml": {
"schema": {
"$ref": "#/components/schemas/HTTPError"
}
}
},
"description": "Bad Request _(validation or deserialization error)_"
},
"500": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPError"
}
},
"application/xml": {
"schema": {
"$ref": "#/components/schemas/HTTPError"
}
}
},
"description": "Internal Server Error _(panics)_"
},
"default": {
"description": ""
}
},
"summary": "get sizing",
"tags": [
"api/v1"
]
}
},
"/api/v1/token": {
"post": {
"description": "#### Controller: \n\n`edp.buildth.ing/DevFW-CICD/forgejo-runner-sizer/internal/receiver.(*Handler).GenerateToken`\n\n#### Middlewares:\n\n- `github.com/go-fuego/fuego.defaultLogger.middleware`\n- `edp.buildth.ing/DevFW-CICD/forgejo-runner-sizer/internal/receiver.(*Handler).requireReadToken`\n\n---\n\n",
"operationId": "POST_/api/v1/token",
"parameters": [
{
"in": "header",
"name": "Accept",
"schema": {
"type": "string"
}
}
],
"requestBody": {
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/TokenRequest"
}
}
},
"description": "Request body for receiver.TokenRequest",
"required": true
},
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/TokenResponse"
}
},
"application/xml": {
"schema": {
"$ref": "#/components/schemas/TokenResponse"
}
}
},
"description": "OK"
},
"400": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPError"
}
},
"application/xml": {
"schema": {
"$ref": "#/components/schemas/HTTPError"
}
}
},
"description": "Bad Request _(validation or deserialization error)_"
},
"500": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPError"
}
},
"application/xml": {
"schema": {
"$ref": "#/components/schemas/HTTPError"
}
}
},
"description": "Internal Server Error _(panics)_"
},
"default": {
"description": ""
}
},
"summary": "generate token",
"tags": [
"api/v1"
]
}
},
"/health": {
"get": {
"description": "#### Controller: \n\n`edp.buildth.ing/DevFW-CICD/forgejo-runner-sizer/internal/receiver.(*Handler).Health`\n\n#### Middlewares:\n\n- `github.com/go-fuego/fuego.defaultLogger.middleware`\n\n---\n\n",
"operationId": "GET_/health",
"parameters": [
{
"in": "header",
"name": "Accept",
"schema": {
"type": "string"
}
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HealthResponse"
}
},
"application/xml": {
"schema": {
"$ref": "#/components/schemas/HealthResponse"
}
}
},
"description": "OK"
},
"400": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPError"
}
},
"application/xml": {
"schema": {
"$ref": "#/components/schemas/HTTPError"
}
}
},
"description": "Bad Request _(validation or deserialization error)_"
},
"500": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/HTTPError"
}
},
"application/xml": {
"schema": {
"$ref": "#/components/schemas/HTTPError"
}
}
},
"description": "Internal Server Error _(panics)_"
},
"default": {
"description": ""
}
},
"summary": "health"
}
}
}
}