func vet(path string) { // parse the Drone yml file script, err := script.ParseBuildFile(path) if err != nil { log.Err(err.Error()) os.Exit(1) return } // print the Drone yml as parsed out, _ := goyaml.Marshal(script) log.Noticef("parsed yaml:\n%s", string(out)) }
func (b *Builder) run() error { // create and run the container conf := docker.Config{ Image: b.image.ID, AttachStdin: false, AttachStdout: true, AttachStderr: true, } // configure if Docker should run in privileged mode host := docker.HostConfig{ Privileged: (b.Privileged && len(b.Repo.PR) == 0), } // debugging log.Noticef("starting build %s", b.Build.Name) // link service containers for i, service := range b.services { // convert name of the image to a slug _, name, _ := parseImageName(b.Build.Services[i]) // link the service container to our // build container. host.Links = append(host.Links, service.Name[1:]+":"+name) } // where are temp files going to go? tmpPath := "/tmp/drone" if len(os.Getenv("DRONE_TMP")) > 0 { tmpPath = os.Getenv("DRONE_TMP") } log.Infof("temp directory is %s", tmpPath) if err := os.MkdirAll(tmpPath, 0777); err != nil { return fmt.Errorf("Failed to create temp directory at %s: %s", tmpPath, err) } // link cached volumes conf.Volumes = make(map[string]struct{}) for _, volume := range b.Build.Cache { name := filepath.Clean(b.Repo.Name) branch := filepath.Clean(b.Repo.Branch) volume := filepath.Clean(volume) // with Docker, volumes must be an absolute path. If an absolute // path is not provided, then assume it is for the repository // working directory. if strings.HasPrefix(volume, "/") == false { volume = filepath.Join(b.Repo.Dir, volume) } // local cache path on the host machine // this path is going to be really long hostpath := filepath.Join(tmpPath, name, branch, volume) // check if the volume is created if _, err := os.Stat(hostpath); err != nil { // if does not exist then create os.MkdirAll(hostpath, 0777) } host.Binds = append(host.Binds, hostpath+":"+volume) conf.Volumes[volume] = struct{}{} // debugging log.Infof("mounting volume %s:%s", hostpath, volume) } // create the container from the image run, err := b.dockerClient.Containers.Create(&conf) if err != nil { return err } // cache instance of docker.Run b.container = run // attach to the container go func() { b.dockerClient.Containers.Attach(run.ID, &writer{b.Stdout}) }() // start the container if err := b.dockerClient.Containers.Start(run.ID, &host); err != nil { b.BuildState.ExitCode = 1 b.BuildState.Finished = time.Now().UTC().Unix() return err } // wait for the container to stop wait, err := b.dockerClient.Containers.Wait(run.ID) if err != nil { b.BuildState.ExitCode = 1 b.BuildState.Finished = time.Now().UTC().Unix() return err } // set completion time b.BuildState.Finished = time.Now().UTC().Unix() // get the exit code if possible b.BuildState.ExitCode = wait.StatusCode return nil }
func run(path string) { dockerClient := docker.New() // parse the Drone yml file s, err := script.ParseBuildFile(path) if err != nil { log.Err(err.Error()) os.Exit(1) return } // get the repository root directory dir := filepath.Dir(path) code := repo.Repo{ Name: dir, Branch: "HEAD", // should we do this? Path: dir, } // does the local repository match the // $GOPATH/src/{package} pattern? This is // important so we know the target location // where the code should be copied inside // the container. if gopath, ok := getRepoPath(dir); ok { code.Dir = gopath } else if gopath, ok := getGoPath(dir); ok { // in this case we found a GOPATH and // reverse engineered the package path code.Dir = gopath } else { // otherwise just use directory name code.Dir = filepath.Base(dir) } // this is where the code gets uploaded to the container // TODO move this code to the build package code.Dir = filepath.Join("/var/cache/drone/src", filepath.Clean(code.Dir)) // track all build results var builders []*build.Builder // ssh key to import into container var key []byte if len(*identity) != 0 { key, err = ioutil.ReadFile(*identity) if err != nil { fmt.Printf("[Error] Could not find or read identity file %s\n", *identity) os.Exit(1) return } } builds := []*script.Build{s} // loop through and create builders for _, b := range builds { //script.Builds { builder := build.New(dockerClient) builder.Build = b builder.Repo = &code builder.Key = key builder.Stdout = os.Stdout builder.Timeout = *timeout if *parallel == true { var buf bytes.Buffer builder.Stdout = &buf } builders = append(builders, builder) } switch *parallel { case false: runSequential(builders) case true: runParallel(builders) } // if in parallel mode, print out the buffer // if we had a failure for _, builder := range builders { if builder.BuildState.ExitCode == 0 { continue } if buf, ok := builder.Stdout.(*bytes.Buffer); ok { log.Noticef("printing stdout for failed build %s", builder.Build.Name) println(buf.String()) } } // this exit code is initially 0 and will // be set to an error code if any of the // builds fail. var exit int fmt.Printf("\nDrone Build Results \033[90m(%v)\033[0m\n", len(builders)) // loop through and print results for _, builder := range builders { build := builder.Build res := builder.BuildState duration := time.Duration(res.Finished - res.Started) switch { case builder.BuildState.ExitCode == 0: fmt.Printf(" \033[32m\u2713\033[0m %v \033[90m(%v)\033[0m\n", build.Name, humanizeDuration(duration*time.Second)) case builder.BuildState.ExitCode != 0: fmt.Printf(" \033[31m\u2717\033[0m %v \033[90m(%v)\033[0m\n", build.Name, humanizeDuration(duration*time.Second)) exit = builder.BuildState.ExitCode } } os.Exit(exit) }
func (b *Builder) run() error { // create and run the container conf := docker.Config{ Image: b.image.ID, AttachStdin: false, AttachStdout: true, AttachStderr: true, } host := docker.HostConfig{ Privileged: false, } // debugging log.Noticef("starting build %s", b.Build.Name) // link service containers for i, service := range b.services { image, ok := services[b.Build.Services[i]] if !ok { continue // THIS SHOULD NEVER HAPPEN } // link the service container to our // build container. host.Links = append(host.Links, service.Name[1:]+":"+image.Name) } // create the container from the image run, err := client.Containers.Create(&conf) if err != nil { return err } // cache instance of docker.Run b.container = run // attach to the container go func() { client.Containers.Attach(run.ID, &writer{b.Stdout}) }() // start the container if err := client.Containers.Start(run.ID, &host); err != nil { b.BuildState.ExitCode = 1 b.BuildState.Finished = time.Now().UTC().Unix() return err } // wait for the container to stop wait, err := client.Containers.Wait(run.ID) if err != nil { b.BuildState.ExitCode = 1 b.BuildState.Finished = time.Now().UTC().Unix() return err } // set completion time b.BuildState.Finished = time.Now().UTC().Unix() // get the exit code if possible b.BuildState.ExitCode = wait.StatusCode return nil }
func (b *Builder) run() error { // create and run the container conf := docker.Config{ Image: b.image.ID, AttachStdin: false, AttachStdout: true, AttachStderr: true, } host := docker.HostConfig{ Privileged: false, } // debugging log.Noticef("starting build %s", b.Build.Name) // link service containers for i, service := range b.services { image, ok := services[b.Build.Services[i]] if !ok { continue // THIS SHOULD NEVER HAPPEN } // link the service container to our // build container. host.Links = append(host.Links, service.Name[1:]+":"+image.Name) } // link cached volumes conf.Volumes = make(map[string]struct{}) for _, volume := range b.Build.Cache { name := filepath.Clean(b.Repo.Name) branch := filepath.Clean(b.Repo.Branch) volume := filepath.Clean(volume) // with Docker, volumes must be an absolute path. If an absolute // path is not provided, then assume it is for the repository // working directory. if strings.HasPrefix(volume, "/") == false { volume = filepath.Join(b.Repo.Dir, volume) } // local cache path on the host machine // this path is going to be really long hostpath := filepath.Join("/tmp/drone", name, branch, volume) // check if the volume is created if _, err := os.Stat(hostpath); err != nil { // if does not exist then create os.MkdirAll(hostpath, 0777) } host.Binds = append(host.Binds, hostpath+":"+volume) conf.Volumes[volume] = struct{}{} // debugging log.Infof("mounting volume %s:%s", hostpath, volume) } // create the container from the image run, err := b.dockerClient.Containers.Create(&conf) if err != nil { return err } // cache instance of docker.Run b.container = run // attach to the container go func() { b.dockerClient.Containers.Attach(run.ID, &writer{b.Stdout}) }() // start the container if err := b.dockerClient.Containers.Start(run.ID, &host); err != nil { b.BuildState.ExitCode = 1 b.BuildState.Finished = time.Now().UTC().Unix() return err } // wait for the container to stop wait, err := b.dockerClient.Containers.Wait(run.ID) if err != nil { b.BuildState.ExitCode = 1 b.BuildState.Finished = time.Now().UTC().Unix() return err } // set completion time b.BuildState.Finished = time.Now().UTC().Unix() // get the exit code if possible b.BuildState.ExitCode = wait.StatusCode return nil }