Giter Club home page Giter Club logo

envdoc's Introduction

envdoc

envdoc is a tool for generating documentation for environment variables in Go structs. It takes comments associated with env tags in Go structs and creates a Markdown, plaintext or HTML file with detailed documentation.


CI Go Reference codecov Go Report Card Mentioned in Awesome Go

Installation

Run it with go run in source file:

//go:generate go run github.com/g4s8/envdoc@latest -output environments.md -type Config
type Config struct {
    // ...
}

Or download binary to run it:

go install github.com/g4s8/envdoc@latest

And use it in code:

//go:generate envdoc -output environments.md
type Config struct {
    // ...
}

Usage

//go:generate envdoc -output <output_file_name>
  • -dir (path string, optional) - Specify the directory to search for files. Default is the file dir with go:generate command.
  • -files (glob string, optional) - File glob pattern to specify file names to process. Default is the single file with go:generate.
  • -types (glob string, optional) - Type glob pattern for type names to process. If not specified, the next type after go:generate is used.
  • -output (path string, required) - Output file name for generated documentation.
  • -format (enum(markdown, plaintext, html, dotenv) string, optional) - Output format for documentation. Default is markdown.
  • -no-styles (bool, optional) - If true, CSS styles will not be included for html format.
  • -env-prefix (string, optional) - Sets additional global prefix for all environment variables.
  • -field-names (bool, optional) - Use field names as env names if env: tag is not specified.
  • -debug (bool, optional) - Enable debug output.

These params are deprecated and will be removed in the next major release:

  • -type - Specify one type to process.
  • -all - Process all types in a file.

Both parameters could be replaced with -types param:

  • Use -types=Foo instead of -type=Foo.
  • Use -types='*' instead of -all.

Example

Suppose you have the following Go file config.go:

package foo

//go:generate envdoc --output env-doc.md
type Config struct {
  // Port to listen for incoming connections
  Port int `env:"PORT,required"`
  // Address to serve
  Address string `env:"ADDRESS" envDefault:"localhost"`
}

And the go:generate line above creates documentation in env-doc.md file:

# Environment Variables

- `PORT` (**required**) - Port to listen for incoming connections
- `ADDRESS` (default: `localhost`) - Address to serve

See _examples dir for more details.

Compatibility

This tool is compatible with

Let me know about any new lib to check compatibility.

Contributing

If you find any issues or have suggestions for improvement, feel free to open an issue or submit a pull request.

License

This project is licensed under the MIT License - see the LICENSE.md file for details.

envdoc's People

Contributors

g4s8 avatar miniscruff avatar

Stargazers

Gabe Cook avatar Oleksandr Nosov avatar Amjad Hossain avatar Matt Love avatar Elliot Courant avatar Abdullah Alaadine avatar Dmitriy Brusenin avatar devlights avatar Sivakumar Kailasam avatar nexovec avatar Abhay Thakur avatar raf avatar Luis Quiñones avatar Elijah Passmore avatar Maksym Kryvchun avatar Emil Valeev avatar  avatar Michael Scholle avatar  avatar Ahmed Spahić avatar Barnaby Keene avatar Jean-Yves CAMIER avatar Lev Zakharov avatar Darwin Smith avatar Oleg Balunenko avatar Lucas Katayama avatar Amanbolat avatar Nicolas Steenlant avatar Matthias Vandermaesen avatar Nathan Allen avatar Piotr Icikowski avatar Troy Zimmerman avatar manicq avatar Artem Prosvetov avatar Emmanuel Ay avatar Josh avatar Ivan Sotnikov avatar  avatar guanguans avatar Dalton avatar Lubomir Anastasov avatar Carlos Alexandro Becker avatar Engin Diri avatar Dawid Cygert avatar Askari avatar Daniel Lewan avatar Ramesh avatar Clayton Kehoe avatar AndreyK avatar

Watchers

 avatar Ayaz Ayupov avatar  avatar

Forkers

miniscruff

envdoc's Issues

Multiple source files support

According to multiple requests, it's important to support generating doc from config types located in different files. It could be done by defining a new CLI flag -project pointing to project root location. Starting from the project root envdoc can parse all project files and collect them in file-set. Then, AST parser should parse the file-set with multiple files, and keep a new context about current package and file. Also, AST parser has to use this context to collect and resolve config types and its relations. Output document could be extended by multiple new related config types.

