Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove user environment validation logic #785

Merged
merged 24 commits into from
Feb 6, 2023
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
8a89957
refactor(compute/init): remove unused argument
Integralist Jan 30, 2023
a2c6d55
refactor(compute/init): rename prompt functions for clarity
Integralist Jan 30, 2023
73810b8
refactor(compute/init): avoid invalid-usage-of-modified-variable issues
Integralist Jan 30, 2023
0774643
refactor(compute/build): move package name logic into separate function
Integralist Jan 30, 2023
5a12b8b
refactor(compute/build): move toolchain logic into separate function
Integralist Jan 30, 2023
3bf6614
refactor(compute/build): move language logic into separate function
Integralist Jan 30, 2023
31052be
refactor(compute/build): move bin directory logic into separate function
Integralist Jan 30, 2023
51a2d89
refactor(compute): remove unused IncludeFiles
Integralist Jan 30, 2023
31e45ac
refactor(compute): remove --skip-verification
Integralist Jan 30, 2023
fc95d60
refactor(compute/init): remove unused args from NewLanguages
Integralist Jan 30, 2023
65c9b4b
refactor(compute): restructure types
Integralist Jan 30, 2023
b239b5f
refactor(compute): remove methods from Toolchain interface
Integralist Jan 30, 2023
249e031
refactor(compute/init): simplify/clean-up init logic
Integralist Jan 30, 2023
17726c1
fix(compute): tests
Integralist Jan 30, 2023
710f722
feat(compute/build): update Rust build logic
Integralist Jan 31, 2023
6909890
feat(compute/build): update Go build logic
Integralist Jan 31, 2023
a391eb8
feat(compute/build): update JavaScript build logic
Integralist Jan 31, 2023
88ec014
refactor(compute/toolchain): clean-up unused types and functions
Integralist Jan 31, 2023
818e80b
feat(compute/build): clean-up tests
Integralist Feb 1, 2023
b3a6fef
refactor(compute/build): implement a cleaner toolchain abstraction
Integralist Feb 1, 2023
4d75162
fix: support for go1.20.0
Integralist Feb 6, 2023
be74e8d
fix(compute/build): correct the src directory for assemblyscript
Integralist Feb 6, 2023
c28f20c
docs(build): reference URL for clearing GitHub Actions cache
Integralist Feb 6, 2023
5c9c7c5
fix: support for go1.19.0
Integralist Feb 6, 2023
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ RELEASE_CHANGELOG.md
rust-toolchain
.cargo
**/node_modules
pkg/commands/compute/package-lock.json

# Binaries for programs and plugins
*.exe
Expand Down
279 changes: 141 additions & 138 deletions pkg/commands/compute/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,10 @@ const CustomPostBuildScriptMessage = "This project has a custom post build scrip

// Flags represents the flags defined for the command.
type Flags struct {
IncludeSrc bool
Lang string
PackageName string
SkipVerification bool
Timeout int
IncludeSrc bool
Lang string
PackageName string
Timeout int
}

