Skip to content

Commit

Permalink
feat(manifest): support scripts.env_vars
Browse files Browse the repository at this point in the history
  • Loading branch information
Integralist committed Aug 29, 2023
1 parent 83340ff commit ebb7a16
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 39 deletions.
4 changes: 3 additions & 1 deletion pkg/commands/compute/build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,11 +264,13 @@ func TestBuildGo(t *testing.T) {
name = "test"
language = "go"
[scripts]
build = "env GOARCH=wasm GOOS=wasip1 go build -o bin/main.wasm ./"
build = "go build -o bin/main.wasm ./"
env_vars = ["GOARCH=wasm", "GOOS=wasip1"]
`,
wantOutput: []string{
"The Fastly CLI build step requires a go version '>= 1.21'",
"Build script to execute",
"Build environment variables set",
"GOARCH=wasm GOOS=wasip1",
"Creating ./bin directory (for Wasm binary)",
"Built package",
Expand Down
20 changes: 16 additions & 4 deletions pkg/commands/compute/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -255,10 +255,22 @@ func (c *InitCommand) Exec(in io.Reader, out io.Writer) (err error) {

s := Shell{}
command, args := s.Build(postInit)
noTimeout := 0 // zero indicates no timeout
err := fstexec.Command(
command, args, msg, out, spinner, c.Globals.Flags.Verbose, noTimeout, c.Globals.ErrLog,
)
// gosec flagged this:
// G204 (CWE-78): Subprocess launched with function call as argument or cmd arguments
// Disabling as we require the user to provide this command.
// #nosec
// nosemgrep: go.lang.security.audit.dangerous-exec-command.dangerous-exec-command
err := fstexec.Command(fstexec.CommandOpts{
Args: args,
Command: command,
Env: c.manifest.File.Scripts.EnvVars,
ErrLog: c.Globals.ErrLog,
Output: out,
Spinner: spinner,
SpinnerMessage: msg,
Timeout: 0, // zero indicates no timeout
Verbose: c.Globals.Flags.Verbose,
})
if err != nil {
return err
}
Expand Down
4 changes: 4 additions & 0 deletions pkg/commands/compute/language_go.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ func NewGo(
autoYes: globals.Flags.AutoYes,
build: fastlyManifest.Scripts.Build,
config: globals.Config.Language.Go,
env: fastlyManifest.Scripts.EnvVars,
errlog: globals.ErrLog,
input: in,
nonInteractive: globals.Flags.NonInteractive,
Expand All @@ -73,6 +74,8 @@ type Go struct {
build string
// config is the Go specific application configuration.
config config.Go
// env is environment variables to be set.
env []string
// errlog is an abstraction for recording errors to disk.
errlog fsterr.LogInterface
// input is the user's terminal stdin stream
Expand Down Expand Up @@ -143,6 +146,7 @@ func (g *Go) Build() error {
autoYes: g.autoYes,
buildFn: g.Shell.Build,
buildScript: g.build,
env: g.env,
errlog: g.errlog,
in: g.input,
nonInteractive: g.nonInteractive,
Expand Down
19 changes: 16 additions & 3 deletions pkg/commands/compute/language_toolchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ type BuildToolchain struct {
buildFn func(string) (string, []string)
// buildScript is the [scripts.build] within the fastly.toml manifest.
buildScript string
// env is environment variables to be set.
env []string
// errlog is an abstraction for recording errors to disk.
errlog fsterr.LogInterface
// in is the user's terminal stdin stream
Expand Down Expand Up @@ -69,6 +71,9 @@ func (bt BuildToolchain) Build() error {
if bt.verbose {
text.Break(bt.out)
text.Description(bt.out, "Build script to execute", fmt.Sprintf("%s %s", cmd, strings.Join(args, " ")))
if len(bt.env) > 0 {
text.Description(bt.out, "Build environment variables set", strings.Join(bt.env, " "))
}
}

var err error
Expand Down Expand Up @@ -194,9 +199,17 @@ func (bt BuildToolchain) handleError(err error) error {
// This causes the spinner message to be displayed twice with different status.
// By passing in the spinner and message we can short-circuit the spinner.
func (bt BuildToolchain) execCommand(cmd string, args []string, spinMessage string) error {
return fstexec.Command(
cmd, args, spinMessage, bt.out, bt.spinner, bt.verbose, bt.timeout, bt.errlog,
)
return fstexec.Command(fstexec.CommandOpts{
Args: args,
Command: cmd,
Env: bt.env,
ErrLog: bt.errlog,
Output: bt.out,
Spinner: bt.spinner,
SpinnerMessage: spinMessage,
Timeout: bt.timeout,
Verbose: bt.verbose,
})
}

// promptForPostBuildContinue ensures the user is happy to continue with the build
Expand Down
86 changes: 55 additions & 31 deletions pkg/exec/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,28 @@ const divider = "---------------------------------------------------------------
// compute commands can use this to standardize the flow control for each
// compiler toolchain.
type Streaming struct {
Args []string
Command string
Env []string
ForceOutput bool
Output io.Writer
Process *os.Process
SignalCh chan os.Signal
Spinner text.Spinner
// Args are the command positional arguments.
Args []string
// Command is the command to be executed.
Command string
// Env is the environment variables to set.
Env []string
// ForceOutput ensures output is displayed (default: only display on error).
ForceOutput bool
// Output is where to write output (e.g. stdout)
Output io.Writer
// Process is the process to terminal if signal received.
Process *os.Process
// SignalCh is a channel handling signal events.
SignalCh chan os.Signal
// Spinner is a specific spinner instance.
Spinner text.Spinner
// SpinnerMessage is the messaging to use.
SpinnerMessage string
Timeout time.Duration
Verbose bool
// Timeout is the command timeout.
Timeout time.Duration
// Verbose outputs additional information.
Verbose bool
}

// MonitorSignals spawns a goroutine that configures signal handling so that
Expand Down Expand Up @@ -157,35 +168,48 @@ func (s *Streaming) Signal(sig os.Signal) error {
return nil
}

// CommandOpts are arguments for executing a streaming command.
type CommandOpts struct {
// Args are the command positional arguments.
Args []string
// Command is the command to be executed.
Command string
// Env is the environment variables to set.
Env []string
// ErrLog provides an interface for recording errors to disk.
ErrLog fsterr.LogInterface
// Output is where to write output (e.g. stdout)
Output io.Writer
// Spinner is a specific spinner instance.
Spinner text.Spinner
// SpinnerMessage is the messaging to use.
SpinnerMessage string
// Timeout is the command timeout.
Timeout int
// Verbose outputs additional information.
Verbose bool
}

// Command is an abstraction over a Streaming type. It is used by both the
// `compute init` and `compute build` commands to run post init/build scripts.
func Command(
cmd string,
args []string,
spinMessage string,
out io.Writer,
spinner text.Spinner,
verbose bool,
timeout int,
errLog fsterr.LogInterface,
) error {
func Command(opts CommandOpts) error {
s := Streaming{
Command: cmd,
Args: args,
Env: os.Environ(),
Output: out,
Spinner: spinner,
SpinnerMessage: spinMessage,
Verbose: verbose,
Command: opts.Command,
Args: opts.Args,
Env: opts.Env,
Output: opts.Output,
Spinner: opts.Spinner,
SpinnerMessage: opts.SpinnerMessage,
Verbose: opts.Verbose,
}
if verbose {
if opts.Verbose {
s.ForceOutput = true
}
if timeout > 0 {
s.Timeout = time.Duration(timeout) * time.Second
if opts.Timeout > 0 {
s.Timeout = time.Duration(opts.Timeout) * time.Second
}
if err := s.Exec(); err != nil {
errLog.Add(err)
opts.ErrLog.Add(err)
return err
}
return nil
Expand Down
2 changes: 2 additions & 0 deletions pkg/manifest/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ func appendSpecRef(w io.Writer) error {
type Scripts struct {
// Build is a custom build script.
Build string `toml:"build,omitempty"`
// EnvVars contains build related environment variables.
EnvVars []string `toml:"env_vars,omitempty"`
// PostBuild is executed after the build step.
PostBuild string `toml:"post_build,omitempty"`
// PostInit is executed after the init step.
Expand Down

0 comments on commit ebb7a16

Please sign in to comment.