#2930: Attempt a plugin using the syft CLI#3542
#2930: Attempt a plugin using the syft CLI#3542dgannon991 wants to merge 3 commits intogetporter:mainfrom
Conversation
efcaea3 to
7d3a567
Compare
fe96703 to
794d76d
Compare
There was a problem hiding this comment.
Pull request overview
This PR introduces SBOM generation during porter publish by adding an SBOM generator plugin type and an internal syft-backed generator that shells out to the Syft CLI, plus integration coverage and CI wiring.
Changes:
- Add SBOM generator plugin protocol/store wiring and a built-in
syftgenerator implementation. - Add
--sbom-filetoporter publishto write an SPDX JSON SBOM to a user-specified path. - Add an SBOM integration test and run it in PR/release integration workflows (including ensuring Syft is installed for tests).
Reviewed changes
Copilot reviewed 33 out of 34 changed files in this pull request and generated 16 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/integration/testdata/porter-sbom-config.yaml | Adds a config for enabling the Syft SBOM generator in integration tests. |
| tests/integration/sbom_test.go | New integration test validating porter publish --sbom-file outputs SPDX JSON. |
| pkg/sbom/sbom.go | Introduces the top-level SBOMGenerator interface. |
| pkg/sbom/plugin_adapter.go | Adds an adapter between the plugin protocol and SBOMGenerator. |
| pkg/sbom/helpers.go | Adds a test SBOM generator provider using the mock plugin. |
| pkg/sbom/pluginstore/sbom.go | Plugin-backed SBOM generator implementation + loader config. |
| pkg/sbom/pluginstore/plugin.go | HashiCorp go-plugin GRPC plugin wrapper for SBOM generators. |
| pkg/sbom/pluginstore/grpc.go | gRPC client/server bridge for SBOM generator protocol. |
| pkg/sbom/pluginstore/doc.go | Package documentation for the SBOM pluginstore. |
| pkg/sbom/plugins/sbom_generator_protocol.go | Defines the SBOM generator plugin protocol interface. |
| pkg/sbom/plugins/sbom_generator_plugin.go | Declares SBOM plugin interface name + protocol version. |
| pkg/sbom/plugins/proto/sbom_generator_protocol.proto | Protobuf definition for SBOM generator RPCs. |
| pkg/sbom/plugins/proto/sbom_generator_protocol.pb.go | Generated protobuf Go types. |
| pkg/sbom/plugins/proto/sbom_generator_protocol_grpc.pb.go | Generated gRPC stubs. |
| pkg/sbom/plugins/proto/doc.go | go:generate for protoc generation of SBOM plugin protobufs. |
| pkg/sbom/plugins/mock/mock.go | Adds a mock SBOM generator plugin implementation for tests. |
| pkg/sbom/plugins/mock/doc.go | Package documentation for the mock SBOM generator. |
| pkg/sbom/plugins/syft/syft.go | Implements SBOM generation via syft CLI and SPDX JSON output. |
| pkg/sbom/plugins/syft/plugin.go | Registers the Syft SBOM generator as a plugin. |
| pkg/sbom/plugins/syft/doc.go | Package documentation for the Syft SBOM generator plugin. |
| pkg/porter/publish.go | Adds SBOM generation call during publish when SBOMPath is set. |
| pkg/porter/porter.go | Wires SBOM generator into the Porter client lifecycle (init + Close). |
| pkg/porter/internal_plugins.go | Registers the internal Syft SBOM generator plugin. |
| pkg/porter/helpers.go | Extends test Porter construction to include an SBOM generator. |
| pkg/grpc/portergrpc/portergrpc.go | Wires SBOM generator into gRPC server connection setup. |
| pkg/config/datastore.go | Adds config fields for SBOM generator defaults and plugin definitions. |
| pkg/config/config.go | Adds GetSBOMGeneratorPlugin lookup helper. |
| magefile.go | Ensures Syft is available for integration test runs. |
| go.mod | Dependency updates. |
| go.sum | Dependency checksum updates. |
| docs/content/docs/references/cli/publish.md | Documents the new --sbom-file flag. |
| cmd/porter/bundle.go | Adds the --sbom-file flag to the publish command. |
| .github/workflows/porter-integration-release.yml | Runs the new SBOM integration test in release integration workflow. |
| .github/workflows/porter-integration-pr.yml | Runs the new SBOM integration test in PR integration workflow. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@dgannon991 Unfortunately this PR have some conflicts, while you fix those I will take a closer look at the changes |
|
@kichristensen - thank you, but please hold off until I get a chance to run through the copilot comments. Most are about copy/pasted comments, so they should be quick wins :) I'll ping you when it's all tidied up :) |
794d76d to
a7380ab
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 35 out of 36 changed files in this pull request and generated 5 comments.
Comments suppressed due to low confidence (1)
pkg/porter/publish.go:83
--sbom-filecan be set even when no SBOM generator is configured (e.g.,default-sbom-generator/default-sbom-generator-pluginmissing). In that case the plugin loader will try to load an empty implementation key and fail later with a confusing error. Add validation here to require an SBOM generator configuration whenSBOMPathis set, and return a clear actionable message.
// Validate performs validation on the publish options
func (o *PublishOptions) Validate(cfg *config.Config) error {
if o.ArchiveFile != "" {
// Verify the archive file can be accessed
if _, err := cfg.FileSystem.Stat(o.ArchiveFile); err != nil {
return fmt.Errorf("unable to access --archive %s: %w", o.ArchiveFile, err)
}
if o.Reference == "" {
return errors.New(
"must provide a value for --reference of the form REGISTRY/bundle:tag",
)
}
} else {
// Proceed with publishing from the resolved build context directory
err := o.BundleDefinitionOptions.Validate(cfg.Context)
if err != nil {
return err
}
if o.File == "" {
return fmt.Errorf(
"could not find porter.yaml in the current directory %s, make sure you are in the right directory or specify the porter manifest with --file",
o.Dir,
)
}
}
if o.Reference != "" {
return o.BundlePullOptions.Validate()
}
if o.Tag != "" {
return o.validateTag()
}
// Apply the global config for force overwrite
if !o.Force && cfg.Data.ForceOverwrite {
o.Force = true
}
return nil
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
a029e5b to
c4ddcec
Compare
Signed-off-by: David Gannon <19214156+dgannon991@users.noreply.github.com>
Signed-off-by: David Gannon <19214156+dgannon991@users.noreply.github.com>
7f81206 to
8176b80
Compare
Signed-off-by: David Gannon <19214156+dgannon991@users.noreply.github.com>
8176b80 to
bdf39f8
Compare
| "get.porter.sh/porter/pkg/sbom/plugins/proto" | ||
| ) | ||
|
|
||
| var _ plugins.SBOMGeneratorProtocol = &GClient{} |
There was a problem hiding this comment.
Is this necessary? I was under the impression that Syft gave us examples and we could just import the necessary libraries.
But to be fair.. that was like 3 years ago.
There was a problem hiding this comment.
(I mean this in referencing to the proto being generated and used throughout - I clicked the wrong area to leave this comment)
There was a problem hiding this comment.
So when I did it that way, it increased the size of the porter binary by approx 50% (from memory, it was a while ago!) and brought in loads of extra dependencies that we wouldn't have needed otherwise. So we tried it this way instead, so that it was opt-in. Happy to go back to bundling it all in (as this is being a massive PITA!)
There was a problem hiding this comment.
You are right
I totally forgot that we discussed this before
I will forget again so prepare to remind me -_-
This closes #2930 with a slightly different approach. Copying the signing plugin approach of using a CLI tool in a plugin this time :)