Skip to content

Commit

Permalink
Add support for build environment variables (digitalocean#1209)
Browse files Browse the repository at this point in the history
  • Loading branch information
nicktate committed Sep 20, 2022
1 parent 1abb918 commit 473b5c0
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 52 deletions.
52 changes: 52 additions & 0 deletions internal/apps/builder/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"os"
"time"

"github.com/MakeNowJust/heredoc"
"github.com/digitalocean/doctl/commands/charm"
"github.com/digitalocean/godo"
)

Expand Down Expand Up @@ -51,6 +53,56 @@ func (b baseComponentBuilder) getLogWriter() io.Writer {
return b.logWriter
}

func (b baseComponentBuilder) getEnvMap() map[string]string {
envs := map[string]string{}

charm.TemplatePrint(heredoc.Doc(`
{{success checkmark}} configuring build environment variables... {{nl}}{{nl}}`,
), nil)

if b.spec != nil {
for _, e := range b.spec.Envs {
if e.Type == godo.AppVariableType_Secret {
charm.TemplatePrint(heredoc.Doc(`
=> Ignoring SECRET variable {{highlight .GetKey}}{{nl}}`,
), e)
continue
}
if e.Scope != godo.AppVariableScope_RunTime {
val := e.Value
envs[e.Key] = val
}
}
}

for _, e := range b.component.GetEnvs() {
if e.Type == godo.AppVariableType_Secret {
charm.TemplatePrint(heredoc.Doc(`
=> Ignoring SECRET variable {{highlight .GetKey}}{{nl}}`,
), e)
continue
}
if e.Scope != godo.AppVariableScope_RunTime {
val := e.Value
envs[e.Key] = val
}
}

for k, v := range b.envOverrides {
v := v
if _, ok := envs[k]; ok {
charm.TemplatePrint(heredoc.Doc(`
=> Overwriting {{highlight .}} with provided env value{{nl}}`,
), k)
}
envs[k] = v
}

charm.TemplatePrint(heredoc.Doc(`{{nl}}`), nil)

return envs
}

