diff --git a/pkg/build/build.go b/pkg/build/build.go index 7ea5e2b..be5be4c 100644 --- a/pkg/build/build.go +++ b/pkg/build/build.go @@ -31,6 +31,7 @@ import ( "github.com/moby/buildkit/cmd/buildctl/build" "github.com/moby/buildkit/session" "github.com/moby/buildkit/session/secrets/secretsprovider" + "github.com/moby/buildkit/session/sshforward/sshprovider" "github.com/sirupsen/logrus" "github.com/tonistiigi/go-csvvalue" "google.golang.org/grpc" @@ -64,7 +65,8 @@ func Build(ctx context.Context, opts *BOpts) error { if len(exports) == 0 { exports = append(exports, client.ExportEntry{ - Type: "oci", + Type: "oci", + Attrs: map[string]string{}, }) } @@ -89,6 +91,10 @@ func Build(ctx context.Context, opts *BOpts) error { var exportsWithOutput []client.ExportEntry for _, export := range exports { + if export.Attrs == nil { + export.Attrs = map[string]string{} + } + switch export.Type { case client.ExporterLocal: localDest := filepath.Join(GlobalExportPath, opts.BuildID, "local") @@ -167,6 +173,14 @@ func Build(ctx context.Context, opts *BOpts) error { } solveOpt.Frontend = "dockerfile.v1" + if len(opts.SSH) > 0 { + sshProvider, err := sshprovider.NewSSHAgentProvider(opts.SSH) + if err != nil { + return err + } + solveOpt.Session = append(solveOpt.Session, sshProvider) + } + _, err = buildkit.Build(opts.Context(ctx), solveOpt, "", frontend, opts.ProgressWriter.Status()) <-opts.ProgressWriter.Done() return err diff --git a/pkg/build/buildopts.go b/pkg/build/buildopts.go index 8658717..bbad12e 100644 --- a/pkg/build/buildopts.go +++ b/pkg/build/buildopts.go @@ -27,6 +27,7 @@ import ( "github.com/moby/buildkit/frontend/dockerfile/instructions" "github.com/moby/buildkit/frontend/dockerfile/parser" "github.com/moby/buildkit/frontend/dockerfile/shell" + "github.com/moby/buildkit/session/sshforward/sshprovider" "github.com/moby/buildkit/util/progress/progresswriter" ocispecs "github.com/opencontainers/image-spec/specs-go/v1" @@ -62,6 +63,8 @@ const ( KeyBuildArgs = "build-args" // RUN --mount=type=secret,... id:value pairs passed to the Dockerfile. KeySecrets = "secrets" + // SSH agent to forward during the build process. + KeySSH = "ssh" // Cache import sources. KeyCacheIn = "cache-in" // Cache export destinations. @@ -94,6 +97,7 @@ type BOpts struct { Target string BuildArgs map[string]string Secrets map[string][]byte + SSH []sshprovider.AgentConfig CacheIn []string CacheOut []string Outputs []string @@ -237,12 +241,42 @@ func NewBuildOpts(ctx context.Context, basePath string, contextMap map[string][] return args, nil } + sshExtract := func(key string) []sshprovider.AgentConfig { + values, ok := contextMap[key] + if !ok { + return nil + } + agentConfigs := make([]sshprovider.AgentConfig, 0, len(values)) + for _, value := range values { + id, path, hasPath := strings.Cut(value, "=") + id = strings.TrimSpace(id) + path = strings.TrimSpace(path) + if !hasPath && strings.HasPrefix(id, "/") { + path = id + id = "default" + hasPath = true + } + if id == "" { + id = "default" + } + config := sshprovider.AgentConfig{ + ID: id, + } + if hasPath && path != "" { + config.Paths = []string{path} + } + agentConfigs = append(agentConfigs, config) + } + return agentConfigs + } + labels := mapExtract(KeyLabels) buildArgs := mapExtract(KeyBuildArgs) secrets, err := mapExtractB64(KeySecrets) if err != nil { return nil, err } + ssh := sshExtract(KeySSH) cacheIn := contextMap[KeyCacheIn] cacheOut := contextMap[KeyCacheOut] outputs := contextMap[KeyOutput] @@ -342,6 +376,7 @@ func NewBuildOpts(ctx context.Context, basePath string, contextMap map[string][] Labels: labels, BuildArgs: buildArgs, Secrets: secrets, + SSH: ssh, CacheIn: cacheIn, CacheOut: cacheOut, Outputs: outputs,