gerrit: Use a Gerrit label instead of hashtag for autosubmit

This moves to using a Gerrit label ('Autosubmit') with boolean values
for determining whether a developer wants to have a change
automatically submitted.

See also https://cl.tvl.fyi/c/depot/+/4172
This commit is contained in:
Vincent Ambo 2021-12-09 13:49:16 +03:00
parent c67b3ba7ea
commit 24f5a642af
5 changed files with 17 additions and 44 deletions

View file

@ -8,7 +8,7 @@ await CI feedback on a rebased changeset, then one clicks submit, and
effectively makes everybody else rebase again. `gerrit-queue` is meant to effectively makes everybody else rebase again. `gerrit-queue` is meant to
remove these races to master. remove these races to master.
Developers can add a specific tag `submit_me` to all changesets in a series, Developers can set the `Autosubmit` label to `+1` on all changesets in a series,
and if all preconditions on are met ("submittable" in gerrit speech, this and if all preconditions on are met ("submittable" in gerrit speech, this
usually means passing CI and passing Code Review), `gerrit-queue` takes care of usually means passing CI and passing Code Review), `gerrit-queue` takes care of
rebasing and submitting it to master rebasing and submitting it to master

View file

@ -16,8 +16,8 @@ type Changeset struct {
Number int Number int
Verified int Verified int
CodeReviewed int CodeReviewed int
Autosubmit int
Submittable bool Submittable bool
HashTags []string
CommitID string CommitID string
ParentCommitIDs []string ParentCommitIDs []string
OwnerName string OwnerName string
@ -32,8 +32,8 @@ func MakeChangeset(changeInfo *goGerrit.ChangeInfo) *Changeset {
Number: changeInfo.Number, Number: changeInfo.Number,
Verified: labelInfoToInt(changeInfo.Labels["Verified"]), Verified: labelInfoToInt(changeInfo.Labels["Verified"]),
CodeReviewed: labelInfoToInt(changeInfo.Labels["Code-Review"]), CodeReviewed: labelInfoToInt(changeInfo.Labels["Code-Review"]),
Autosubmit: labelInfoToInt(changeInfo.Labels["Autosubmit"]),
Submittable: changeInfo.Submittable, Submittable: changeInfo.Submittable,
HashTags: changeInfo.Hashtags,
CommitID: changeInfo.CurrentRevision, // yes, this IS the commit ID. CommitID: changeInfo.CurrentRevision, // yes, this IS the commit ID.
ParentCommitIDs: getParentCommitIDs(changeInfo), ParentCommitIDs: getParentCommitIDs(changeInfo),
OwnerName: changeInfo.Owner.Name, OwnerName: changeInfo.Owner.Name,
@ -41,15 +41,13 @@ func MakeChangeset(changeInfo *goGerrit.ChangeInfo) *Changeset {
} }
} }
// HasTag returns true if a Changeset has the given tag. // IsAutosubmit returns true if the changeset is intended to be
func (c *Changeset) HasTag(tag string) bool { // automatically submitted by gerrit-queue.
hashTags := c.HashTags //
for _, hashTag := range hashTags { // This is determined by the Change Owner setting +1 on the
if hashTag == tag { // "Autosubmit" label.
return true func (c *Changeset) IsAutosubmit() bool {
} return c.Autosubmit == 1
}
return false
} }
// IsVerified returns true if the changeset passed CI, // IsVerified returns true if the changeset passed CI,

View file

