fix: enable strict mode for swagger generation & upgrade swag (#21975)

Adds a Go wrapper (`scripts/apidocgen/swaginit/main.go`) that calls
swag's Go API with `Strict: true`. The `--strict` flag isn't available
in swag's CLI in any version, so the wrapper is the only way to enable
it.

Also upgrades swag from v1.16.2 to v1.16.6 (better generics support,
precise numeric formats, `x-enum-descriptions`, CVE-2024-45338 fix).
This commit is contained in:
Marcin Tojek
2026-02-06 13:04:35 +01:00
committed by GitHub
parent 193e4bd73b
commit 456c0bced9
7 changed files with 97 additions and 25 deletions
+1
View File
@@ -938,6 +938,7 @@ coderd/apidoc/.gen: \
coderd/rbac/object_gen.go \
.swaggo \
scripts/apidocgen/generate.sh \
scripts/apidocgen/swaginit/main.go \
$(wildcard scripts/apidocgen/postprocess/*) \
$(wildcard scripts/apidocgen/markdown-template/*)
./scripts/apidocgen/generate.sh
+26 -8
View File
@@ -14901,6 +14901,16 @@ const docTemplate = `{
"ExperimentWorkspaceSharing": "Enables updating workspace ACLs for sharing with users and groups.",
"ExperimentWorkspaceUsage": "Enables the new workspace usage tracking."
},
"x-enum-descriptions": [
"This isn't used for anything.",
"This should not be taken out of experiments until we have redesigned the feature.",
"Sends notifications via SMTP and webhooks following certain events.",
"Enables the new workspace usage tracking.",
"Enables web push notifications through the browser.",
"Enables OAuth2 provider functionality.",
"Enables the MCP HTTP server functionality.",
"Enables updating workspace ACLs for sharing with users and groups."
],
"x-enum-varnames": [
"ExperimentExample",
"ExperimentAutoFillParameters",
@@ -21495,10 +21505,12 @@ const docTemplate = `{
"type": "object",
"properties": {
"p50": {
"type": "number"
"type": "number",
"format": "float64"
},
"p95": {
"type": "number"
"type": "number",
"format": "float64"
}
}
},
@@ -21884,10 +21896,12 @@ const docTemplate = `{
]
},
"recv": {
"type": "integer"
"type": "integer",
"format": "int64"
},
"sent": {
"type": "integer"
"type": "integer",
"format": "int64"
}
}
},
@@ -22514,21 +22528,24 @@ const docTemplate = `{
"description": "keyed by DERP Region ID",
"type": "object",
"additionalProperties": {
"type": "integer"
"type": "integer",
"format": "int64"
}
},
"regionV4Latency": {
"description": "keyed by DERP Region ID",
"type": "object",
"additionalProperties": {
"type": "integer"
"type": "integer",
"format": "int64"
}
},
"regionV6Latency": {
"description": "keyed by DERP Region ID",
"type": "object",
"additionalProperties": {
"type": "integer"
"type": "integer",
"format": "int64"
}
},
"udp": {
@@ -22771,7 +22788,8 @@ const docTemplate = `{
"description": "RegionScore scales latencies of DERP regions by a given scaling\nfactor when determining which region to use as the home\n(\"preferred\") DERP. Scores in the range (0, 1) will cause this\nregion to be proportionally more preferred, and scores in the range\n(1, ∞) will penalize a region.\n\nIf a region is not present in this map, it is treated as having a\nscore of 1.0.\n\nScores should not be 0 or negative; such scores will be ignored.\n\nA nil map means no change from the previous value (if any); an empty\nnon-nil map can be sent to reset all scores back to 1.0.",
"type": "object",
"additionalProperties": {
"type": "number"
"type": "number",
"format": "float64"
}
}
}
+26 -8
View File
@@ -13442,6 +13442,16 @@
"ExperimentWorkspaceSharing": "Enables updating workspace ACLs for sharing with users and groups.",
"ExperimentWorkspaceUsage": "Enables the new workspace usage tracking."
},
"x-enum-descriptions": [
"This isn't used for anything.",
"This should not be taken out of experiments until we have redesigned the feature.",
"Sends notifications via SMTP and webhooks following certain events.",
"Enables the new workspace usage tracking.",
"Enables web push notifications through the browser.",
"Enables OAuth2 provider functionality.",
"Enables the MCP HTTP server functionality.",
"Enables updating workspace ACLs for sharing with users and groups."
],
"x-enum-varnames": [
"ExperimentExample",
"ExperimentAutoFillParameters",
@@ -19744,10 +19754,12 @@
"type": "object",
"properties": {
"p50": {
"type": "number"
"type": "number",
"format": "float64"
},
"p95": {
"type": "number"
"type": "number",
"format": "float64"
}
}
},
@@ -20112,10 +20124,12 @@
]
},
"recv": {
"type": "integer"
"type": "integer",
"format": "int64"
},
"sent": {
"type": "integer"
"type": "integer",
"format": "int64"
}
}
},
@@ -20698,21 +20712,24 @@
"description": "keyed by DERP Region ID",
"type": "object",
"additionalProperties": {
"type": "integer"
"type": "integer",
"format": "int64"
}
},
"regionV4Latency": {
"description": "keyed by DERP Region ID",
"type": "object",
"additionalProperties": {
"type": "integer"
"type": "integer",
"format": "int64"
}
},
"regionV6Latency": {
"description": "keyed by DERP Region ID",
"type": "object",
"additionalProperties": {
"type": "integer"
"type": "integer",
"format": "int64"
}
},
"udp": {
@@ -20949,7 +20966,8 @@
"description": "RegionScore scales latencies of DERP regions by a given scaling\nfactor when determining which region to use as the home\n(\"preferred\") DERP. Scores in the range (0, 1) will cause this\nregion to be proportionally more preferred, and scores in the range\n(1, ∞) will penalize a region.\n\nIf a region is not present in this map, it is treated as having a\nscore of 1.0.\n\nScores should not be 0 or negative; such scores will be ignored.\n\nA nil map means no change from the previous value (if any); an empty\nnon-nil map can be sent to reset all scores back to 1.0.",
"type": "object",
"additionalProperties": {
"type": "number"
"type": "number",
"format": "float64"
}
}
}
+1 -1
View File
@@ -176,7 +176,7 @@ require (
github.com/sqlc-dev/pqtype v0.3.0
github.com/stretchr/testify v1.11.1
github.com/swaggo/http-swagger/v2 v2.0.1
github.com/swaggo/swag v1.16.2
github.com/swaggo/swag v1.16.6
github.com/tidwall/gjson v1.18.0
github.com/u-root/u-root v0.14.0
github.com/unrolled/secure v1.17.0
+2 -2
View File
@@ -1851,8 +1851,8 @@ github.com/swaggo/files/v2 v2.0.0 h1:hmAt8Dkynw7Ssz46F6pn8ok6YmGZqHSVLZ+HQM7i0kw
github.com/swaggo/files/v2 v2.0.0/go.mod h1:24kk2Y9NYEJ5lHuCra6iVwkMjIekMCaFq/0JQj66kyM=
github.com/swaggo/http-swagger/v2 v2.0.1 h1:mNOBLxDjSNwCKlMxcErjjvct/xhc9t2KIO48xzz/V/k=
github.com/swaggo/http-swagger/v2 v2.0.1/go.mod h1:XYhrQVIKz13CxuKD4p4kvpaRB4jJ1/MlfQXVOE+CX8Y=
github.com/swaggo/swag v1.16.2 h1:28Pp+8DkQoV+HLzLx8RGJZXNGKbFqnuvSbAAtoxiY04=
github.com/swaggo/swag v1.16.2/go.mod h1:6YzXnDcpr0767iOejs318CwYkCQqyGer6BizOg03f+E=
github.com/swaggo/swag v1.16.6 h1:qBNcx53ZaX+M5dxVyTrgQ0PJ/ACK+NzhwcbieTt+9yI=
github.com/swaggo/swag v1.16.6/go.mod h1:ngP2etMK5a0P3QBizic5MEwpRmluJZPHjXcMoj4Xesg=
github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af h1:6yITBqGTE2lEeTPG04SN9W+iWHCRyHqlVYILiSXziwk=
github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af/go.mod h1:4F09kP5F+am0jAwlQLddpoMDM+iewkxxt6nxUQ5nq5o=
github.com/tailscale/certstore v0.1.1-0.20220316223106-78d6e1c49d8d h1:K3j02b5j2Iw1xoggN9B2DIEkhWGheqFOeDkdJdBrJI8=
+4 -6
View File
@@ -18,12 +18,10 @@ trap cleanup EXIT
log "Use temporary file: ${API_MD_TMP_FILE}"
pushd "${PROJECT_ROOT}"
go tool github.com/swaggo/swag/cmd/swag init \
--generalInfo="coderd.go" \
--dir="./coderd,./codersdk,./enterprise/coderd,./enterprise/wsproxy/wsproxysdk" \
--output="./coderd/apidoc" \
--outputTypes="go,json" \
--parseDependency=true
# Use our custom wrapper instead of "go tool swag init" to enable
# Strict mode, which turns duplicate-route warnings into hard errors.
# The upstream swag CLI does not expose a --strict flag.
go run "${APIDOCGEN_DIR}/swaginit/main.go"
popd
pushd "${APIDOCGEN_DIR}"
+37
View File
@@ -0,0 +1,37 @@
// Package main wraps swag init with Strict mode enabled.
//
// The upstream swag CLI (v1.16.2) does not expose a --strict
// flag, so warnings about duplicate routes are silently
// ignored. This wrapper calls the Go API directly with
// Strict: true, turning those warnings into hard errors.
package main
import (
"log"
"os"
"github.com/swaggo/swag/gen"
)
func main() {
logger := log.New(os.Stdout, "", log.LstdFlags)
err := gen.New().Build(&gen.Config{
SearchDir: "./coderd,./codersdk,./enterprise/coderd,./enterprise/wsproxy/wsproxysdk",
MainAPIFile: "coderd.go",
OutputDir: "./coderd/apidoc",
OutputTypes: []string{"go", "json"},
ParseDependency: 1,
Strict: true,
OverridesFile: gen.DefaultOverridesFile,
ParseGoList: true,
ParseDepth: 100,
CollectionFormat: "csv",
Debugger: logger,
LeftTemplateDelim: "{{",
RightTemplateDelim: "}}",
})
if err != nil {
log.Fatalf("swag init failed: %v", err)
}
}