func (srv *Service) Start() error {
	if srv.logListener == nil {
		srv.logListener = make(map[string]*jobLog)
	}
	srv.Executor.OnUpdate = srv.handleJobUpdate
	srv.metrics.GithubJobPreparationSeconds = prometheus.NewHistogram(prometheus.HistogramOpts{
		Name:    "github_job_preparation_seconds",
		Help:    "Time it took to retrieve all required data from GitHub prior to starting a job",
		Buckets: []float64{0, 0.25, 0.5, 0.75, 1},
	})
	srv.metrics.ExecutorJobPreperationSeconds = prometheus.NewHistogram(prometheus.HistogramOpts{
		Namespace: "werft",
		Subsystem: "executor",
		Name:      "job_preparation_seconds",
		Help:      "Time it took to start executing the job",
		Buckets:   []float64{0, 0.25, 0.5, 0.75, 1},
	})
	srv.metrics.ExecutorJobStartsCounter = prometheus.NewCounter(prometheus.CounterOpts{
		Namespace: "werft",
		Subsystem: "executor",
		Name:      "job_starts_total",
		Help:      "Total amount of jobs executor tried to start.",
	})
	srv.metrics.ExecutorJobFailedStartsCounter = prometheus.NewCounter(prometheus.CounterOpts{
		Namespace: "werft",
		Subsystem: "executor",
		Name:      "job_starts_failed_total",
		Help:      "Total amount of jobs executor failed to start.",
	})
	waitingJobs, _, err := srv.Jobs.Find(context.Background(), []*v1.FilterExpression{
		{Terms: []*v1.FilterTerm{
			{
				Field:     "phase",
				Value:     "waiting",
				Operation: v1.FilterOp_OP_EQUALS,
			},
		}},
	}, []*v1.OrderExpression{}, 0, 0)
	if err != nil {
		return xerrors.Errorf("cannot restore waiting jobs: %w", err)
	}
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
	defer cancel()
	for _, j := range waitingJobs {
		cancelJob := func(err error) {
			log.WithError(err).Errorf("cannot restore waiting job %s", j.Name)
			j.Phase = v1.JobPhase_PHASE_DONE
			j.Details = fmt.Sprintf("cannot restore execution context upon werft restart: %v", err)
			j.Conditions.Success = false
			srv.handleJobUpdate(nil, &j)
		}
		jobYAML, err := srv.Jobs.GetJobSpec(j.Name)
		if err != nil {
			cancelJob(err)
			continue
		}
		waitUntil, err := ptypes.Timestamp(j.Conditions.WaitUntil)
		if err != nil {
			cancelJob(err)
			continue
		}
		md := j.Metadata
		cp, err := srv.RepositoryProvider.ContentProvider(ctx, md.Repository)
		if err != nil {
			cancelJob(err)
			continue
		}
		_, err = srv.RunJob(context.Background(), j.Name, *md, cp, jobYAML, true, waitUntil)
		if err != nil {
			cancelJob(err)
			continue
		}
	}
	go srv.doHousekeeping()
	return nil
}
Start sets up everything to run this werft instance, including executor config
package werft
import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io"
	"path/filepath"
	"reflect"
	"strings"
	"sync"
	"text/template"
	"time"
	sprig "github.com/Masterminds/sprig/v3"
	"github.com/csweichel/werft/pkg/api/repoconfig"
	v1 "github.com/csweichel/werft/pkg/api/v1"
	"github.com/csweichel/werft/pkg/executor"
	"github.com/csweichel/werft/pkg/logcutter"
	"github.com/csweichel/werft/pkg/store"
	"github.com/golang/protobuf/ptypes"
	"github.com/olebedev/emitter"
	"github.com/prometheus/client_golang/prometheus"
	"github.com/segmentio/textio"
	log "github.com/sirupsen/logrus"
	"golang.org/x/xerrors"
	"gopkg.in/yaml.v3"
	corev1 "k8s.io/api/core/v1"
	k8sjson "k8s.io/apimachinery/pkg/runtime/serializer/json"
	k8syaml "k8s.io/apimachinery/pkg/util/yaml"
	"k8s.io/client-go/kubernetes/scheme"
)
var (
	annotationCleanupJob = "cleanupJob"
)
type Config struct {
	BaseURL string `yaml:"baseURL,omitempty"`
	WorkspaceNodePathPrefix string `yaml:"workspaceNodePathPrefix,omitempty"`
	CleanupJobSpec *configPodSpec `yaml:"cleanupJobSpec,omitempty"`
	DebugProxy string
}
type configPodSpec corev1.PodSpec
func (spec *configPodSpec) UnmarshalYAML(value *yaml.Node) error {
	raw, err := yaml.Marshal(value)
	if err != nil {
		return err
	}
	err = k8syaml.NewYAMLOrJSONDecoder(bytes.NewReader(raw), 4096).Decode(spec)
	if err != nil {
		return err
	}
	return nil
}
type jobLog struct {
	CancelExecutorListener context.CancelFunc
	LogStore               io.Closer
}
type Service struct {
	Logs               store.Logs
	Jobs               store.Jobs
	Groups             store.NumberGroup
	Executor           *executor.Executor
	Cutter             logcutter.Cutter
	RepositoryProvider RepositoryProvider
	Config Config
	mu          sync.RWMutex
	logListener map[string]*jobLog
	events  emitter.Emitter
	metrics struct {
		GithubJobPreparationSeconds    prometheus.Histogram
		ExecutorJobPreperationSeconds  prometheus.Histogram
		ExecutorJobStartsCounter       prometheus.Counter
		ExecutorJobFailedStartsCounter prometheus.Counter
	}
}