Skip to content

Commit

Permalink
refactor(compute/build): implement a cleaner toolchain abstraction
Browse files Browse the repository at this point in the history
  • Loading branch information
Integralist committed Feb 1, 2023
1 parent 475790c commit 17410d7
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 88 deletions.
22 changes: 15 additions & 7 deletions pkg/commands/compute/language_assemblyscript.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,21 @@ func (a *AssemblyScript) Build(out io.Writer, progress text.Progress, verbose bo
text.Break(out)
}

return build(buildOpts{
buildScript: a.build,
buildFn: a.Shell.Build,
errlog: a.errlog,
postBuild: a.postBuild,
timeout: a.timeout,
}, out, progress, verbose, nil, callback)
progress.Step("Running [scripts.build]...")

bt := BuildToolchain{
buildFn: a.Shell.Build,
buildScript: a.build,
errlog: a.errlog,
postBuild: a.postBuild,
timeout: a.timeout,
out: out,
postBuildCallback: callback,
progress: progress,
verbose: verbose,
}

return bt.Build()
}

func (a AssemblyScript) checkForWebpack() (bool, error) {
Expand Down
22 changes: 15 additions & 7 deletions pkg/commands/compute/language_go.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,21 @@ func (g *Go) Build(out io.Writer, progress text.Progress, verbose bool, callback
"tinygo", `tinygo version (?P<version>\d[^\s]+)`, g.config.TinyGoConstraint,
)

return build(buildOpts{
buildScript: g.build,
buildFn: g.Shell.Build,
errlog: g.errlog,
postBuild: g.postBuild,
timeout: g.timeout,
}, out, progress, verbose, nil, callback)
progress.Step("Running [scripts.build]...")

bt := BuildToolchain{
buildFn: g.Shell.Build,
buildScript: g.build,
errlog: g.errlog,
postBuild: g.postBuild,
timeout: g.timeout,
out: out,
postBuildCallback: callback,
progress: progress,
verbose: verbose,
}

return bt.Build()
}

// toolchainConstraint warns the user if the required constraint is not met.
Expand Down
22 changes: 15 additions & 7 deletions pkg/commands/compute/language_javascript.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,21 @@ func (j *JavaScript) Build(out io.Writer, progress text.Progress, verbose bool,
text.Break(out)
}

return build(buildOpts{
buildScript: j.build,
buildFn: j.Shell.Build,
errlog: j.errlog,
postBuild: j.postBuild,
timeout: j.timeout,
}, out, progress, verbose, nil, callback)
progress.Step("Running [scripts.build]...")

bt := BuildToolchain{
buildFn: j.Shell.Build,
buildScript: j.build,
errlog: j.errlog,
postBuild: j.postBuild,
timeout: j.timeout,
out: out,
postBuildCallback: callback,
progress: progress,
verbose: verbose,
}

return bt.Build()
}

