func (b *BuildPipelineRuby) SavePipeline(p *gaia.Pipeline) error {
	dest := filepath.Join(gaia.Cfg.PipelinePath, pipelinehelper.AppendTypeToName(p.Name, p.Type))
	p.ExecPath = dest
	p.Type = gaia.PTypeRuby
	p.Name = strings.TrimSuffix(filepath.Base(dest), typeDelimiter+gaia.PTypeRuby.String())
	p.Created = time.Now()
	storeService, _ := services.StorageService()
	return storeService.PipelinePut(p)
}
SavePipeline saves the current pipeline configuration.
package pipeline
import (
	"errors"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"time"
	"github.com/gaia-pipeline/gaia/helper/filehelper"
	"github.com/gaia-pipeline/gaia/helper/pipelinehelper"
	"github.com/gaia-pipeline/gaia"
	"github.com/gaia-pipeline/gaia/services"
	"github.com/gofrs/uuid"
)
var (
	gemBinaryName = "gem"
)
const gemspecNameKey = "${NAME}"
const gemInitFile = "gaia.rb"
type BuildPipelineRuby struct {
	Type        gaia.PipelineType
	GemfileName string
}
func (b *BuildPipelineRuby) PrepareEnvironment(p *gaia.CreatePipeline) error {
	v4, err := uuid.NewV4()
	if err != nil {
		gaia.Cfg.Logger.Debug("unable to generate uuid", "error", err.Error())
		return err
	}
	uniqueName := uuid.Must(v4, nil)
	cloneFolder := filepath.Join(gaia.Cfg.HomePath, gaia.TmpFolder, gaia.TmpRubyFolder, gaia.SrcFolder, uniqueName.String())
	err = os.MkdirAll(cloneFolder, 0700)
	if err != nil {
		return err
	}
	if p.Pipeline.Repo == nil {
		p.Pipeline.Repo = &gaia.GitRepo{}
	}
	p.Pipeline.Repo.LocalDest = cloneFolder
	p.Pipeline.UUID = uniqueName.String()
	return nil
}
func (b *BuildPipelineRuby) ExecuteBuild(p *gaia.CreatePipeline) error {
	path, err := exec.LookPath(gemBinaryName)
	if err != nil {
		gaia.Cfg.Logger.Debug("cannot find gem binary executable", "error", err.Error())
		return err
	}
	localDest := ""
	if p.Pipeline.Repo != nil {
		localDest = p.Pipeline.Repo.LocalDest
	}
	gemspec, err := filterPathContentBySuffix(localDest, ".gemspec")
	if err != nil {
		gaia.Cfg.Logger.Error("cannot find gemspec file in cloned repository folder", "path", localDest)
		return err
	}
	if len(gemspec) != 1 {
		gaia.Cfg.Logger.Debug("cannot find gemspec file in cloned repo", "foundGemspecs", len(gemspec), "gemspecs", gemspec)
		return errors.New("cannot find gemspec file in cloned repo")
	}
	v4, err := uuid.NewV4()
	if err != nil {
		return err
	}
	uuid := uuid.Must(v4, nil).String()
	gemspecContent, err := ioutil.ReadFile(gemspec[0])
	if err != nil {
		gaia.Cfg.Logger.Debug("cannot read gemspec file", "error", err.Error(), "pipeline", p.Pipeline.Name)
		return err
	}
	gemspecContentStr := strings.Replace(string(gemspecContent[:]), gemspecNameKey, uuid, 1)
	err = ioutil.WriteFile(gemspec[0], []byte(gemspecContentStr), 0644)
	if err != nil {
		gaia.Cfg.Logger.Debug("cannot write/edit gemspec file", "error", err.Error(), "pipeline", p.Pipeline.Name)
		return err
	}
	err = os.Rename(filepath.Join(localDest, "lib", gemInitFile), filepath.Join(localDest, "lib", uuid+".rb"))
	if err != nil {
		gaia.Cfg.Logger.Debug("cannot rename initial ruby file", "error", err.Error(), "pipeline", p.Pipeline)
		return err
	}
	args := []string{
		"build",
		gemspec[0],
	}
	output, err := executeCmd(path, args, os.Environ(), localDest)
	p.Output = string(output)
	if err != nil {
		gaia.Cfg.Logger.Debug("cannot build pipeline", "error", err.Error(), "output", string(output))
		return err
	}
	gemfile, err := findGemFileByGlob(localDest, uuid+"*.gem")
	if err != nil {
		gaia.Cfg.Logger.Error("cannot find final gem file after build", "path", p.Pipeline.Repo.LocalDest)
		return err
	}
	if gemfile == nil {
		gemfile, err = findGemFileByGlob(localDest, "*.gem")
		if err != nil {
			gaia.Cfg.Logger.Error("cannot find final gem file after build", "path", p.Pipeline.Repo.LocalDest)
			return err
		}
	}
	if len(gemfile) != 1 {
		gaia.Cfg.Logger.Debug("cannot find gem file in cloned repo", "gems", gemfile)
		return errors.New("cannot find gem file in cloned repo")
	}
	p.Pipeline.ExecPath = gemfile[0]
	b.GemfileName = gemfile[0]
	return nil
}
func filterPathContentBySuffix(path, suffix string) ([]string, error) {
	filteredFiles := []string{}
	files, err := ioutil.ReadDir(path)
	if err != nil {
		return filteredFiles, err
	}
	for _, file := range files {
		if strings.HasSuffix(file.Name(), suffix) {
			filteredFiles = append(filteredFiles, filepath.Join(path, file.Name()))
		}
	}
	return filteredFiles, nil
}
func findGemFileByGlob(path, glob string) ([]string, error) {
	fullPath := filepath.Join(path, glob)
	return filepath.Glob(fullPath)
}
func (b *BuildPipelineRuby) CopyBinary(p *gaia.CreatePipeline) error {
	src := b.GemfileName
	gaia.Cfg.Logger.Debug("Copying over ruby gem file", "gem", src)
	dest := filepath.Join(gaia.Cfg.PipelinePath, pipelinehelper.AppendTypeToName(p.Pipeline.Name, p.Pipeline.Type))
	if err := filehelper.CopyFileContents(src, dest); err != nil {
		return err
	}
	return os.Chmod(dest, gaia.ExecutablePermission)
}