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

refactor: run plugin system from main #77

Merged
merged 1 commit into from
Dec 8, 2021
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: 2 additions & 0 deletions cmd/aspect/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ go_library(
deps = [
"//cmd/aspect/root",
"//pkg/aspecterrors",
"//pkg/ioutils",
"//pkg/plugin/system",
],
)

Expand Down
4 changes: 2 additions & 2 deletions cmd/aspect/build/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ go_library(
deps = [
"//cmd/aspect/root/flags",
"//pkg/aspect/build",
"//pkg/aspect/build/bep",
"//pkg/aspecterrors",
"//pkg/bazel",
"//pkg/hooks",
"//pkg/ioutils",
"//pkg/plugin/system",
"//pkg/plugin/system/bep",
"@com_github_spf13_cobra//:cobra",
],
)
46 changes: 26 additions & 20 deletions cmd/aspect/build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,59 +7,65 @@ Not licensed for re-use.
package build

import (
"errors"
"fmt"

"github.com/spf13/cobra"

rootFlags "aspect.build/cli/cmd/aspect/root/flags"
"aspect.build/cli/pkg/aspect/build"
"aspect.build/cli/pkg/aspect/build/bep"
"aspect.build/cli/pkg/aspecterrors"
"aspect.build/cli/pkg/bazel"
"aspect.build/cli/pkg/hooks"
"aspect.build/cli/pkg/ioutils"
"aspect.build/cli/pkg/plugin/system"
"aspect.build/cli/pkg/plugin/system/bep"
)

