Skip to content

Commit

Permalink
feat: post-run hook (#111)
Browse files Browse the repository at this point in the history
  • Loading branch information
f0rmiga authored Jan 14, 2022
1 parent f17a4e7 commit 0ea3f54
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 6 deletions.
3 changes: 1 addition & 2 deletions cmd/aspect/run/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,9 @@ use 'bazel run --script_path' to write a script and then execute it.
[]interceptors.Interceptor{
interceptors.WorkspaceRootInterceptor(),
pluginSystem.BESBackendInterceptor(),
pluginSystem.RunHooksInterceptor(streams),
},
func(ctx context.Context, cmd *cobra.Command, args []string) (exitErr error) {
// TODO(f0rmiga): post-run hook.

workspaceRoot := ctx.Value(interceptors.WorkspaceRootKey).(string)
bzl.SetWorkspaceRoot(workspaceRoot)
r := run.New(streams, bzl)
Expand Down
40 changes: 40 additions & 0 deletions pkg/plugin/sdk/v1alpha2/plugin/grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,25 @@ func (m *GRPCServer) PostTestHook(
m.Impl.PostTestHook(req.IsInteractiveMode, prompter)
}

// PostRunHook translates the gRPC call to the Plugin PostRunHook
// implementation. It starts a prompt runner that is passed to the Plugin
// instance to be able to perform prompt actions to the CLI user.
func (m *GRPCServer) PostRunHook(
ctx context.Context,
req *proto.PostRunHookReq,
) (*proto.PostRunHookRes, error) {
conn, err := m.broker.Dial(req.BrokerId)
if err != nil {
return nil, err
}
defer conn.Close()

client := proto.NewPrompterClient(conn)
prompter := &PrompterGRPCClient{client: client}
return &proto.PostRunHookRes{},
m.Impl.PostRunHook(req.IsInteractiveMode, prompter)
}

// GRPCClient implements the gRPC client that is used by the Core to communicate
// with the Plugin instances.
type GRPCClient struct {
Expand Down Expand Up @@ -149,6 +168,27 @@ func (m *GRPCClient) PostTestHook(isInteractiveMode bool, promptRunner ioutils.P
return err
}

// PostRunHook is called from the Core to execute the Plugin PostRunHook. It
// starts the prompt runner server with the provided PromptRunner.
func (m *GRPCClient) PostRunHook(isInteractiveMode bool, promptRunner ioutils.PromptRunner) error {
prompterServer := &PrompterGRPCServer{promptRunner: promptRunner}
var s *grpc.Server
serverFunc := func(opts []grpc.ServerOption) *grpc.Server {
s = grpc.NewServer(opts...)
proto.RegisterPrompterServer(s, prompterServer)
return s
}
brokerID := m.broker.NextId()
go m.broker.AcceptAndServe(brokerID, serverFunc)
req := &proto.PostRunHookReq{
BrokerId: brokerID,
IsInteractiveMode: isInteractiveMode,
}
_, err := m.client.PostRunHook(context.Background(), req)
s.Stop()
return err
}

// PrompterGRPCServer implements the gRPC server that runs on the Core and is
// passed to the Plugin to allow prompt actions to the CLI user.
type PrompterGRPCServer struct {
Expand Down
4 changes: 4 additions & 0 deletions pkg/plugin/sdk/v1alpha2/plugin/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,8 @@ type Plugin interface {
isInteractiveMode bool,
promptRunner ioutils.PromptRunner,
) error
PostRunHook(
isInteractiveMode bool,
promptRunner ioutils.PromptRunner,
) error
}
8 changes: 8 additions & 0 deletions pkg/plugin/sdk/v1alpha2/proto/plugin.proto
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ service Plugin {
rpc BEPEventCallback(BEPEventCallbackReq) returns (BEPEventCallbackRes);
rpc PostBuildHook(PostBuildHookReq) returns (PostBuildHookRes);
rpc PostTestHook(PostTestHookReq) returns (PostTestHookRes);
rpc PostRunHook(PostRunHookReq) returns (PostRunHookRes);
}

message BEPEventCallbackReq {
Expand All @@ -33,6 +34,13 @@ message PostTestHookReq {

message PostTestHookRes {}

message PostRunHookReq {
uint32 broker_id = 1;
bool is_interactive_mode = 2;
}

message PostRunHookRes {}

// Prompter is the service used by the Plugin instances to request prompt
// actions to the Core from the CLI users.
service Prompter {
Expand Down
7 changes: 7 additions & 0 deletions pkg/plugin/system/system.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ type PluginSystem interface {
BESBackendInterceptor() interceptors.Interceptor
BuildHooksInterceptor(streams ioutils.Streams) interceptors.Interceptor
TestHooksInterceptor(streams ioutils.Streams) interceptors.Interceptor
RunHooksInterceptor(streams ioutils.Streams) interceptors.Interceptor
}

type pluginSystem struct {
Expand Down Expand Up @@ -160,6 +161,12 @@ func (ps *pluginSystem) TestHooksInterceptor(streams ioutils.Streams) intercepto
return ps.commandHooksInterceptor("PostTestHook", streams)
}

// TestHooksInterceptor returns an interceptor that runs the pre and post-test
// hooks from all plugins.
func (ps *pluginSystem) RunHooksInterceptor(streams ioutils.Streams) interceptors.Interceptor {
return ps.commandHooksInterceptor("PostRunHook", streams)
}

func (ps *pluginSystem) commandHooksInterceptor(methodName string, streams ioutils.Streams) interceptors.Interceptor {
return func(ctx context.Context, cmd *cobra.Command, args []string, next interceptors.RunEContextFn) (exitErr error) {
isInteractiveMode, err := cmd.Root().PersistentFlags().GetBool(rootFlags.InteractiveFlagName)
Expand Down
15 changes: 11 additions & 4 deletions plugins/fix-visibility/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,17 +154,24 @@ func (plugin *FixVisibilityPlugin) PostBuildHook(
return nil
}

// PostTestHook satisfies the Plugin interface. It prompts the user for
// automatic fixes when in interactive mode. If the user rejects the automatic
// fixes, or if running in non-interactive mode, the commands to perform the fixes
// are printed to the terminal.
// PostTestHook satisfies the Plugin interface. In this case, it just calls the
// PostBuildHook.
func (plugin *FixVisibilityPlugin) PostTestHook(
isInteractiveMode bool,
promptRunner ioutils.PromptRunner,
) error {
return plugin.PostBuildHook(isInteractiveMode, promptRunner)
}

// PostRunHook satisfies the Plugin interface. In this case, it just calls the
// PostBuildHook.
func (plugin *FixVisibilityPlugin) PostRunHook(
isInteractiveMode bool,
promptRunner ioutils.PromptRunner,
) error {
return plugin.PostBuildHook(isInteractiveMode, promptRunner)
}

func (plugin *FixVisibilityPlugin) hasPrivateVisibility(toFix string) (bool, error) {
visibility, err := plugin.buildozer.run("print visibility", toFix)
if err != nil {
Expand Down

0 comments on commit 0ea3f54

Please sign in to comment.