repositories / bugabinga.net
bugabinga.net
personal infrastructure for bugabinga!
owned by admin
services/luci/internal/trigger/trigger.go
Rawpackage trigger
import (
"encoding/json"
"fmt"
"strings"
"time"
)
type Event interface {
Validate() error
EventKind() string
}
type PushEvent struct {
Kind string `json:"kind"`
Repo string `json:"repo"`
Old string `json:"old"`
New string `json:"new"`
Ref string `json:"ref"`
}
func (e PushEvent) EventKind() string { return "push" }
func (e PushEvent) Validate() error {
if e.Kind != "push" {
return fmt.Errorf("push event kind must be push")
}
if strings.TrimSpace(e.Repo) == "" || strings.TrimSpace(e.New) == "" || strings.TrimSpace(e.Ref) == "" {
return fmt.Errorf("push event requires repo, new, and ref")
}
return nil
}
type ScheduleEvent struct {
Kind string `json:"kind"`
Repo string `json:"repo"`
Job string `json:"job"`
Rev string `json:"rev"`
Ref string `json:"ref"`
Minute string `json:"minute"`
}
func (e ScheduleEvent) EventKind() string { return "schedule" }
func (e ScheduleEvent) Validate() error {
if e.Kind != "schedule" {
return fmt.Errorf("schedule event kind must be schedule")
}
if strings.TrimSpace(e.Repo) == "" || strings.TrimSpace(e.Job) == "" || strings.TrimSpace(e.Rev) == "" || strings.TrimSpace(e.Ref) == "" {
return fmt.Errorf("schedule event requires repo, job, revision, and ref")
}
if _, err := time.Parse("2006-01-02T15:04Z", e.Minute); err != nil {
return fmt.Errorf("schedule event has invalid minute %q", e.Minute)
}
return nil
}
type ManualEvent struct {
Kind string `json:"kind"`
Repo string `json:"repo"`
Job string `json:"job"`
Ref *string `json:"ref"`
Rev *string `json:"rev"`
RequestedBy string `json:"requested_by"`
ResolvedRev string `json:"resolved_rev,omitempty"`
}
func (e ManualEvent) EventKind() string { return "manual" }
func (e ManualEvent) Validate() error {
if e.Kind != "manual" {
return fmt.Errorf("manual event kind must be manual")
}
if strings.TrimSpace(e.Repo) == "" || strings.TrimSpace(e.Job) == "" {
return fmt.Errorf("manual event requires repo and job")
}
hasRef := e.Ref != nil && strings.TrimSpace(*e.Ref) != ""
hasRev := e.Rev != nil && strings.TrimSpace(*e.Rev) != ""
if hasRef == hasRev {
return fmt.Errorf("manual event requires exactly one of ref or rev")
}
return nil
}
func Decode(data []byte) (Event, error) {
var header struct {
Kind string `json:"kind"`
}
if err := json.Unmarshal(data, &header); err != nil {
return nil, err
}
switch header.Kind {
case "push":
var event PushEvent
if err := json.Unmarshal(data, &event); err != nil {
return nil, err
}
return event, event.Validate()
case "manual":
var event ManualEvent
if err := json.Unmarshal(data, &event); err != nil {
return nil, err
}
return event, event.Validate()
case "schedule":
var event ScheduleEvent
if err := json.Unmarshal(data, &event); err != nil {
return nil, err
}
return event, event.Validate()
default:
return nil, fmt.Errorf("unknown trigger kind %q", header.Kind)
}
}