// NewDefaultBuildCmd creates a new build cobra command with the default
// dependencies.
func NewDefaultBuildCmd() *cobra.Command {
func NewDefaultBuildCmd(pluginSystem system.PluginSystem) *cobra.Command {
return NewBuildCmd(
ioutils.DefaultStreams,
pluginSystem,
bazel.New(),
bep.NewBESBackend(),
hooks.New(),
)
}

// NewBuildCmd creates a new build cobra command.
func NewBuildCmd(
streams ioutils.Streams,
pluginSystem system.PluginSystem,
bzl bazel.Spawner,
besBackend bep.BESBackend,
hooks *hooks.Hooks,
) *cobra.Command {
cmd := &cobra.Command{
Use: "build",
Short: "Builds the specified targets, using the options.",
Long: "Invokes bazel build on the specified targets. " +
"See 'bazel help target-syntax' for details and examples on how to specify targets to build.",
RunE: func(cmd *cobra.Command, args []string) (exitErr error) {
pluginSystem := system.NewPluginSystem()
if err := pluginSystem.Configure(streams); err != nil {
return err
}
defer pluginSystem.TearDown()

for node := pluginSystem.PluginList().Head; node != nil; node = node.Next {
besBackend.RegisterSubscriber(node.Plugin.BEPEventCallback)
hooks.RegisterPostBuild(node.Plugin.PostBuildHook)
}

isInteractiveMode, err := cmd.Root().PersistentFlags().GetBool(rootFlags.InteractiveFlagName)
if err != nil {
return err
}

b := build.New(streams, bzl, besBackend, hooks)
return b.Run(cmd.Context(), cmd, args, isInteractiveMode)
// TODO(f0rmiga): test this post-build hook.
defer func() {
errs := pluginSystem.ExecutePostBuild(isInteractiveMode).Errors()
if len(errs) > 0 {
for _, err := range errs {
fmt.Fprintf(streams.Stderr, "Error: failed to run build command: %v\n", err)
}
var err *aspecterrors.ExitError
if errors.As(exitErr, &err) {
err.ExitCode = 1
}
}
}()

b := build.New(streams, bzl)
return pluginSystem.WithBESBackend(cmd.Context(), func(besBackend bep.BESBackend) error {
return b.Run(args, besBackend)
})
},
}

Expand Down
12 changes: 11 additions & 1 deletion cmd/aspect/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import (

"aspect.build/cli/cmd/aspect/root"
"aspect.build/cli/pkg/aspecterrors"
"aspect.build/cli/pkg/ioutils"
"aspect.build/cli/pkg/plugin/system"
)

func main() {
Expand All @@ -34,7 +36,15 @@ func main() {
if wd, exists := os.LookupEnv("BUILD_WORKING_DIRECTORY"); exists {
_ = os.Chdir(wd)
}
cmd := root.NewDefaultRootCmd()

pluginSystem := system.NewPluginSystem()
if err := pluginSystem.Configure(ioutils.DefaultStreams); err != nil {
fmt.Fprintln(os.Stderr, "Error:", err)
os.Exit(1)
}
defer pluginSystem.TearDown()

cmd := root.NewDefaultRootCmd(pluginSystem)
if err := cmd.ExecuteContext(context.Background()); err != nil {
var exitErr *aspecterrors.ExitError
if errors.As(err, &exitErr) {
Expand Down
1 change: 1 addition & 0 deletions cmd/aspect/root/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ go_library(
"//cmd/aspect/version",
"//docs/help/topics",
"//pkg/ioutils",
"//pkg/plugin/system",
"@com_github_fatih_color//:color",
"@com_github_mattn_go_isatty//:go-isatty",
"@com_github_mitchellh_go_homedir//:go-homedir",
Expand Down
13 changes: 9 additions & 4 deletions cmd/aspect/root/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,24 @@ import (
"aspect.build/cli/cmd/aspect/version"
"aspect.build/cli/docs/help/topics"
"aspect.build/cli/pkg/ioutils"
"aspect.build/cli/pkg/plugin/system"
)

var (
boldCyan = color.New(color.FgCyan, color.Bold)
faint = color.New(color.Faint)
)

func NewDefaultRootCmd() *cobra.Command {
func NewDefaultRootCmd(pluginSystem system.PluginSystem) *cobra.Command {
defaultInteractive := isatty.IsTerminal(os.Stdout.Fd()) || isatty.IsCygwinTerminal(os.Stdout.Fd())
return NewRootCmd(ioutils.DefaultStreams, defaultInteractive)
return NewRootCmd(ioutils.DefaultStreams, pluginSystem, defaultInteractive)
}

func NewRootCmd(streams ioutils.Streams, defaultInteractive bool) *cobra.Command {
func NewRootCmd(
streams ioutils.Streams,
pluginSystem system.PluginSystem,
defaultInteractive bool,
) *cobra.Command {
cmd := &cobra.Command{
Use: "aspect",
Short: "Aspect.build bazel wrapper",
Expand Down Expand Up @@ -73,7 +78,7 @@ func NewRootCmd(streams ioutils.Streams, defaultInteractive bool) *cobra.Command

// ### Child commands
// IMPORTANT: when adding a new command, also update the _DOCS list in /docs/BUILD.bazel
cmd.AddCommand(build.NewDefaultBuildCmd())
cmd.AddCommand(build.NewDefaultBuildCmd(pluginSystem))
cmd.AddCommand(clean.NewDefaultCleanCmd())
cmd.AddCommand(version.NewDefaultVersionCmd())
cmd.AddCommand(docs.NewDefaultDocsCmd())
Expand Down
2 changes: 1 addition & 1 deletion cmd/docgen/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ func main() {
os.Exit(1)
}

err := doc.GenMarkdownTree(root.NewDefaultRootCmd(), os.Args[1])
err := doc.GenMarkdownTree(root.NewDefaultRootCmd(nil), os.Args[1])
if err != nil {
log.Fatal(err)
}
Expand Down
7 changes: 2 additions & 5 deletions pkg/aspect/build/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,10 @@ go_library(
importpath = "aspect.build/cli/pkg/aspect/build",
visibility = ["//cmd/aspect/build:__pkg__"],
deps = [
"//pkg/aspect/build/bep",
"//pkg/aspecterrors",
"//pkg/bazel",
"//pkg/hooks",
"//pkg/ioutils",
"@com_github_spf13_cobra//:cobra",
"//pkg/plugin/system/bep",
],
)

Expand All @@ -20,11 +18,10 @@ go_test(
srcs = ["build_test.go"],
deps = [
":build",
"//pkg/aspect/build/bep/mock",
"//pkg/aspecterrors",
"//pkg/bazel/mock",
"//pkg/hooks",
"//pkg/ioutils",
"//pkg/plugin/system/bep/mock",
"@com_github_golang_mock//gomock",
"@com_github_onsi_gomega//:gomega",
],
Expand Down
56 changes: 7 additions & 49 deletions pkg/aspect/build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,81 +7,39 @@ Not licensed for re-use.
package build

import (
"context"
"errors"
"fmt"
"time"

"github.com/spf13/cobra"

"aspect.build/cli/pkg/aspect/build/bep"
"aspect.build/cli/pkg/aspecterrors"
"aspect.build/cli/pkg/bazel"
"aspect.build/cli/pkg/hooks"
"aspect.build/cli/pkg/ioutils"
"aspect.build/cli/pkg/plugin/system/bep"
)

// Build represents the aspect build command.
type Build struct {
ioutils.Streams
bzl bazel.Spawner
besBackend bep.BESBackend
hooks *hooks.Hooks
bzl bazel.Spawner
}

// New creates a Build command.
func New(
streams ioutils.Streams,
bzl bazel.Spawner,
besBackend bep.BESBackend,
hooks *hooks.Hooks,
) *Build {
return &Build{
Streams: streams,
bzl: bzl,
besBackend: besBackend,
hooks: hooks,
Streams: streams,
bzl: bzl,
}
}

// Run runs the aspect build command, calling `bazel build` with a local Build
// Event Protocol backend used by Aspect plugins to subscribe to build events.
func (b *Build) Run(
ctx context.Context,
cmd *cobra.Command,
args []string,
isInteractiveMode bool,
) (exitErr error) {
// TODO(f0rmiga): this is a hook for the build command and should be discussed
// as part of the plugin design.
defer func() {
errs := b.hooks.ExecutePostBuild(isInteractiveMode).Errors()
if len(errs) > 0 {
for _, err := range errs {
fmt.Fprintf(b.Streams.Stderr, "Error: failed to run build command: %v\n", err)
}
var err *aspecterrors.ExitError
if errors.As(exitErr, &err) {
err.ExitCode = 1
}
}
}()

if err := b.besBackend.Setup(); err != nil {
return fmt.Errorf("failed to run build command: %w", err)
}
ctx, cancel := context.WithTimeout(ctx, time.Second)
defer cancel()
if err := b.besBackend.ServeWait(ctx); err != nil {
return fmt.Errorf("failed to run build command: %w", err)
}
defer b.besBackend.GracefulStop()

besBackendFlag := fmt.Sprintf("--bes_backend=grpc://%s", b.besBackend.Addr())
func (b *Build) Run(args []string, besBackend bep.BESBackend) (exitErr error) {
besBackendFlag := fmt.Sprintf("--bes_backend=grpc://%s", besBackend.Addr())
exitCode, bazelErr := b.bzl.Spawn(append([]string{"build", besBackendFlag}, args...))

// Process the subscribers errors before the Bazel one.
subscriberErrors := b.besBackend.Errors()
subscriberErrors := besBackend.Errors()
if len(subscriberErrors) > 0 {
for _, err := range subscriberErrors {
fmt.Fprintf(b.Streams.Stderr, "Error: failed to run build command: %v\n", err)
Expand Down
Loading