refactor: serve the api specs as plain json (#38715)

The api specs were Go templates whose committed form was not a valid
swagger document, so `swagger-validate`, `generate-openapi.go` and
`.spectral.yaml` each worked around it. They are now plain json,
substituted at serve time.

Renaming them off `.tmpl` also stops `make fmt` rewriting them, which
used to bump their mtime and silently skip the next `make
generate-swagger`.

Also enables stricter spectral linting: extends `lint-swagger` to the
OpenAPI 3 spec, turns on `openapi-tags`, `operation-singular-tag` and
`operation-tag-defined`, adds a top-level `tags` array with descriptions
to the swagger input, and drops the redundant `repository` tag from
`POST /user/repos`.

---------

Signed-off-by: silverwind <me@silverwind.io>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
Co-authored-by: Giteabot <teabot@gitea.io>
This commit is contained in:
silverwind
2026-07-31 16:16:27 +02:00
committed by GitHub
parent a3e7fe1f11
commit f0a95eebe3
16 changed files with 178 additions and 79 deletions
+1
View File
@@ -482,6 +482,7 @@ func OIDCWellKnown(ctx *context.Context) {
ctx.Data["OidcIssuer"] = jwtRegisteredClaims.Issuer // use the consistent issuer from the JWT registered claims
ctx.Data["OidcBaseUrl"] = strings.TrimSuffix(setting.AppURL, "/")
ctx.Data["SigningKeyMethodAlg"] = oauth2_provider.DefaultSigningKey.SigningMethod().Alg()
// FIXME: no need to use a Golang template to render JSON, just build the JSON response directly in the future
ctx.JSONTemplate("user/auth/oidc_wellknown")
}
+22 -10
View File
@@ -5,21 +5,33 @@ package web
import (
"html/template"
"net/http"
"strings"
"gitea.dev/modules/setting"
"gitea.dev/modules/templates"
"gitea.dev/modules/util"
"gitea.dev/services/context"
)
// SwaggerV1Json render swagger v1 json
func SwaggerV1Json(ctx *context.Context) {
ctx.Data["SwaggerAppVer"] = template.HTML(template.JSEscapeString(setting.AppVer))
ctx.Data["SwaggerAppSubUrl"] = setting.AppSubURL // it is JS-safe
ctx.JSONTemplate("swagger/v1_json")
func swaggerJsonServe(ctx *context.Context, file string) {
buf, err := templates.AssetFS().ReadFile(file)
if err != nil {
ctx.HTTPError(http.StatusInternalServerError, "unable to read api json file: "+file)
return
}
r := strings.NewReplacer(
"0.0.0+GITEA-API-APP-VERSION", template.JSEscapeString(setting.AppVer),
"/GITEA-API-APP-SUBURL/", template.JSEscapeString(setting.AppSubURL)+"/",
)
ctx.Resp.Header().Set("Content-Type", "application/json")
_, _ = r.WriteString(ctx.Resp, util.UnsafeBytesToString(buf))
}
// OpenAPI3Json render OpenAPI 3.0 json (auto-converted from Swagger 2.0)
func OpenAPI3Json(ctx *context.Context) {
ctx.Data["SwaggerAppVer"] = template.HTML(template.JSEscapeString(setting.AppVer))
ctx.Data["SwaggerAppSubUrl"] = setting.AppSubURL // it is JS-safe
ctx.JSONTemplate("swagger/v1_openapi3_json")
func SwaggerV1Json(ctx *context.Context) {
swaggerJsonServe(ctx, "swagger/v1-swagger.generated.json")
}
func OpenAPI3Json(ctx *context.Context) {
swaggerJsonServe(ctx, "swagger/v1-openapi3.generated.json")
}