Skip to content

Conversation

@jedevc
Copy link
Member

@jedevc jedevc commented Dec 2, 2025

Fixes #3037.

Follow-ups:

  • Secret passing. This PR is already going to be large, and adding support for secrets also intersects with secrets for cache exporter backends, so it's not super trivial to just add on.

Comment on lines 79 to 106
var foundFiles []string
var foundDescs []ocispecs.Descriptor
export := func(ctx context.Context, c gateway.Client, conn *grpc.ClientConn, _ exptypes.ExporterTarget, result *gateway.Result) error {
entries, err := result.Ref.ReadDir(ctx, gateway.ReadDirRequest{Path: "/"})
if err != nil {
return err
}
for _, entry := range entries {
foundFiles = append(foundFiles, entry.Path)
}

store := contentproxy.NewContentStore(conn)
descs, err := result.Ref.GetRemote(ctx)
if err != nil {
return err
}
foundDescs = filterAvailableDescriptors(ctx, store, descs)

return nil
}

_, err = c.BuildExport(sb.Context(), client.SolveOpt{}, "", frontend, export, nil)
require.NoError(t, err)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels like a fun interface to me - allowing the client to easily do its own local export. This actually works entirely without any server-side changes - it's just calling the exporter function right after a build, using the same gateway.

We have access to the entire buildkit content store (so there's no isolation here, but this is client-trusted code).

Comment on lines 441 to 557
func buildSampleExporter(ctx context.Context, c *client.Client, dest string) error {
gatewayDir, err := fsutil.NewFS(integration.BuildkitSourcePath)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't work out a good test strategy that doesn't involve doing this 😢

To actually test the gateway exporter codepath + the isolation it provides, we actually need to build one so we can test it. It feels weird to do this in a test (as @tonistiigi points out in #3633 (comment)). But not sure what the alternative is 🤷 Some tests in exporter_test.go might not need it, but could otherwise just build it in bake, and connect it in?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I seem to remember writing this code before - but can't remember when.

@tonistiigi is there another implementation of this that you're aware of?

return exporter.NewConfig()
}

func (e *gatewayExporterInstance) Export(ctx context.Context, llbBridge frontend.FrontendLLBBridge, exec executor.Executor, src *exporter.Source, inlineCache exptypes.InlineCache, sessionID string) (_ map[string]string, descref exporter.DescriptorReference, err error) {
Copy link
Member Author

@jedevc jedevc Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the gateway exporter allow returning an arbitrary exporter response map? I haven't added that yet.

Seems like it would be nice to allow it:

  • Could either reuse the existing Return gateway API
    • New exporter response field
    • Use the result metadata somehow
  • Or create a new API (hoping to avoid this)

Comment on lines +261 to +262
// Target indicates the target type of the exporter
ExporterTarget Target = 3;
Copy link
Member Author

@jedevc jedevc Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is required to support the new file/dir keys (pointing out, since I didn't realize this in #3037 (comment)).

Without something like this, the exporter can't actually know what type was attached (since we strip out the attribute itself to avoid leaking it to the server).

@github-actions github-actions bot added area/dependencies Pull requests that update a dependency file area/ci area/docs labels Dec 5, 2025
@jedevc jedevc force-pushed the gateway-exporter branch 2 times, most recently from 45e4d38 to a930686 Compare December 5, 2025 10:50
@github-actions github-actions bot removed area/hack building buildkit itself area/dependencies Pull requests that update a dependency file area/ci area/docs labels Dec 5, 2025
@github-actions github-actions bot added area/hack building buildkit itself area/ci labels Dec 5, 2025
@jedevc
Copy link
Member Author

jedevc commented Dec 5, 2025

Getting really close now, the only things I need to get done are:

  • Tests 🎉
  • Some refactorings of code that got that little bit more complicated
  • Authoring a real commit history 👀

Edit: done! This PR is now ready for review.

This allows the client to be explicit as to what client-side inputs the
client has provided (instead of implying this through the use of
exporter attributes).

Signed-off-by: Justin Chadwell <[email protected]>
Additionally, simplify some of the result loading/stashing logic into
helpers.

Signed-off-by: Justin Chadwell <[email protected]>
We'll need this in the exporter package, so break it up a little bit so
it can be used there later.

Signed-off-by: Justin Chadwell <[email protected]>
This wasn't previously used *at all*. However, now, we need to be able
to do this, since exporters will speak the gateway api, and we want to
be able to access provenance attestations.

Signed-off-by: Justin Chadwell <[email protected]>
Signed-off-by: Justin Chadwell <[email protected]>
Signed-off-by: Justin Chadwell <[email protected]>
@jedevc jedevc marked this pull request as ready for review December 8, 2025 17:01
@jedevc jedevc requested a review from tonistiigi December 8, 2025 17:02
@WYGIN
Copy link

WYGIN commented Dec 9, 2025

Will it be a breaking change? How can I figure out if a buildkit demon support BuildFromEnvironment or ExportFromEnvironment supported As a gateway frontend?

@jedevc
Copy link
Member Author

jedevc commented Dec 9, 2025

This will not be a breaking change.

ExportFromEnvironment will only be callable when invoked from --output type=gateway,source=<image>. We should probably add a sanity check that it's running in the right environment though - so that if you try and put a frontend image instead of a exporter image, you get a sane error.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Exporter plugin (like frontend but for exporters)

2 participants