Skip to content

Commit

Permalink
feat: allow for build env vars (#2609)
Browse files Browse the repository at this point in the history
This allows for multi platform builds on go
  • Loading branch information
stuartwdouglas authored Sep 4, 2024
1 parent e389b46 commit efc799d
Show file tree
Hide file tree
Showing 9 changed files with 45 additions and 31 deletions.
17 changes: 8 additions & 9 deletions frontend/cli/cmd_box.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,10 @@ func init() {
}

type boxCmd struct {
BaseImage string `help:"Name of the ftl-box Docker image to use as a base." default:"ftl0/ftl-box:${version}"`
Parallelism int `short:"j" help:"Number of modules to build in parallel." default:"${numcpu}"`
Compose string `help:"Path to a compose file to generate."`
Name string `arg:"" help:"Name of the project."`
Dirs []string `arg:"" help:"Base directories containing modules (defaults to modules in project config)." type:"existingdir" optional:""`
BaseImage string `help:"Name of the ftl-box Docker image to use as a base." default:"ftl0/ftl-box:${version}"`
Compose string `help:"Path to a compose file to generate."`
Name string `arg:"" help:"Name of the project."`
Build buildCmd `embed:""`
}

func (b *boxCmd) Help() string {
Expand All @@ -117,13 +116,13 @@ Bring the box down:
}

func (b *boxCmd) Run(ctx context.Context, client ftlv1connect.ControllerServiceClient, projConfig projectconfig.Config) error {
if len(b.Dirs) == 0 {
b.Dirs = projConfig.AbsModuleDirs()
if len(b.Build.Dirs) == 0 {
b.Build.Dirs = projConfig.AbsModuleDirs()
}
if len(b.Dirs) == 0 {
if len(b.Build.Dirs) == 0 {
return errors.New("no directories specified")
}
engine, err := buildengine.New(ctx, client, projConfig.Root(), b.Dirs, buildengine.Parallelism(b.Parallelism))
engine, err := buildengine.New(ctx, client, projConfig.Root(), b.Build.Dirs, buildengine.BuildEnv(b.Build.BuildEnv), buildengine.Parallelism(b.Build.Parallelism))
if err != nil {
return err
}
Expand Down
3 changes: 2 additions & 1 deletion frontend/cli/cmd_build.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
type buildCmd struct {
Parallelism int `short:"j" help:"Number of modules to build in parallel." default:"${numcpu}"`
Dirs []string `arg:"" help:"Base directories containing modules (defaults to modules in project config)." type:"existingdir" optional:""`
BuildEnv []string `help:"Environment variables to set for the build."`
}

func (b *buildCmd) Run(ctx context.Context, client ftlv1connect.ControllerServiceClient, projConfig projectconfig.Config) error {
Expand All @@ -22,7 +23,7 @@ func (b *buildCmd) Run(ctx context.Context, client ftlv1connect.ControllerServic
if len(b.Dirs) == 0 {
return errors.New("no directories specified")
}
engine, err := buildengine.New(ctx, client, projConfig.Root(), b.Dirs, buildengine.Parallelism(b.Parallelism))
engine, err := buildengine.New(ctx, client, projConfig.Root(), b.Dirs, buildengine.BuildEnv(b.BuildEnv), buildengine.Parallelism(b.Parallelism))
if err != nil {
return err
}
Expand Down
9 changes: 4 additions & 5 deletions frontend/cli/cmd_deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,14 @@ import (
)

type deployCmd struct {
Parallelism int `short:"j" help:"Number of modules to build in parallel." default:"${numcpu}"`
Replicas int32 `short:"n" help:"Number of replicas to deploy." default:"1"`
Dirs []string `arg:"" help:"Base directories containing modules." type:"existingdir" required:""`
NoWait bool `help:"Do not wait for deployment to complete." default:"false"`
Replicas int32 `short:"n" help:"Number of replicas to deploy." default:"1"`
NoWait bool `help:"Do not wait for deployment to complete." default:"false"`
Build buildCmd `embed:""`
}

func (d *deployCmd) Run(ctx context.Context, projConfig projectconfig.Config) error {
client := rpc.ClientFromContext[ftlv1connect.ControllerServiceClient](ctx)
engine, err := buildengine.New(ctx, client, projConfig.Root(), d.Dirs, buildengine.Parallelism(d.Parallelism))
engine, err := buildengine.New(ctx, client, projConfig.Root(), d.Build.Dirs, buildengine.BuildEnv(d.Build.BuildEnv), buildengine.Parallelism(d.Build.Parallelism))
if err != nil {
return err
}
Expand Down
13 changes: 6 additions & 7 deletions frontend/cli/cmd_dev.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,20 @@ import (
)

type devCmd struct {
Parallelism int `short:"j" help:"Number of modules to build in parallel." default:"${numcpu}"`
Dirs []string `arg:"" help:"Base directories containing modules." type:"existingdir" optional:""`
Watch time.Duration `help:"Watch template directory at this frequency and regenerate on change." default:"500ms"`
NoServe bool `help:"Do not start the FTL server." default:"false"`
Lsp bool `help:"Run the language server." default:"false"`
ServeCmd serveCmd `embed:""`
InitDB bool `help:"Initialize the database and exit." default:"false"`
languageServer *lsp.Server
Build buildCmd `embed:""`
}

func (d *devCmd) Run(ctx context.Context, projConfig projectconfig.Config) error {
if len(d.Dirs) == 0 {
d.Dirs = projConfig.AbsModuleDirs()
if len(d.Build.Dirs) == 0 {
d.Build.Dirs = projConfig.AbsModuleDirs()
}
if len(d.Dirs) == 0 {
if len(d.Build.Dirs) == 0 {
return errors.New("no directories specified")
}

Expand Down Expand Up @@ -78,7 +77,7 @@ func (d *devCmd) Run(ctx context.Context, projConfig projectconfig.Config) error
case <-controllerReady:
}

opts := []buildengine.Option{buildengine.Parallelism(d.Parallelism)}
opts := []buildengine.Option{buildengine.Parallelism(d.Build.Parallelism), buildengine.BuildEnv(d.Build.BuildEnv)}
if d.Lsp {
d.languageServer = lsp.NewServer(ctx)
opts = append(opts, buildengine.WithListener(d.languageServer))
Expand All @@ -88,7 +87,7 @@ func (d *devCmd) Run(ctx context.Context, projConfig projectconfig.Config) error
})
}

engine, err := buildengine.New(ctx, client, projConfig.Root(), d.Dirs, opts...)
engine, err := buildengine.New(ctx, client, projConfig.Root(), d.Build.Dirs, opts...)
if err != nil {
return err
}
Expand Down
8 changes: 6 additions & 2 deletions go-runtime/compile/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func buildDir(moduleDir string) string {
}

// Build the given module.
func Build(ctx context.Context, projectRootDir, moduleDir string, sch *schema.Schema, filesTransaction ModifyFilesTransaction) (err error) {
func Build(ctx context.Context, projectRootDir, moduleDir string, sch *schema.Schema, filesTransaction ModifyFilesTransaction, buildEnv []string) (err error) {
if err := filesTransaction.Begin(); err != nil {
return err
}
Expand Down Expand Up @@ -246,7 +246,11 @@ func Build(ctx context.Context, projectRootDir, moduleDir string, sch *schema.Sc
}

logger.Debugf("Compiling")
return exec.Command(ctx, log.Debug, mainDir, "go", "build", "-o", "../../main", ".").RunBuffered(ctx)
err = exec.CommandWithEnv(ctx, log.Debug, mainDir, buildEnv, "go", "build", "-o", "../../main", ".").RunBuffered(ctx)
if err != nil {
return fmt.Errorf("failed to compile: %w", err)
}
return nil
}

// CleanStubs removes all generated stubs.
Expand Down
8 changes: 4 additions & 4 deletions internal/buildengine/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ const BuildLockTimeout = time.Minute
// Build a module in the given directory given the schema and module config.
//
// A lock file is used to ensure that only one build is running at a time.
func Build(ctx context.Context, projectRootDir string, sch *schema.Schema, module Module, filesTransaction ModifyFilesTransaction) error {
return buildModule(ctx, projectRootDir, sch, module, filesTransaction)
func Build(ctx context.Context, projectRootDir string, sch *schema.Schema, module Module, filesTransaction ModifyFilesTransaction, buildEnv []string) error {
return buildModule(ctx, projectRootDir, sch, module, filesTransaction, buildEnv)
}

func buildModule(ctx context.Context, projectRootDir string, sch *schema.Schema, module Module, filesTransaction ModifyFilesTransaction) error {
func buildModule(ctx context.Context, projectRootDir string, sch *schema.Schema, module Module, filesTransaction ModifyFilesTransaction, buildEnv []string) error {
release, err := flock.Acquire(ctx, filepath.Join(module.Config.Dir, ".ftl.lock"), BuildLockTimeout)
if err != nil {
return err
Expand All @@ -46,7 +46,7 @@ func buildModule(ctx context.Context, projectRootDir string, sch *schema.Schema,

switch module.Config.Language {
case "go":
err = buildGoModule(ctx, projectRootDir, sch, module, filesTransaction)
err = buildGoModule(ctx, projectRootDir, sch, module, filesTransaction, buildEnv)
case "java", "kotlin":
err = buildJavaModule(ctx, module)
case "rust":
Expand Down
4 changes: 2 additions & 2 deletions internal/buildengine/build_go.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import (
"github.com/TBD54566975/ftl/go-runtime/compile"
)

func buildGoModule(ctx context.Context, projectRootDir string, sch *schema.Schema, module Module, transaction ModifyFilesTransaction) error {
if err := compile.Build(ctx, projectRootDir, module.Config.Dir, sch, transaction); err != nil {
func buildGoModule(ctx context.Context, projectRootDir string, sch *schema.Schema, module Module, transaction ModifyFilesTransaction, buildEnv []string) error {
if err := compile.Build(ctx, projectRootDir, module.Config.Dir, sch, transaction, buildEnv); err != nil {
return CompilerBuildError{err: fmt.Errorf("failed to build module %q: %w", module.Config.Module, err)}
}
return nil
Expand Down
9 changes: 8 additions & 1 deletion internal/buildengine/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ type Engine struct {
parallelism int
listener Listener
modulesToBuild *xsync.MapOf[string, bool]
buildEnv []string
}

type Option func(o *Engine)
Expand All @@ -85,6 +86,12 @@ func Parallelism(n int) Option {
}
}

func BuildEnv(env []string) Option {
return func(o *Engine) {
o.buildEnv = env
}
}

// WithListener sets the event listener for the Engine.
func WithListener(listener Listener) Option {
return func(o *Engine) {
Expand Down Expand Up @@ -698,7 +705,7 @@ func (e *Engine) build(ctx context.Context, moduleName string, builtModules map[
e.listener.OnBuildStarted(meta.module)
}

err := Build(ctx, e.projectRoot, sch, meta.module, e.watcher.GetTransaction(meta.module.Config.Dir))
err := Build(ctx, e.projectRoot, sch, meta.module, e.watcher.GetTransaction(meta.module.Config.Dir), e.buildEnv)
if err != nil {
return err
}
Expand Down
5 changes: 5 additions & 0 deletions internal/exec/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,18 @@ func Capture(ctx context.Context, dir, exe string, args ...string) ([]byte, erro
}

func Command(ctx context.Context, level log.Level, dir, exe string, args ...string) *Cmd {
return CommandWithEnv(ctx, level, dir, []string{}, exe, args...)
}

func CommandWithEnv(ctx context.Context, level log.Level, dir string, env []string, exe string, args ...string) *Cmd {
logger := log.FromContext(ctx)
pgid, err := syscall.Getpgid(0)
if err != nil {
panic(err)
}
logger.Tracef("exec: cd %s && %s %s", shellquote.Join(dir), exe, shellquote.Join(args...))
cmd := exec.CommandContext(ctx, exe, args...)
cmd.Env = append(cmd.Env, env...)
cmd.SysProcAttr = &syscall.SysProcAttr{
Pgid: pgid,
Setpgid: true,
Expand Down

0 comments on commit efc799d

Please sign in to comment.