Skip to content

Commit

Permalink
Add initial commit for docgen
Browse files Browse the repository at this point in the history
  • Loading branch information
nikhilsbhat committed May 30, 2023
0 parents commit 58a3c9c
Show file tree
Hide file tree
Showing 8 changed files with 344 additions and 0 deletions.
22 changes: 22 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@

# dropping IDE data's
.vscode
.idea

.DS_Store

# dropping some kubernetes metadata .kube
.kube

# dropping vendor and other data directories
vendor/

# dropping local built binaries
/dist

# dropping all test results
cover.out
cover.html

# dropping all local builds generated for testing
bin/
69 changes: 69 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
linters:
disable-all: false
enable-all: true
disable:
- gci
- wsl
- gochecknoglobals
- tagliatelle
- exhaustivestruct
- nolintlint
- exhaustruct
- forbidigo
- paralleltest
- cyclop
- ireturn
- wrapcheck
- interfacebloat
- forcetypeassert
- dupl
- goconst
- maligned

issues:
exclude-rules:
- path: _test\.go
linters:
- gomnd

# https://github.com/go-critic/go-critic/issues/926
- linters:
- gocritic
text: "unnecessaryDefer:"

linters-settings:
funlen:
lines: 160

lll:
line-length: 165

dupl:
threshold: 450

gocognit:
min-complexity: 50

run:
concurrency: 10
timeout: 10m
issues-exit-code: 1
tests: true
skip-dirs:
- scripts/
- vendor/
- docs/

skip-files:
- Makefile
- README.md
- Dockerfile

severity:
default-severity: error

service:
golangci-lint-version: 1.27.x
prepare:
- make local.check
28 changes: 28 additions & 0 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# This is an example .goreleaser.yml file with some sane defaults.
# Make sure to check the documentation at http://goreleaser.com
before:
hooks:
# You may remove this if you don't use go modules.
- go mod tidy

builds:
- skip: true

archives:
- format: 'tar.gz'
id: source-code
- format: 'zip'
id: source-code-2

checksum:
name_template: 'checksums.txt'

snapshot:
name_template: "{{ .Tag }}"

changelog:
sort: asc
filters:
exclude:
- '^docs:'
- '^test:'
48 changes: 48 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
GOFMT_FILES?=$(shell find . -not -path "./vendor/*" -type f -name '*.go')
BUILD_ENVIRONMENT?=${ENVIRONMENT}
GOVERSION?=$(shell go version | awk '{printf $$3}')
APP_DIR?=$(shell git rev-parse --show-toplevel)
SOURCE_PACKAGES?=$(shell go list -mod=vendor ./... | grep -v "vendor" | grep -v "mocks")
TEST_FILES?=$(shell go list ./... | grep -v /vendor/ | grep -v examples)

# 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: help
help: ## Prints help (only for targets with comments)
@grep -E '^[a-zA-Z0-9._-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'

local.fmt: ## Lints all the go code in the application.
@gofmt -w $(GOFMT_FILES)
$(GOBIN)/gofumpt -l -w $(GOFMT_FILES)
$(GOBIN)/goimports -w $(GOFMT_FILES)
$(GOBIN)/gci write $(GOFMT_FILES) --skip-generated

local.check: local.fmt ## Loads all the dependencies to vendor directory
@go mod vendor
@go mod tidy

local.build: local.check ## Generates the artifact with the help of 'go build'
GOVERSION=${GOVERSION} BUILD_ENVIRONMENT=${BUILD_ENVIRONMENT} goreleaser build --rm-dist

publish: local.check ## Builds and publishes the app
GOVERSION=${GOVERSION} BUILD_ENVIRONMENT=${BUILD_ENVIRONMENT} PLUGIN_PATH=${APP_DIR} goreleaser release --rm-dist

mock.publish: local.check ## Builds and mocks app release
GOVERSION=${GOVERSION} BUILD_ENVIRONMENT=${BUILD_ENVIRONMENT} PLUGIN_PATH=${APP_DIR} goreleaser release --skip-publish --rm-dist

lint: ## Lint's application for errors, it is a linters aggregator (https://github.com/golangci/golangci-lint).
if [ -z "${DEV}" ]; then golangci-lint run --color always ; else docker run --rm -v $(APP_DIR):/app -w /app golangci/golangci-lint:v1.46.2-alpine golangci-lint run --color always ; fi

report: ## Publishes the go-report of the appliction (uses go-reportcard)
if [ -z "${DEV}" ]; then goreportcard -v ; else docker run --rm -v $(APP_DIR):/app -w /app basnik/goreportcard-cli:latest goreportcard-cli -v ; fi

test: ## runs test cases
@time go test $(TEST_FILES) -mod=vendor -coverprofile cover.out && go tool cover -html=cover.out -o cover.html && open cover.html

generate.mocks: ## Generates mocks to those methods that has comments //go:generate
@go generate ${SOURCE_PACKAGES}
118 changes: 118 additions & 0 deletions document.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package docgen

import (
"bytes"
"errors"
"fmt"
"log"
"os"
"path/filepath"
"time"

"github.com/nikhilsbhat/gocd-sdk-go"
"github.com/sirupsen/logrus"
"github.com/urfave/cli/v2"
)

const (
docGenName = "UrFaveCliDocGen"
docFilePermission = 0o600
)

