diff options
Diffstat (limited to 'third_party/gerrit-queue/submitqueue/runner.go')
-rw-r--r-- | third_party/gerrit-queue/submitqueue/runner.go | 220 |
1 files changed, 0 insertions, 220 deletions
diff --git a/third_party/gerrit-queue/submitqueue/runner.go b/third_party/gerrit-queue/submitqueue/runner.go deleted file mode 100644 index 0b4cbcd8dd7c..000000000000 --- a/third_party/gerrit-queue/submitqueue/runner.go +++ /dev/null @@ -1,220 +0,0 @@ -package submitqueue - -import ( - "fmt" - "sync" - - "github.com/apex/log" - - "github.com/tweag/gerrit-queue/gerrit" -) - -// Runner is a struct existing across the lifetime of a single run of the submit queue -// it contains a mutex to avoid being run multiple times. -// In fact, it even cancels runs while another one is still in progress. -// It contains a Gerrit object facilitating access, a log object, the configured submit queue tag -// and a `wipSerie` (only populated if waiting for a rebase) -type Runner struct { - mut sync.Mutex - currentlyRunning bool - wipSerie *gerrit.Serie - logger *log.Logger - gerrit *gerrit.Client -} - -// NewRunner creates a new Runner struct -func NewRunner(logger *log.Logger, gerrit *gerrit.Client) *Runner { - return &Runner{ - logger: logger, - gerrit: gerrit, - } -} - -// isAutoSubmittable determines if something could be autosubmitted, potentially requiring a rebase -// for this, it needs to: -// * have the "Autosubmit" label set to +1 -// * have gerrit's 'submittable' field set to true -// it doesn't check if the series is rebased on HEAD -func (r *Runner) isAutoSubmittable(s *gerrit.Serie) bool { - for _, c := range s.ChangeSets { - if c.Submittable != true || !c.IsAutosubmit() { - return false - } - } - return true -} - -// IsCurrentlyRunning returns true if the runner is currently running -func (r *Runner) IsCurrentlyRunning() bool { - return r.currentlyRunning -} - -// GetWIPSerie returns the current wipSerie, if any, nil otherwiese -// Acquires a lock, so check with IsCurrentlyRunning first -func (r *Runner) GetWIPSerie() *gerrit.Serie { - r.mut.Lock() - defer func() { - r.mut.Unlock() - }() - return r.wipSerie -} - -// Trigger gets triggered periodically -func (r *Runner) Trigger(fetchOnly bool) error { - // TODO: If CI fails, remove the auto-submit labels => rules.pl - // Only one trigger can run at the same time - r.mut.Lock() - if r.currentlyRunning { - return fmt.Errorf("Already running, skipping") - } - r.currentlyRunning = true - r.mut.Unlock() - defer func() { - r.mut.Lock() - r.currentlyRunning = false - r.mut.Unlock() - }() - - // Prepare the work by creating a local cache of gerrit state - err := r.gerrit.Refresh() - if err != nil { - return err - } - - // early return if we only want to fetch - if fetchOnly { - return nil - } - - if r.wipSerie != nil { - // refresh wipSerie with how it looks like in gerrit now - wipSerie := r.gerrit.FindSerie(func(s *gerrit.Serie) bool { - // the new wipSerie needs to have the same number of changesets - if len(r.wipSerie.ChangeSets) != len(s.ChangeSets) { - return false - } - // … and the same ChangeIDs. - for idx, c := range s.ChangeSets { - if r.wipSerie.ChangeSets[idx].ChangeID != c.ChangeID { - return false - } - } - return true - }) - if wipSerie == nil { - r.logger.WithField("wipSerie", r.wipSerie).Warn("wipSerie has disappeared") - r.wipSerie = nil - } else { - r.wipSerie = wipSerie - } - } - - for { - // initialize logger - r.logger.Info("Running") - if r.wipSerie != nil { - // if we have a wipSerie - l := r.logger.WithField("wipSerie", r.wipSerie) - l.Info("Checking wipSerie") - - // discard wipSerie not rebased on HEAD - // we rebase them at the end of the loop, so this means master advanced without going through the submit queue - if !r.gerrit.SerieIsRebasedOnHEAD(r.wipSerie) { - l.Warnf("HEAD has moved to %v while still waiting for wipSerie, discarding it", r.gerrit.GetHEAD()) - r.wipSerie = nil - continue - } - - // we now need to check CI feedback: - // wipSerie might have failed CI in the meantime - for _, c := range r.wipSerie.ChangeSets { - if c == nil { - l.Error("BUG: changeset is nil") - continue - } - if c.Verified < 0 { - l.WithField("failingChangeset", c).Warnf("wipSerie failed CI in the meantime, discarding.") - r.wipSerie = nil - continue - } - } - - // it might still be waiting for CI - for _, c := range r.wipSerie.ChangeSets { - if c == nil { - l.Error("BUG: changeset is nil") - continue - } - if c.Verified == 0 { - l.WithField("pendingChangeset", c).Warnf("still waiting for CI feedback in wipSerie, going back to sleep.") - // break the loop, take a look at it at the next trigger. - return nil - } - } - - // it might be autosubmittable - if r.isAutoSubmittable(r.wipSerie) { - l.Infof("submitting wipSerie") - // if the WIP changeset is ready (auto submittable and rebased on HEAD), submit - for _, changeset := range r.wipSerie.ChangeSets { - _, err := r.gerrit.SubmitChangeset(changeset) - if err != nil { - l.WithField("changeset", changeset).Error("error submitting changeset") - r.wipSerie = nil - return err - } - } - r.wipSerie = nil - } else { - l.Error("BUG: wipSerie is not autosubmittable") - r.wipSerie = nil - } - } - - r.logger.Info("Looking for series ready to submit") - // Find serie, that: - // * has the auto-submit label - // * has +2 review - // * has +1 CI - // * is rebased on master - serie := r.gerrit.FindSerie(func(s *gerrit.Serie) bool { - return r.isAutoSubmittable(s) && s.ChangeSets[0].ParentCommitIDs[0] == r.gerrit.GetHEAD() - }) - if serie != nil { - r.logger.WithField("serie", serie).Info("Found serie to submit without necessary rebase") - r.wipSerie = serie - continue - } - - // Find serie, that: - // * has the auto-submit label - // * has +2 review - // * has +1 CI - // * is NOT rebased on master - serie = r.gerrit.FindSerie(r.isAutoSubmittable) - if serie == nil { - r.logger.Info("no more submittable series found, going back to sleep.") - break - } - - l := r.logger.WithField("serie", serie) - l.Info("found serie, which needs a rebase") - // TODO: move into Client.RebaseSeries function - head := r.gerrit.GetHEAD() - for _, changeset := range serie.ChangeSets { - changeset, err := r.gerrit.RebaseChangeset(changeset, head) - if err != nil { - l.Error(err.Error()) - return err - } - head = changeset.CommitID - } - // we don't need to care about updating the rebased changesets or getting the updated HEAD, - // as we'll refetch it on the beginning of the next trigger anyways - r.wipSerie = serie - break - } - - r.logger.Info("Run complete") - return nil -} |