Skip to content

Commit

Permalink
Merge pull request #41 from nicholaswilde/refactor-config
Browse files Browse the repository at this point in the history
refactor config
  • Loading branch information
nicholaswilde committed Jul 19, 2022
2 parents ada48a5 + b952e80 commit 70a9703
Show file tree
Hide file tree
Showing 13 changed files with 394 additions and 327 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
**/testdata/*.md

.cookdocs
.cookdocs.yml
.cookdocs.yaml

/site
/cook-docs
/cmd/cook-docs/cook-docs
Expand Down
3 changes: 3 additions & 0 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ signs:
- artifacts: checksum
args: ["-u", "{{ .Env.GPG_FINGERPRINT }}", "--output", "${signature}", "--detach-sign", "${artifact}"]

release:
draft: true

brews:
- tap:
owner: nicholaswilde
Expand Down
14 changes: 11 additions & 3 deletions cmd/cook-docs/command_line.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/nicholaswilde/cook-docs/pkg/types"
)

var version string
Expand All @@ -22,8 +23,8 @@ func possibleLogLevels() []string {
return levels
}

func initializeCli() {
logLevelName := viper.GetString("log-level")
func initializeCli(config *types.Config) {
logLevelName := config.LogLevel
logLevel, err := log.ParseLevel(logLevelName)
if err != nil {
log.Errorf("Failed to parse provided log level %s: %s", logLevelName, err)
Expand All @@ -48,7 +49,8 @@ func newCookDocsCommand(run func(cmd *cobra.Command, args []string)) (*cobra.Com
command.PersistentFlags().StringP("recipe-search-root", "c", ".", "directory to search recursively within for recipes")
command.PersistentFlags().StringP("log-level", "l", "info", logLevelUsage)
command.PersistentFlags().StringSliceP("template-files", "t", []string{"recipe.md.gotmpl"}, "gotemplate file paths relative to each recipe directory from which documentation will be generated")

command.PersistentFlags().IntP("word-wrap", "w", 120, "word wrap line length for recipe steps section")

viper.SetConfigName(".cookdocs")
viper.SetConfigType("yaml")
viper.AddConfigPath("/etc/cook-docs/")
Expand All @@ -69,6 +71,12 @@ func newCookDocsCommand(run func(cmd *cobra.Command, args []string)) (*cobra.Com
viper.AutomaticEnv()
viper.SetEnvPrefix("COOK_DOCS")
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
viper.RegisterAlias("wordWrap", "word-wrap")
viper.RegisterAlias("dryRun", "dry-run")
viper.RegisterAlias("ignoreFile", "ignore-file")
viper.RegisterAlias("recipeSearchRoot", "recipe-search-root")
viper.RegisterAlias("logLevel", "log-level")
viper.RegisterAlias("templateFiles", "template-files")
err = viper.BindPFlags(command.PersistentFlags())
return command, err
}
176 changes: 89 additions & 87 deletions cmd/cook-docs/main.go
Original file line number Diff line number Diff line change
@@ -1,87 +1,89 @@
package main

import (
"os"
"path"
"strings"
"sync"

"github.com/aquilax/cooklang-go"
"github.com/nicholaswilde/cook-docs/pkg/cook"
"github.com/nicholaswilde/cook-docs/pkg/document"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

func retrieveInfoAndPrintDocumentation(recipeSearchRoot string, recipePath string, templateFiles []string, waitGroup *sync.WaitGroup, dryRun bool) {
defer waitGroup.Done()

recipeInfo := cook.ParseRecipeInformation(recipePath)

recipeData, err := cooklang.ParseFile(recipeInfo.RecipePath)

if err != nil {
log.Warnf("Error parsing file for recipe %s, skipping: %s", recipeInfo.RecipePath, err)
return
}

recipeData = cook.MergeRecipeData(recipeInfo, recipeData)

document.PrintDocumentation(recipeSearchRoot, recipeData, recipeInfo, templateFiles, dryRun)
}

func cookDocs(_ *cobra.Command, _ []string) {
initializeCli()

recipeSearchRoot := viper.GetString("recipe-search-root")

var fullRecipeSearchRoot string
if path.IsAbs(recipeSearchRoot) {
fullRecipeSearchRoot = recipeSearchRoot
} else {
cwd, err := os.Getwd()
if err != nil {
log.Warnf("Error getting working directory: %s", err)
return
}
fullRecipeSearchRoot = path.Join(cwd, recipeSearchRoot)
}

recipePaths, err := cook.FindRecipePaths(fullRecipeSearchRoot)
if err != nil {
log.Errorf("Error finding recipe paths: %s", err)
os.Exit(1)
}
log.Infof("Found recipes [%s]", strings.Join(recipePaths, ", "))

templateFiles := viper.GetStringSlice("template-files")
log.Debugf("Rendering from optional template files [%s]", strings.Join(templateFiles, ", "))

dryRun := viper.GetBool("dry-run")
waitGroup := sync.WaitGroup{}

for _, r := range recipePaths {
waitGroup.Add(1)

// On dry runs all output goes to stdout, and so as to not jumble things, generate serially
if dryRun {
retrieveInfoAndPrintDocumentation(fullRecipeSearchRoot, r, templateFiles, &waitGroup, dryRun)
} else {
go retrieveInfoAndPrintDocumentation(fullRecipeSearchRoot, r, templateFiles, &waitGroup, dryRun)
}
}
waitGroup.Wait()
}

func main() {
command, err := newCookDocsCommand(cookDocs)
if err != nil {
log.Errorf("Failed to create the CLI commander: %s", err)
os.Exit(1)
}
if err := command.Execute(); err != nil {
log.Errorf("Failed to start the CLI: %s", err)
os.Exit(1)
}
}
package main

import (
"os"
"path"
"strings"
"sync"

"github.com/nicholaswilde/cook-docs/pkg/cook"
"github.com/nicholaswilde/cook-docs/pkg/document"
"github.com/nicholaswilde/cook-docs/pkg/types"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)

func retrieveInfoAndPrintDocumentation(recipePath string, waitGroup *sync.WaitGroup, config *types.Config) {
defer waitGroup.Done()

recipe, err := cook.ParseFile(recipePath, config)
if err != nil {
log.Warnf("Error parsing file for recipe %s, skipping: %s", recipePath, err)
return
}

document.PrintDocumentation(recipe)
}

func GetFullSearchRoot(searchRoot string) (string, error) {
var fullSearchRoot string
if path.IsAbs(searchRoot) {
fullSearchRoot = searchRoot
} else {
cwd, err := os.Getwd()
if err != nil {
return "", err
}
fullSearchRoot = path.Join(cwd, searchRoot)
}
return fullSearchRoot, nil
}

func cookDocs(_ *cobra.Command, _ []string) {
var config types.Config
viper.Unmarshal(&config)

initializeCli(&config)

fullSearchRoot, err := GetFullSearchRoot(config.RecipeSearchRoot)
if err != nil {
log.Warnf("Error getting working directory: %s", err)
return
}

recipePaths, err := cook.FindRecipeFilePaths(fullSearchRoot)
if err != nil {
log.Errorf("Error finding recipe paths: %s", err)
os.Exit(1)
}
log.Infof("Found recipes [%s]", strings.Join(recipePaths, ", "))

log.Debugf("Rendering from optional template files [%s]", strings.Join(config.TemplateFiles, ", "))

waitGroup := sync.WaitGroup{}

for _, r := range recipePaths {
waitGroup.Add(1)

// On dry runs all output goes to stdout, and so as to not jumble things, generate serially
if config.DryRun {
retrieveInfoAndPrintDocumentation(r, &waitGroup, &config)
} else {
go retrieveInfoAndPrintDocumentation(r, &waitGroup, &config)
}
}
waitGroup.Wait()
}

func main() {
command, err := newCookDocsCommand(cookDocs)
if err != nil {
log.Errorf("Failed to create the CLI commander: %s", err)
os.Exit(1)
}
if err := command.Execute(); err != nil {
log.Errorf("Failed to start the CLI: %s", err)
os.Exit(1)
}
}
35 changes: 20 additions & 15 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,23 @@

Here is a list of the current supported parameters:

| Command Line | Environmental Variable | Config File | Default | Description |
|---------------------------------|------------------------------|--------------------|--------------------|----------------------------------------------------------------------------------------------------|
| -d, --dry-run | COOK_DOCS_DRY_RUN | dry-run | false | don't actually render any markdown files just print to stdout passed |
| -h, --help | N/A | N/A | N/A | help for cook-docs |
| -i, --ignore-file string | COOK_DOCS_IGNORE_FILE | ignore-file | .cookdocsignore | filename to use as an ignore file to exclude recipe directories |
| -j, --jsonify | COOK_DOCS_JSONIFY | jsonify | false | parse the recipe and display it in json format |
| -l, --log-level string | COOK_DOCS_LOG_LEVEL | log-level | info | level of logs that should printed, one of (panic, fatal, error, warning, info, debug, trace) |
| -c, --recipe-search-root string | COOK_DOCS_RECIPE_SEARCH_ROOT | recipe-search-root | . | directory to search recursively within for recipes. |
| -t, --template-files strings | COOK_DOCS_TEMPLATE_FILES | template-files | [recipe.md.gotmpl] | gotemplate file paths relative to each recipe directory from which documentation will be generated |
| -v, --version | N/A | N/A | N/A | diplay the version of cook-docs |
| Command Line | Environmental Variable | Config File | Default | Description |
|---------------------------------|-------------------------------|-------------------|---------------------|-----------------------------------------------------------------------------------------------------|
| -d, --dry-run | COOK_DOCS_DRY_RUN | dryRun | false | don't actually render any markdown files just print to stdout passed |
| -h, --help | N/A | N/A | N/A | help for cook-docs |
| -i, --ignore-file string | COOK_DOCS_IGNORE_FILE | ignoreFile | .cookdocsignore | filename to use as an ignore file to exclude recipe directories |
| -j, --jsonify | COOK_DOCS_JSONIFY | jsonify | false | parse the recipe and display it in json format |
| -l, --log-level string | COOK_DOCS_LOG_LEVEL | logLevel | info | level of logs that should printed, one of (panic, fatal, error, warning, info, debug, trace) |
| -c, --recipe-search-root string | COOK_DOCS_RECIPE_SEARCH_ROOT | recipeSearchRoot | . | directory to search recursively within for recipes. |
| -t, --template-files strings | COOK_DOCS_TEMPLATE_FILES | templateFiles | [recipe.md.gotmpl] | gotemplate file paths relative to each recipe directory from which documentation will be generated |
| -w, --word-wrap int | COOK_DOCS_WORD_WRAP | wordWrap | 120 | word wrap line length for recipe steps section |
| -v, --version | N/A | N/A | N/A | diplay the version of cook-docs |

## Config Files

Configuration files may be used to set the default app settings.

The config file name is `.cookdocs.yaml` or `.cookdocs.yml` and can be located in
The config file name is `.cookdocs`, `.cookdocs.yaml` or `.cookdocs.yml` and can be located in
any of the following locations:

- `/etc/cook-docs/`
Expand All @@ -28,14 +29,18 @@ any of the following locations:

```yaml title=".cookdocs.yaml"
---
dry-run: false
ignore-file: .cookdocsignore
dryRun: false
ignoreFile: .cookdocsignore
jsonify: false
log-level: info
template-files:
logLevel: info
templateFiles:
- recipe.md.gotmpl
wordWrap: 120
```

!!! note
The variables in the config file can be both in the `Command Line` or `Config File` format. E.g. `dry-run` and `dryRun`.

## Environmental Variables

Environmental variables are also supported. They start with the prefix `COOK_DOCS_` and use
Expand Down
Loading

0 comments on commit 70a9703

Please sign in to comment.