github.com/JarrahG/buffalocli@v0.0.0-20230801092127-b85bfd5d395a/internal/genny/build/build.go (about)

     1  package build
     2  
     3  import (
     4  	"embed"
     5  	"io/fs"
     6  	"os"
     7  	"path/filepath"
     8  	"strings"
     9  	"time"
    10  
    11  	"github.com/JarrahG/buffalocli/internal/runtime"
    12  	"github.com/gobuffalo/events"
    13  	"github.com/gobuffalo/genny/v2"
    14  	"github.com/gobuffalo/genny/v2/plushgen"
    15  	"github.com/gobuffalo/plush/v4"
    16  )
    17  
    18  //go:embed templates/*
    19  var templates embed.FS
    20  
    21  // New generator for building a Buffalo application
    22  // This powers the `buffalo build` command and can be
    23  // used to programatically build/compile Buffalo
    24  // applications.
    25  func New(opts *Options) (*genny.Generator, error) {
    26  	g := genny.New()
    27  
    28  	if err := opts.Validate(); err != nil {
    29  		return g, err
    30  	}
    31  	g.ErrorFn = func(err error) {
    32  		events.EmitError(EvtBuildStopErr, err, events.Payload{"opts": opts})
    33  	}
    34  
    35  	g.RunFn(func(r *genny.Runner) error {
    36  		events.EmitPayload(EvtBuildStart, events.Payload{"opts": opts})
    37  		return nil
    38  	})
    39  
    40  	g.Transformer(genny.Dot())
    41  	// TODO: workaround for 1.16, remove when we upgrade to 1.17 and rename "dot-*" files back to "-dot-*"
    42  	g.Transformer(genny.NewTransformer("*", func(f genny.File) (genny.File, error) {
    43  		name := f.Name()
    44  		if strings.HasPrefix(name, "dot-") {
    45  			name = strings.TrimPrefix(name, "dot-")
    46  			name = "." + name
    47  		}
    48  		return genny.NewFile(name, f), nil
    49  	}))
    50  	g.Transformer(genny.Replace("/dot-", "/."))
    51  
    52  	// validate templates
    53  	templatesPath := filepath.Join(opts.App.Root, "/templates")
    54  	if _, err := os.Stat(templatesPath); err == nil {
    55  		g.RunFn(ValidateTemplates(os.DirFS(templatesPath), opts.TemplateValidators))
    56  	}
    57  
    58  	// rename main() to originalMain()
    59  	g.RunFn(transformMain(opts))
    60  
    61  	// add any necessary templates for the build
    62  	sub, err := fs.Sub(templates, "templates")
    63  	if err != nil {
    64  		return g, err
    65  	}
    66  
    67  	if err := g.FS(sub); err != nil {
    68  		return g, err
    69  	}
    70  
    71  	// configure plush
    72  	ctx := plush.NewContext()
    73  	ctx.Set("opts", opts)
    74  	ctx.Set("buildTime", opts.BuildTime.Format(time.RFC3339))
    75  	ctx.Set("buildVersion", opts.BuildVersion)
    76  	ctx.Set("buffaloVersion", runtime.Version)
    77  	g.Transformer(plushgen.Transformer(ctx))
    78  
    79  	// create the ./a pkg
    80  	ag, err := apkg(opts)
    81  	if err != nil {
    82  		return g, err
    83  	}
    84  	g.Merge(ag)
    85  
    86  	if opts.WithAssets {
    87  		// mount the assets generator
    88  		ag, err := assets(opts)
    89  		if err != nil {
    90  			return g, err
    91  		}
    92  		g.Merge(ag)
    93  	}
    94  
    95  	if opts.WithBuildDeps {
    96  		// mount the build time dependency generator
    97  		dg, err := buildDeps(opts)
    98  		if err != nil {
    99  			return g, err
   100  		}
   101  		g.Merge(dg)
   102  	}
   103  
   104  	// create the final go build command
   105  	c, err := buildCmd(opts)
   106  	if err != nil {
   107  		return g, err
   108  	}
   109  
   110  	g.Command(c)
   111  	g.RunFn(func(r *genny.Runner) error {
   112  		events.EmitPayload(EvtBuildStop, events.Payload{"opts": opts})
   113  		return nil
   114  	})
   115  
   116  	g.RunFn(Cleanup(opts))
   117  	return g, nil
   118  }