Skip to content

Standardize API self-documentation + included Swagger as a Service #2321

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/github-pages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ jobs:
uses: Legion2/swagger-ui-action@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
spec-file: ./docs/swagger/collections.yaml
spec-file: ./docs/swagger/swagger.yaml
output: ./docs/publish/docs/swagger

- name: Deploy
Expand Down
22 changes: 20 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
# Determine which grep to use: ggrep (GNU grep) or default grep.
GREP := $(shell if command -v ggrep > /dev/null 2>&1; then echo "ggrep"; else echo "grep"; fi)

# Try to get the commit hash from 1) git 2) the VERSION file 3) fallback.
LAST_COMMIT := $(or $(shell git rev-parse --short HEAD 2> /dev/null),$(shell head -n 1 VERSION | grep -oP -m 1 "^[a-z0-9]+$$"),"")
LAST_COMMIT := $(or $(shell git rev-parse --short HEAD 2> /dev/null),$(shell head -n 1 VERSION | ${GREP} -oP -m 1 "^[a-z0-9]+$$"),"")

# Try to get the semver from 1) git 2) the VERSION file 3) fallback.
VERSION := $(or $(LISTMONK_VERSION),$(shell git describe --tags --abbrev=0 2> /dev/null),$(shell grep -oP 'tag: \Kv\d+\.\d+\.\d+(-[a-zA-Z0-9.-]+)?' VERSION),"v0.0.0")
VERSION := $(or $(LISTMONK_VERSION),$(shell git describe --tags --abbrev=0 2> /dev/null),$(shell ${GREP} -oP 'tag: \Kv\d+\.\d+\.\d+(-[a-zA-Z0-9.-]+)?' VERSION),"v0.0.0")