Open questions:

  • Do we need primary config type? Support -type param with -project?
  • Documentation resolver issues?
  • CLI flag conflicts?

Breakdown:

  • Keep package and file context with AST type
  • Resolve documentation for each package separately
  • Pay attention to type package name when building types relations
  • Add -project flag and parse file-set from dir if the flag specified

Related tickets:

-types='*' is not working, -all is

version used: 1.0.0
go version 1.22.6

//go:generate envdoc --output environment.md -all
type Appconfig struct {
	// Environment, has some effects on logging. Options are: production, debug, development
	Environment string `env:"ENVIRONMENT" envDefault:"production"`
	// timeout in seconds for DB operations like select or insert
	Timeout_DB int `env:"TIMEOUT_DB" envDefault:"10"`
}

// DBconfig contains all env values needed for configuration of the database connection
type DBconfig struct {
	// Username of Metadatastore Service-Account
	DB_User string `env:"DB_USER,notEmpty"`
	// Password of Metadatastore Service-Account
	DB_Pass string `env:"DB_PASS,notEmpty"`
}

in a situation like this, the new flag -types='*' results in an empty file, while -all is working, despite the warning.

Parsing anonymous nested structs fails

Parsing this config struct panics on the nested struct:

type Config struct {
	Repo struct {
		Conn  string  `env:"CONN,notEmpty"`
	} `envPrefix:"REPO_"`
}

Error message:

main.(*inspector).parseField(0xc0000ca400, 0xc0000f2380)
        /Users/xxx/go/pkg/mod/github.com/g4s8/[email protected]/inspector.go:207 +0x678
main.(*inspector).Visit(0xc0000ca400, {0x1236658?, 0xc0000f21c0?})
        /Users/xxx/go/pkg/mod/github.com/g4s8/[email protected]/inspector.go:136 +0x2e5
go/ast.Walk({0x1236018?, 0xc0000ca400?}, {0x1236658?, 0xc0000f21c0?})
        /usr/local/Cellar/go/1.21.6/libexec/src/go/ast/walk.go:51 +0x5c
go/ast.Walk({0x1236018?, 0xc0000ca400?}, {0x1236ec8?, 0xc0000f2400?})
        /usr/local/Cellar/go/1.21.6/libexec/src/go/ast/walk.go:344 +0x1b85
go/ast.walkDeclList(...)
        /usr/local/Cellar/go/1.21.6/libexec/src/go/ast/walk.go:38
go/ast.Walk({0x1236018?, 0xc0000ca400?}, {0x1236608?, 0xc0000ba8c0?})
        /usr/local/Cellar/go/1.21.6/libexec/src/go/ast/walk.go:366 +0x1b05
main.(*inspector).inspect(0xc0000ca400, {0x1236608?, 0xc0000ba8c0?})
        /Users/xxx/go/pkg/mod/github.com/g4s8/[email protected]/inspector.go:66 +0x5b
main.(*inspector).inspectFile(0xc0000ca400, {0xc000012107, 0x9})
        /Users/xxx/go/pkg/mod/github.com/g4s8/[email protected]/inspector.go:61 +0x128
main.(*generator).generate(0xc0000f0600, {0x1235fd8, 0xc000090400})
        /Users/xxx/go/pkg/mod/github.com/g4s8/[email protected]/generator.go:91 +0xc5
main.run(0xc0000e7e60)
        /Users/xxx/go/pkg/mod/github.com/g4s8/[email protected]/main.go:116 +0x618
main.main()
        /Users/xxx/go/pkg/mod/github.com/g4s8/[email protected]/main.go:64 +0x112

Thanks for a handy tool!

Some fields are ignored with `-field-names` flag

When -field-names flag is enabled, envdoc should use field names as environment variables if env tag is not specified, or it doesn't have env name. Examples:

// FieldNames uses field names as env names.
//
//go:generate go run ../ -output complex-fields.md -field-names
type FieldNames struct {
	// Foo is a single field.
	Foo string
	// Bar and Baz are two fields.
	Bar, Baz string
	// Quux is a field with a tag.
	Quux string `env:"QUUX"`
	// FooBar is a field with a default value.
	FooBar string `envDefault:"quuux"`
	// Required is a required field.
	Required string `env:",required"`
}

