-
Notifications
You must be signed in to change notification settings - Fork 36
#2090 - Introduce extensibility to Chainloop CLI #2091
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
base: main
Are you sure you want to change the base?
#2090 - Introduce extensibility to Chainloop CLI #2091
Conversation
Signed-off-by: Rafał Kuć <[email protected]>
Signed-off-by: Rafał Kuć <[email protected]>
Signed-off-by: Rafał Kuć <[email protected]>
Signed-off-by: Rafał Kuć <[email protected]>
pkg/plugins/interface.go
Outdated
} | ||
|
||
// CommandInfo describes a command provided by the plugin | ||
type CommandInfo struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm wondering if we can use a Cobra struct here. That way, there's no need to parse this structure in createPluginCommand
, just use them natively.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've been looking into that and I may be mistaken, but it seems that we can't be sure we will fully serialize and deserialize the cobra.Command
- we have pointers there and we have functions there, we could even have unexported variables potentially and that won't be serialized. But maybe I'm missing something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @gr0 . This is looking great. I've left a couple of comments.
app/cli/cmd/plugins.go
Outdated
arguments["args"] = args | ||
|
||
// Execute plugin command | ||
result, err := plugin.Plugin.Exec(ctx, cmdInfo.Name, arguments) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are some variables in root.go that get their values from some persistent flags. They should be passed as well. For example apiToken
, flagDebug
, flagOutputFormat
, cpPanelAPI
, etc.
Not sure what's the best pattern, but plugins might need to use them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, I'll review which ones we should pass and if we are missing anything that needs to be added.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now I added the token, CP and CAS API addresses. I'm not sure if there is anything that we need more. If you have anything in mind let me know.
pkg/plugins/manager.go
Outdated
} | ||
|
||
// On Unix, check if executable | ||
if runtime.GOOS != "windows" && info.Mode()&0111 == 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does it need to be executable? Is this a requirement of the plugin library, I wasn't aware of it.
How did you build the test plugin? I did
go build -o ~/.config/chainloop/plugins/test-plugin main.go
in the test plugin you pasted and it doesn't load it.
go run main.go plugin ls
WRN API contacted in insecure mode
No plugins installed
if I make it executable I get this error
go run main.go plugin ls
2025-06-05T16:15:53.855+0200 [DEBUG] plugin: starting plugin: path=/Users/miguelmartinez/.config/chainloop/plugins/test-plugin args=["/Users/miguelmartinez/.config/chainloop/plugins/test-plugin"]
2025-06-05T16:15:53.856+0200 [WARN] plugin: plugin failed to exit gracefully
WRN API contacted in insecure mode
No plugins installed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my case I was just building an example with:
go build -o plugin-one ./cmd/
Let me create an example repository with a plugin, so I can show the whole implementation. I'll prepare something for tomorrow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Btw - can you try running the compiled Chainloop binary and listing the plugins - I was testing using the locally compiled binary using goreleased
. I'm wondering if that can be the case, I'll try running in a similar way you did.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm I managed to run the code even with the following command:
go run main.go plugin list
And the output was:
┌─────────┬─────────┬─────────────────────────────────────────────────┬──────────────┐
│ NAME │ VERSION │ DESCRIPTION │ COMMANDS │
├─────────┼─────────┼─────────────────────────────────────────────────┼──────────────┤
│ example │ 3.0.0 │ GitHub rulesets plugin with JSON output support │ 1 command(s) │
└─────────┴─────────┴─────────────────────────────────────────────────┴──────────────┘
┌─────────┬─────────────────┐
│ PLUGIN │ COMMAND │
├─────────┼─────────────────┤
│ example │ example-hello │
└─────────┴─────────────────┘
I'll create a simple repo with a plugin tomorrow morning, so you can test it on your machine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@migmartri I created this repository: https://github.com/gr0/chainloop_example_plugin - have a look there, it is a very basic plugin, which in my case works:
$ ./dist/cli_darwin_arm64_v8.0/chainloop plugin list
┌──────────────────────────┬─────────┬───────────────────────────┬──────────────┐
│ NAME │ VERSION │ DESCRIPTION │ COMMANDS │
├──────────────────────────┼─────────┼───────────────────────────┼──────────────┤
│ example-chainloop-plugin │ 1.0.0 │ GitHub example CLI plugin │ 1 command(s) │
└──────────────────────────┴─────────┴───────────────────────────┴──────────────┘
┌──────────────────────────┬──────────────────────────┐
│ PLUGIN │ COMMAND │
├──────────────────────────┼──────────────────────────┤
│ example-chainloop-plugin │ example-chainloop-plugin │
$ ./dist/cli_darwin_arm64_v8.0/chainloop plugin describe --name example-chainloop-plugin
┌──────────────────────────┬─────────┬───────────────────────────┬──────────────┐
│ NAME │ VERSION │ DESCRIPTION │ COMMANDS │
├──────────────────────────┼─────────┼───────────────────────────┼──────────────┤
│ example-chainloop-plugin │ 1.0.0 │ GitHub example CLI plugin │ 1 command(s) │
└──────────────────────────┴─────────┴───────────────────────────┴──────────────┘
┌──────────────────────────┬──────────────────────────┬──────────────────┬────────────────────────────────────┐
│ PLUGIN │ COMMAND │ DESCRIPTION │ USAGE │
├──────────────────────────┼──────────────────────────┼──────────────────┼────────────────────────────────────┤
│ example-chainloop-plugin │ example-chainloop-plugin │ Greet with hello │ chainloop example-chainloop-plugin │
└──────────────────────────┴──────────────────────────┴──────────────────┴────────────────────────────────────┘
┌────────┬─────────┬──────┬─────────────┬──────┬─────────┬──────────┐
│ PLUGIN │ COMMAND │ FLAG │ DESCRIPTION │ TYPE │ DEFAULT │ REQUIRED │
├────────┼─────────┼──────┼─────────────┼──────┼─────────┼──────────┤
└────────┴─────────┴──────┴─────────────┴──────┴─────────┴──────────┘
And finally:
$ ./dist/cli_darwin_arm64_v8.0/chainloop example-chainloop-plugin
Hello, World!%
Signed-off-by: Rafał Kuć <[email protected]>
Signed-off-by: Rafał Kuć <[email protected]>
Signed-off-by: Rafał Kuć <[email protected]>
67c1add
to
3d0f5da
Compare
Signed-off-by: Rafał Kuć <[email protected]>
3d0f5da
to
9b9ae91
Compare
Signed-off-by: Rafał Kuć <[email protected]>
Signed-off-by: Rafał Kuć <[email protected]>
Signed-off-by: Rafał Kuć <[email protected]>
Signed-off-by: Rafał Kuć <[email protected]>
Signed-off-by: Rafał Kuć <[email protected]>
909a8df
to
2366269
Compare
This is an experimental approach to #2090 - the part of the whole solution providing the framework part.
I also created an example plugin that can be used for testing https://github.com/gr0/chainloop_example_plugin - everything that is needed is described in the readme file of the plugin.