Skip to content

Commit

Permalink
feat(pipe/build): Add support for flexible build hooks (#1414)
Browse files Browse the repository at this point in the history
  • Loading branch information
radeksimko committed Apr 12, 2020
1 parent 7fe4d0a commit 8032d12
Show file tree
Hide file tree
Showing 8 changed files with 509 additions and 49 deletions.
4 changes: 2 additions & 2 deletions internal/builders/golang/build_test.go
Expand Up @@ -400,7 +400,7 @@ func TestRunPipeWithoutMainFunc(t *testing.T) {
Builds: []config.Build{
{
Binary: "no-main",
Hooks: config.Hooks{},
Hooks: config.HookConfig{},
Targets: []string{
runtimeTarget,
},
Expand Down Expand Up @@ -448,7 +448,7 @@ func TestRunPipeWithMainFuncNotInMainGoFile(t *testing.T) {
{
Env: []string{"GO111MODULE=off"},
Binary: "foo",
Hooks: config.Hooks{},
Hooks: config.HookConfig{},
Targets: []string{
runtimeTarget,
},
Expand Down
90 changes: 67 additions & 23 deletions internal/pipe/build/build.go
Expand Up @@ -76,43 +76,84 @@ func buildWithDefaults(ctx *context.Context, build config.Build) config.Build {
}

func runPipeOnBuild(ctx *context.Context, build config.Build) error {
if err := runHook(ctx, build.Env, build.Hooks.Pre); err != nil {
return errors.Wrap(err, "pre hook failed")
}
var g = semerrgroup.New(ctx.Parallelism)
for _, target := range build.Targets {
target := target
build := build
g.Go(func() error {
return doBuild(ctx, build, target)
opts, err := buildOptionsForTarget(ctx, build, target)
if err != nil {
return err
}

if err := runHook(ctx, *opts, build.Env, build.Hooks.Pre); err != nil {
return errors.Wrap(err, "pre hook failed")
}
if err := doBuild(ctx, build, *opts); err != nil {
return err
}
if err := runHook(ctx, *opts, build.Env, build.Hooks.Post); err != nil {
return errors.Wrap(err, "post hook failed")
}
return nil
})
}
if err := g.Wait(); err != nil {
return err
}
return errors.Wrap(runHook(ctx, build.Env, build.Hooks.Post), "post hook failed")

return g.Wait()
}

func runHook(ctx *context.Context, env []string, hook string) error {
if hook == "" {
func runHook(ctx *context.Context, opts builders.Options, buildEnv []string, hooks config.BuildHooks) error {
if len(hooks) == 0 {
return nil
}
sh, err := tmpl.New(ctx).WithEnvS(env).Apply(hook)
if err != nil {
return err

for _, hook := range hooks {
var env []string

env = append(env, ctx.Env.Strings()...)
env = append(env, buildEnv...)

for _, rawEnv := range hook.Env {
e, err := tmpl.New(ctx).WithBuildOptions(opts).Apply(rawEnv)
if err != nil {
return err
}
env = append(env, e)
}

dir, err := tmpl.New(ctx).WithBuildOptions(opts).Apply(hook.Dir)
if err != nil {
return err
}

sh, err := tmpl.New(ctx).WithBuildOptions(opts).
WithEnvS(env).
Apply(hook.Cmd)
if err != nil {
return err
}

log.WithField("hook", sh).Info("running hook")
cmd := strings.Fields(sh)

if err := run(ctx, dir, cmd, env); err != nil {
return err
}
}
log.WithField("hook", sh).Info("running hook")
cmd := strings.Fields(sh)
env = append(env, ctx.Env.Strings()...)
return run(ctx, cmd, env)

return nil
}

func doBuild(ctx *context.Context, build config.Build, target string) error {
func doBuild(ctx *context.Context, build config.Build, opts builders.Options) error {
return builders.For(build.Lang).Build(ctx, build, opts)
}

func buildOptionsForTarget(ctx *context.Context, build config.Build, target string) (*builders.Options, error) {
var ext = extFor(target, build.Flags)

binary, err := tmpl.New(ctx).Apply(build.Binary)
if err != nil {
return err
return nil, err
}

build.Binary = binary
Expand All @@ -125,15 +166,15 @@ func doBuild(ctx *context.Context, build config.Build, target string) error {
),
)
if err != nil {
return err
return nil, err
}
log.WithField("binary", path).Info("building")
return builders.For(build.Lang).Build(ctx, build, builders.Options{
return &builders.Options{
Target: target,
Name: name,
Path: path,
Ext: ext,
})
}, nil
}

func extFor(target string, flags config.FlagArray) string {
Expand All @@ -154,11 +195,14 @@ func extFor(target string, flags config.FlagArray) string {
return ""
}

func run(ctx *context.Context, command, env []string) error {
func run(ctx *context.Context, dir string, command, env []string) error {
/* #nosec */
var cmd = exec.CommandContext(ctx, command[0], command[1:]...)
var log = log.WithField("env", env).WithField("cmd", command)
cmd.Env = env
if dir != "" {
cmd.Dir = dir
}
log.Debug("running")
if out, err := cmd.CombinedOutput(); err != nil {
log.WithError(err).Debug("failed")
Expand Down

0 comments on commit 8032d12

Please sign in to comment.