Skip to content
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

switch logging to slog #189

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
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
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't feel right, I think we should either use a global slog.Default() or pass the logger instance as a function argument everywhere.

}

// 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