From b05e96c6585d91cbaf560a2bafc68f1a7648e967 Mon Sep 17 00:00:00 2001 From: qwerty287 Date: Mon, 11 Nov 2024 06:35:08 +0000 Subject: [PATCH 1/3] Translated using Weblate (German) Currently translated at 100.0% (348 of 348 strings) Translation: Woodpecker CI/UI Translate-URL: http://translate.woodpecker-ci.org/projects/woodpecker-ci/ui/de/ --- web/src/assets/locales/de.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/src/assets/locales/de.json b/web/src/assets/locales/de.json index 5992761c6..d385dd3e9 100644 --- a/web/src/assets/locales/de.json +++ b/web/src/assets/locales/de.json @@ -388,8 +388,8 @@ }, "general": "Allgemein", "netrc_only_trusted": { - "desc": "Netrc-Zugangsdaten nur in vertrauenswürdigen Containern bereitstellen (empfohlen).", - "netrc_only_trusted": "Netrc-Zugangsdaten nur in vertrauenswürdigen Containern zum Klonen bereitstellen" + "desc": "Wenn aktiviert, werden Netrc-Zugangsdaten für Git nur für vertrauenswürdige Plugin zum Klonen, die in `WOODPECKER_PLUGINS_TRUSTED_CLONE` gesetzt sind, zur Verfügung gestellt. Ansonsten erhalten alle Plugins zum Klonen die Netrc-Zugangsdaten. Diese Option hat keinen Effekt auf Schritte, die nicht zum Klonen da sind.", + "netrc_only_trusted": "Netrc-Zugangsdaten nur in vertrauenswürdigen Plugins zum Klonen bereitstellen" }, "pipeline_path": { "default": "Standardmäßig: .woodpecker/*.{'{yaml,yml}'} -> .woodpecker.yaml -> .woodpecker.yml", From 8e0aac4cabf8a00149313e862cccdb9391113aec Mon Sep 17 00:00:00 2001 From: Kirill Isakov Date: Sun, 10 Nov 2024 22:24:23 +0000 Subject: [PATCH 2/3] Translated using Weblate (Russian) Currently translated at 100.0% (348 of 348 strings) Translation: Woodpecker CI/UI Translate-URL: http://translate.woodpecker-ci.org/projects/woodpecker-ci/ui/ru/ --- web/src/assets/locales/ru.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/web/src/assets/locales/ru.json b/web/src/assets/locales/ru.json index 78c0bc7b0..f56447311 100644 --- a/web/src/assets/locales/ru.json +++ b/web/src/assets/locales/ru.json @@ -271,10 +271,10 @@ "log_download_error": "Произошла ошибка при скачивании файла журнала", "log_title": "Журнал шага", "no_files": "Никакие файлы не были изменены.", - "no_pipeline_steps": "Нет доступных шагов конвеера!", - "no_pipelines": "Ни один конвеер ещё не запущен.", + "no_pipeline_steps": "Нет доступных шагов конвейера!!", + "no_pipelines": "Ни один конвейер ещё не запущен.", "pipeline": "Конвейер №{pipelineId}", - "pipelines_for": "Конвееры для ветви «{branch}»", + "pipelines_for": "Конвейеры для ветви «{branch}»", "pipelines_for_pr": "Конвейер для запроса на слияние №{index}", "protected": { "approve": "Подтвердить", @@ -387,8 +387,8 @@ }, "general": "Главное", "netrc_only_trusted": { - "desc": "Вводите учетные данные netrc только внутри контейнеров, которым вы доверяете (рекомендуется).", - "netrc_only_trusted": "Вводите учетные данные netrc только внутри контейнеров, которым вы доверяете" + "desc": "Если включено, учётные данные netrc будут доступны только доверенным плагинам клонирования кода, перечисленным в `WOODPECKER_PLUGINS_TRUSTED_CLONE`. В противном случае, данные netrc будут доступны всем плагинам клонирования. Параметр не влияет на другие шаги, отличные от клонирования.", + "netrc_only_trusted": "Передавать учётные данные netrc только доверенным плагинам клонирования" }, "pipeline_path": { "default": "По умолчанию: .woodpecker/*.{'{yaml,yml}'} -> .woodpecker.yaml -> .woodpecker.yml", From 07c8765b72110a71e38c7d1e5491c39148e8830f Mon Sep 17 00:00:00 2001 From: Anbraten <6918444+anbraten@users.noreply.github.com> Date: Sat, 23 Nov 2024 09:17:19 +0100 Subject: [PATCH 3/3] Cleanup openapi generation (#4331) Co-authored-by: oauth Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: 6543 <6543@obermui.de> --- .cspell.json | 3 +- .ecrc | 5 +- .gitignore | 3 + .woodpecker/test.yaml | 6 +- Makefile | 17 ++- cmd/server/main.go | 7 +- cmd/server/openapi.go | 38 +++++++ cmd/server/{docs => openapi}/docs.go | 39 +++---- ...pecker_docs_gen.go => openapi_json_gen.go} | 21 ++-- cmd/server/openapi_test.go | 14 +++ cmd/server/swagger.go | 39 ------- cmd/server/swagger_test.go | 14 --- .../{09-swagger.md => 09-openapi.md} | 12 +- docs/docusaurus.config.ts | 2 +- flake.nix | 2 +- go.mod | 27 +++-- go.sum | 105 ++++++++++++------ server/api/agent.go | 44 ++++---- server/api/forge.go | 16 +-- server/api/global_registry.go | 14 +-- server/api/org_registry.go | 14 +-- server/api/pipeline.go | 22 ++-- server/api/repo.go | 32 +++--- server/api/z.go | 2 +- server/router/router.go | 10 +- tools/tools.go | 23 ++++ 26 files changed, 296 insertions(+), 235 deletions(-) create mode 100644 cmd/server/openapi.go rename cmd/server/{docs => openapi}/docs.go (99%) rename cmd/server/{woodpecker_docs_gen.go => openapi_json_gen.go} (80%) create mode 100644 cmd/server/openapi_test.go delete mode 100644 cmd/server/swagger.go delete mode 100644 cmd/server/swagger_test.go rename docs/docs/92-development/{09-swagger.md => 09-openapi.md} (88%) create mode 100644 tools/tools.go diff --git a/.cspell.json b/.cspell.json index f495a2e5e..8774c09be 100644 --- a/.cspell.json +++ b/.cspell.json @@ -129,6 +129,7 @@ "nosniff", "ntfy", "octocat", + "openapi", "opensource", "Pacman", "picus", @@ -250,7 +251,7 @@ "flake.lock", "pnpm-lock.yaml", "**/node_modules/**/*", - "cmd/server/docs/docs.go", + "cmd/server/openapi/docs.go", "renovate.json", // TODO: remove the following "docs/**/*.js", diff --git a/.ecrc b/.ecrc index 21b8d92b8..53c5abd81 100644 --- a/.ecrc +++ b/.ecrc @@ -1,14 +1,15 @@ { "Exclude": [ ".git", - "go.mod", "go.sum", + "go.mod", + "go.sum", "vendor", "fixtures", "LICENSE", "node_modules", "server/store/datastore/migration/test-files/sqlite.db", "server/store/datastore/feed.go", - "cmd/server/docs/docs.go", + "cmd/server/openapi/docs.go", "_test.go", "Makefile" ] diff --git a/.gitignore b/.gitignore index 4cbc9626d..08a30ad70 100644 --- a/.gitignore +++ b/.gitignore @@ -51,4 +51,7 @@ docs/venv ### Generated by CI ### docs/docs/40-cli.md +docs/openapi.json + +# Removed once v3.0.x is minimum version to be touched docs/swagger.json diff --git a/.woodpecker/test.yaml b/.woodpecker/test.yaml index 9eb3a9f61..e5f367217 100644 --- a/.woodpecker/test.yaml +++ b/.woodpecker/test.yaml @@ -58,14 +58,14 @@ steps: - make lint when: *when - check-swagger: + check-openapi: depends_on: - vendor image: *golang_image commands: - - 'make generate-swagger' + - 'make generate-openapi' - 'DIFF=$(git diff | head)' - - '[ -n "$DIFF" ] && { echo "swagger not up to date, exec `make generate-swagger` and commit"; exit 1; } || true' + - '[ -n "$DIFF" ] && { echo "openapi not up to date, exec `make generate-openapi` and commit"; exit 1; } || true' when: *when lint-license-header: diff --git a/Makefile b/Makefile index 5f0609fe5..dadacae45 100644 --- a/Makefile +++ b/Makefile @@ -109,15 +109,15 @@ clean: ## Clean build artifacts clean-all: clean ## Clean all artifacts rm -rf ${DIST_DIR} web/dist docs/build docs/node_modules web/node_modules # delete generated - rm -rf docs/docs/40-cli.md docs/swagger.json + rm -rf docs/docs/40-cli.md docs/openapi.json .PHONY: generate -generate: install-tools generate-swagger ## Run all code generations +generate: install-tools generate-openapi ## Run all code generations CGO_ENABLED=0 go generate ./... -generate-swagger: install-tools ## Run swagger code generation - swag init -g server/api/ -g cmd/server/swagger.go --outputTypes go -output cmd/server/docs - CGO_ENABLED=0 go generate cmd/server/swagger.go +generate-openapi: install-tools ## Run openapi code generation and format it + go run github.com/swaggo/swag/cmd/swag fmt + CGO_ENABLED=0 go generate cmd/server/openapi.go generate-license-header: install-tools addlicense -c "Woodpecker Authors" -ignore "vendor/**" **/*.go @@ -134,9 +134,6 @@ install-tools: ## Install development tools hash gofumpt > /dev/null 2>&1; if [ $$? -ne 0 ]; then \ go install mvdan.cc/gofumpt@latest; \ fi ; \ - hash swag > /dev/null 2>&1; if [ $$? -ne 0 ]; then \ - go install github.com/swaggo/swag/cmd/swag@latest; \ - fi ; \ hash addlicense > /dev/null 2>&1; if [ $$? -ne 0 ]; then \ go install github.com/google/addlicense@latest; \ fi ; \ @@ -196,7 +193,7 @@ test: test-agent test-server test-server-datastore test-cli test-lib ## Run all build-ui: ## Build UI (cd web/; pnpm install --frozen-lockfile; pnpm build) -build-server: build-ui generate-swagger ## Build server +build-server: build-ui generate-openapi ## Build server CGO_ENABLED=${CGO_ENABLED} GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -tags '$(TAGS)' -ldflags '${LDFLAGS}' -o ${DIST_DIR}/woodpecker-server${BIN_SUFFIX} go.woodpecker-ci.org/woodpecker/v2/cmd/server build-agent: ## Build agent @@ -343,6 +340,6 @@ spellcheck: .PHONY: docs docs: ## Generate docs (currently only for the cli) CGO_ENABLED=0 go generate cmd/cli/app.go - CGO_ENABLED=0 go generate cmd/server/swagger.go + CGO_ENABLED=0 go generate cmd/server/openapi.go endif diff --git a/cmd/server/main.go b/cmd/server/main.go index 71b17b23b..009e14b9d 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -12,6 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !generate +// +build !generate + package main import ( @@ -22,7 +25,7 @@ import ( "github.com/rs/zerolog/log" "github.com/urfave/cli/v3" - _ "go.woodpecker-ci.org/woodpecker/v2/cmd/server/docs" + _ "go.woodpecker-ci.org/woodpecker/v2/cmd/server/openapi" "go.woodpecker-ci.org/woodpecker/v2/shared/utils" "go.woodpecker-ci.org/woodpecker/v2/version" ) @@ -46,7 +49,7 @@ func main() { } app.Flags = flags - setupSwaggerStaticConfig() + setupOpenAPIStaticConfig() if err := app.Run(ctx, os.Args); err != nil { log.Error().Err(err).Msgf("error running server") diff --git a/cmd/server/openapi.go b/cmd/server/openapi.go new file mode 100644 index 000000000..37b68179a --- /dev/null +++ b/cmd/server/openapi.go @@ -0,0 +1,38 @@ +// Copyright 2023 Woodpecker Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "go.woodpecker-ci.org/woodpecker/v2/cmd/server/openapi" + "go.woodpecker-ci.org/woodpecker/v2/version" +) + +// Generate docs/openapi.json via: +//go:generate go run github.com/swaggo/swag/cmd/swag init -g cmd/server/openapi.go --outputTypes go -output openapi -d ../../ +//go:generate go run openapi_json_gen.go openapi.go +//go:generate go run github.com/getkin/kin-openapi/cmd/validate@latest ../../docs/openapi.json + +// setupOpenAPIStaticConfig initializes static content (version) for the OpenAPI config. +// +// @title Woodpecker CI API +// @description Woodpecker is a simple, yet powerful CI/CD engine with great extensibility. +// @description To get a personal access token (PAT) for authentication, please log in your Woodpecker server, +// @description and go to you personal profile page, by clicking the user icon at the top right. +// @BasePath /api +// @contact.name Woodpecker CI +// @contact.url https://woodpecker-ci.org/ +func setupOpenAPIStaticConfig() { + openapi.SwaggerInfo.Version = version.String() +} diff --git a/cmd/server/docs/docs.go b/cmd/server/openapi/docs.go similarity index 99% rename from cmd/server/docs/docs.go rename to cmd/server/openapi/docs.go index 32b7a70b9..645933163 100644 --- a/cmd/server/docs/docs.go +++ b/cmd/server/openapi/docs.go @@ -1,5 +1,5 @@ -// Package docs Code generated by swaggo/swag. DO NOT EDIT -package docs +// Package openapi Code generated by swaggo/swag. DO NOT EDIT +package openapi import "github.com/swaggo/swag" @@ -10,7 +10,7 @@ const docTemplate = `{ "description": "{{escape .Description}}", "title": "{{.Title}}", "contact": { - "name": "Woodpecker CI Community", + "name": "Woodpecker CI", "url": "https://woodpecker-ci.org/" }, "version": "{{.Version}}" @@ -122,7 +122,7 @@ const docTemplate = `{ { "type": "integer", "description": "the agent's id", - "name": "agent", + "name": "agent_id", "in": "path", "required": true } @@ -156,7 +156,7 @@ const docTemplate = `{ { "type": "integer", "description": "the agent's id", - "name": "agent", + "name": "agent_id", "in": "path", "required": true } @@ -187,7 +187,7 @@ const docTemplate = `{ { "type": "integer", "description": "the agent's id", - "name": "agent", + "name": "agent_id", "in": "path", "required": true }, @@ -232,7 +232,7 @@ const docTemplate = `{ { "type": "integer", "description": "the agent's id", - "name": "agent", + "name": "agent_id", "in": "path", "required": true } @@ -4554,22 +4554,15 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "allOf": [ - { + "type": "object", + "properties": { + "source": { "type": "string" }, - { - "type": "object", - "properties": { - "source": { - "type": "string" - }, - "version": { - "type": "string" - } - } + "version": { + "type": "string" } - ] + } } } } @@ -5791,10 +5784,10 @@ const docTemplate = `{ var SwaggerInfo = &swag.Spec{ Version: "", Host: "", - BasePath: "", + BasePath: "/api", Schemes: []string{}, - Title: "", - Description: "", + Title: "Woodpecker CI API", + Description: "Woodpecker is a simple, yet powerful CI/CD engine with great extensibility.\nTo get a personal access token (PAT) for authentication, please log in your Woodpecker server,\nand go to you personal profile page, by clicking the user icon at the top right.", InfoInstanceName: "swagger", SwaggerTemplate: docTemplate, LeftDelim: "{{", diff --git a/cmd/server/woodpecker_docs_gen.go b/cmd/server/openapi_json_gen.go similarity index 80% rename from cmd/server/woodpecker_docs_gen.go rename to cmd/server/openapi_json_gen.go index 9c3eac261..cccbd3e30 100644 --- a/cmd/server/woodpecker_docs_gen.go +++ b/cmd/server/openapi_json_gen.go @@ -12,9 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -// ************************************************************************************************ -// This is a generator tool, to update the Markdown documentation for the woodpecker-ci.org website -// ************************************************************************************************ +// ********************************************************* +// This is a generator tool, to update the openapi.json file +// ********************************************************* //go:build generate // +build generate @@ -30,23 +30,24 @@ import ( "github.com/getkin/kin-openapi/openapi2" "github.com/getkin/kin-openapi/openapi2conv" - "go.woodpecker-ci.org/woodpecker/v2/cmd/server/docs" + + "go.woodpecker-ci.org/woodpecker/v2/cmd/server/openapi" ) func main() { - // set swagger infos - setupSwaggerStaticConfig() + // set openapi infos + setupOpenAPIStaticConfig() basePath := path.Join("..", "..") - filePath := path.Join(basePath, "docs", "swagger.json") + filePath := path.Join(basePath, "docs", "openapi.json") - // generate swagger file + // generate openapi file f, err := os.Create(filePath) if err != nil { panic(err) } defer f.Close() - doc := docs.SwaggerInfo.ReadDoc() + doc := openapi.SwaggerInfo.ReadDoc() doc, err = removeHost(doc) if err != nil { panic(err) @@ -56,6 +57,8 @@ func main() { panic(err) } + fmt.Println("generated openapi.json") + // convert to OpenApi3 if err := toOpenApi3(filePath, filePath); err != nil { fmt.Printf("converting '%s' from openapi v2 to v3 failed\n", filePath) diff --git a/cmd/server/openapi_test.go b/cmd/server/openapi_test.go new file mode 100644 index 000000000..95773ce00 --- /dev/null +++ b/cmd/server/openapi_test.go @@ -0,0 +1,14 @@ +package main + +import ( + "testing" + + "github.com/stretchr/testify/assert" + + "go.woodpecker-ci.org/woodpecker/v2/cmd/server/openapi" +) + +func TestSetupOpenApiStaticConfig(t *testing.T) { + setupOpenAPIStaticConfig() + assert.Equal(t, "/api", openapi.SwaggerInfo.BasePath) +} diff --git a/cmd/server/swagger.go b/cmd/server/swagger.go deleted file mode 100644 index 2acb8be76..000000000 --- a/cmd/server/swagger.go +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2023 Woodpecker Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package main - -import ( - "go.woodpecker-ci.org/woodpecker/v2/cmd/server/docs" - "go.woodpecker-ci.org/woodpecker/v2/version" -) - -// Generate docs/swagger.json via: -//go:generate go run woodpecker_docs_gen.go swagger.go -//go:generate go run github.com/getkin/kin-openapi/cmd/validate@latest ../../docs/swagger.json - -// setupSwaggerStaticConfig initializes static content only (contacts, title and description) -// for dynamic configuration of e.g. hostname, etc. see router.setupSwaggerConfigAndRoutes -// -// @contact.name Woodpecker CI Community -// @contact.url https://woodpecker-ci.org/ -func setupSwaggerStaticConfig() { - docs.SwaggerInfo.BasePath = "/api" - docs.SwaggerInfo.InfoInstanceName = "api" - docs.SwaggerInfo.Title = "Woodpecker CI API" - docs.SwaggerInfo.Version = version.String() - docs.SwaggerInfo.Description = "Woodpecker is a simple, yet powerful CI/CD engine with great extensibility.\n" + - "To get a personal access token (PAT) for authentication, please log in your Woodpecker server,\n" + - "and go to you personal profile page, by clicking the user icon at the top right." -} diff --git a/cmd/server/swagger_test.go b/cmd/server/swagger_test.go deleted file mode 100644 index 5d678aed9..000000000 --- a/cmd/server/swagger_test.go +++ /dev/null @@ -1,14 +0,0 @@ -package main - -import ( - "testing" - - "github.com/stretchr/testify/assert" - - "go.woodpecker-ci.org/woodpecker/v2/cmd/server/docs" -) - -func TestSetupSwaggerStaticConfig(t *testing.T) { - setupSwaggerStaticConfig() - assert.Equal(t, "/api", docs.SwaggerInfo.BasePath) -} diff --git a/docs/docs/92-development/09-swagger.md b/docs/docs/92-development/09-openapi.md similarity index 88% rename from docs/docs/92-development/09-swagger.md rename to docs/docs/92-development/09-openapi.md index 5bf303c7b..1d7e58533 100644 --- a/docs/docs/92-development/09-swagger.md +++ b/docs/docs/92-development/09-openapi.md @@ -36,12 +36,12 @@ type User struct { } // @name User ``` -These guidelines aim to have consistent wording in the swagger doc: +These guidelines aim to have consistent wording in the OpenAPI doc: - first word after `@Summary` and `@Summary` are always uppercase - `@Summary` has no `.` (dot) at the end of the line - model structs shall use custom short names, to ease life for API consumers, using `@name` -- `@Success` object or array declarations shall be short, this means the actual `model.User` struct must have a `@name` annotation, so that the model can be rendered in Swagger +- `@Success` object or array declarations shall be short, this means the actual `model.User` struct must have a `@name` annotation, so that the model can be rendered in OpenAPI - when pagination is used, `@Param page` and `@Param perPage` must be added manually - `@Param Authorization` is almost always present, there are just a few un-protected endpoints @@ -50,14 +50,10 @@ More enhanced information you can find here ) -// @Param agent path int true "the agent's id" +// @Param agent_id path int true "the agent's id" func GetAgent(c *gin.Context) { agentID, err := strconv.ParseInt(c.Param("agent_id"), 10, 64) if err != nil { @@ -81,7 +81,7 @@ func GetAgent(c *gin.Context) { // @Success 200 {array} Task // @Tags Agents // @Param Authorization header string true "Insert your personal access token" default(Bearer ) -// @Param agent path int true "the agent's id" +// @Param agent_id path int true "the agent's id" func GetAgentTasks(c *gin.Context) { agentID, err := strconv.ParseInt(c.Param("agent_id"), 10, 64) if err != nil { @@ -114,7 +114,7 @@ func GetAgentTasks(c *gin.Context) { // @Success 200 {object} Agent // @Tags Agents // @Param Authorization header string true "Insert your personal access token" default(Bearer ) -// @Param agent path int true "the agent's id" +// @Param agent_id path int true "the agent's id" // @Param agentData body Agent true "the agent's data" func PatchAgent(c *gin.Context) { _store := store.FromContext(c) @@ -156,14 +156,14 @@ func PatchAgent(c *gin.Context) { // PostAgent // -// @Summary Create a new agent -// @Description Creates a new agent with a random token -// @Router /agents [post] -// @Produce json -// @Success 200 {object} Agent -// @Tags Agents -// @Param Authorization header string true "Insert your personal access token" default(Bearer ) -// @Param agent body Agent true "the agent's data (only 'name' and 'no_schedule' are read)" +// @Summary Create a new agent +// @Description Creates a new agent with a random token +// @Router /agents [post] +// @Produce json +// @Success 200 {object} Agent +// @Tags Agents +// @Param Authorization header string true "Insert your personal access token" default(Bearer ) +// @Param agent body Agent true "the agent's data (only 'name' and 'no_schedule' are read)" func PostAgent(c *gin.Context) { in := &model.Agent{} err := c.Bind(in) @@ -196,7 +196,7 @@ func PostAgent(c *gin.Context) { // @Success 200 // @Tags Agents // @Param Authorization header string true "Insert your personal access token" default(Bearer ) -// @Param agent path int true "the agent's id" +// @Param agent_id path int true "the agent's id" func DeleteAgent(c *gin.Context) { _store := store.FromContext(c) @@ -237,15 +237,15 @@ func DeleteAgent(c *gin.Context) { // PostOrgAgent // -// @Summary Create a new organization-scoped agent -// @Description Creates a new agent with a random token, scoped to the specified organization -// @Router /orgs/{org_id}/agents [post] -// @Produce json -// @Success 200 {object} Agent -// @Tags Agents -// @Param Authorization header string true "Insert your personal access token" default(Bearer ) -// @Param org_id path int true "the organization's id" -// @Param agent body Agent true "the agent's data (only 'name' and 'no_schedule' are read)" +// @Summary Create a new organization-scoped agent +// @Description Creates a new agent with a random token, scoped to the specified organization +// @Router /orgs/{org_id}/agents [post] +// @Produce json +// @Success 200 {object} Agent +// @Tags Agents +// @Param Authorization header string true "Insert your personal access token" default(Bearer ) +// @Param org_id path int true "the organization's id" +// @Param agent body Agent true "the agent's data (only 'name' and 'no_schedule' are read)" func PostOrgAgent(c *gin.Context) { _store := store.FromContext(c) user := session.User(c) @@ -286,7 +286,7 @@ func PostOrgAgent(c *gin.Context) { // @Produce json // @Success 200 {array} Agent // @Tags Agents -// @Param Authorization header string true "Insert your personal access token" default(Bearer ) +// @Param Authorization header string true "Insert your personal access token" default(Bearer ) // @Param org_id path int true "the organization's id" // @Param page query int false "for response pagination, page offset number" default(1) // @Param perPage query int false "for response pagination, max items per page" default(50) diff --git a/server/api/forge.go b/server/api/forge.go index cf82e3aa5..57bc1469e 100644 --- a/server/api/forge.go +++ b/server/api/forge.go @@ -144,14 +144,14 @@ func PatchForge(c *gin.Context) { // PostForge // -// @Summary Create a new forge -// @Description Creates a new forge with a random token -// @Router /forges [post] -// @Produce json -// @Success 200 {object} Forge -// @Tags Forges -// @Param Authorization header string true "Insert your personal access token" default(Bearer ) -// @Param forge body Forge true "the forge's data (only 'name' and 'no_schedule' are read)" +// @Summary Create a new forge +// @Description Creates a new forge with a random token +// @Router /forges [post] +// @Produce json +// @Success 200 {object} Forge +// @Tags Forges +// @Param Authorization header string true "Insert your personal access token" default(Bearer ) +// @Param forge body Forge true "the forge's data (only 'name' and 'no_schedule' are read)" func PostForge(c *gin.Context) { in := &model.Forge{} err := c.Bind(in) diff --git a/server/api/global_registry.go b/server/api/global_registry.go index a9ffd9a89..b175d4043 100644 --- a/server/api/global_registry.go +++ b/server/api/global_registry.go @@ -32,7 +32,7 @@ import ( // @Success 200 {array} Registry // @Tags Registries // @Param Authorization header string true "Insert your personal access token" default(Bearer ) -// @Param page query int false "for response pagination, page offset number" default(1) +// @Param page query int false "for response pagination, page offset number" default(1) // @Param perPage query int false "for response pagination, max items per page" default(50) func GetGlobalRegistryList(c *gin.Context) { registryService := server.Config.Services.Manager.RegistryService() @@ -57,7 +57,7 @@ func GetGlobalRegistryList(c *gin.Context) { // @Success 200 {object} Registry // @Tags Registries // @Param Authorization header string true "Insert your personal access token" default(Bearer ) -// @Param registry path string true "the registry's name" +// @Param registry path string true "the registry's name" func GetGlobalRegistry(c *gin.Context) { addr := c.Param("registry") registryService := server.Config.Services.Manager.RegistryService() @@ -76,8 +76,8 @@ func GetGlobalRegistry(c *gin.Context) { // @Produce json // @Success 200 {object} Registry // @Tags Registries -// @Param Authorization header string true "Insert your personal access token" default(Bearer ) -// @Param registry body Registry true "the registry object data" +// @Param Authorization header string true "Insert your personal access token" default(Bearer ) +// @Param registry body Registry true "the registry object data" func PostGlobalRegistry(c *gin.Context) { in := new(model.Registry) if err := c.Bind(in); err != nil { @@ -109,8 +109,8 @@ func PostGlobalRegistry(c *gin.Context) { // @Produce json // @Success 200 {object} Registry // @Tags Registries -// @Param Authorization header string true "Insert your personal access token" default(Bearer ) -// @Param registry path string true "the registry's name" +// @Param Authorization header string true "Insert your personal access token" default(Bearer ) +// @Param registry path string true "the registry's name" // @Param registryData body Registry true "the registry's data" func PatchGlobalRegistry(c *gin.Context) { addr := c.Param("registry") @@ -158,7 +158,7 @@ func PatchGlobalRegistry(c *gin.Context) { // @Success 204 // @Tags Registries // @Param Authorization header string true "Insert your personal access token" default(Bearer ) -// @Param registry path string true "the registry's name" +// @Param registry path string true "the registry's name" func DeleteGlobalRegistry(c *gin.Context) { addr := c.Param("registry") registryService := server.Config.Services.Manager.RegistryService() diff --git a/server/api/org_registry.go b/server/api/org_registry.go index 6476e2c53..89f16c145 100644 --- a/server/api/org_registry.go +++ b/server/api/org_registry.go @@ -56,8 +56,8 @@ func GetOrgRegistry(c *gin.Context) { // @Tags Organization registries // @Param Authorization header string true "Insert your personal access token" default(Bearer ) // @Param org_id path string true "the org's id" -// @Param page query int false "for response pagination, page offset number" default(1) -// @Param perPage query int false "for response pagination, max items per page" default(50) +// @Param page query int false "for response pagination, page offset number" default(1) +// @Param perPage query int false "for response pagination, max items per page" default(50) func GetOrgRegistryList(c *gin.Context) { org := session.Org(c) @@ -83,8 +83,8 @@ func GetOrgRegistryList(c *gin.Context) { // @Success 200 {object} Registry // @Tags Organization registries // @Param Authorization header string true "Insert your personal access token" default(Bearer ) -// @Param org_id path string true "the org's id" -// @Param registryData body Registry true "the new registry" +// @Param org_id path string true "the org's id" +// @Param registryData body Registry true "the new registry" func PostOrgRegistry(c *gin.Context) { org := session.Org(c) @@ -119,9 +119,9 @@ func PostOrgRegistry(c *gin.Context) { // @Produce json // @Success 200 {object} Registry // @Tags Organization registries -// @Param Authorization header string true "Insert your personal access token" default(Bearer ) -// @Param org_id path string true "the org's id" -// @Param registry path string true "the registry's name" +// @Param Authorization header string true "Insert your personal access token" default(Bearer ) +// @Param org_id path string true "the org's id" +// @Param registry path string true "the registry's name" // @Param registryData body Registry true "the update registry data" func PatchOrgRegistry(c *gin.Context) { org := session.Org(c) diff --git a/server/api/pipeline.go b/server/api/pipeline.go index a1b191ab4..2106fe32e 100644 --- a/server/api/pipeline.go +++ b/server/api/pipeline.go @@ -104,18 +104,18 @@ func createTmpPipeline(event model.WebhookEvent, commit *model.Commit, user *mod // GetPipelines // -// @Summary List repository pipelines +// @Summary List repository pipelines // @Description Get a list of pipelines for a repository. -// @Router /repos/{repo_id}/pipelines [get] -// @Produce json -// @Success 200 {array} Pipeline -// @Tags Pipelines -// @Param Authorization header string true "Insert your personal access token" default(Bearer ) -// @Param repo_id path int true "the repository id" -// @Param page query int false "for response pagination, page offset number" default(1) -// @Param perPage query int false "for response pagination, max items per page" default(50) -// @Param before query string false "only return pipelines before this RFC3339 date" -// @Param after query string false "only return pipelines after this RFC3339 date" +// @Router /repos/{repo_id}/pipelines [get] +// @Produce json +// @Success 200 {array} Pipeline +// @Tags Pipelines +// @Param Authorization header string true "Insert your personal access token" default(Bearer ) +// @Param repo_id path int true "the repository id" +// @Param page query int false "for response pagination, page offset number" default(1) +// @Param perPage query int false "for response pagination, max items per page" default(50) +// @Param before query string false "only return pipelines before this RFC3339 date" +// @Param after query string false "only return pipelines after this RFC3339 date" func GetPipelines(c *gin.Context) { repo := session.Repo(c) before := c.Query("before") diff --git a/server/api/repo.go b/server/api/repo.go index b63851dec..10388edc4 100644 --- a/server/api/repo.go +++ b/server/api/repo.go @@ -591,16 +591,16 @@ func MoveRepo(c *gin.Context) { // GetAllRepos // -// @Summary List all repositories on the server +// @Summary List all repositories on the server // @Description Returns a list of all repositories. Requires admin rights. -// @Router /repos [get] -// @Produce json -// @Success 200 {array} Repo -// @Tags Repositories -// @Param Authorization header string true "Insert your personal access token" default(Bearer ) -// @Param active query bool false "only list active repos" -// @Param page query int false "for response pagination, page offset number" default(1) -// @Param perPage query int false "for response pagination, max items per page" default(50) +// @Router /repos [get] +// @Produce json +// @Success 200 {array} Repo +// @Tags Repositories +// @Param Authorization header string true "Insert your personal access token" default(Bearer ) +// @Param active query bool false "only list active repos" +// @Param page query int false "for response pagination, page offset number" default(1) +// @Param perPage query int false "for response pagination, max items per page" default(50) func GetAllRepos(c *gin.Context) { _store := store.FromContext(c) @@ -617,13 +617,13 @@ func GetAllRepos(c *gin.Context) { // RepairAllRepos // -// @Summary Repair all repositories on the server -// @Description Executes a repair process on all repositories. Requires admin rights. -// @Router /repos/repair [post] -// @Produce plain -// @Success 204 -// @Tags Repositories -// @Param Authorization header string true "Insert your personal access token" default(Bearer ) +// @Summary Repair all repositories on the server +// @Description Executes a repair process on all repositories. Requires admin rights. +// @Router /repos/repair [post] +// @Produce plain +// @Success 204 +// @Tags Repositories +// @Param Authorization header string true "Insert your personal access token" default(Bearer ) func RepairAllRepos(c *gin.Context) { _store := store.FromContext(c) diff --git a/server/api/z.go b/server/api/z.go index b1557733d..2156f8507 100644 --- a/server/api/z.go +++ b/server/api/z.go @@ -48,7 +48,7 @@ func Health(c *gin.Context) { // @Description Endpoint returns the server version and build information. // @Router /version [get] // @Produce json -// @Success 200 {object} string{source=string,version=string} +// @Success 200 {object} object{source=string,version=string} // @Tags System func Version(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ diff --git a/server/router/router.go b/server/router/router.go index c873062d3..ea154fe4a 100644 --- a/server/router/router.go +++ b/server/router/router.go @@ -20,10 +20,10 @@ import ( "github.com/gin-gonic/gin" "github.com/rs/zerolog/log" - swagger_files "github.com/swaggo/files" + openapi_files "github.com/swaggo/files" ginSwagger "github.com/swaggo/gin-swagger" - "go.woodpecker-ci.org/woodpecker/v2/cmd/server/docs" + "go.woodpecker-ci.org/woodpecker/v2/cmd/server/openapi" "go.woodpecker-ci.org/woodpecker/v2/server" "go.woodpecker-ci.org/woodpecker/v2/server/api" "go.woodpecker-ci.org/woodpecker/v2/server/api/metrics" @@ -78,9 +78,9 @@ func Load(noRouteHandler http.HandlerFunc, middleware ...gin.HandlerFunc) http.H } func setupSwaggerConfigAndRoutes(e *gin.Engine) { - docs.SwaggerInfo.Host = getHost(server.Config.Server.Host) - docs.SwaggerInfo.BasePath = server.Config.Server.RootPath + "/api" - e.GET(server.Config.Server.RootPath+"/swagger/*any", ginSwagger.WrapHandler(swagger_files.Handler)) + openapi.SwaggerInfo.Host = getHost(server.Config.Server.Host) + openapi.SwaggerInfo.BasePath = server.Config.Server.RootPath + "/api" + e.GET(server.Config.Server.RootPath+"/swagger/*any", ginSwagger.WrapHandler(openapi_files.Handler)) } func getHost(s string) string { diff --git a/tools/tools.go b/tools/tools.go new file mode 100644 index 000000000..80d4e2cd8 --- /dev/null +++ b/tools/tools.go @@ -0,0 +1,23 @@ +// Copyright 2024 Woodpecker Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build tools +// +build tools + +package main + +import ( + _ "github.com/getkin/kin-openapi/cmd/validate" + _ "github.com/swaggo/swag/cmd/swag" +)