Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
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
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ build: config ## Compile program (CGO disabled)

GO_BIN ?= go ## Allows overriding go executable.
TEST_COMMAND ?= $(GO_BIN) test ## Enables support for tools such as https://github.com/rakyll/gotest
TEST_ARGS ?= -timeout 15m ./... ## The compute tests can sometimes exceed the default 10m limit
TEST_ARGS ?= -v -timeout 15m ./... ## The compute tests can sometimes exceed the default 10m limit

GOHOSTOS ?= $(shell go env GOHOSTOS || echo unknown)
GOHOSTARCH ?= $(shell go env GOHOSTARCH || echo unknown)
Expand Down
6 changes: 3 additions & 3 deletions pkg/commands/compute/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ import (
// IgnoreFilePath is the filepath name of the Fastly ignore file.
const IgnoreFilePath = ".fastlyignore"

// CustomPostBuildScriptMessage is the message displayed to a user when there is a
// custom post build script.
const CustomPostBuildScriptMessage = "This project has a custom post build script defined in the fastly.toml manifest"
// CustomPostScriptMessage is the message displayed to a user when there is
// either a post_init or post_build script defined.
const CustomPostScriptMessage = "This project has a custom post_%s script defined in the fastly.toml manifest"

// Flags represents the flags defined for the command.
type Flags struct {
Expand Down
15 changes: 7 additions & 8 deletions pkg/commands/compute/build_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package compute_test

import (
"bytes"
"fmt"
"os"
"os/exec"
Expand Down Expand Up @@ -185,7 +184,7 @@ func TestBuildRust(t *testing.T) {
}
defer os.Chdir(pwd)

var stdout bytes.Buffer
var stdout threadsafe.Buffer
opts := testutil.NewRunOpts(testcase.args, &stdout)
opts.ConfigFile = testcase.applicationConfig
err = app.Run(opts)
Expand Down Expand Up @@ -345,7 +344,7 @@ func TestBuildGo(t *testing.T) {
}
defer os.Chdir(pwd)

var stdout bytes.Buffer
var stdout threadsafe.Buffer
opts := testutil.NewRunOpts(testcase.args, &stdout)
opts.ConfigFile = testcase.applicationConfig
err = app.Run(opts)
Expand Down Expand Up @@ -651,7 +650,7 @@ func TestBuildAssemblyScript(t *testing.T) {
}
}

var stdout bytes.Buffer
var stdout threadsafe.Buffer
opts := testutil.NewRunOpts(testcase.args, &stdout)
err = app.Run(opts)
t.Log(stdout.String())
Expand Down Expand Up @@ -726,7 +725,7 @@ func TestBuildOther(t *testing.T) {
stdin: "N",
wantOutput: []string{
"echo doing a post build",
"Are you sure you want to continue with the post build step?",
"Do you want to run this now?",
},
wantError: "build process stopped by user",
},
Expand All @@ -743,7 +742,7 @@ func TestBuildOther(t *testing.T) {
stdin: "Y",
wantOutput: []string{
"echo doing a post build",
"Are you sure you want to continue with the post build step?",
"Do you want to run this now?",
"Built package",
},
},
Expand All @@ -760,7 +759,7 @@ func TestBuildOther(t *testing.T) {
stdin: "Y",
wantOutput: []string{
"echo doing a post build",
"Are you sure you want to continue with the post build step?",
"Do you want to run this now?",
"Built package",
},
},
Expand All @@ -777,7 +776,7 @@ func TestBuildOther(t *testing.T) {
"doing a post build with no confirmation prompt",
},
dontWantOutput: []string{
"Are you sure you want to continue with the build step?",
"Do you want to run this now?",
},
wantError: "exit status 1", // because we have to trigger an error to see the post_build output
},
Expand Down
5 changes: 3 additions & 2 deletions pkg/commands/compute/compute_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ import (
"reflect"
"testing"

"github.com/fastly/kingpin"
"github.com/mholt/archiver/v3"

"github.com/fastly/cli/pkg/commands/compute"
"github.com/fastly/cli/pkg/github"
"github.com/fastly/cli/pkg/global"
"github.com/fastly/cli/pkg/manifest"
"github.com/fastly/cli/pkg/testutil"
"github.com/fastly/kingpin"
"github.com/mholt/archiver/v3"
)

// TestPublishFlagDivergence validates that the manually curated list of flags
Expand Down
64 changes: 64 additions & 0 deletions pkg/commands/compute/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/fastly/cli/pkg/cmd"
"github.com/fastly/cli/pkg/config"
fsterr "github.com/fastly/cli/pkg/errors"
fstexec "github.com/fastly/cli/pkg/exec"
"github.com/fastly/cli/pkg/file"
"github.com/fastly/cli/pkg/filesystem"
"github.com/fastly/cli/pkg/global"
Expand Down Expand Up @@ -225,6 +226,50 @@ func (c *InitCommand) Exec(in io.Reader, out io.Writer) (err error) {
return fmt.Errorf("error initializing package: %w", err)
}

var md manifest.Data
err = md.File.Read(manifest.Filename)
if err != nil {
return fmt.Errorf("failed to read manifest after initialisation: %w", err)
}

postInit := md.File.Scripts.PostInit
if postInit != "" {
if !c.Globals.Flags.AutoYes && !c.Globals.Flags.NonInteractive {
msg := fmt.Sprintf(CustomPostScriptMessage, "init")
err := promptForPostInitContinue(msg, postInit, out, in)
if err != nil {
if errors.Is(err, fsterr.ErrPostInitStopped) {
displayOutput(mf.Name, dst, language.Name, out)
return nil
}
return err
}
}

err = spinner.Start()
if err != nil {
return err
}
msg := "Running [scripts.post_init]..."
spinner.Message(msg)

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,
)
if err != nil {
return err
}

spinner.StopMessage(msg)
err = spinner.Stop()
if err != nil {
return err
}
}