// NewBuilderOpts ...
type NewBuilderOpts struct {
Component string
Expand Down
28 changes: 24 additions & 4 deletions internal/apps/builder/cnb.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"errors"
"os"
"sort"
"strings"
"time"

"github.com/docker/docker/api/types"
Expand All @@ -16,6 +17,9 @@ import (
const (
// CNBBuilderImage represents the local cnb builder.
CNBBuilderImage = "digitaloceanapps/cnb-local-builder:dev"

appVarAllowListKey = "APP_VARS"
appVarPrefix = "APP_VAR_"
)

// CNBComponentBuilder represents a CNB builder
Expand Down Expand Up @@ -117,13 +121,29 @@ func (b *CNBComponentBuilder) Build(ctx context.Context) (res ComponentBuilderRe
}

func (b *CNBComponentBuilder) cnbEnv() []string {
args := getBuildArgs(b.spec, b.component, b.envOverrides)
envMap := b.getEnvMap()
envs := []string{}
for k, v := range args {
// NOTE(ntate) getBuildArgs already preprends _APP
envs = append(envs, k+"="+*v)

appVars := []string{}
for k, v := range envMap {
envs = append(envs, appVarPrefix+k+"="+v)
appVars = append(appVars, k)
}
if len(appVars) > 0 {
sort.Strings(appVars)
envs = append(envs, appVarAllowListKey+"="+strings.Join(appVars, ","))
}

envs = append(envs, "APP_IMAGE_URL="+b.ImageOutputName())
envs = append(envs, "APP_PLATFORM_COMPONENT_TYPE="+string(b.component.GetType()))
if b.component.GetSourceDir() != "" {
envs = append(envs, "SOURCE_DIR="+b.component.GetSourceDir())
}
if b.component.GetBuildCommand() != "" {
envs = append(envs, "BUILD_COMMAND="+b.component.GetBuildCommand())
}

sort.Strings(envs)

return envs
}
7 changes: 4 additions & 3 deletions internal/apps/builder/cnb_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,11 @@ func TestCNBComponentBuild(t *testing.T) {
Env: []string{
"APP_IMAGE_URL=" + builder.ImageOutputName(),
"APP_PLATFORM_COMPONENT_TYPE=" + string(service.GetType()),
appVarAllowListKey + "=build-arg-1,override-1,run-build-arg-1",
appVarPrefix + "build-arg-1=build-val-1",
appVarPrefix + "override-1=newval",
appVarPrefix + "run-build-arg-1=run-build-val-1",
"SOURCE_DIR=" + service.GetSourceDir(),
"build-arg-1=build-val-1",
"override-1=newval",
"run-build-arg-1=run-build-val-1",
},
Cmd: []string{"sh", "-c", "/.app_platform/build.sh"},
}).Return(types.IDResponse{
Expand Down
44 changes: 4 additions & 40 deletions internal/apps/builder/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import (
"path/filepath"
"time"

"github.com/digitalocean/godo"

"github.com/docker/docker/api/types"
"github.com/docker/docker/pkg/archive"
)
Expand Down Expand Up @@ -58,7 +56,7 @@ func (b *DockerComponentBuilder) Build(ctx context.Context) (ComponentBuilderRes
Tags: []string{
b.ImageOutputName(),
},
BuildArgs: getBuildArgs(b.spec, b.component, b.envOverrides),
BuildArgs: b.getBuildArgs(),
}
dockerRes, err := b.cli.ImageBuild(ctx, tar, opts)
if err != nil {
Expand All @@ -73,49 +71,15 @@ func (b *DockerComponentBuilder) Build(ctx context.Context) (ComponentBuilderRes
return res, nil
}

// TODO(ntate) doesn't handle encrypted secrets
func getBuildArgs(spec *godo.AppSpec, component godo.AppBuildableComponentSpec, userEnv map[string]string) map[string]*string {
func (b *DockerComponentBuilder) getBuildArgs() map[string]*string {
envMap := b.getEnvMap()
args := map[string]*string{}

if spec != nil {
for _, e := range spec.Envs {
if e.Type == godo.AppVariableType_Secret {
fmt.Printf("--> Ignoring SECRET variable %s\n", e.Key)
continue
}
if e.Scope != godo.AppVariableScope_RunTime {
val := e.Value
args[e.Key] = &val
}
}
}

for _, e := range component.GetEnvs() {
if e.Type == godo.AppVariableType_Secret {
fmt.Printf("--> Ignoring SECRET variable %s\n", e.Key)
continue
}
if e.Scope != godo.AppVariableScope_RunTime {
val := e.Value
args[e.Key] = &val
}
}

for k, v := range userEnv {
for k, v := range envMap {
v := v
if _, ok := args[k]; ok {
fmt.Printf("--> Overwriting %s with provided env value...\n", k)
}
args[k] = &v
}

cType := string(component.GetType())
args["APP_PLATFORM_COMPONENT_TYPE"] = &cType
if component.GetSourceDir() != "" {
dir := component.GetSourceDir()
args["SOURCE_DIR"] = &dir
}

return args
}

Expand Down
8 changes: 3 additions & 5 deletions internal/apps/builder/docker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,11 +86,9 @@ func TestDockerComponentBuild(t *testing.T) {
builder.ImageOutputName(),
},
BuildArgs: map[string]*string{
"APP_PLATFORM_COMPONENT_TYPE": strPtr(string(service.GetType())),
"SOURCE_DIR": strPtr(service.GetSourceDir()),
"build-arg-1": strPtr("build-val-1"),
"override-1": strPtr("newval"),
"run-build-arg-1": strPtr("run-build-val-1"),
"build-arg-1": strPtr("build-val-1"),
"override-1": strPtr("newval"),
"run-build-arg-1": strPtr("run-build-val-1"),
},
}).Return(types.ImageBuildResponse{
Body: ioutil.NopCloser(strings.NewReader("")),
Expand Down

0 comments on commit 473b5c0

Please sign in to comment.