// Copyright 2019 Drone.IO Inc. All rights reserved. // Use of this source code is governed by the Polyform License // that can be found in the LICENSE file. package command import ( "encoding/json" "fmt" "io/ioutil" "os" "strings" "github.com/drone-runners/drone-runner-docker/command/internal" "github.com/drone-runners/drone-runner-docker/engine/compiler" "github.com/drone-runners/drone-runner-docker/engine/resource" "github.com/drone/envsubst" "github.com/drone/runner-go/environ" "github.com/drone/runner-go/manifest" "github.com/drone/runner-go/secret" "gopkg.in/alecthomas/kingpin.v2" ) type compileCommand struct { *internal.Flags Source *os.File Environ map[string]string Secrets map[string]string } func (c *compileCommand) run(*kingpin.ParseContext) error { rawsource, err := ioutil.ReadAll(c.Source) if err != nil { return err } envs := environ.Combine( c.Environ, environ.System(c.System), environ.Repo(c.Repo), environ.Build(c.Build), environ.Stage(c.Stage), environ.Link(c.Repo, c.Build, c.System), c.Build.Params, ) // string substitution function ensures that string // replacement variables are escaped and quoted if they // contain newlines. subf := func(k string) string { v := envs[k] if strings.Contains(v, "\n") { v = fmt.Sprintf("%q", v) } return v } // evaluates string replacement expressions and returns an // update configuration. config, err := envsubst.Eval(string(rawsource), subf) if err != nil { return err } // parse and lint the configuration manifest, err := manifest.ParseString(config) if err != nil { return err } // a configuration can contain multiple pipelines. // get a specific pipeline resource for execution. resource, err := resource.Lookup(c.Stage.Name, manifest) if err != nil { return err } // compile the pipeline to an intermediate representation. comp := &compiler.Compiler{ Pipeline: resource, Manifest: manifest, Build: c.Build, Netrc: c.Netrc, Repo: c.Repo, Stage: c.Stage, System: c.System, Environ: c.Environ, Secret: secret.StaticVars(c.Secrets), } spec := comp.Compile(nocontext) // encode the pipeline in json format and print to the // console for inspection. enc := json.NewEncoder(os.Stdout) enc.SetIndent("", " ") enc.Encode(spec) return nil } func registerCompile(app *kingpin.Application) { c := new(compileCommand) c.Environ = map[string]string{} c.Secrets = map[string]string{} cmd := app.Command("compile", "compile the yaml file"). Action(c.run) cmd.Flag("source", "source file location"). Default(".drone.yml"). FileVar(&c.Source) cmd.Flag("secrets", "secret parameters"). StringMapVar(&c.Secrets) cmd.Flag("environ", "environment variables"). StringMapVar(&c.Environ) // shared pipeline flags c.Flags = internal.ParseFlags(cmd) }