@ -26,7 +26,6 @@ type IClient interface {
GetChangesetURL(changeset *Changeset) string GetChangesetURL(changeset *Changeset) string
SubmitChangeset(changeset *Changeset) (*Changeset, error) SubmitChangeset(changeset *Changeset) (*Changeset, error)
RebaseChangeset(changeset *Changeset, ref string) (*Changeset, error) RebaseChangeset(changeset *Changeset, ref string) (*Changeset, error)
RemoveTag(changeset *Changeset, tag string) (*Changeset, error)
ChangesetIsRebasedOnHEAD(changeset *Changeset) bool ChangesetIsRebasedOnHEAD(changeset *Changeset) bool
SerieIsRebasedOnHEAD(serie *Serie) bool SerieIsRebasedOnHEAD(serie *Serie) bool
FilterSeries(filter func(s *Serie) bool) []*Serie FilterSeries(filter func(s *Serie) bool) []*Serie
@ -161,21 +160,6 @@ func (c *Client) RebaseChangeset(changeset *Changeset, ref string) (*Changeset,
return c.fetchChangeset(changeInfo.ChangeID) return c.fetchChangeset(changeInfo.ChangeID)
} }
// RemoveTag removes the submit queue tag from a changeset and updates gerrit
// we never add, that's something users should do in the GUI.
func (c *Client) RemoveTag(changeset *Changeset, tag string) (*Changeset, error) {
hashTags := changeset.HashTags
newHashTags := []string{}
for _, hashTag := range hashTags {
if hashTag != tag {
newHashTags = append(newHashTags, hashTag)
}
}
// TODO: implement setting hashtags api in go-gerrit and use here
// https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#set-hashtags
return changeset, nil
}
// GetBaseURL returns the gerrit base URL // GetBaseURL returns the gerrit base URL
func (c *Client) GetBaseURL() string { func (c *Client) GetBaseURL() string {
return c.baseURL return c.baseURL

11
main.go
View file

@ -21,7 +21,7 @@ import (
) )
func main() { func main() {
var URL, username, password, projectName, branchName, submitQueueTag string var URL, username, password, projectName, branchName string
var fetchOnly bool var fetchOnly bool
var triggerInterval int var triggerInterval int
@ -64,13 +64,6 @@ func main() {
Destination: &branchName, Destination: &branchName,
Value: "master", Value: "master",
}, },
cli.StringFlag{
Name: "submit-queue-tag",
Usage: "the tag used to submit something to the submit queue",
EnvVar: "SUBMIT_QUEUE_TAG",
Destination: &submitQueueTag,
Value: "submit_me",
},
cli.IntFlag{ cli.IntFlag{
Name: "trigger-interval", Name: "trigger-interval",
Usage: "How often we should trigger ourselves (interval in seconds)", Usage: "How often we should trigger ourselves (interval in seconds)",
@ -102,7 +95,7 @@ func main() {
} }
log.Infof("Successfully connected to gerrit at %s", URL) log.Infof("Successfully connected to gerrit at %s", URL)
runner := submitqueue.NewRunner(l, gerrit, submitQueueTag) runner := submitqueue.NewRunner(l, gerrit)
handler := frontend.MakeFrontend(rotatingLogHandler, gerrit, runner) handler := frontend.MakeFrontend(rotatingLogHandler, gerrit, runner)

View file

@ -20,26 +20,24 @@ type Runner struct {
wipSerie *gerrit.Serie wipSerie *gerrit.Serie
logger *log.Logger logger *log.Logger
gerrit *gerrit.Client gerrit *gerrit.Client
submitQueueTag string // the tag used to submit something to the submit queue
} }
// NewRunner creates a new Runner struct // NewRunner creates a new Runner struct
func NewRunner(logger *log.Logger, gerrit *gerrit.Client, submitQueueTag string) *Runner { func NewRunner(logger *log.Logger, gerrit *gerrit.Client) *Runner {
return &Runner{ return &Runner{
logger: logger, logger: logger,
gerrit: gerrit, gerrit: gerrit,
submitQueueTag: submitQueueTag,
} }
} }
// isAutoSubmittable determines if something could be autosubmitted, potentially requiring a rebase // isAutoSubmittable determines if something could be autosubmitted, potentially requiring a rebase
// for this, it needs to: // for this, it needs to:
// * have the auto-submit label // * have the "Autosubmit" label set to +1
// * have gerrit's 'submittable' field set to true // * have gerrit's 'submittable' field set to true
// it doesn't check if the series is rebased on HEAD // it doesn't check if the series is rebased on HEAD
func (r *Runner) isAutoSubmittable(s *gerrit.Serie) bool { func (r *Runner) isAutoSubmittable(s *gerrit.Serie) bool {
for _, c := range s.ChangeSets { for _, c := range s.ChangeSets {
if c.Submittable != true || !c.HasTag(r.submitQueueTag) { if c.Submittable != true || !c.IsAutosubmit() {
return false return false
} }
} }