// BuildCommand produces a deployable artifact from files on the local disk.
Expand All @@ -58,7 +57,6 @@ func NewBuildCommand(parent cmd.Registerer, globals *config.Data, data manifest.
c.CmdClause.Flag("include-source", "Include source code in built package").BoolVar(&c.Flags.IncludeSrc)
c.CmdClause.Flag("language", "Language type").StringVar(&c.Flags.Lang)
c.CmdClause.Flag("package-name", "Package name").StringVar(&c.Flags.PackageName)
c.CmdClause.Flag("skip-verification", "Skip verification steps and force build").BoolVar(&c.Flags.SkipVerification)
c.CmdClause.Flag("timeout", "Timeout, in seconds, for the build compilation step").IntVar(&c.Flags.Timeout)

return &c
Expand Down Expand Up @@ -92,24 +90,135 @@ func (c *BuildCommand) Exec(in io.Reader, out io.Writer) (err error) {
return err
}

var packageName string
packageName, err := packageName(c)
if err != nil {
return err
}

toolchain, err := toolchain(c)
if err != nil {
return err
}

language, err := language(toolchain, c, progress)
if err != nil {
return err
}

err = binDir(c)
if err != nil {
return err
}

// NOTE: We set the progress indicator to Done() so that any output we now
// print doesn't get hidden by the progress status.
progress.Done()

if c.Globals.Verbose() {
text.Break(out)
}

progress = text.ResetProgress(out, c.Globals.Verbose())

postBuildCallback := func() error {
if !c.Globals.Flag.AutoYes && !c.Globals.Flag.NonInteractive {
err := promptForBuildContinue(CustomPostBuildScriptMessage, c.Manifest.File.Scripts.PostBuild, out, in, c.Globals.Verbose())
if err != nil {
return err
}
}
return nil
}

if err := language.Build(out, progress, c.Globals.Flag.Verbose, postBuildCallback); err != nil {
c.Globals.ErrLog.AddWithContext(err, map[string]any{
"Language": language.Name,
})
return err
}

if c.Globals.Verbose() {
text.Break(out)
}

progress = text.ResetProgress(out, c.Globals.Verbose())
progress.Step("Creating package archive...")

dest := filepath.Join("pkg", fmt.Sprintf("%s.tar.gz", packageName))

files := []string{
manifest.Filename,
}

ignoreFiles, err := GetIgnoredFiles(IgnoreFilePath)
if err != nil {
c.Globals.ErrLog.Add(err)
return err
}

binFiles, err := GetNonIgnoredFiles("bin", ignoreFiles)
if err != nil {
c.Globals.ErrLog.AddWithContext(err, map[string]any{
"Ignore files": ignoreFiles,
})
return err
}
files = append(files, binFiles...)

if c.Flags.IncludeSrc {
srcFiles, err := GetNonIgnoredFiles(language.SourceDirectory, ignoreFiles)
if err != nil {
c.Globals.ErrLog.AddWithContext(err, map[string]any{
"Source directory": language.SourceDirectory,
"Ignore files": ignoreFiles,
})
return err
}
files = append(files, srcFiles...)
}

err = CreatePackageArchive(files, dest)
if err != nil {
c.Globals.ErrLog.AddWithContext(err, map[string]any{
"Files": files,
"Destination": dest,
})
return fmt.Errorf("error creating package archive: %w", err)
}

progress.Done()

out = originalOut
text.Success(out, "Built package (%s)", dest)
return nil
}

// packageName acquires the package name from either a flag or manifest.
// Additionally it will sanitize the name.
func packageName(c *BuildCommand) (string, error) {
var name string

switch {
case c.Flags.PackageName != "":
packageName = c.Flags.PackageName
name = c.Flags.PackageName
case c.Manifest.File.Name != "":
packageName = c.Manifest.File.Name // use the project name as a fallback
name = c.Manifest.File.Name // use the project name as a fallback
default:
return fsterr.RemediationError{
return "", fsterr.RemediationError{
Inner: fmt.Errorf("package name is missing"),
Remediation: "Add a name to the fastly.toml 'name' field. Reference: https://developer.fastly.com/reference/compute/fastly-toml/",
}
}

packageName = sanitize.BaseName(packageName)
return sanitize.BaseName(name), nil
}

// Language from flag takes priority, otherwise infer from manifest and
// error if neither are provided. Sanitize by trim and lowercase.
// toolchain determines the programming language.
//
// It prioritises the --language flag over the manifest field.
// Will error if neither are provided.
// Lastly, it will normalise with a trim and lowercase.
func toolchain(c *BuildCommand) (string, error) {
var toolchain string

switch {
Expand All @@ -118,69 +227,64 @@ func (c *BuildCommand) Exec(in io.Reader, out io.Writer) (err error) {
case c.Manifest.File.Language != "":
toolchain = c.Manifest.File.Language
default:
return fmt.Errorf("language cannot be empty, please provide a language")
return "", fmt.Errorf("language cannot be empty, please provide a language")
}

toolchain = strings.ToLower(strings.TrimSpace(toolchain))

// ch is used to identify if the fastly.toml manifest has been patched with a
// language specific default build command (because one was missing).
ch := make(chan string)
return strings.ToLower(strings.TrimSpace(toolchain)), nil
}

// language returns a pointer to a supported language.
func language(toolchain string, c *BuildCommand, progress text.Progress) (*Language, error) {
var language *Language
switch toolchain {
case "assemblyscript":
language = NewLanguage(&LanguageOptions{
Name: "assemblyscript",
SourceDirectory: AsSourceDirectory,
IncludeFiles: []string{},
Toolchain: NewAssemblyScript(
&c.Manifest.File,
c.Globals.ErrLog,
c.Flags.Timeout,
progress,
ch,
c.Globals.Verbose(),
),
})
case "go":
language = NewLanguage(&LanguageOptions{
Name: "go",
SourceDirectory: GoSourceDirectory,
IncludeFiles: []string{},
Toolchain: NewGo(
&c.Manifest.File,
c.Globals.ErrLog,
c.Flags.Timeout,
c.Globals.File.Language.Go,
progress,
ch,
c.Globals.Verbose(),
),
})
case "javascript":
language = NewLanguage(&LanguageOptions{
Name: "javascript",
SourceDirectory: JsSourceDirectory,
IncludeFiles: []string{},
Toolchain: NewJavaScript(
&c.Manifest.File,
c.Globals.ErrLog,
c.Flags.Timeout,
progress,
ch,
c.Globals.Verbose(),
),
})
case "rust":
language = NewLanguage(&LanguageOptions{
Name: "rust",
SourceDirectory: RustSourceDirectory,
IncludeFiles: []string{},
Toolchain: NewRust(
&c.Manifest.File,
c.Globals.ErrLog,
c.Flags.Timeout,
c.Globals.File.Language.Rust,
progress,
ch,
c.Globals.Verbose(),
),
})
case "other":
Expand All @@ -193,10 +297,18 @@ func (c *BuildCommand) Exec(in io.Reader, out io.Writer) (err error) {
),
})
default:
return fmt.Errorf("unsupported language %s", toolchain)
return nil, fmt.Errorf("unsupported language %s", toolchain)
}

// NOTE: A ./bin directory is required for the main.wasm to be placed inside.
return language, nil
}

