Newer
Older
log "github.com/sirupsen/logrus"
"gitlab.com/gitlab-org/gitlab-runner/common"
"gitlab.com/gitlab-org/gitlab-runner/network"
type RunSingleCommand struct {
common.RunnerConfig
network common.Network
WaitTimeout int `long:"wait-timeout" description:"How long to wait in seconds before receiving the first job"`
lastBuild time.Time
runForever bool
MaxBuilds int `long:"max-builds" description:"How many builds to process before exiting"`
finished *abool.AtomicBool
interruptSignals chan os.Signal
func waitForInterrupts(finished *abool.AtomicBool, abortSignal chan os.Signal, doneSignal chan int, interruptSignals chan os.Signal) {
if interruptSignals == nil {
interruptSignals = make(chan os.Signal)
}
signal.Notify(interruptSignals, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT)
interrupt := <-interruptSignals
}
// request stop, but wait for force exit
for interrupt == syscall.SIGQUIT {
log.Warningln("Requested quit, waiting for builds to finish")
interrupt = <-interruptSignals
}
log.Warningln("Requested exit:", interrupt)
go func() {
for {
abortSignal <- interrupt
}
}()
select {
case newSignal := <-interruptSignals:
log.Fatalln("forced exit:", newSignal)
case <-time.After(common.ShutdownTimeout * time.Second):
log.Fatalln("shutdown timedout")
case <-doneSignal:
}
}
Andrew Chin
committed
// Things to do after a build
func (r *RunSingleCommand) postBuild() {
if r.MaxBuilds > 0 {
r.MaxBuilds--
}
r.lastBuild = time.Now()
}
func (r *RunSingleCommand) processBuild(data common.ExecutorData, abortSignal chan os.Signal) (err error) {
jobData, healthy := r.network.RequestJob(r.RunnerConfig, nil)
if !healthy {
log.Println("Runner is not healthy!")
select {
case <-time.After(common.NotHealthyCheckInterval * time.Second):
case <-abortSignal:
}
return
}
case <-time.After(common.CheckInterval):
case <-abortSignal:
}
return
}
config := common.NewConfig()
newBuild := common.NewBuild(*jobData, &r.RunnerConfig, abortSignal, data)
jobCredentials := &common.JobCredentials{
ID: jobData.ID,
Token: jobData.Token,
Tomasz Maczukin
committed
}
trace := r.network.ProcessJob(r.RunnerConfig, jobCredentials)
Andrew Chin
committed
r.postBuild()
return
}
func (r *RunSingleCommand) checkFinishedConditions() {
if r.MaxBuilds < 1 && !r.runForever {
log.Println("This runner has processed its build limit, so now exiting")
Andrew Chin
committed
}
if r.WaitTimeout > 0 && int(time.Since(r.lastBuild).Seconds()) > r.WaitTimeout {
log.Println("This runner has not received a job in", r.WaitTimeout, "seconds, so now exiting")
Andrew Chin
committed
}
func (r *RunSingleCommand) Execute(c *cli.Context) {
if len(r.URL) == 0 {
log.Fatalln("Missing Token")
}
log.Fatalln("Missing Executor")
}
executorProvider := common.GetExecutor(r.Executor)
if executorProvider == nil {
log.Fatalln("Unknown executor:", r.Executor)
log.Println("Starting runner for", r.URL, "with token", r.ShortDescription(), "...")
abortSignal := make(chan os.Signal)
doneSignal := make(chan int, 1)
Andrew Chin
committed
r.runForever = r.MaxBuilds == 0
go waitForInterrupts(r.finished, abortSignal, doneSignal, r.interruptSignals)
Andrew Chin
committed
r.lastBuild = time.Now()
data, err := executorProvider.Acquire(&r.RunnerConfig)
if err != nil {
log.Warningln("Executor update:", err)
}
r.processBuild(data, abortSignal)
Andrew Chin
committed
r.checkFinishedConditions()
executorProvider.Release(&r.RunnerConfig, data)
common.RegisterCommand2("run-single", "start single runner", &RunSingleCommand{
network: network.NewGitLabClient(),