func (j JavaScript) checkForWebpack() (bool, error) {
Expand Down
32 changes: 15 additions & 17 deletions pkg/commands/compute/language_other.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,24 +35,22 @@ type Other struct {
timeout int
}

// Initialize is a no-op.
func (o Other) Initialize(_ io.Writer) error {
return nil
}

// Verify is a no-op.
func (o Other) Verify(_ io.Writer) error {
return nil
}

// Build implements the Toolchain interface and attempts to compile the package
// source to a Wasm binary.
func (o Other) Build(out io.Writer, progress text.Progress, verbose bool, callback func() error) error {
return build(buildOpts{
buildScript: o.build,
buildFn: o.Shell.Build,
errlog: o.errlog,
postBuild: o.postBuild,
timeout: o.timeout,
}, out, progress, verbose, nil, callback)
progress.Step("Running [scripts.build]...")

bt := BuildToolchain{
buildFn: o.Shell.Build,
buildScript: o.build,
errlog: o.errlog,
postBuild: o.postBuild,
timeout: o.timeout,
out: out,
postBuildCallback: callback,
progress: progress,
verbose: verbose,
}

return bt.Build()
}
21 changes: 14 additions & 7 deletions pkg/commands/compute/language_rust.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,13 +106,20 @@ func (r *Rust) Build(out io.Writer, progress text.Progress, verbose bool, callba

progress.Step("Running [scripts.build]...")

return build(buildOpts{
buildScript: r.build,
buildFn: r.Shell.Build,
errlog: r.errlog,
postBuild: r.postBuild,
timeout: r.timeout,
}, out, progress, verbose, r.ProcessLocation, callback)
bt := BuildToolchain{
buildFn: r.Shell.Build,
buildScript: r.build,
errlog: r.errlog,
internalPostBuildCallback: r.ProcessLocation,
postBuild: r.postBuild,
timeout: r.timeout,
out: out,
postBuildCallback: callback,
progress: progress,
verbose: verbose,
}

return bt.Build()
}

// modifyCargoPackageName validates whether the --bin flag matches the
Expand Down
72 changes: 29 additions & 43 deletions pkg/commands/compute/language_toolchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,30 +31,22 @@ type Toolchain interface {
Build(out io.Writer, progress text.Progress, verbose bool, callback func() error) error
}

// buildOpts enables reducing the number of arguments passed to `build()`.
//
// NOTE: We're unable to make the build function generic.
// The generics support in Go1.18 doesn't include accessing struct fields.
type buildOpts struct {
buildScript string
buildFn func(string) (string, []string)
errlog fsterr.LogInterface
postBuild string
timeout int
// BuildToolchain enables a language toolchain to compile their build script.
type BuildToolchain struct {
buildFn func(string) (string, []string)
buildScript string
errlog fsterr.LogInterface
internalPostBuildCallback func() error
out io.Writer
postBuild string
postBuildCallback func() error
progress text.Progress
timeout int
verbose bool
}

// build compiles the user's source code into a Wasm binary.
func build(
opts buildOpts,
out io.Writer,
progress text.Progress,
verbose bool,
internalPostBuildCallback func() error,
postBuildCallback func() error,
) error {
cmd, args := opts.buildFn(opts.buildScript)

err := execCommand(cmd, args, out, progress, verbose, opts.timeout, opts.errlog)
func (bt BuildToolchain) Build() error {
err := bt.execCommand(bt.buildScript)
if err != nil {
return fsterr.RemediationError{
Inner: err,
Expand All @@ -66,8 +58,8 @@ func build(
// It's not a step that would be configured by a user in their fastly.toml
// It enables Rust to move the compiled binary to a different location.
// This has to happen BEFORE the postBuild step.
if internalPostBuildCallback != nil {
err := internalPostBuildCallback()
if bt.internalPostBuildCallback != nil {
err := bt.internalPostBuildCallback()
if err != nil {
return fsterr.RemediationError{
Inner: err,
Expand All @@ -89,12 +81,11 @@ func build(
// NOTE: We set the progress indicator to Done() so that any output we now
// print via the post_build callback doesn't get hidden by the progress status.
// The progress is 'reset' inside the main build controller `build.go`.
progress.Done()
bt.progress.Done()

if opts.postBuild != "" {
if err = postBuildCallback(); err == nil {
cmd, args := opts.buildFn(opts.postBuild)
err := execCommand(cmd, args, out, progress, verbose, opts.timeout, opts.errlog)
if bt.postBuild != "" {
if err = bt.postBuildCallback(); err == nil {
err := bt.execCommand(bt.postBuild)
if err != nil {
return fsterr.RemediationError{
Inner: err,
Expand All @@ -108,27 +99,22 @@ func build(
}

// execCommand opens a sub shell to execute the language build script.
func execCommand(
cmd string,
args []string,
out, progress io.Writer,
verbose bool,
timeout int,
errlog fsterr.LogInterface,
) error {
func (bt BuildToolchain) execCommand(script string) error {
cmd, args := bt.buildFn(script)

s := fstexec.Streaming{
Command: cmd,
Args: args,
Env: os.Environ(),
Output: out,
Progress: progress,
Verbose: verbose,
Output: bt.out,
Progress: bt.progress,
Verbose: bt.verbose,
}
if timeout > 0 {
s.Timeout = time.Duration(timeout) * time.Second
if bt.timeout > 0 {
s.Timeout = time.Duration(bt.timeout) * time.Second
}
if err := s.Exec(); err != nil {
errlog.Add(err)
bt.errlog.Add(err)
return err
}
return nil
Expand Down

0 comments on commit 17410d7

Please sign in to comment.