// getDocs generates markdown documentation for the commands in app.
// Shamelessly copied code from https://github.com/urfave/cli/issues/340#issuecomment-334389849 with few modification.
func getDocs(app *cli.App, logger *logrus.Logger) string {
buffer := bytes.Buffer{}

buffer.WriteString(fmt.Sprintf("# `%s`\n\n", app.Name))
buffer.WriteString(fmt.Sprintf("%s\n%s - <%s>\n\n", app.Usage, app.Version, app.Authors[0].String()))

if app.Description != "" {
buffer.WriteString(app.Description)
buffer.WriteString("\n\n")
}

logger.Info("generating documents for subcommands")
buffer.WriteString("## Subcommands\n\n")

for _, command := range app.Commands {
logger.Infof("generating documents for subcommand '%s'", command.Name)

buffer.WriteString(fmt.Sprintf("### `%s`\n\n", command.Name))
if command.Usage != "" {
logger.Infof("generating documents on usage subcommand '%s'", command.Name)
buffer.WriteString(command.Usage)
buffer.WriteString("\n\n")
}
if command.Description != "" {
logger.Infof("generating documents on description of subcommand '%s'", command.Name)
buffer.WriteString(command.Description)
buffer.WriteString("\n\n")
}
if len(command.Flags) > 0 {
logger.Infof("generating documents on flags used by subcommand '%s'", command.Name)
buffer.WriteString("#### Flags\n\n")
for _, flag := range command.Flags {
buffer.WriteString(fmt.Sprintf("- `--%s`\n", flag.String()))
}
buffer.WriteString("\n\n")
}
}

if len(app.Flags) > 0 {
logger.Infof("generating documents on global flags of app '%s'", app.Name)
buffer.WriteString("## Global Flags\n\n")
for _, flag := range app.Flags {
buffer.WriteString(fmt.Sprintf("- `--%s`\n", flag.String()))
}
buffer.WriteString("\n\n")
}

buffer.WriteString("###### Auto generated by nikhilsbhat/urfavecli-docgen on " + time.Now().Format("2-Jan-2006") + "\n")

return buffer.String()
}

func GenerateDocs(app *cli.App) {
docsRootPath := "doc"
docsPath := filepath.Join(docsRootPath, "docs.md")

logger := logrus.New()
logger.SetLevel(gocd.GetLoglevel("info"))
logger.WithField(docGenName, true)
logger.SetFormatter(&logrus.JSONFormatter{})

logger.Infof("generating cli documents for '%s'", docGenName)
logger.Infof("documets would be generated under '%s'", docsPath)

docString := getDocs(app, logger)

logger.Infof("documets for cli '%s' was rendered, proceeding to wrtite the same to path '%s'", docGenName, docsPath)

logger.Infof("creating directory 'doc' to place document files")

if _, err := os.Stat(docsRootPath); errors.Is(err, os.ErrNotExist) {
if err = os.Mkdir(docsRootPath, docFilePermission); err != nil {
logger.Fatalf("creating document directory errored with: '%v'", err)
}
}

logger.Infof("proceeding to write rendered document to file")

if _, err := os.Stat(docsPath); errors.Is(err, os.ErrNotExist) {
if err = os.WriteFile(docsPath, []byte(docString), docFilePermission); err != nil {
logger.Fatalf("writing document to file '%s' errored with: '%v'", docsPath, err)
}
} else {
docFile, err := os.OpenFile(docsPath, os.O_WRONLY, os.ModeAppend) //nolint:nosnakecase
if err != nil {
log.Fatalf("reading existing document file '%s' to update it failed", docsPath)
}

if _, err := docFile.WriteString(docString); err != nil {
log.Fatalf("updating document file '%s' with newer information errored with: '%v'", docsPath, err)
}
}

logger.Infof("documents were successfully rendered to '%s'", docsPath)
}
19 changes: 19 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module github.com/nikhilsbhat/urfavecli-docgen

go 1.19

require (
github.com/nikhilsbhat/gocd-sdk-go v0.1.2
github.com/sirupsen/logrus v1.9.2
github.com/urfave/cli/v2 v2.25.5
)

require (
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/go-resty/resty/v2 v2.7.0 // indirect
github.com/jinzhu/copier v0.3.5 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
golang.org/x/net v0.7.0 // indirect
golang.org/x/sys v0.5.0 // indirect
)
39 changes: 39 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY=
github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I=
github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk=
github.com/jinzhu/copier v0.3.5 h1:GlvfUwHk62RokgqVNvYsku0TATCF7bAHVwEXoBh3iJg=
github.com/jinzhu/copier v0.3.5/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
github.com/nikhilsbhat/gocd-sdk-go v0.1.2 h1:O84UWArpzc4CRDmjUYgQzkfWYRIrlm9rW9Z/Kv+8mNs=
github.com/nikhilsbhat/gocd-sdk-go v0.1.2/go.mod h1:qco6B1kpMYtTkWqNhxjDajjQBYKrab7G52SFAvuhmT0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sirupsen/logrus v1.9.2 h1:oxx1eChJGI6Uks2ZC4W1zpLlVgqB8ner4EuQwV4Ik1Y=
github.com/sirupsen/logrus v1.9.2/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/urfave/cli/v2 v2.25.5 h1:d0NIAyhh5shGscroL7ek/Ya9QYQE0KNabJgiUinIQkc=
github.com/urfave/cli/v2 v2.25.5/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
1 change: 1 addition & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package docgen

0 comments on commit 58a3c9c

Please sign in to comment.