app/deploy.go
func Deploy(opts DeployOptions) (string, error) {
	if opts.Event == nil {
		return "", errors.Errorf("missing event in deploy opts")
	}
	if opts.Rollback && !regexp.MustCompile(":v[0-9]+$").MatchString(opts.Image) {
		imageName, err := image.GetAppImageBySuffix(opts.App.Name, opts.Image)
		if err != nil {
			return "", err
		}
		opts.Image = imageName
	}
	logWriter := LogWriter{App: opts.App}
	logWriter.Async()
	defer logWriter.Close()
	opts.Event.SetLogWriter(io.MultiWriter(&tsuruIo.NoErrorWriter{Writer: opts.OutputStream}, &logWriter))
	imageID, err := deployToProvisioner(&opts, opts.Event)
	rebuild.RoutesRebuildOrEnqueue(opts.App.Name)
	quotaErr := opts.App.fixQuota()
	if quotaErr != nil {
		log.Errorf("WARNING: unable to ensure quota is up-to-date after deploy: %v", quotaErr)
	}
	if err != nil {
		var logLines []Applog
		if provision.IsStartupError(err) {
			logLines, _ = opts.App.lastLogs(10, Applog{
				Source: "tsuru",
			}, true)
		}
		err = &errorWithLog{err: err, logs: logLines}
		return "", err
	}
	err = incrementDeploy(opts.App)
	if err != nil {
		log.Errorf("WARNING: couldn't increment deploy count, deploy opts: %#v", opts)
	}
	if opts.Kind == DeployImage || opts.Kind == DeployRollback {
		if !opts.App.UpdatePlatform {
			opts.App.SetUpdatePlatform(true)
		}
	} else if opts.App.UpdatePlatform {
		opts.App.SetUpdatePlatform(false)
	}
	return imageID, nil
}
func Deploy(opts DeployOptions) (string, error) {
	if opts.Event == nil {
		return "", errors.Errorf("missing event in deploy opts")
	}
	if opts.Rollback && !regexp.MustCompile(":v[0-9]+$").MatchString(opts.Image) {
		imageName, err := image.GetAppImageBySuffix(opts.App.Name, opts.Image)
		if err != nil {
			return "", err
		}
		opts.Image = imageName
	}
	logWriter := LogWriter{App: opts.App}
	logWriter.Async()
	defer logWriter.Close()
	opts.Event.SetLogWriter(io.MultiWriter(&tsuruIo.NoErrorWriter{Writer: opts.OutputStream}, &logWriter))
	imageID, err := deployToProvisioner(&opts, opts.Event)
	rebuild.RoutesRebuildOrEnqueue(opts.App.Name)
	quotaErr := opts.App.fixQuota()
	if quotaErr != nil {
		log.Errorf("WARNING: unable to ensure quota is up-to-date after deploy: %v", quotaErr)
	}
	if err != nil {
		var logLines []Applog
		if provision.IsStartupError(err) {
			logLines, _ = opts.App.lastLogs(10, Applog{
				Source: "tsuru",
			}, true)
		}
		err = &errorWithLog{err: err, logs: logLines}
		return "", err
	}
	err = incrementDeploy(opts.App)
	if err != nil {
		log.Errorf("WARNING: couldn't increment deploy count, deploy opts: %#v", opts)
	}
	if opts.Kind == DeployImage || opts.Kind == DeployRollback {
		if !opts.App.UpdatePlatform {
			opts.App.SetUpdatePlatform(true)
		}
	} else if opts.App.UpdatePlatform {
		opts.App.SetUpdatePlatform(false)
	}
	return imageID, nil
}
// Deploy runs a deployment of an application. It will first try to run an
// archive based deploy (if opts.ArchiveURL is not empty), and then fallback to
// the Git based deployment.