func (pp *PipelineProvider) PipelineTrigger(c echo.Context) error {
	err := pp.PipelineTriggerAuth(c)
	if err != nil {
		return c.String(http.StatusForbidden, "User rejected")
	}
	pipelineIDStr := c.Param("pipelineid")
	pipelineToken := c.Param("pipelinetoken")
	pipelineID, err := strconv.Atoi(pipelineIDStr)
	if err != nil {
		return c.String(http.StatusBadRequest, errInvalidPipelineID.Error())
	}
	var foundPipeline gaia.Pipeline
	for _, p := range pipeline.GlobalActivePipelines.GetAll() {
		if p.ID == pipelineID {
			foundPipeline = p
			break
		}
	}
	if foundPipeline.Name == "" {
		return c.String(http.StatusBadRequest, "Pipeline not found.")
	}
	if foundPipeline.TriggerToken != pipelineToken {
		return c.String(http.StatusForbidden, "Invalid remote trigger token.")
	}
	var args []*gaia.Argument
	_ = c.Bind(&args)
	pipelineRun, err := pp.deps.Scheduler.SchedulePipeline(&foundPipeline, gaia.StartReasonRemote, args)
	if err != nil {
		return c.String(http.StatusBadRequest, err.Error())
	} else if pipelineRun != nil {
		return c.String(http.StatusOK, "Trigger successful for pipeline: "+pipelineIDStr)
	}
	return c.String(http.StatusBadRequest, "Failed to trigger pipeline run.")
}
PipelineTrigger allows for a remote running of a pipeline.
This endpoint does not require authentication. It will use a TOKEN
that is specific to a pipeline. It can only be used by the `auto`
user.
@Summary Trigger a pipeline.
@Description Using a trigger token, start a pipeline run. This endpoint does not require authentication.
@Tags pipelines
@Accept plain
@Produce plain
@Param pipelineid query string true "The ID of the pipeline."
@Param pipelinetoken query string true "The trigger token for this pipeline."
@Success 200 {string} string "Trigger successful for pipeline: {pipelinename}"
@Failure 400 {string} string "Error while triggering pipeline"
@Failure 403 {string} string "Invalid trigger token"
@Router /pipeline/{pipelineid}/{pipelinetoken}/trigger [post]
package pipelines
import (
	"errors"
	"net/http"
	"strconv"
	"time"
	"github.com/gofrs/uuid"
	"github.com/labstack/echo/v4"
	"github.com/robfig/cron"
	"github.com/gaia-pipeline/gaia"
	"github.com/gaia-pipeline/gaia/helper/pipelinehelper"
	"github.com/gaia-pipeline/gaia/helper/stringhelper"
	"github.com/gaia-pipeline/gaia/security"
	"github.com/gaia-pipeline/gaia/services"
	"github.com/gaia-pipeline/gaia/workers/pipeline"
)
var (
	errPipelineNotFound = errors.New("pipeline not found with the given id")
	errInvalidPipelineID = errors.New("the given pipeline id is not valid")
	errPipelineDelete = errors.New("pipeline could not be deleted. Perhaps you don't have the right permissions")
	errPipelineRename = errors.New("pipeline could not be renamed")
	errWrongDockerValue = errors.New("invalid value for docker parameter")
)
func (pp *PipelineProvider) PipelineGitLSRemote(c echo.Context) error {
	repo := &gaia.GitRepo{}
	if err := c.Bind(repo); err != nil {
		return c.String(http.StatusBadRequest, err.Error())
	}
	err := pipeline.GitLSRemote(repo)
	if err != nil {
		return c.String(http.StatusForbidden, err.Error())
	}
	return c.JSON(http.StatusOK, repo.Branches)
}
func (pp *PipelineProvider) CreatePipeline(c echo.Context) error {
	storeService, _ := services.StorageService()
	p := &gaia.CreatePipeline{}
	if err := c.Bind(p); err != nil {
		return c.String(http.StatusBadRequest, err.Error())
	}
	if err := pipeline.ValidatePipelineName(p.Pipeline.Name); err != nil {
		return c.String(http.StatusBadRequest, err.Error())
	}
	p.Created = time.Now()
	p.StatusType = gaia.CreatePipelineRunning
	v4, err := uuid.NewV4()
	if err != nil {
		return c.String(http.StatusBadRequest, err.Error())
	}
	p.ID = uuid.Must(v4, nil).String()
	if !stringhelper.IsContainedInSlice(p.Pipeline.Tags, p.Pipeline.Type.String(), true) {
		p.Pipeline.Tags = append(p.Pipeline.Tags, p.Pipeline.Type.String())
	}
	err = storeService.CreatePipelinePut(p)
	if err != nil {
		gaia.Cfg.Logger.Debug("cannot put pipeline into store", "error", err.Error())
		return c.String(http.StatusInternalServerError, err.Error())
	}
	go pp.deps.PipelineService.CreatePipeline(p)
	return c.JSON(http.StatusOK, nil)
}
func (pp *PipelineProvider) CreatePipelineGetAll(c echo.Context) error {
	storeService, _ := services.StorageService()
	pipelineList, err := storeService.CreatePipelineGet()
	if err != nil {
		gaia.Cfg.Logger.Debug("cannot get create pipelines from store", "error", err.Error())
		return c.String(http.StatusInternalServerError, err.Error())
	}
	return c.JSON(http.StatusOK, pipelineList)
}
func (pp *PipelineProvider) PipelineNameAvailable(c echo.Context) error {
	pName := c.QueryParam("name")
	if err := pipeline.ValidatePipelineName(pName); err != nil {
		return c.String(http.StatusBadRequest, err.Error())
	}
	return c.JSON(http.StatusOK, nil)
}
func (pp *PipelineProvider) PipelineGetAll(c echo.Context) error {
	pipelines := pipeline.GlobalActivePipelines.GetAll()
	for id := range pipelines {
		obscurePipelineData(&pipelines[id])
	}
	return c.JSON(http.StatusOK, pipelines)
}
func (pp *PipelineProvider) PipelineGet(c echo.Context) error {
	pipelineIDStr := c.Param("pipelineid")
	pipelineID, err := strconv.Atoi(pipelineIDStr)
	if err != nil {
		return c.String(http.StatusBadRequest, errInvalidPipelineID.Error())
	}
	for _, p := range pipeline.GlobalActivePipelines.GetAll() {
		if p.ID == pipelineID {
			obscurePipelineData(&p)
			return c.JSON(http.StatusOK, p)
		}
	}
	return c.String(http.StatusNotFound, errPipelineNotFound.Error())
}
func (pp *PipelineProvider) PipelineUpdate(c echo.Context) error {
	storeService, _ := services.StorageService()
	p := gaia.Pipeline{}
	if err := c.Bind(&p); err != nil {
		return c.String(http.StatusBadRequest, err.Error())
	}
	var foundPipeline gaia.Pipeline
	for _, pipe := range pipeline.GlobalActivePipelines.GetAll() {
		if pipe.ID == p.ID {
			foundPipeline = pipe
			break
		}
	}
	if foundPipeline.Name == "" {
		return c.String(http.StatusNotFound, errPipelineNotFound.Error())
	}
	if foundPipeline.Name != p.Name {
		currentName := foundPipeline.Name
		err := pipeline.RenameBinary(foundPipeline, p.Name)
		if err != nil {
			return c.String(http.StatusInternalServerError, errPipelineRename.Error())
		}
		foundPipeline.Name = p.Name
		foundPipeline.ExecPath = pipeline.GetExecPath(p)
		err = storeService.PipelinePut(&foundPipeline)
		if err != nil {
			return c.String(http.StatusInternalServerError, err.Error())
		}
		pipeline.GlobalActivePipelines.ReplaceByName(currentName, foundPipeline)
	}
	if !stringSliceEqual(foundPipeline.PeriodicSchedules, p.PeriodicSchedules) {
		if foundPipeline.CronInst != nil {
			foundPipeline.CronInst.Stop()
		}
		foundPipeline.CronInst = cron.New()
		for _, schedule := range p.PeriodicSchedules {
			err := foundPipeline.CronInst.AddFunc(schedule, func() {
				_, err := pp.deps.Scheduler.SchedulePipeline(&foundPipeline, gaia.StartReasonScheduled, []*gaia.Argument{})
				if err != nil {
					gaia.Cfg.Logger.Error("cannot schedule pipeline from periodic schedule", "error", err, "pipeline", foundPipeline)
					return
				}
				gaia.Cfg.Logger.Info("pipeline has been automatically scheduled by periodic scheduling:", "name", foundPipeline.Name)
			})
			if err != nil {
				return c.String(http.StatusBadRequest, err.Error())
			}
		}
		err := storeService.PipelinePut(&foundPipeline)
		if err != nil {
			return c.String(http.StatusInternalServerError, err.Error())
		}
		foundPipeline.CronInst.Start()
		pipeline.GlobalActivePipelines.Replace(foundPipeline)
	}
	if p.Docker != foundPipeline.Docker {
		foundPipeline.Docker = p.Docker
		err := storeService.PipelinePut(&foundPipeline)
		if err != nil {
			return c.String(http.StatusInternalServerError, err.Error())
		}
		pipeline.GlobalActivePipelines.Replace(foundPipeline)
	}
	return c.String(http.StatusOK, "Pipeline has been updated")
}
func stringSliceEqual(a, b []string) bool {
	if len(a) != len(b) {
		return false
	}
	for i := range a {
		if a[i] != b[i] {
			return false
		}
	}
	return true
}
func (pp *PipelineProvider) PipelineDelete(c echo.Context) error {
	storeService, _ := services.StorageService()
	pipelineIDStr := c.Param("pipelineid")
	pipelineID, err := strconv.Atoi(pipelineIDStr)
	if err != nil {
		return c.String(http.StatusBadRequest, errInvalidPipelineID.Error())
	}
	var foundPipeline gaia.Pipeline
	var deletedPipelineIndex int
	for index, p := range pipeline.GlobalActivePipelines.GetAll() {
		if p.ID == pipelineID {
			foundPipeline = p
			deletedPipelineIndex = index
			break
		}
	}
	if foundPipeline.Name == "" {
		return c.String(http.StatusNotFound, errPipelineNotFound.Error())
	}
	if ct := foundPipeline.CronInst; ct != nil {
		ct.Stop()
	}
	err = pipeline.DeleteBinary(foundPipeline)
	if err != nil {
		return c.String(http.StatusInternalServerError, errPipelineDelete.Error())
	}
	err = storeService.PipelineDelete(pipelineID)
	if err != nil {
		return c.String(http.StatusInternalServerError, err.Error())
	}
	if err := pipeline.GlobalActivePipelines.Remove(deletedPipelineIndex); err != nil {
		return c.String(http.StatusInternalServerError, err.Error())
	}
	return c.String(http.StatusOK, "Pipeline has been deleted")
}