Skip to content

Commit

Permalink
refactor: run plugin system from main
Browse files Browse the repository at this point in the history
Signed-off-by: Thulio Ferraz Assis <3149049+f0rmiga@users.noreply.github.com>
  • Loading branch information
f0rmiga committed Nov 23, 2021
1 parent 27b3719 commit cd21ef5
Show file tree
Hide file tree
Showing 24 changed files with 182 additions and 333 deletions.
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

0 comments on commit cd21ef5

Please sign in to comment.