cli/build.go
cli/build.goBrowse 1970 files
1,192 tokens
4,259 bytes
Token encoding: o200k_base
Snapshot 21a254f
← Back to SKILL.md
1// entrypoint to the `build` subcommand2// Primarily bundles CLI options into the structure that `BuildWithBuildkitClient` expects3 4package cli5 6import (7 "context"8 "crypto/sha256"9 "encoding/json"10 "fmt"11 "os"12 "strings"13 14 "github.com/railwayapp/railpack/buildkit"15 "github.com/railwayapp/railpack/core"16 "github.com/railwayapp/railpack/core/app"17 "github.com/railwayapp/railpack/core/plan"18 "github.com/urfave/cli/v3"19)20 21var BuildCommand = &cli.Command{22 Name: "build",23 Aliases: []string{"b"},24 Usage: "build an image with BuildKit",25 ArgsUsage: "DIRECTORY",26 EnableShellCompletion: true,27 Flags: append([]cli.Flag{28 &cli.StringFlag{29 Name: "name",30 Usage: "name of the image to build",31 },32 &cli.StringFlag{33 Name: "output",34 Usage: "output the final filesystem to a local directory",35 },36 &cli.StringFlag{37 Name: "platform",38 Usage: "platform to build for (e.g. linux/amd64, linux/arm64)",39 },40 &cli.StringFlag{41 Name: "progress",42 Usage: "buildkit progress output mode. Values: auto, plain, tty",43 Value: "auto",44 },45 &cli.BoolFlag{46 Name: "show-plan",47 Usage: "Show the build plan before building. This is useful for development and debugging.",48 Value: false,49 },50 &cli.StringFlag{51 Name: "cache-key",52 Usage: "Unique id to prefix to cache keys",53 },54 &cli.StringSliceFlag{55 Name: "cache-from",56 Usage: "External cache sources",57 },58 &cli.StringSliceFlag{59 Name: "cache-to",60 Usage: "Cache export destinations",61 },62 &cli.BoolFlag{63 Name: "no-cache",64 Usage: "Do not use cache when building",65 Value: false,66 },67 &cli.BoolFlag{68 Name: "dump-llb",69 Hidden: true,70 Value: false,71 },72 }, commonPlanFlags()...),73 Action: func(ctx context.Context, cmd *cli.Command) error {74 buildResult, app, env, err := GenerateBuildResultForCommand(cmd)75 if err != nil {76 return cli.Exit(err, exitCodeForError(err))77 }78 79 if !cmd.Bool("dump-llb") {80 core.PrettyPrintBuildResult(buildResult, core.PrintOptions{Version: Version})81 }82 83 if !buildResult.Success {84 os.Exit(ExitCodeFailure)85 return nil86 }87 88 if cmd.Bool("show-plan") && !cmd.Bool("dump-llb") {89 planMap, err := addSchemaToPlanMap(buildResult.Plan)90 if err != nil {91 return cli.Exit(err, ExitCodeFailure)92 }93 94 serializedPlan, err := json.MarshalIndent(planMap, "", " ")95 if err != nil {96 return cli.Exit(err, ExitCodeFailure)97 }98 99 core.PrettyPrintSectionHeader(os.Stdout, "Generated railpack-plan.json")100 core.PrettyPrintJSON(os.Stdout, serializedPlan)101 }102 103 err = validateSecrets(buildResult.Plan, env)104 if err != nil {105 return cli.Exit(err, ExitCodeFailure)106 }107 108 secretsHash := getSecretsHash(env)109 110 platformStr := cmd.String("platform")111 err = buildkit.BuildWithBuildkitClient(app.Source, buildResult.Plan, buildkit.BuildWithBuildkitClientOptions{112 ImageName: cmd.String("name"),113 DumpLLB: cmd.Bool("dump-llb"),114 OutputDir: cmd.String("output"),115 ProgressMode: cmd.String("progress"),116 CacheKey: cmd.String("cache-key"),117 // StringSlice to support multiple cache-from / cache-to entries, same shape as docker buildx118 ImportCache: cmd.StringSlice("cache-from"),119 ExportCache: cmd.StringSlice("cache-to"),120 SecretsHash: secretsHash,121 Secrets: env.Variables,122 Platform: platformStr,123 GitHubToken: os.Getenv("GITHUB_TOKEN"),124 NoCache: cmd.Bool("no-cache"),125 })126 if err != nil {127 return cli.Exit(err, ExitCodeFailure)128 }129 130 return nil131 },132}133 134// make sure all secrets referenced in the build plan are present in the environment135func validateSecrets(plan *plan.BuildPlan, env *app.Environment) error {136 for _, secret := range plan.Secrets {137 if _, ok := env.Variables[secret]; !ok {138 return fmt.Errorf("missing environment variable: %s. Please set using --env %s=%s", secret, secret, "...")139 }140 }141 return nil142}143 144// generate a hash all of build secrets to invalidate all caches when any secret changes145func getSecretsHash(env *app.Environment) string {146 var secretsValue strings.Builder147 for _, v := range env.Variables {148 secretsValue.WriteString(v)149 }150 hasher := sha256.New()151 hasher.Write([]byte(secretsValue.String()))152 return fmt.Sprintf("%x", hasher.Sum(nil))153}154