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

go(feat): Add the dry-run flag to gomplate (#2301) #2302

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
8 changes: 8 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ type Config struct {

ExecPipe bool `yaml:"execPipe,omitempty"`
Experimental bool `yaml:"experimental,omitempty"`
DryRun bool `yaml:"dryRun,omitempty"`
}

// TODO: remove when we remove the deprecated array format for templates
Expand Down Expand Up @@ -107,6 +108,7 @@ type rawConfig struct {

ExecPipe bool `yaml:"execPipe,omitempty"`
Experimental bool `yaml:"experimental,omitempty"`
DryRun bool `yaml:"dryRun,omitempty"`
}

// TODO: remove when we remove the deprecated array format for templates
Expand Down Expand Up @@ -140,6 +142,7 @@ func (c *Config) UnmarshalYAML(value *yaml.Node) error {
PluginTimeout: r.PluginTimeout,
ExecPipe: r.ExecPipe,
Experimental: r.Experimental,
DryRun: r.DryRun,
}

return nil
Expand Down Expand Up @@ -170,6 +173,7 @@ func (c Config) MarshalYAML() (interface{}, error) {
PluginTimeout: c.PluginTimeout,
ExecPipe: c.ExecPipe,
Experimental: c.Experimental,
DryRun: c.DryRun,
}

return aux, nil
Expand Down Expand Up @@ -274,6 +278,10 @@ func (c *Config) MergeFrom(o *Config) *Config {
}
}

if !isZero(o.DryRun) {
c.DryRun = true
}

if !isZero(o.OutputMap) {
c.OutputDir = ""
c.OutputFiles = nil
Expand Down
12 changes: 12 additions & 0 deletions gomplate.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,17 @@ func Run(ctx context.Context, cfg *Config) error {
}
Metrics.TemplatesGathered = len(tmpl)

// Check for dry-run flag
slog.InfoContext(ctx, "dry-run", "value", cfg.DryRun)
if cfg.DryRun {
err = tr.RenderTemplatesToBuffer(ctx, cfg, namer, tmpl)
if err != nil {
return fmt.Errorf("failed to render templates: %w", err)
}

return nil
}

err = tr.RenderTemplates(ctx, tmpl)
if err != nil {
return err
Expand Down Expand Up @@ -133,6 +144,7 @@ func mappingNamer(outMap string, tr *renderer) outputNamer {
return "", fmt.Errorf("failed to render outputMap with ctx %+v and inPath %s: %w", tctx, inPath, err)
}

slog.Info("outputMap rendered", "in", inPath, "out", out.String())
return filepath.Clean(strings.TrimSpace(out.String())), nil
})
}
6 changes: 6 additions & 0 deletions internal/cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,12 @@ func cobraConfig(cmd *cobra.Command, args []string) (cfg *gomplate.Config, err e
if err != nil {
return nil, err
}

cfg.DryRun, err = getBool(cmd, "dry-run")
if err != nil {
return nil, err
}

return cfg, nil
}

Expand Down
2 changes: 2 additions & 0 deletions internal/cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ func InitFlags(command *cobra.Command) {
command.Flags().BoolP("verbose", "V", false, "output extra information about what gomplate is doing")

command.Flags().String("config", defaultConfigFile, "config file (overridden by commandline flags)")

command.Flags().Bool("dry-run", false, "render the templates without writing the output files")
}

// Main -
Expand Down
88 changes: 70 additions & 18 deletions render.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package gomplate