BUILDSTR := ${VERSION} (\#${LAST_COMMIT} $(shell date -u +"%Y-%m-%dT%H:%M:%S%z"))

Expand Down Expand Up @@ -114,3 +117,18 @@ rm-dev-docker: build ## Delete the docker containers including DB volumes.
init-dev-docker: build-dev-docker ## Delete the docker containers including DB volumes.
cd dev; \
docker compose run --rm backend sh -c "make dist && ./listmonk --install --idempotent --yes --config dev/config.toml"

.PHONY: install-swag
install-swag:
go install github.com/swaggo/swag/cmd/swag@latest

# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
ifeq (,$(shell go env GOBIN))
GOBIN=$(shell go env GOPATH)/bin
else
GOBIN=$(shell go env GOBIN)
endif

.PHONY: init-swag
init-swag: install-swag
${GOBIN}/swag init -g cmd/main.go --pd -o docs/swagger --ot go,yaml
225 changes: 119 additions & 106 deletions cmd/handlers.go

Large diffs are not rendered by default.

19 changes: 19 additions & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import (
"github.com/knadh/listmonk/models"
"github.com/knadh/paginator"
"github.com/knadh/stuffbin"

docs "github.com/knadh/listmonk/docs/swagger"
)

const (
Expand Down Expand Up @@ -168,7 +170,24 @@ func init() {
queries = prepareQueries(qMap, db, ko)
}

// @title Listmonk API
// @version 0.0
// @description Self-hosted newsletter and mailing list manager

// @contact.url https://github.com/knadh/listmonk/discussions

// @license.name GNU AFFERO GENERAL PUBLIC LICENSE
// @license.url https://github.com/knadh/listmonk/blob/master/LICENSE

// @host localhost
// @BasePath /api
func main() {
// programmatically set swagger info
docs.SwaggerInfo.Version = buildString
docs.SwaggerInfo.BasePath = apiPath
docs.SwaggerInfo.Host = "localhost" // TODO: set to current listmonk exposed host
docs.SwaggerInfo.Schemes = []string{"http", "https"} // TODO set to current listmonk exposed schemes

// Initialize the main app controller that wraps all of the app's
// components. This is passed around HTTP handlers.
app := &App{
Expand Down
42 changes: 42 additions & 0 deletions docs/swagger/docs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Package swagger Code generated by swaggo/swag. DO NOT EDIT
package swagger

import "github.com/swaggo/swag"

const docTemplate = `{
"schemes": {{ marshal .Schemes }},
"swagger": "2.0",
"info": {
"description": "{{escape .Description}}",
"title": "{{.Title}}",
"contact": {
"url": "https://github.com/knadh/listmonk/discussions"
},
"license": {
"name": "GNU AFFERO GENERAL PUBLIC LICENSE",
"url": "https://github.com/knadh/listmonk/blob/master/LICENSE"
},
"version": "{{.Version}}"
},
"host": "{{.Host}}",
"basePath": "{{.BasePath}}",
"paths": {}
}`

// SwaggerInfo holds exported Swagger Info so clients can modify it
var SwaggerInfo = &swag.Spec{
Version: "0.0",
Host: "localhost",
BasePath: "/api",
Schemes: []string{},
Title: "Listmonk API",
Description: "Self-hosted newsletter and mailing list manager",
InfoInstanceName: "swagger",
SwaggerTemplate: docTemplate,
LeftDelim: "{{",
RightDelim: "}}",
}

func init() {
swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo)
}
13 changes: 13 additions & 0 deletions docs/swagger/swagger.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
basePath: /api
host: localhost
info:
contact:
url: https://github.com/knadh/listmonk/discussions
description: Self-hosted newsletter and mailing list manager
license:
name: GNU AFFERO GENERAL PUBLIC LICENSE
url: https://github.com/knadh/listmonk/blob/master/LICENSE
title: Listmonk API
version: "0.0"
paths: {}
swagger: "2.0"
41 changes: 31 additions & 10 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
module github.com/knadh/listmonk

go 1.20
go 1.23.0

toolchain go1.23.6

require (
github.com/Masterminds/sprig/v3 v3.2.3
Expand All @@ -25,7 +27,7 @@ require (
github.com/knadh/paginator v1.0.1
github.com/knadh/smtppool v1.2.1
github.com/knadh/stuffbin v1.1.0
github.com/labstack/echo/v4 v4.11.4
github.com/labstack/echo/v4 v4.13.3
github.com/lib/pq v1.10.9
github.com/paulbellamy/ratecounter v0.2.0
github.com/rhnvrm/simples3 v0.8.3
Expand All @@ -34,18 +36,27 @@ require (
github.com/zerodha/easyjson v1.0.0
github.com/zerodha/simplesessions/stores/postgres/v3 v3.0.0
github.com/zerodha/simplesessions/v3 v3.0.0
golang.org/x/mod v0.17.0
golang.org/x/mod v0.23.0
golang.org/x/oauth2 v0.13.0
golang.org/x/text v0.21.0
golang.org/x/text v0.22.0
gopkg.in/volatiletech/null.v6 v6.0.0-20170828023728-0bef4e07ae1b
)

require (
github.com/KyleBanks/depth v1.2.1 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.2.0 // indirect
github.com/PuerkitoBio/purell v1.2.1 // indirect
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect
github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/ghodss/yaml v1.0.0 // indirect
github.com/go-jose/go-jose/v3 v3.0.3 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/jsonreference v0.21.0 // indirect
github.com/go-openapi/spec v0.21.0 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/uuid v1.3.0 // indirect
Expand All @@ -54,24 +65,34 @@ require (
github.com/josharian/intern v1.0.0 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/labstack/gommon v0.4.2 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mailru/easyjson v0.9.0 // indirect
github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/russross/blackfriday/v2 v2.0.1 // indirect
github.com/shopspring/decimal v1.3.1 // indirect
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/swaggo/echo-swagger v1.4.1 // indirect
github.com/swaggo/files/v2 v2.0.2 // indirect
github.com/swaggo/swag v1.16.4 // indirect
github.com/urfave/cli/v2 v2.3.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
golang.org/x/crypto v0.31.0 // indirect
golang.org/x/crypto v0.34.0 // indirect
golang.org/x/image v0.18.0 // indirect
golang.org/x/net v0.33.0 // indirect
golang.org/x/sys v0.28.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/net v0.35.0 // indirect
golang.org/x/sys v0.30.0 // indirect
golang.org/x/time v0.8.0 // indirect
golang.org/x/tools v0.30.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/yaml.v2 v2.3.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)

replace github.com/imdario/mergo => github.com/imdario/mergo v0.3.8
Loading