Right now, only QUUX env doc is generated. But all other fields should be included into documentation too.

--all flag causes panic if functions are present in the file

Hi again,
using the newest version 0.2.3 with the fix #19 now correctly generates documentation for a unexported struct, thank you for that!

However, I liked it so much that I decided to split my huge struct into 3 smaller ones to have a nice grouping in the generated markdown.

I included the --all flag. This works perfectly, as long as there are no functions present in the file. When there are functions, it stops with the error:
panic: expected type node root child, got nodeField ()

To reproduce:

package main

//go:generate envdoc -output test.md --all
type aconfig struct {
	// this is some value
	somevalue string `env:"SOME_VALUE" envDefault:"somevalue"`
}

type anotherconfig struct {
	// this is some value
	somevalue string `env:"SOME_VALUE" envDefault:"somevalue"`
}

// // when this function is present, go generate panics with "expected type node root child, got nodeField ()".
// func someFuncThatTakesInput(configs ...interface{}) {
// 	// this is some comment
// }

// // When this function is present, go generate will panic with "expected type node root child,got nodeField (int)"
// func someFuncThatReturnsSomething() int {
// 	return 1
// }

// // This function can be present and go generate work fine
// func someUselessFunc() {
// 	// this is some comment
// }

Without knowing too much about the code of envdoc (or go in general ;) ), I think that traverses everything in the file, looking for types. And because in the two first functions, type definitions are present in the functions signature, it leads to an error somewhere. When a function does not have a type inside the signature, it works fine.

go version 1.22.2
envdoc 0.2.3

envPrefix is not supported

I use caarlos0/env for my REST API project. The package has support for envPrefix which looks like this:

//go:generate go run github.com/g4s8/envdoc@latest -output environments.md -type Settings
type Settings struct {
	Database     Database     `envPrefix:"DB_"`
}

type Database struct {
	Port     Int     `env:"PORT,required"`
}

..which should result in: DB_PORT as an environment variable.
But instead it renders an markdown with a header, and nothing else.

Is this expected behavior or am I doing something wrong?

Many config files to one

Hi,

I really like the purpose of this tool. However, I am unsure how to create one md file or one env file from all our config files across our repo.

We do not have one giant config file for the application, but instead a config file for each of the components that needs some type of configuration.

I'd like to merge all those config files into one documentation. Is this possible in some way? :)

Importing configs from other packages results in an empty value

Consider a project layout such as

> config
    > env.example
    > CONFIGURATION.md
    > config.go
> models
    > config.go

If the config/config.go imports the models/config.go as part of its config, the resulting envdoc output will simply show as empty.

//go:generate go run github.com/g4s8/envdoc@latest -output CONFIGURATION.md -type Config -field-names
//go:generate go run github.com/g4s8/envdoc@latest -output .env.example -type Config -field-names -format dotenv

// Config manages all our app configurations.
type Config struct {
	Database models.PostgresConfig `envPrefix:"DB_"`
	// not included is my postgres config but imagine it has username, password, host, etc
}

Resulting markdown file:

# Environment Variables

## Config

Config manages all our app configurations.

 - `DATABASE` - 

I believe the issue is also relevant if you were importing from an entirely different project as well.

go generate panics (only have package main though)

Hi, I really like the idea of auto-generating documentation, so thanks for creating this project!

However, I cannot generate the documentation, as go generate panics.
I am using caarlos0/env.

I have a few .go files, but for simplicity, all are in package main.
This is config.go:

package main

import (
	"errors"
	"time"
	"github.com/caarlos0/env"
)

const (
	//Environment values, used for logger configuration
	EnvironmentProduction  = "production"
)

// Error messages
var (
	ErrNoRowsFound           = errors.New("no rows found")
)

//go:generate envdoc -output environments.md
type appconfig struct {
	// Port the application will listen on inside the container
	Port int `env:"PORT" envDefault:"8080"`
       // some more stuff I omitted here
}

func (c *appconfig) ParseEnvVariablesIntoConfigStruct() error {
	if err := env.Parse(c); err != nil {
		return err
	}
	return nil
}