import (
"bytes"
"context"
"fmt"
"io"
Expand Down Expand Up @@ -173,13 +174,7 @@ type Template struct {
}

func (r *renderer) RenderTemplates(ctx context.Context, templates []Template) error {
if datafs.FSProviderFromContext(ctx) == nil {
ctx = datafs.ContextWithFSProvider(ctx, DefaultFSProvider)
}

// configure the template context with the refreshed Data value
// only done here because the data context may have changed
tmplctx, err := createTmplContext(ctx, r.tctxAliases, r.sr)
ctx, tmplctx, err := r.initializeTemplateContext(ctx)
if err != nil {
return err
}
Expand All @@ -188,28 +183,33 @@ func (r *renderer) RenderTemplates(ctx context.Context, templates []Template) er
}

func (r *renderer) renderTemplatesWithData(ctx context.Context, templates []Template, tmplctx interface{}) error {
// update funcs with the current context
// only done here to ensure the context is properly set in func namespaces
f := CreateFuncs(ctx)

// add datasource funcs here because they need to share the source reader
addToMap(f, funcs.CreateDataSourceFuncs(ctx, r.sr))

// add user-defined funcs last so they override the built-in funcs
addToMap(f, r.funcs)
f := r.initializeTemplateFuncs(ctx)

// track some metrics for debug output
start := time.Now()
defer func() { Metrics.TotalRenderDuration = time.Since(start) }()
for _, template := range templates {
err := r.renderTemplate(ctx, template, f, tmplctx)
for _, t := range templates {
err := r.renderTemplate(ctx, t, f, tmplctx)
if err != nil {
return fmt.Errorf("renderTemplate: %w", err)
}
}
return nil
}

func (r *renderer) initializeTemplateFuncs(ctx context.Context) template.FuncMap {
// update funcs with the current context
// only done here to ensure the context is properly set in func namespaces
f := CreateFuncs(ctx)

// add datasource funcs here because they need to share the source reader
addToMap(f, funcs.CreateDataSourceFuncs(ctx, r.sr))

// add user-defined funcs last so they override the built-in funcs
addToMap(f, r.funcs)
return f
}

func (r *renderer) renderTemplate(ctx context.Context, template Template, f template.FuncMap, tmplctx interface{}) error {
if template.Writer != nil {
if wr, ok := template.Writer.(io.Closer); ok {
Expand Down Expand Up @@ -335,6 +335,58 @@ func (r *renderer) parseNestedTemplates(ctx context.Context, tmpl *template.Temp
return nil
}

func (r *renderer) RenderTemplatesToBuffer(ctx context.Context, cfg *Config, namer outputNamer, tmpl []Template) error {
ctx, tmplctx, err := r.initializeTemplateContext(ctx)
if err != nil {
return err
}

f := r.initializeTemplateFuncs(ctx)

// track some metrics for debug output
start := time.Now()
defer func() { Metrics.TotalRenderDuration = time.Since(start) }()
for _, t := range tmpl {
inFile := t.Name
if cfg.InputDir != "" {
inFile = strings.Replace(inFile, cfg.InputDir, "", 1)
}

outFile, err := namer.Name(ctx, inFile)
fmt.Println("---")
fmt.Println("##::gomplate::output::file", outFile)
fmt.Println("##::gomplate::template::file", t.Name)
fmt.Println("---")
var buf bytes.Buffer
// Set the template's writer to the buffer
t.Writer = &buf
err = r.renderTemplate(ctx, t, f, tmplctx)
if err != nil {
return fmt.Errorf("renderTemplate: %w", err)
}

// Print the rendered content to the console
fmt.Println(buf.String() + "\n")
}

return nil
}

func (r *renderer) initializeTemplateContext(ctx context.Context) (context.Context, interface{}, error) {
if datafs.FSProviderFromContext(ctx) == nil {
ctx = datafs.ContextWithFSProvider(ctx, DefaultFSProvider)
}

// configure the template context with the refreshed Data value
// only done here because the data context may have changed
tmplctx, err := createTmplContext(ctx, r.tctxAliases, r.sr)
if err != nil {
return nil, nil, err
}

return ctx, tmplctx, nil
}

func parseNestedTemplateDir(ctx context.Context, fsys fs.FS, alias, fname string, tmpl *template.Template) error {
files, err := fs.ReadDir(fsys, fname)
if err != nil {
Expand Down
Loading