Skip to content

Commit

Permalink
switch logging to slog
Browse files Browse the repository at this point in the history
  • Loading branch information
jlambert121 committed Aug 11, 2024
1 parent 3d740c5 commit 9e3b71e
Show file tree
Hide file tree
Showing 21 changed files with 152 additions and 55 deletions.
4 changes: 4 additions & 0 deletions cli/boilerplate_cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ func CreateBoilerplateCli() *cli.App {
Name: options.OptDisableDependencyPrompt,
Usage: fmt.Sprintf("Do not prompt for confirmation to include dependencies. Has the same effect as --%s, without disabling variable prompts.", options.OptNonInteractive),
},
&cli.BoolFlag{
Name: options.OptSilent,
Usage: "Do not output any log messages",
},
}

// We pass JSON/YAML content to various CLI flags, such as --var, and this JSON/YAML content may contain commas or
Expand Down
12 changes: 6 additions & 6 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ func (config *BoilerplateConfig) GetVariablesMap() map[string]variables.Variable

// Implement the go-yaml unmarshal interface for BoilerplateConfig. We can't let go-yaml handle this itself because:
//
// 1. Variable is an interface
// 2. We need to provide Defaults for optional fields, such as "type"
// 3. We want to validate the variable as part of the unmarshalling process so we never have invalid Variable or
// Dependency classes floating around
// 1. Variable is an interface
// 2. We need to provide Defaults for optional fields, such as "type"
// 3. We want to validate the variable as part of the unmarshalling process so we never have invalid Variable or
// Dependency classes floating around
func (config *BoilerplateConfig) UnmarshalYAML(unmarshal func(interface{}) error) error {
var fields map[string]interface{}
if err := unmarshal(&fields); err != nil {
Expand Down Expand Up @@ -176,15 +176,15 @@ func LoadBoilerplateConfig(opts *options.BoilerplateOptions) (*BoilerplateConfig
configPath := BoilerplateConfigPath(opts.TemplateFolder)

if util.PathExists(configPath) {
util.Logger.Printf("Loading boilerplate config from %s", configPath)
opts.Logger.Info(fmt.Sprintf("Loading boilerplate config from %s", configPath))
bytes, err := ioutil.ReadFile(configPath)
if err != nil {
return nil, errors.WithStackTrace(err)
}

return ParseBoilerplateConfig(bytes)
} else if opts.OnMissingConfig == options.Ignore {
util.Logger.Printf("Warning: boilerplate config file not found at %s. The %s flag is set, so ignoring. Note that no variables will be available while generating.", configPath, options.OptMissingConfigAction)
opts.Logger.Info(fmt.Sprintf("Warning: boilerplate config file not found at %s. The %s flag is set, so ignoring. Note that no variables will be available while generating.", configPath, options.OptMissingConfigAction))
return &BoilerplateConfig{}, nil
} else {
// If the template URL is similar to a git URL, surface in error message that there may be a misspelling/typo.
Expand Down
17 changes: 14 additions & 3 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package config

import (
"bytes"
"io"
"io/ioutil"
"log/slog"
"path"
"path/filepath"
"reflect"
Expand Down Expand Up @@ -620,7 +622,10 @@ func TestParseBoilerplateConfigMultipleHooks(t *testing.T) {
func TestLoadBoilerplateConfigFullConfig(t *testing.T) {
t.Parallel()

actual, err := LoadBoilerplateConfig(&options.BoilerplateOptions{TemplateFolder: "../test-fixtures/config-test/full-config"})
actual, err := LoadBoilerplateConfig(&options.BoilerplateOptions{
Logger: slog.New(slog.NewJSONHandler(io.Discard, nil)),
TemplateFolder: "../test-fixtures/config-test/full-config",
})
expected := &BoilerplateConfig{
Partials: []string{"../templates/foo"},
Variables: []variables.Variable{
Expand Down Expand Up @@ -664,7 +669,10 @@ func TestLoadBoilerplateConfigNoConfigIgnore(t *testing.T) {
t.Parallel()

templateFolder := "../test-fixtures/config-test/no-config"
actual, err := LoadBoilerplateConfig(&options.BoilerplateOptions{TemplateFolder: templateFolder, OnMissingConfig: options.Ignore})
actual, err := LoadBoilerplateConfig(&options.BoilerplateOptions{
Logger: slog.New(slog.NewJSONHandler(io.Discard, nil)),
TemplateFolder: templateFolder, OnMissingConfig: options.Ignore,
})
expected := &BoilerplateConfig{}

assert.Nil(t, err, "Unexpected error: %v", err)
Expand All @@ -674,7 +682,10 @@ func TestLoadBoilerplateConfigNoConfigIgnore(t *testing.T) {
func TestLoadBoilerplateConfigInvalidConfig(t *testing.T) {
t.Parallel()

_, err := LoadBoilerplateConfig(&options.BoilerplateOptions{TemplateFolder: "../test-fixtures/config-test/invalid-config"})
_, err := LoadBoilerplateConfig(&options.BoilerplateOptions{
Logger: slog.New(slog.NewJSONHandler(io.Discard, nil)),
TemplateFolder: "../test-fixtures/config-test/invalid-config",
})

assert.NotNil(t, err)

Expand Down
6 changes: 3 additions & 3 deletions config/get_variables.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,10 +170,10 @@ func getVariable(variable variables.Variable, opts *options.BoilerplateOptions)
valueFromVars, valueSpecifiedInVars := getVariableFromVars(variable, opts)

if valueSpecifiedInVars {
util.Logger.Printf("Using value specified via command line options for variable '%s': %s", variable.FullName(), valueFromVars)
opts.Logger.Info(fmt.Sprintf("Using value specified via command line options for variable '%s': %s", variable.FullName(), valueFromVars))
return valueFromVars, nil
} else if opts.NonInteractive && variable.Default() != nil {
util.Logger.Printf("Using default value for variable '%s': %v", variable.FullName(), variable.Default())
opts.Logger.Info(fmt.Sprintf("Using default value for variable '%s': %v", variable.FullName(), variable.Default()))
return variable.Default(), nil
} else if opts.NonInteractive {
return nil, errors.WithStackTrace(MissingVariableWithNonInteractiveMode(variable.FullName()))
Expand Down Expand Up @@ -269,7 +269,7 @@ func getVariableFromUser(variable variables.Variable, opts *options.BoilerplateO

if value == "" {
// TODO: what if the user wanted an empty string instead of the default?
util.Logger.Printf("Using default value for variable '%s': %v", variable.FullName(), variable.Default())
opts.Logger.Info(fmt.Sprintf("Using default value for variable '%s': %v", variable.FullName(), variable.Default()))
return variable.Default(), nil
}

Expand Down
7 changes: 6 additions & 1 deletion config/get_variables_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package config

import (
"io"
"log/slog"
"reflect"
"testing"

Expand All @@ -15,7 +17,7 @@ func TestGetVariableFromVarsEmptyVars(t *testing.T) {
t.Parallel()

variable := variables.NewStringVariable("foo")
opts := &options.BoilerplateOptions{}
opts := &options.BoilerplateOptions{Logger: slog.New(slog.NewJSONHandler(io.Discard, nil))}

_, containsValue := getVariableFromVars(variable, opts)
assert.False(t, containsValue)
Expand Down Expand Up @@ -108,6 +110,7 @@ func TestGetVariableInVarsNonInteractive(t *testing.T) {

variable := variables.NewStringVariable("foo")
opts := &options.BoilerplateOptions{
Logger: slog.New(slog.NewJSONHandler(io.Discard, nil)),
NonInteractive: true,
Vars: map[string]interface{}{
"key1": "value1",
Expand All @@ -128,6 +131,7 @@ func TestGetVariableDefaultNonInteractive(t *testing.T) {

variable := variables.NewStringVariable("foo").WithDefault("bar")
opts := &options.BoilerplateOptions{
Logger: slog.New(slog.NewJSONHandler(io.Discard, nil)),
NonInteractive: true,
Vars: map[string]interface{}{
"key1": "value1",
Expand Down Expand Up @@ -225,6 +229,7 @@ func TestGetVariablesMatchFromVarsAndDefaults(t *testing.T) {
t.Parallel()

opts := &options.BoilerplateOptions{
Logger: slog.New(slog.NewJSONHandler(io.Discard, nil)),
NonInteractive: true,
Vars: map[string]interface{}{
"key1": "value1",
Expand Down
6 changes: 3 additions & 3 deletions getter-helper/getter_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package getter_helper
import (
"context"
"fmt"
"log/slog"
"net/url"
"os"
"path/filepath"
Expand All @@ -12,7 +13,6 @@ import (
urlhelper "github.com/hashicorp/go-getter/helper/url"

"github.com/gruntwork-io/boilerplate/errors"
"github.com/gruntwork-io/boilerplate/util"
)

var forcedRegexp = regexp.MustCompile(`^([A-Za-z0-9]+)::(.+)$`)
Expand Down Expand Up @@ -100,7 +100,7 @@ func NewGetterClient(src string, dst string) (*getter.Client, error) {
// DownloadTemplatesToTemporaryFolder uses the go-getter library to fetch the templates from the configured URL to a
// temporary folder and returns the path to that folder. If there is a subdir in the template URL, return the combined
// path as well.
func DownloadTemplatesToTemporaryFolder(templateUrl string) (string, string, error) {
func DownloadTemplatesToTemporaryFolder(templateUrl string, logger *slog.Logger) (string, string, error) {
workingDir, err := getTempFolder()
if err != nil {
return workingDir, workingDir, errors.WithStackTrace(err)
Expand All @@ -109,7 +109,7 @@ func DownloadTemplatesToTemporaryFolder(templateUrl string) (string, string, err
// Always set a subdir path because go-getter can not clone into an existing dir.
cloneDir := filepath.Join(workingDir, "wd")

util.Logger.Printf("Downloading templates from %s to %s", templateUrl, workingDir)
logger.Info(fmt.Sprintf("Downloading templates from %s to %s", templateUrl, workingDir))

// If there is a subdir component, we download everything and combine the path at the end to return the working path
mainPath, subDir := getter.SourceDirSubdir(templateUrl)
Expand Down
4 changes: 3 additions & 1 deletion getter-helper/getter_helper_unix_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ package getter_helper

import (
"fmt"
"io"
"log/slog"
"os"
"path/filepath"
"testing"
Expand All @@ -24,7 +26,7 @@ func TestDownloadTemplatesToTempDir(t *testing.T) {

branch := git.GetCurrentBranchName(t)
templateUrl := fmt.Sprintf("[email protected]:gruntwork-io/boilerplate.git//examples/for-learning-and-testing/variables?ref=%s", branch)
workingDir, workPath, err := DownloadTemplatesToTemporaryFolder(templateUrl)
workingDir, workPath, err := DownloadTemplatesToTemporaryFolder(templateUrl, slog.New(slog.NewJSONHandler(io.Discard, nil)))
defer os.RemoveAll(workingDir)
require.NoError(t, err, errors.PrintErrorWithStackTrace(err))

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/gruntwork-io/boilerplate

go 1.18
go 1.21

require (
github.com/AlecAivazis/survey/v2 v2.3.4
Expand Down
1 change: 1 addition & 0 deletions integration-tests/error_message_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ func TestMisspelledTemplateURLErrorMessage(t *testing.T) {
"--output-folder",
outputFolder,
"--non-interactive",
"--silent",
}
runErr := app.Run(args)
assert.Error(t, runErr, errors.PrintErrorWithStackTrace(runErr))
Expand Down
1 change: 1 addition & 0 deletions integration-tests/examples_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ func testExample(t *testing.T, templateFolder string, outputFolder string, varFi
"--non-interactive",
"--missing-key-action",
missingKeyAction,
"--silent",
}

// Special handling for the shell-disabled case, which we use to test that we can disable hooks and shell helpers
Expand Down
1 change: 1 addition & 0 deletions integration-tests/required_version_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ func runRequiredVersionExample(t *testing.T, templateFolder string) error {
"--output-folder",
outputPath,
"--non-interactive",
"--silent",
}
return app.Run(args)
}
1 change: 1 addition & 0 deletions integration-tests/slice_parsing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ func TestSliceParsing(t *testing.T) {
"--var",
fmt.Sprintf("MapValue=%s", mapValue),
"--non-interactive",
"--silent",
}

runErr := app.Run(args)
Expand Down
5 changes: 5 additions & 0 deletions options/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package options

import (
"fmt"
"log/slog"

"github.com/urfave/cli/v2"

Expand All @@ -20,6 +21,7 @@ const OptMissingConfigAction = "missing-config-action"
const OptDisableHooks = "disable-hooks"
const OptDisableShell = "disable-shell"
const OptDisableDependencyPrompt = "disable-dependency-prompt"
const OptSilent = "silent"

// The command-line options for the boilerplate app
type BoilerplateOptions struct {
Expand All @@ -36,6 +38,8 @@ type BoilerplateOptions struct {
DisableHooks bool
DisableShell bool
DisableDependencyPrompt bool
Silent bool
Logger *slog.Logger
}

// Validate that the options have reasonable values and return an error if they don't
Expand Down Expand Up @@ -96,6 +100,7 @@ func ParseOptions(cliContext *cli.Context) (*BoilerplateOptions, error) {
DisableHooks: cliContext.Bool(OptDisableHooks),
DisableShell: cliContext.Bool(OptDisableShell),
DisableDependencyPrompt: cliContext.Bool(OptDisableDependencyPrompt),
Silent: cliContext.Bool(OptSilent),
}

if err := options.Validate(); err != nil {
Expand Down
5 changes: 3 additions & 2 deletions render/template_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,8 @@ func include(templatePath string, opts *options.BoilerplateOptions, path string,
// Example:
//
// pathRelativeToTemplate("/foo/bar/template-file.txt, "../src/code.java")
// Returns: "/foo/src/code.java"
//
// Returns: "/foo/src/code.java"
func PathRelativeToTemplate(templatePath string, filePath string) string {
if path.IsAbs(filePath) {
return filePath
Expand Down Expand Up @@ -606,7 +607,7 @@ func keys(value interface{}) ([]string, error) {
// string.
func shell(templatePath string, opts *options.BoilerplateOptions, rawArgs ...string) (string, error) {
if opts.DisableShell {
util.Logger.Printf("Shell helpers are disabled. Will not execute shell command '%v'. Returning placeholder value '%s' instead.", rawArgs, SHELL_DISABLED_PLACEHOLDER)
opts.Logger.Info(fmt.Sprintf("Shell helpers are disabled. Will not execute shell command '%v'. Returning placeholder value '%s' instead.", rawArgs, SHELL_DISABLED_PLACEHOLDER))
return SHELL_DISABLED_PLACEHOLDER, nil
}

Expand Down
8 changes: 7 additions & 1 deletion render/template_helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"bufio"
"bytes"
"fmt"
"io"
"log/slog"
"path/filepath"
"reflect"
"runtime"
Expand Down Expand Up @@ -473,7 +475,11 @@ func TestShellError(t *testing.T) {
func TestShellDisabled(t *testing.T) {
t.Parallel()

output, err := shell(".", &options.BoilerplateOptions{NonInteractive: true, DisableShell: true}, "echo", "hi")
output, err := shell(".", &options.BoilerplateOptions{
Logger: slog.New(slog.NewJSONHandler(io.Discard, nil)),
NonInteractive: true,
DisableShell: true,
}, "echo", "hi")
assert.Nil(t, err, "Unexpected error: %v", err)
assert.Equal(t, SHELL_DISABLED_PLACEHOLDER, output)
}
Expand Down
2 changes: 1 addition & 1 deletion templates/engines_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func processEngines(
if err != nil {
return nil, err
}
debugLogForMatchedPaths(engine.Path, matchedPaths, "Engine", "Path")
debugLogForMatchedPaths(engine.Path, matchedPaths, "Engine", "Path", opts.Logger)

processedEngine := ProcessedEngine{
EvaluatedPaths: matchedPaths,
Expand Down
21 changes: 11 additions & 10 deletions templates/skip_files_processor.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package templates

import (
"fmt"
"log/slog"
"path/filepath"

zglob "github.com/mattn/go-zglob"

"github.com/gruntwork-io/boilerplate/errors"
"github.com/gruntwork-io/boilerplate/options"
"github.com/gruntwork-io/boilerplate/render"
"github.com/gruntwork-io/boilerplate/util"
"github.com/gruntwork-io/boilerplate/variables"
)

Expand All @@ -35,15 +36,15 @@ func processSkipFiles(skipFiles []variables.SkipFile, opts *options.BoilerplateO
return nil, errors.WithStackTrace(err)
}
if skipFile.Path != "" {
debugLogForMatchedPaths(skipFile.Path, matchedPaths, "SkipFile", "Path")
debugLogForMatchedPaths(skipFile.Path, matchedPaths, "SkipFile", "Path", opts.Logger)
}

matchedNotPaths, err := renderGlobPath(opts, skipFile.NotPath, variables)
if err != nil {
return nil, errors.WithStackTrace(err)
}
if skipFile.NotPath != "" {
debugLogForMatchedPaths(skipFile.NotPath, matchedNotPaths, "SkipFile", "NotPath")
debugLogForMatchedPaths(skipFile.NotPath, matchedNotPaths, "SkipFile", "NotPath", opts.Logger)
}

renderedSkipIf, err := skipFileIfCondition(skipFile, opts, variables)
Expand Down Expand Up @@ -75,20 +76,20 @@ func skipFileIfCondition(skipFile variables.SkipFile, opts *options.BoilerplateO

// TODO: logger-debug - switch to debug
if skipFile.Path != "" {
util.Logger.Printf("If attribute for SkipFile Path %s evaluated to '%s'", skipFile.Path, rendered)
opts.Logger.Info(fmt.Sprintf("If attribute for SkipFile Path %s evaluated to '%s'", skipFile.Path, rendered))
} else if skipFile.NotPath != "" {
util.Logger.Printf("If attribute for SkipFile NotPath %s evaluated to '%s'", skipFile.NotPath, rendered)
opts.Logger.Info(fmt.Sprintf("If attribute for SkipFile NotPath %s evaluated to '%s'", skipFile.NotPath, rendered))
} else {
util.Logger.Printf("WARN: SkipFile has no path or not_path!")
opts.Logger.Info(fmt.Sprintf("WARN: SkipFile has no path or not_path!"))
}
return rendered == "true", nil
}

func debugLogForMatchedPaths(sourcePath string, paths []string, directiveName string, directiveAttribute string) {
func debugLogForMatchedPaths(sourcePath string, paths []string, directiveName string, directiveAttribute string, logger *slog.Logger) {
// TODO: logger-debug - switch to debug
util.Logger.Printf("Following paths were picked up by %s attribute for %s (%s):", directiveAttribute, directiveName, sourcePath)
logger.Info(fmt.Sprintf("Following paths were picked up by %s attribute for %s (%s):", directiveAttribute, directiveName, sourcePath))
for _, path := range paths {
util.Logger.Printf("\t- %s", path)
logger.Info(fmt.Sprintf("\t- %s", path))
}
}

Expand All @@ -108,7 +109,7 @@ func renderGlobPath(opts *options.BoilerplateOptions, path string, variables map
rawMatchedPaths, err := zglob.Glob(globPath)
if err != nil {
// TODO: logger-debug - switch to debug
util.Logger.Printf("ERROR: could not glob %s", globPath)
opts.Logger.Info(fmt.Sprintf("ERROR: could not glob %s", globPath))
return nil, errors.WithStackTrace(err)
}
// Canonicalize the matched paths prior to storage
Expand Down
Loading

0 comments on commit 9e3b71e

Please sign in to comment.