I get this error:

panic: expected type node root child, got nodeField ()

When I uncomment the method at the end, I at least get no errors, and the environments.md file is generated, but only contains
# Environment Variables, nothing else.

go version is 1.22.2

Type filter is broken in v0.2.0

Got error when using the latest version v0.2.0. Everything works fine with v0.1.2. Minimal example to reproduce problem:

package main

import "time"

//go:generate go run github.com/g4s8/[email protected] -output environments.md -type Config

type Config struct {
	// Some time.
	SomeTime MyTime `env:"SOME_TIME"`
}

type MyTime time.Time

func (t *MyTime) UnmarshalText(text []byte) error {
	tt, err := time.Parse("2006-01-02", string(text))
	*t = MyTime(tt)
	return err
}
➜  go generate ./...
panic: expected type node root child, got 4

goroutine 1 [running]:
main.(*inspector).traverseAST(0x14000125b78, 0x14000126f80, {0x16ee330f2, 0x6})
        /Users/lz/go/pkg/mod/github.com/g4s8/[email protected]/inspector.go:59 +0x344
main.(*inspector).inspectFile(0x14000125b78, {0x1400000e0c7, 0x7})
        /Users/lz/go/pkg/mod/github.com/g4s8/[email protected]/inspector.go:51 +0x2e0
main.(*generator).generate(0x1400007d040, {0x1011bc838, 0x14000050a70})
        /Users/lz/go/pkg/mod/github.com/g4s8/[email protected]/generator.go:99 +0x94
main.run(0x14000125e58)
        /Users/lz/go/pkg/mod/github.com/g4s8/[email protected]/main.go:133 +0x514
main.main()
        /Users/lz/go/pkg/mod/github.com/g4s8/[email protected]/main.go:70 +0xf0
exit status 2
main.go:5: running "go": exit status 1

Panic on generate

Hello!

I'm trying to make documentation out of a structure
There is a config.Config structure, and nested structures in different packages

package config
//go:generate go run github.com/g4s8/envdoc@latest -output environments.md
type Config struct {
	ProgName         string `env:"PROG_NAME,notEmpty" envDefault:"prog"`
	Logger           log.Config

	Application lifecycle.Config
	RestAPI     restapi.Config
}

package log
type Config struct {
	Level    string `env:"LOG_LEVEL,notEmpty"  envDefault:"info"`
	Format   string `env:"LOG_FORMAT,notEmpty" envDefault:"json"`
}

package lifecycle
type Config struct {
	AppGracePeriod        time.Duration `env:"APP_GRACE_PERIOD,notEmpty"        envDefault:"10s"`
}

package restapi
type Config struct {
	Port         int           `env:"RESTAPI_PORT"          envDefault:"8080"`
	ReadTimeout  time.Duration `env:"RESTAPI_READ_TIMEOUT"  envDefault:"5s"`
	WriteTimeout time.Duration `env:"RESTAPI_WRITE_TIMEOUT" envDefault:"10s"`
	IdleTimeout  time.Duration `env:"RESTAPI_IDLE_TIMEOUT"  envDefault:"120s"`
}

When trying to generate an error is thrown

go generate ./internal/config/...
panic: expected type node root child, got nodeField (Config)

goroutine 1 [running]:
main.(*inspector).traverseAST(0xc0000bdc60, 0xc0000bf200, {0xc000012ad0, 0x6})
        /root/go/pkg/mod/github.com/g4s8/[email protected]/inspector.go:64 +0x445
main.(*inspector).inspectFile(0xc0000bdc60, {0xc0000120c7, 0x9})
        /root/go/pkg/mod/github.com/g4s8/[email protected]/inspector.go:51 +0x308
main.(*generator).generate(0xc00007f110, {0x60b9e8, 0xc00005aa98})
        /root/go/pkg/mod/github.com/g4s8/[email protected]/generator.go:99 +0xc6
main.run(0xc0000bde40)
        /root/go/pkg/mod/github.com/g4s8/[email protected]/main.go:133 +0x629
main.main()
        /root/go/pkg/mod/github.com/g4s8/[email protected]/main.go:70 +0x12a
exit status 2
internal/config/config.go:20: running "go": exit status 1

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.