// binDir ensures a ./bin directory exists.
// The directory is required so a main.wasm can be placed inside it.
func binDir(c *BuildCommand) error {
if c.Globals.Verbose() {
text.Info(c.Globals.Output, "Creating ./bin directory (for Wasm binary)")
}
dir, err := os.Getwd()
if err != nil {
c.Globals.ErrLog.Add(err)
Expand All @@ -207,115 +319,6 @@ func (c *BuildCommand) Exec(in io.Reader, out io.Writer) (err error) {
c.Globals.ErrLog.Add(err)
return fmt.Errorf("failed to create bin directory: %w", err)
}

if !c.Flags.SkipVerification {
progress.Step(fmt.Sprintf("Verifying local %s toolchain...", toolchain))

err = language.Verify(progress)
if err != nil {
c.Globals.ErrLog.AddWithContext(err, map[string]any{
"Language": language.Name,
})
return err
}
}

// NOTE: We set the progress indicator to Done() so that any output we now
// print doesn't get hidden by the progress status.
progress.Done()

if c.Globals.Verbose() {
text.Break(out)
}

progress = text.ResetProgress(out, c.Globals.Verbose())
progress.Step("Running [scripts.build]...")

postBuildCallback := func() error {
if !c.Globals.Flag.AutoYes && !c.Globals.Flag.NonInteractive {
err := promptForBuildContinue(CustomPostBuildScriptMessage, c.Manifest.File.Scripts.PostBuild, out, in, c.Globals.Verbose())
if err != nil {
return err
}
}
return nil
}

if err := language.Build(out, progress, c.Globals.Flag.Verbose, postBuildCallback); err != nil {
c.Globals.ErrLog.AddWithContext(err, map[string]any{
"Language": language.Name,
})
return err
}

if c.Globals.Verbose() {
text.Break(out)
}

progress = text.ResetProgress(out, c.Globals.Verbose())
progress.Step("Creating package archive...")

dest := filepath.Join("pkg", fmt.Sprintf("%s.tar.gz", packageName))

files := []string{
manifest.Filename,
}
files = append(files, language.IncludeFiles...)

ignoreFiles, err := GetIgnoredFiles(IgnoreFilePath)
if err != nil {
c.Globals.ErrLog.Add(err)
return err
}

binFiles, err := GetNonIgnoredFiles("bin", ignoreFiles)
if err != nil {
c.Globals.ErrLog.AddWithContext(err, map[string]any{
"Ignore files": ignoreFiles,
})
return err
}
files = append(files, binFiles...)

if c.Flags.IncludeSrc {
srcFiles, err := GetNonIgnoredFiles(language.SourceDirectory, ignoreFiles)
if err != nil {
c.Globals.ErrLog.AddWithContext(err, map[string]any{
"Source directory": language.SourceDirectory,
"Ignore files": ignoreFiles,
})
return err
}
files = append(files, srcFiles...)
}

err = CreatePackageArchive(files, dest)
if err != nil {
c.Globals.ErrLog.AddWithContext(err, map[string]any{
"Files": files,
"Destination": dest,
})
return fmt.Errorf("error creating package archive: %w", err)
}

progress.Done()

// When patching fastly.toml with a default build command, in --verbose mode
// that information is already printed to the screen, but in standard output
// mode we need to ensure it's visible so users know the fastly.toml has been
// updated.
if !c.Globals.Verbose() {
select {
case msg := <-ch:
text.Info(out, msg)
default:
// no message, so moving on to prevent deadlock
}
close(ch)
}

out = originalOut
text.Success(out, "Built package (%s)", dest)
return nil
}

Expand Down
Loading