c05803ff14
gerrit.Watcher is a class which watches the Gerrit stream-events SSH connection and produces events. There's a basic CLBot binary as well, to demonstrate driving it to produce messages on the logging output. It doesn't really do anything else. Change-Id: I274fe0a77c8329f79456425405e2fbdc3ca2edf0 Reviewed-on: https://cl.tvl.fyi/c/depot/+/245 Reviewed-by: tazjin <mail@tazj.in>
321 lines
9.4 KiB
Go
321 lines
9.4 KiB
Go
package gerritevents
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
)
|
|
|
|
var events = map[string]func() Event{}
|
|
|
|
func registerEvent(e func() Event) {
|
|
t := e().EventType()
|
|
if _, ok := events[t]; ok {
|
|
panic(fmt.Sprintf("%s already registered", t))
|
|
}
|
|
events[t] = e
|
|
}
|
|
|
|
// These events are taken from https://cl.tvl.fyi/Documentation/cmd-stream-events.html.
|
|
|
|
// Event is implemented by Gerrit event structs.
|
|
type Event interface {
|
|
EventType() string
|
|
}
|
|
|
|
type simpleEvent struct {
|
|
Type string `json:"type"`
|
|
}
|
|
|
|
// Parse parses a Gerrit event from JSON.
|
|
func Parse(bs []byte) (Event, error) {
|
|
var s simpleEvent
|
|
if err := json.Unmarshal(bs, &s); err != nil {
|
|
return nil, fmt.Errorf("unmarshalling %q as Gerrit Event: %v", string(bs), err)
|
|
}
|
|
ef, ok := events[s.Type]
|
|
if !ok {
|
|
return nil, fmt.Errorf("unknown event type %q", s.Type)
|
|
}
|
|
e := ef()
|
|
if err := json.Unmarshal(bs, e); err != nil {
|
|
return nil, fmt.Errorf("unmarshalling %q as Gerrit Event %q: %v", string(bs), e.EventType(), err)
|
|
}
|
|
return e, nil
|
|
}
|
|
|
|
// AssigneeChanged indicates that a change's assignee has been changed.
|
|
type AssigneeChanged struct {
|
|
Type string `json:"type"`
|
|
Change Change `json:"change"`
|
|
Changer Account `json:"changer"`
|
|
OldAssignee Account `json:"oldAssignee"`
|
|
EventCreatedOn Time `json:"eventCreatedOn"`
|
|
}
|
|
|
|
// EventType implements Event.
|
|
func (AssigneeChanged) EventType() string { return "assignee-changed" }
|
|
|
|
func init() {
|
|
registerEvent(func() Event { return &AssigneeChanged{} })
|
|
}
|
|
|
|
// ChangeAbandoned indicates that a change has been abandoned.
|
|
type ChangeAbandoned struct {
|
|
Type string `json:"type"`
|
|
Change Change `json:"change"`
|
|
PatchSet PatchSet `json:"patchSet"`
|
|
Abandoner Account `json:"abandoner"`
|
|
Reason string `json:"reason"`
|
|
EventCreatedOn Time `json:"eventCreatedOn"`
|
|
}
|
|
|
|
// EventType implements Event.
|
|
func (ChangeAbandoned) EventType() string { return "change-abandoned" }
|
|
|
|
func init() {
|
|
registerEvent(func() Event { return &ChangeAbandoned{} })
|
|
}
|
|
|
|
// ChangeDeleted indicates that a change has been deleted.
|
|
type ChangeDeleted struct {
|
|
Type string `json:"type"`
|
|
Change Change `json:"change"`
|
|
Deleter Account `json:"deleter"`
|
|
}
|
|
|
|
// EventType implements Event.
|
|
func (ChangeDeleted) EventType() string { return "change-deleted" }
|
|
|
|
func init() {
|
|
registerEvent(func() Event { return &ChangeDeleted{} })
|
|
}
|
|
|
|
// ChangeMerged indicates that a change has been merged into the target branch.
|
|
type ChangeMerged struct {
|
|
Type string `json:"type"`
|
|
Change Change `json:"change"`
|
|
PatchSet PatchSet `json:"patchSet"`
|
|
Submitter Account `json:"submitter"`
|
|
NewRev string `json:"newRev"`
|
|
EventCreatedOn Time `json:"eventCreatedOn"`
|
|
}
|
|
|
|
// EventType implements Event.
|
|
func (ChangeMerged) EventType() string { return "change-merged" }
|
|
|
|
func init() {
|
|
registerEvent(func() Event { return &ChangeMerged{} })
|
|
}
|
|
|
|
// ChangeRestored indicates a change has been restored (i.e. un-abandoned).
|
|
type ChangeRestored struct {
|
|
Type string `json:"type"`
|
|
Change Change `json:"change"`
|
|
PatchSet PatchSet `json:"patchSet"`
|
|
Restorer Account `json:"restorer"`
|
|
Reason string `json:"reason"`
|
|
EventCreatedOn Time `json:"eventCreatedOn"`
|
|
}
|
|
|
|
// EventType implements Event.
|
|
func (ChangeRestored) EventType() string { return "change-restored" }
|
|
|
|
func init() {
|
|
registerEvent(func() Event { return &ChangeRestored{} })
|
|
}
|
|
|
|
// CommentAdded indicates someone has commented on a patchset.
|
|
type CommentAdded struct {
|
|
Type string `json:"type"`
|
|
Change Change `json:"change"`
|
|
PatchSet PatchSet `json:"patchSet"`
|
|
Author Account `json:"author"`
|
|
Approvals []Approval `json:"approvals"`
|
|
Comment string `json:"comment"`
|
|
EventCreatedOn Time `json:"eventCreatedOn"`
|
|
}
|
|
|
|
// EventType implements Event.
|
|
func (CommentAdded) EventType() string { return "comment-added" }
|
|
|
|
func init() {
|
|
registerEvent(func() Event { return &CommentAdded{} })
|
|
}
|
|
|
|
// DroppedOutput indicates that some events may be missing from the stream.
|
|
type DroppedOutput struct {
|
|
Type string `json:"type"`
|
|
}
|
|
|
|
// EventType implements Event.
|
|
func (DroppedOutput) EventType() string { return "dropped-output" }
|
|
|
|
func init() {
|
|
registerEvent(func() Event { return &DroppedOutput{} })
|
|
}
|
|
|
|
// HashtagsChanged indicates that someone has added or removed hashtags from a change.
|
|
type HashtagsChanged struct {
|
|
Type string `json:"type"`
|
|
Change Change `json:"change"`
|
|
Editor Account `json:"editor"`
|
|
Added []string `json:"added"`
|
|
Removed []string `json:"removed"`
|
|
Hashtags []string `json:"hashtags"`
|
|
EventCreatedOn Time `json:"eventCreatedOn"`
|
|
}
|
|
|
|
// EventType implements Event.
|
|
func (HashtagsChanged) EventType() string { return "hashtags-changed" }
|
|
|
|
func init() {
|
|
registerEvent(func() Event { return &HashtagsChanged{} })
|
|
}
|
|
|
|
// ProjectCreated indicates that a new project has been created.
|
|
type ProjectCreated struct {
|
|
Type string `json:"type"`
|
|
ProjectName string `json:"projectName"`
|
|
ProjectHead string `json:"projectHead"`
|
|
EventCreatedOn Time `json:"eventCreatedOn"`
|
|
}
|
|
|
|
// EventType implements Event.
|
|
func (ProjectCreated) EventType() string { return "project-created" }
|
|
|
|
func init() {
|
|
registerEvent(func() Event { return &ProjectCreated{} })
|
|
}
|
|
|
|
// PatchSetCreated indicates that a new patchset has been added to a change.
|
|
type PatchSetCreated struct {
|
|
Type string `json:"type"`
|
|
Change Change `json:"change"`
|
|
PatchSet PatchSet `json:"patchSet"`
|
|
Uploader Account `json:"uploader"`
|
|
EventCreatedOn Time `json:"eventCreatedOn"`
|
|
}
|
|
|
|
// EventType implements Event.
|
|
func (PatchSetCreated) EventType() string { return "patchset-created" }
|
|
|
|
func init() {
|
|
registerEvent(func() Event { return &PatchSetCreated{} })
|
|
}
|
|
|
|
// RefUpdated indicates that a ref has been updated.
|
|
type RefUpdated struct {
|
|
Type string `json:"type"`
|
|
Submitter Account `json:"submitter"`
|
|
RefUpdate RefUpdate `json:"refUpdate"`
|
|
EventCreatedOn Time `json:"eventCreatedOn"`
|
|
}
|
|
|
|
// EventType implements Event.
|
|
func (RefUpdated) EventType() string { return "ref-updated" }
|
|
|
|
func init() {
|
|
registerEvent(func() Event { return &RefUpdated{} })
|
|
}
|
|
|
|
// ReviewerAdded indicates that a reviewer has been added to a change.
|
|
type ReviewerAdded struct {
|
|
Type string `json:"type"`
|
|
Change Change `json:"change"`
|
|
PatchSet PatchSet `json:"patchSet"`
|
|
Reviewer Account `json:"reviewer"`
|
|
Adder Account `json:"adder"`
|
|
EventCreatedOn Time `json:"eventCreatedOn"`
|
|
}
|
|
|
|
// EventType implements Event.
|
|
func (ReviewerAdded) EventType() string { return "reviewer-added" }
|
|
|
|
func init() {
|
|
registerEvent(func() Event { return &ReviewerAdded{} })
|
|
}
|
|
|
|
// ReviewerDeleted indicates that a reviewer has been removed from a change, possibly removing one or more approvals.
|
|
type ReviewerDeleted struct {
|
|
Type string `json:"type"`
|
|
Change Change `json:"change"`
|
|
PatchSet PatchSet `json:"patchSet"`
|
|
Reviewer Account `json:"reviewer"`
|
|
Remover Account `json:"remover"`
|
|
Approvals []Approval `json:"approvals"`
|
|
Comment string `json:"comment"`
|
|
EventCreatedOn Time `json:"eventCreatedOn"`
|
|
}
|
|
|
|
// EventType implements Event.
|
|
func (ReviewerDeleted) EventType() string { return "reviewer-deleted" }
|
|
|
|
func init() {
|
|
registerEvent(func() Event { return &ReviewerDeleted{} })
|
|
}
|
|
|
|
// TopicChanged indicates that the topic attached to a change has been changed.
|
|
type TopicChanged struct {
|
|
Type string `json:"type"`
|
|
Change Change `json:"change"`
|
|
Changer Account `json:"changer"`
|
|
OldTopic string `json:"oldTopic"`
|
|
EventCreatedOn Time `json:"eventCreatedOn"`
|
|
}
|
|
|
|
// EventType implements Event.
|
|
func (TopicChanged) EventType() string { return "topic-changed" }
|
|
|
|
func init() {
|
|
registerEvent(func() Event { return &TopicChanged{} })
|
|
}
|
|
|
|
// WIPStateChanged indicates that the work-in-progress state of a change has changed.
|
|
type WIPStateChanged struct {
|
|
Type string `json:"type"`
|
|
Change Change `json:"change"`
|
|
PatchSet PatchSet `json:"patchSet"`
|
|
Changer Account `json:"changer"`
|
|
EventCreatedOn Time `json:"eventCreatedOn"`
|
|
}
|
|
|
|
// EventType implements Event.
|
|
func (WIPStateChanged) EventType() string { return "wip-state-changed" }
|
|
|
|
func init() {
|
|
registerEvent(func() Event { return &WIPStateChanged{} })
|
|
}
|
|
|
|
// PrivateStateChanged indicates that the private state of a change has changed.
|
|
type PrivateStateChanged struct {
|
|
Type string `json:"type"`
|
|
Change Change `json:"change"`
|
|
PatchSet PatchSet `json:"patchSet"`
|
|
Changer Account `json:"changer"`
|
|
EventCreatedOn Time `json:"eventCreatedOn"`
|
|
}
|
|
|
|
// EventType implements Event.
|
|
func (PrivateStateChanged) EventType() string { return "private-state-changed" }
|
|
|
|
func init() {
|
|
registerEvent(func() Event { return &PrivateStateChanged{} })
|
|
}
|
|
|
|
// VoteDeleted indicates that an approval vote has been deleted from a change.
|
|
type VoteDeleted struct {
|
|
Type string `json:"type"`
|
|
Change Change `json:"change"`
|
|
PatchSet PatchSet `json:"patchSet"`
|
|
Reviewer Account `json:"reviewer"`
|
|
Remover Account `json:"remover"`
|
|
Approvals []Approval `json:"approvals"`
|
|
Comment string `json:"comment"`
|
|
}
|
|
|
|
// EventType implements Event.
|
|
func (VoteDeleted) EventType() string { return "vote-deleted" }
|
|
|
|
func init() {
|
|
registerEvent(func() Event { return &VoteDeleted{} })
|
|
}
|