mirror of
https://github.com/drone/drone-cli.git
synced 2026-01-17 08:21:34 +01:00
224 lines
4.6 KiB
Go
224 lines
4.6 KiB
Go
package main
|
|
|
|
import (
|
|
"crypto/tls"
|
|
"crypto/x509"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/codegangsta/cli"
|
|
"github.com/drone/drone-exec/docker"
|
|
"github.com/drone/drone-go/drone"
|
|
"github.com/drone/drone/yaml/matrix"
|
|
"github.com/fatih/color"
|
|
"github.com/samalba/dockerclient"
|
|
)
|
|
|
|
var ExecCmd = cli.Command{
|
|
Name: "exec",
|
|
Usage: "executes a local build",
|
|
Action: func(c *cli.Context) {
|
|
if err := execCmd(c); err != nil {
|
|
fmt.Println(err)
|
|
os.Exit(1)
|
|
}
|
|
},
|
|
Flags: []cli.Flag{
|
|
cli.StringFlag{
|
|
EnvVar: "DOCKER_HOST",
|
|
Name: "docker-host",
|
|
Usage: "docker deamon address",
|
|
Value: "unix:///var/run/docker.sock",
|
|
},
|
|
cli.BoolFlag{
|
|
EnvVar: "DOCKER_TLS_VERIFY",
|
|
Name: "docker-tls-verify",
|
|
Usage: "docker daemon supports tlsverify",
|
|
},
|
|
cli.StringFlag{
|
|
EnvVar: "DOCKER_CERT_PATH",
|
|
Name: "docker-cert-path",
|
|
Usage: "docker certificate directory",
|
|
Value: "",
|
|
},
|
|
cli.BoolFlag{
|
|
Name: "cache",
|
|
Usage: "execute cache steps",
|
|
},
|
|
cli.BoolFlag{
|
|
Name: "deploy",
|
|
Usage: "execute publish and deployment steps",
|
|
},
|
|
cli.BoolFlag{
|
|
Name: "notify",
|
|
Usage: "execute notification steps",
|
|
},
|
|
cli.BoolFlag{
|
|
Name: "pull",
|
|
Usage: "always pull the latest docker image",
|
|
},
|
|
cli.BoolTFlag{
|
|
Name: "debug",
|
|
Usage: "execute the build in debug mode",
|
|
},
|
|
},
|
|
}
|
|
|
|
func execCmd(c *cli.Context) error {
|
|
|
|
cert, _ := ioutil.ReadFile(filepath.Join(
|
|
c.String("docker-cert-path"),
|
|
"cert.pem",
|
|
))
|
|
|
|
key, _ := ioutil.ReadFile(filepath.Join(
|
|
c.String("docker-cert-path"),
|
|
"key.pem",
|
|
))
|
|
|
|
ca, _ := ioutil.ReadFile(filepath.Join(
|
|
c.String("docker-cert-path"),
|
|
"ca.pem",
|
|
))
|
|
if len(cert) == 0 || len(key) == 0 || len(ca) == 0 {
|
|
println("")
|
|
}
|
|
|
|
yml, err := ioutil.ReadFile(".drone.yml")
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
axes, err := matrix.Parse(string(yml))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if len(axes) == 0 {
|
|
axes = append(axes, matrix.Axis{})
|
|
}
|
|
|
|
cli, err := newDockerClient(c.String("docker-host"), cert, key, ca)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
pwd, err := os.Getwd()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
proj := resolvePath(pwd)
|
|
|
|
var exits []int
|
|
|
|
for i, axis := range axes {
|
|
color.Magenta("[DRONE] starting job #%d", i+1)
|
|
if len(axis) != 0 {
|
|
color.Magenta("[DRONE] export %s", axis)
|
|
}
|
|
|
|
payload := struct {
|
|
System drone.System `json:"system"`
|
|
Workspace drone.Workspace `json:"workspace"`
|
|
Repo drone.Repo `json:"repo"`
|
|
Build drone.Build `json:"build"`
|
|
Job drone.Job `json:"job"`
|
|
Config string `json:"config"`
|
|
}{
|
|
Job: drone.Job{
|
|
Status: drone.StatusRunning,
|
|
Environment: axis,
|
|
},
|
|
Config: string(yml),
|
|
Build: drone.Build{
|
|
Status: drone.StatusRunning,
|
|
Commit: "0000000000", // hack
|
|
},
|
|
}
|
|
if len(proj) != 0 {
|
|
payload.Repo.Link = fmt.Sprintf("https://%s", proj)
|
|
}
|
|
out, _ := json.Marshal(payload)
|
|
|
|
exit, err := run(cli, pwd, string(out))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
exits = append(exits, exit)
|
|
|
|
color.Magenta("[DRONE] finished job #%d", i+1)
|
|
color.Magenta("[DRONE] exit code %d", exit)
|
|
}
|
|
|
|
var passed = true
|
|
for i, _ := range axes {
|
|
exit := exits[i]
|
|
if exit == 0 {
|
|
color.Green("[DRONE] job #%d passed", i+1)
|
|
} else {
|
|
color.Red("[DRONE] job #%d failed", i+1)
|
|
passed = false
|
|
}
|
|
}
|
|
if passed {
|
|
color.Green("[DRONE] build passed")
|
|
} else {
|
|
color.Red("[DRONE] build failed")
|
|
os.Exit(1)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func run(client dockerclient.Client, mount, input string) (int, error) {
|
|
|
|
image := "drone/drone-exec:latest"
|
|
entrypoint := []string{"/bin/drone-exec"}
|
|
args := []string{"--build", "--debug", "--mount", mount, "--", input}
|
|
|
|
conf := &dockerclient.ContainerConfig{
|
|
Image: image,
|
|
Entrypoint: entrypoint,
|
|
Cmd: args,
|
|
HostConfig: dockerclient.HostConfig{
|
|
Binds: []string{"/var/run/docker.sock:/var/run/docker.sock"},
|
|
},
|
|
Volumes: map[string]struct{}{
|
|
"/var/run/docker.sock": struct{}{},
|
|
},
|
|
}
|
|
|
|
info, err := docker.Run(client, conf, false)
|
|
|
|
client.StopContainer(info.Id, 15)
|
|
client.RemoveContainer(info.Id, true, true)
|
|
return info.State.ExitCode, err
|
|
}
|
|
|
|
func newDockerClient(addr string, cert, key, ca []byte) (dockerclient.Client, error) {
|
|
var tlc *tls.Config
|
|
|
|
if len(cert) != 0 {
|
|
pem, err := tls.X509KeyPair(cert, key)
|
|
if err != nil {
|
|
return dockerclient.NewDockerClient(addr, nil)
|
|
}
|
|
tlc = &tls.Config{}
|
|
tlc.Certificates = []tls.Certificate{pem}
|
|
|
|
if len(ca) != 0 {
|
|
pool := x509.NewCertPool()
|
|
pool.AppendCertsFromPEM(ca)
|
|
tlc.RootCAs = pool
|
|
|
|
} else {
|
|
tlc.InsecureSkipVerify = true
|
|
}
|
|
}
|
|
|
|
return dockerclient.NewDockerClient(addr, tlc)
|
|
}
|