Files
pack/buildkit/convert.go
T

105 lines
2.5 KiB
Go

package buildkit
import (
"fmt"
"maps"
"slices"
"strings"
"github.com/moby/buildkit/client/llb"
"github.com/moby/buildkit/util/system"
specs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/railwayapp/railpack/buildkit/build_llb"
p "github.com/railwayapp/railpack/core/plan"
)
type ConvertPlanOptions struct {
BuildPlatform BuildPlatform
SecretsHash string
CacheKey string
SessionID string
}
const (
WorkingDir = "/app"
)
func ConvertPlanToLLB(plan *p.BuildPlan, opts ConvertPlanOptions) (*llb.State, *Image, error) {
platform := opts.BuildPlatform.ToPlatform()
localState := llb.Local("context",
llb.SharedKeyHint("local"),
llb.SessionID(opts.SessionID),
llb.WithCustomName("loading ."),
llb.FollowPaths([]string{"."}),
)
cacheStore := build_llb.NewBuildKitCacheStore(opts.CacheKey)
graph, err := build_llb.NewBuildGraph(plan, &localState, cacheStore, opts.SecretsHash, &platform)
if err != nil {
return nil, nil, err
}
graphOutput, err := graph.GenerateLLB()
if err != nil {
return nil, nil, err
}
state := getStartState(*graphOutput.State)
imageEnv := getImageEnv(graphOutput, plan)
startCommand := plan.Deploy.StartCmd
if startCommand == "" {
startCommand = "/bin/bash"
}
image := Image{
Image: specs.Image{
Platform: specs.Platform{
OS: platform.OS,
Architecture: platform.Architecture,
},
RootFS: specs.RootFS{
Type: "layers",
},
},
Variant: platform.Variant,
Config: specs.ImageConfig{
Env: imageEnv,
WorkingDir: WorkingDir,
Entrypoint: []string{"/bin/sh", "-c"},
Cmd: []string{startCommand},
},
}
return &state, &image, nil
}
func getStartState(buildState llb.State) llb.State {
startState := buildState.Dir(WorkingDir)
return startState
}
func getImageEnv(graphOutput *build_llb.BuildGraphOutput, plan *p.BuildPlan) []string {
paths := []string{}
paths = append(paths, plan.Deploy.Paths...)
paths = append(paths, graphOutput.GraphEnv.PathList...)
paths = append(paths, system.DefaultPathEnvUnix)
slices.Sort(paths)
pathString := strings.Join(paths, ":")
envMap := make(map[string]string, len(graphOutput.GraphEnv.EnvVars)+len(plan.Deploy.Variables)+1)
maps.Copy(envMap, graphOutput.GraphEnv.EnvVars)
maps.Copy(envMap, plan.Deploy.Variables)
envMap["PATH"] = pathString
envVars := make([]string, 0, len(envMap))
for _, k := range slices.Sorted(maps.Keys(envMap)) {
v := envMap[k]
envVars = append(envVars, fmt.Sprintf("%s=%s", k, v))
}
return envVars
}