forked from buildpacks/pack
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbuild.go
130 lines (118 loc) · 4.46 KB
/
build.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package commands
import (
"io/ioutil"
"os"
"strings"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/buildpack/pack"
"github.com/buildpack/pack/config"
"github.com/buildpack/pack/logging"
"github.com/buildpack/pack/style"
)
type BuildFlags struct {
AppPath string
Builder string
RunImage string
Env []string
EnvFiles []string
Publish bool
NoPull bool
ClearCache bool
Buildpacks []string
Network string
}
func Build(logger logging.Logger, cfg config.Config, packClient PackClient) *cobra.Command {
var flags BuildFlags
ctx := createCancellableContext()
cmd := &cobra.Command{
Use: "build <image-name>",
Args: cobra.ExactArgs(1),
Short: "Generate app image from source code",
RunE: logError(logger, func(cmd *cobra.Command, args []string) error {
imageName := args[0]
if flags.Builder == "" {
suggestSettingBuilder(logger, packClient)
return MakeSoftError()
}
env, err := parseEnv(flags.EnvFiles, flags.Env)
if err != nil {
return err
}
if err := packClient.Build(ctx, pack.BuildOptions{
AppPath: flags.AppPath,
Builder: flags.Builder,
AdditionalMirrors: getMirrors(cfg),
RunImage: flags.RunImage,
Env: env,
Image: imageName,
Publish: flags.Publish,
NoPull: flags.NoPull,
ClearCache: flags.ClearCache,
Buildpacks: flags.Buildpacks,
ContainerConfig: pack.ContainerConfig{
Network: flags.Network,
},
}); err != nil {
return err
}
logger.Infof("Successfully built image %s", style.Symbol(imageName))
return nil
}),
}
buildCommandFlags(cmd, &flags, cfg)
cmd.Flags().BoolVar(&flags.Publish, "publish", false, "Publish to registry")
AddHelpFlag(cmd, "build")
return cmd
}
func buildCommandFlags(cmd *cobra.Command, buildFlags *BuildFlags, cfg config.Config) {
cmd.Flags().StringVarP(&buildFlags.AppPath, "path", "p", "", "Path to app dir or zip-formatted file (defaults to current working directory)")
cmd.Flags().StringVar(&buildFlags.Builder, "builder", cfg.DefaultBuilder, "Builder image")
cmd.Flags().StringVar(&buildFlags.RunImage, "run-image", "", "Run image (defaults to default stack's run image)")
cmd.Flags().StringArrayVarP(&buildFlags.Env, "env", "e", []string{}, "Build-time environment variable, in the form 'VAR=VALUE' or 'VAR'.\nWhen using latter value-less form, value will be taken from current\n environment at the time this command is executed.\nThis flag may be specified multiple times and will override\n individual values defined by --env-file.")
cmd.Flags().StringArrayVar(&buildFlags.EnvFiles, "env-file", []string{}, "Build-time environment variables file\nOne variable per line, of the form 'VAR=VALUE' or 'VAR'\nWhen using latter value-less form, value will be taken from current\n environment at the time this command is executed")
cmd.Flags().BoolVar(&buildFlags.NoPull, "no-pull", false, "Skip pulling builder and run images before use")
cmd.Flags().BoolVar(&buildFlags.ClearCache, "clear-cache", false, "Clear image's associated cache before building")
cmd.Flags().StringSliceVar(&buildFlags.Buildpacks, "buildpack", nil, "Buildpack reference in the form of '<buildpack>@<version>',\n path to a buildpack directory (not supported on Windows), or\n path/URL to a buildpack .tar or .tgz file"+multiValueHelp("buildpack"))
cmd.Flags().StringVar(&buildFlags.Network, "network", "", "Connect detect and build containers to network")
}
func parseEnv(envFiles []string, envVars []string) (map[string]string, error) {
env := map[string]string{}
for _, envFile := range envFiles {
envFileVars, err := parseEnvFile(envFile)
if err != nil {
return nil, errors.Wrapf(err, "failed to parse env file '%s'", envFile)
}
for k, v := range envFileVars {
env[k] = v
}
}
for _, envVar := range envVars {
env = addEnvVar(env, envVar)
}
return env, nil
}
func parseEnvFile(filename string) (map[string]string, error) {
out := make(map[string]string)
f, err := ioutil.ReadFile(filename)
if err != nil {
return nil, errors.Wrapf(err, "open %s", filename)
}
for _, line := range strings.Split(string(f), "\n") {
line = strings.TrimSpace(line)
if line == "" {
continue
}
out = addEnvVar(out, line)
}
return out, nil
}
func addEnvVar(env map[string]string, item string) map[string]string {
arr := strings.SplitN(item, "=", 2)
if len(arr) > 1 {
env[arr[0]] = arr[1]
} else {
env[arr[0]] = os.Getenv(arr[0])
}
return env
}