Ejemplo n.º 1
0
func (a *Agent) prep(w *queue.Work) (*yaml.Config, error) {

	envs := toEnv(w)
	w.Yaml = expander.ExpandString(w.Yaml, envs)

	// inject the netrc file into the clone plugin if the repository is
	// private and requires authentication.
	var secrets []*model.Secret
	if w.Verified {
		secrets = append(secrets, w.Secrets...)
	}

	if w.Repo.IsPrivate {
		secrets = append(secrets, &model.Secret{
			Name:   "DRONE_NETRC_USERNAME",
			Value:  w.Netrc.Login,
			Images: []string{"*"},
			Events: []string{"*"},
		})
		secrets = append(secrets, &model.Secret{
			Name:   "DRONE_NETRC_PASSWORD",
			Value:  w.Netrc.Password,
			Images: []string{"*"},
			Events: []string{"*"},
		})
		secrets = append(secrets, &model.Secret{
			Name:   "DRONE_NETRC_MACHINE",
			Value:  w.Netrc.Machine,
			Images: []string{"*"},
			Events: []string{"*"},
		})
	}

	conf, err := yaml.ParseString(w.Yaml)
	if err != nil {
		return nil, err
	}

	src := "src"
	if url, _ := url.Parse(w.Repo.Link); url != nil {
		host, _, err := net.SplitHostPort(url.Host)
		if err == nil {
			url.Host = host
		}
		src = filepath.Join(src, url.Host, url.Path)
	}

	transform.Clone(conf, w.Repo.Kind)
	transform.Environ(conf, envs)
	transform.DefaultFilter(conf)
	if w.BuildLast != nil {
		transform.ChangeFilter(conf, w.BuildLast.Status)
	}

	transform.ImageSecrets(conf, secrets, w.Build.Event)
	transform.Identifier(conf)
	transform.WorkspaceTransform(conf, "/drone", src)

	if err := transform.Check(conf, w.Repo.IsTrusted); err != nil {
		return nil, err
	}

	transform.CommandTransform(conf)
	transform.ImagePull(conf, a.Pull)
	transform.ImageTag(conf)
	transform.ImageName(conf)
	transform.ImageNamespace(conf, a.Namespace)
	if err := transform.ImageEscalate(conf, a.Escalate); err != nil {
		return nil, err
	}
	transform.PluginParams(conf)

	if a.Local != "" {
		transform.PluginDisable(conf, a.Disable)
		transform.ImageVolume(conf, []string{a.Local + ":" + conf.Workspace.Path})
	}

	transform.Pod(conf)

	return conf, nil
}
Ejemplo n.º 2
0
Archivo: exec.go Proyecto: tnaoto/drone
func (r *pipeline) run() error {
	w, err := r.drone.Pull("linux", "amd64")
	if err != nil {
		return err
	}

	logrus.Infof("Starting build %s/%s#%d.%d",
		w.Repo.Owner, w.Repo.Name, w.Build.Number, w.Job.Number)

	w.Job.Status = model.StatusRunning
	w.Job.Started = time.Now().Unix()

	prefix := fmt.Sprintf("drone_%s", uniuri.New())

	envs := toEnv(w)
	w.Yaml = expander.ExpandString(w.Yaml, envs)

	// inject the netrc file into the clone plugin if the repositroy is
	// private and requires authentication.
	var secrets []*model.Secret
	if w.Verified {
		secrets = append(secrets, w.Secrets...)
	}

	if w.Repo.IsPrivate {
		secrets = append(secrets, &model.Secret{
			Name:   "DRONE_NETRC_USERNAME",
			Value:  w.Netrc.Login,
			Images: []string{"*"},
			Events: []string{"*"},
		})
		secrets = append(secrets, &model.Secret{
			Name:   "DRONE_NETRC_PASSWORD",
			Value:  w.Netrc.Password,
			Images: []string{"*"},
			Events: []string{"*"},
		})
		secrets = append(secrets, &model.Secret{
			Name:   "DRONE_NETRC_MACHINE",
			Value:  w.Netrc.Machine,
			Images: []string{"*"},
			Events: []string{"*"},
		})
	}

	var lastStatus string
	if w.BuildLast != nil {
		lastStatus = w.BuildLast.Status
	}

	trans := []compiler.Transform{
		builtin.NewCloneOp("git", true),
		builtin.NewCacheOp(
			"plugins/cache:latest",
			"/var/lib/drone/cache/"+w.Repo.FullName,
			false,
		),
		builtin.NewSecretOp(w.Build.Event, secrets),
		builtin.NewNormalizeOp(r.config.namespace),
		builtin.NewWorkspaceOp("/drone", "/drone/src/github.com/"+w.Repo.FullName),
		builtin.NewValidateOp(
			w.Repo.IsTrusted,
			r.config.whitelist,
		),
		builtin.NewEnvOp(envs),
		builtin.NewShellOp(builtin.Linux_adm64),
		builtin.NewArgsOp(),
		builtin.NewEscalateOp(r.config.privileged),
		builtin.NewPodOp(prefix),
		builtin.NewAliasOp(prefix),
		builtin.NewPullOp(r.config.pull),
		builtin.NewFilterOp(
			lastStatus,
			w.Build.Branch,
			w.Build.Event,
			w.Build.Deploy,
			w.Job.Environment,
		),
	}

	compile := compiler.New()
	compile.Transforms(trans)
	spec, err := compile.CompileString(w.Yaml)
	if err != nil {
		w.Job.Error = err.Error()
		w.Job.ExitCode = 255
		w.Job.Finished = w.Job.Started
		w.Job.Status = model.StatusError
		pushRetry(r.drone, w)
		return nil
	}

	pushRetry(r.drone, w)

	conf := runner.Config{
		Engine: docker.New(r.docker),
	}

	c := context.TODO()
	c, timout := context.WithTimeout(c, time.Minute*time.Duration(w.Repo.Timeout))
	c, cancel := context.WithCancel(c)
	defer cancel()
	defer timout()

	run := conf.Runner(c, spec)
	run.Run()

	wait := r.drone.Wait(w.Job.ID)
	defer wait.Cancel()
	go func() {
		if _, err := wait.Done(); err == nil {
			logrus.Infof("Cancel build %s/%s#%d.%d",
				w.Repo.Owner, w.Repo.Name, w.Build.Number, w.Job.Number)
			cancel()
		}
	}()

	rc, wc := io.Pipe()
	go func() {
		// TODO(bradrydzewski) figure out how to resume upload on failure
		err := r.drone.Stream(w.Job.ID, rc)
		if err != nil && err != io.ErrClosedPipe {
			logrus.Errorf("Error streaming build logs. %s", err)
		}
	}()

	pipe := run.Pipe()
	for {
		line := pipe.Next()
		if line == nil {
			break
		}
		linejson, _ := json.Marshal(line)
		wc.Write(linejson)
		wc.Write([]byte{'\n'})
	}

	err = run.Wait()

	pipe.Close()
	wc.Close()
	rc.Close()

	// catch the build result
	if err != nil {
		w.Job.ExitCode = 255
	}
	if exitErr, ok := err.(*runner.ExitError); ok {
		w.Job.ExitCode = exitErr.Code
	}

	w.Job.Finished = time.Now().Unix()

	switch w.Job.ExitCode {
	case 128, 130, 137:
		w.Job.Status = model.StatusKilled
	case 0:
		w.Job.Status = model.StatusSuccess
	default:
		w.Job.Status = model.StatusFailure
	}

	pushRetry(r.drone, w)

	logrus.Infof("Finished build %s/%s#%d.%d",
		w.Repo.Owner, w.Repo.Name, w.Build.Number, w.Job.Number)

	return nil
}