Skip to content
Permalink
e97b1e968b
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
178 lines (154 sloc) 4.06 KB
// Copyright 2019 Drone.IO Inc. All rights reserved.
// Use of this source code is governed by the Drone Non-Commercial License
// that can be found in the LICENSE file.
// +build !oss
package cron
import (
"context"
"fmt"
"time"
"github.com/drone/drone/core"
"github.com/hashicorp/go-multierror"
"github.com/robfig/cron"
"github.com/sirupsen/logrus"
)
// New returns a new Cron scheduler.
func New(
commits core.CommitService,
cron core.CronStore,
repos core.RepositoryStore,
users core.UserStore,
trigger core.Triggerer,
) *Scheduler {
return &Scheduler{
commits: commits,
cron: cron,
repos: repos,
users: users,
trigger: trigger,
}
}
// Scheduler defines a cron scheduler.
type Scheduler struct {
commits core.CommitService
cron core.CronStore
repos core.RepositoryStore
users core.UserStore
trigger core.Triggerer
}
// Start starts the cron scheduler.
func (s *Scheduler) Start(ctx context.Context, dur time.Duration) error {
for {
select {
case <-ctx.Done():
return ctx.Err()
case <-time.After(dur):
s.run(ctx)
}
}
}
func (s *Scheduler) run(ctx context.Context) error {
var result error
logrus.Debugln("cron: begin process pending jobs")
defer func() {
if err := recover(); err != nil {
logger := logrus.WithField("error", err)
logger.Errorln("cron: unexpected panic")
}
}()
now := time.Now()
jobs, err := s.cron.Ready(ctx, now.Unix())
if err != nil {
logger := logrus.WithError(err)
logger.Error("cron: cannot list pending jobs")
return err
}
for _, job := range jobs {
// jobs can be manually disabled in the user interface,
// and should be skipped.
if job.Disabled {
continue
}
sched, err := cron.Parse(job.Expr)
if err != nil {
result = multierror.Append(result, err)
// this should never happen since we parse and verify
// the cron expression when the cron entry is created.
continue
}
// calculate the next execution date.
job.Prev = job.Next
job.Next = sched.Next(now).Unix()
logger := logrus.WithFields(
logrus.Fields{
"repo": job.RepoID,
"cron": job.ID,
},
)
err = s.cron.Update(ctx, job)
if err != nil {
logger := logrus.WithError(err)
logger.Warnln("cron: cannot re-schedule job")
result = multierror.Append(result, err)
continue
}
repo, err := s.repos.Find(ctx, job.RepoID)
if err != nil {
logger := logrus.WithError(err)
logger.Warnln("cron: cannot find repository")
result = multierror.Append(result, err)
continue
}
user, err := s.users.Find(ctx, repo.UserID)
if err != nil {
logger := logrus.WithError(err)
logger.Warnln("cron: cannot find repository owner")
result = multierror.Append(result, err)
continue
}
// TODO(bradrydzewski) we may actually need to query the branch
// first to get the sha, and then query the commit. This works fine
// with github and gitlab, but may not work with other providers.
commit, err := s.commits.FindRef(ctx, user, repo.Slug, job.Branch)
if err != nil {
logger.WithFields(
logrus.Fields{
"error": err,
"repo": repo.Slug,
"branch": repo.Branch,
}).Warnln("cron: cannot find commit")
result = multierror.Append(result, err)
continue
}
hook := &core.Hook{
Trigger: core.TriggerCron,
Event: core.EventCron,
Link: commit.Link,
Timestamp: commit.Author.Date,
Message: commit.Message,
After: commit.Sha,
Ref: fmt.Sprintf("refs/heads/%s", job.Branch),
Target: job.Branch,
Author: commit.Author.Login,
AuthorName: commit.Author.Name,
AuthorEmail: commit.Author.Email,
AuthorAvatar: commit.Author.Avatar,
Cron: job.Name,
Sender: commit.Author.Login,
}
_, err = s.trigger.Trigger(ctx, repo, hook)
if err != nil {
logger.WithFields(
logrus.Fields{
"error": err,
"repo": repo.Slug,
"branch": repo.Branch,
"sha": commit.Sha,
}).Warnln("cron: cannot trigger build")
result = multierror.Append(result, err)
continue
}
}
logrus.Debugf("cron: finished processing jobs")
return result
}