displayOutput(mf.Name, dst, language.Name, out)
return nil
}
Expand Down Expand Up @@ -1141,6 +1186,25 @@ func initializeLanguage(spinner text.Spinner, language *Language, languages []*L
return language, nil
}

// promptForPostInitContinue ensures the user is happy to continue with running
// the define post_init script in the fastly.toml manifest file.
func promptForPostInitContinue(msg, script string, out io.Writer, in io.Reader) error {
text.Info(out, "%s:\n", msg)
text.Break(out)
text.Indent(out, 4, "%s", script)

label := "\nDo you want to run this now? [y/N] "
answer, err := text.AskYesNo(out, label, in)
if err != nil {
return err
}
if !answer {
return fsterr.ErrPostInitStopped
}
text.Break(out)
return nil
}

// displayOutput of package information and useful links.
func displayOutput(name, dst, language string, out io.Writer) {
text.Break(out)
Expand Down
38 changes: 10 additions & 28 deletions pkg/commands/compute/language_toolchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"io"
"os"
"strings"
"time"

fsterr "github.com/fastly/cli/pkg/errors"
fstexec "github.com/fastly/cli/pkg/exec"
Expand Down Expand Up @@ -148,7 +147,8 @@ func (bt BuildToolchain) Build() error {

if bt.postBuild != "" {
if !bt.autoYes && !bt.nonInteractive {
err := bt.promptForBuildContinue(CustomPostBuildScriptMessage, bt.postBuild, bt.out, bt.in)
msg := fmt.Sprintf(CustomPostScriptMessage, "build")
err := bt.promptForPostBuildContinue(msg, bt.postBuild, bt.out, bt.in)
if err != nil {
return err
}
Expand Down Expand Up @@ -194,43 +194,25 @@ 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 {
s := fstexec.Streaming{
Command: cmd,
Args: args,
Env: os.Environ(),
Output: bt.out,
Spinner: bt.spinner,
SpinnerMessage: spinMessage,
Verbose: bt.verbose,
}
if bt.verbose {
s.ForceOutput = true
}
if bt.timeout > 0 {
s.Timeout = time.Duration(bt.timeout) * time.Second
}
if err := s.Exec(); err != nil {
bt.errlog.Add(err)
return err
}
return nil
return fstexec.Command(
cmd, args, spinMessage, bt.out, bt.spinner, bt.verbose, bt.timeout, bt.errlog,
)
}

// promptForBuildContinue ensures the user is happy to continue with the build
// when there is either a custom build or post build in the fastly.toml
// manifest file.
func (bt BuildToolchain) promptForBuildContinue(msg, script string, out io.Writer, in io.Reader) error {
// promptForPostBuildContinue ensures the user is happy to continue with the build
// when there is a post_build in the fastly.toml manifest file.
func (bt BuildToolchain) promptForPostBuildContinue(msg, script string, out io.Writer, in io.Reader) error {
text.Info(out, "%s:\n", msg)
text.Break(out)
text.Indent(out, 4, "%s", script)

label := "\nAre you sure you want to continue with the post build step? [y/N] "
label := "\nDo you want to run this now? [y/N] "
answer, err := text.AskYesNo(out, label, in)
if err != nil {
return err
}
if !answer {
return fsterr.ErrBuildStopped
return fsterr.ErrPostBuildStopped
}
text.Break(out)
return nil
Expand Down
13 changes: 10 additions & 3 deletions pkg/errors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,18 @@ var ErrInvalidArchive = RemediationError{
Remediation: "Ensure the archive contains all required package files (such as a 'fastly.toml' manifest, and a 'src' folder etc).",
}

// ErrBuildStopped means the user stopped the build because they were unhappy
// ErrPostInitStopped means the user stopped the init process because they were
// unhappy with the custom post_init defined in the fastly.toml manifest file.
var ErrPostInitStopped = RemediationError{
Inner: fmt.Errorf("init process stopped by user"),
Remediation: "Check the [scripts.post_init] in the fastly.toml manifest is safe to execute or skip this prompt using either `--auto-yes` or `--non-interactive`.",
}

// ErrPostBuildStopped means the user stopped the build because they were unhappy
// with the custom build defined in the fastly.toml manifest file.
var ErrBuildStopped = RemediationError{
var ErrPostBuildStopped = RemediationError{
Inner: fmt.Errorf("build process stopped by user"),
Remediation: "Check the [scripts.build] in the fastly.toml manifest is safe to execute or skip this prompt using either `--auto-yes` or `--non-interactive`.",
Remediation: "Check the [scripts.post_build] in the fastly.toml manifest is safe to execute or skip this prompt using either `--auto-yes` or `--non-interactive`.",
}

// ErrInvalidVerboseJSONCombo means the user provided both a --verbose and
Expand Down
35 changes: 35 additions & 0 deletions pkg/exec/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"syscall"
"time"

fsterr "github.com/fastly/cli/pkg/errors"
"github.com/fastly/cli/pkg/text"
"github.com/fastly/cli/pkg/threadsafe"
)
Expand Down Expand Up @@ -155,3 +156,37 @@ func (s *Streaming) Signal(sig os.Signal) error {
}
return nil
}

// 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 {
s := Streaming{
Command: cmd,
Args: args,
Env: os.Environ(),
Output: out,
Spinner: spinner,
SpinnerMessage: spinMessage,
Verbose: verbose,
}
if verbose {
s.ForceOutput = true
}
if timeout > 0 {
s.Timeout = time.Duration(timeout) * time.Second
}
if err := s.Exec(); err != nil {
errLog.Add(err)
return err
}
return nil
}
1 change: 1 addition & 0 deletions pkg/manifest/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,4 +190,5 @@ func appendSpecRef(w io.Writer) error {
type Scripts struct {
Build string `toml:"build,omitempty"`
PostBuild string `toml:"post_build,omitempty"`
PostInit string `toml:"post_init,omitempty"`
}