(ctx context.Context, cfg *configfile.ConfigFile, rootCmd, subCmd *cobra.Command, subCmdStr string, flags map[string]string, cmdErrorMessage string)
| 54 | } |
| 55 | |
| 56 | func invokeAndCollectHooks(ctx context.Context, cfg *configfile.ConfigFile, rootCmd, subCmd *cobra.Command, subCmdStr string, flags map[string]string, cmdErrorMessage string) []string { |
| 57 | if ctx.Err() != nil { |
| 58 | return nil |
| 59 | } |
| 60 | |
| 61 | pluginsCfg := cfg.Plugins |
| 62 | if pluginsCfg == nil { |
| 63 | return nil |
| 64 | } |
| 65 | |
| 66 | pluginDirs := getPluginDirs(cfg) |
| 67 | nextSteps := make([]string, 0, len(pluginsCfg)) |
| 68 | |
| 69 | tryInvokeHook := func(pluginName string, pluginCfg map[string]string) (messages []string, ok bool, err error) { |
| 70 | match, matched := pluginMatch(pluginCfg, subCmdStr, cmdErrorMessage) |
| 71 | if !matched { |
| 72 | return nil, false, nil |
| 73 | } |
| 74 | |
| 75 | p, err := getPlugin(pluginName, pluginDirs, rootCmd) |
| 76 | if err != nil { |
| 77 | return nil, false, err |
| 78 | } |
| 79 | |
| 80 | resp, err := p.RunHook(ctx, hooks.Request{ |
| 81 | RootCmd: match, |
| 82 | Flags: flags, |
| 83 | CommandError: cmdErrorMessage, |
| 84 | }) |
| 85 | if err != nil { |
| 86 | return nil, false, err |
| 87 | } |
| 88 | |
| 89 | var message hooks.Response |
| 90 | if err := json.Unmarshal(resp, &message); err != nil { |
| 91 | return nil, false, fmt.Errorf("failed to unmarshal hook response (%q): %w", string(resp), err) |
| 92 | } |
| 93 | |
| 94 | // currently the only hook type |
| 95 | if message.Type != hooks.NextSteps { |
| 96 | return nil, false, errors.New("unexpected hook response type: " + strconv.Itoa(int(message.Type))) |
| 97 | } |
| 98 | |
| 99 | messages, err = hooks.ParseTemplate(message.Template, subCmd) |
| 100 | if err != nil { |
| 101 | return nil, false, err |
| 102 | } |
| 103 | |
| 104 | return messages, true, nil |
| 105 | } |
| 106 | |
| 107 | for pluginName, pluginCfg := range pluginsCfg { |
| 108 | messages, ok, err := tryInvokeHook(pluginName, pluginCfg) |
| 109 | if err != nil { |
| 110 | // skip misbehaving plugins, but don't halt execution |
| 111 | logrus.WithFields(logrus.Fields{ |
| 112 | "error": err, |
| 113 | "plugin": pluginName, |
searching dependent graphs…