github.com/mongodb/grip@v0.0.0-20240213223901-f906268d82b9/message/github_status.go (about)

     1  package message
     2  
     3  import (
     4  	"fmt"
     5  	"net/url"
     6  
     7  	"github.com/mongodb/grip/level"
     8  )
     9  
    10  // GithubState represents the 4 valid states for the Github State API in
    11  // a safer way
    12  type GithubState string
    13  
    14  // The list of valid states for Github Status API requests
    15  const (
    16  	GithubStatePending = GithubState("pending")
    17  	GithubStateSuccess = GithubState("success")
    18  	GithubStateError   = GithubState("error")
    19  	GithubStateFailure = GithubState("failure")
    20  )
    21  
    22  // GithubStatus is a message to be posted to Github's Status API
    23  type GithubStatus struct {
    24  	Owner string `bson:"owner,omitempty" json:"owner,omitempty" yaml:"owner,omitempty"`
    25  	Repo  string `bson:"repo,omitempty" json:"repo,omitempty" yaml:"repo,omitempty"`
    26  	Ref   string `bson:"ref,omitempty" json:"ref,omitempty" yaml:"ref,omitempty"`
    27  
    28  	Context     string      `bson:"context" json:"context" yaml:"context"`
    29  	State       GithubState `bson:"state" json:"state" yaml:"state"`
    30  	URL         string      `bson:"url" json:"url" yaml:"url"`
    31  	Description string      `bson:"description" json:"description" yaml:"description"`
    32  }
    33  
    34  // Valid returns true if the message is well formed
    35  func (p *GithubStatus) Valid() bool {
    36  	// owner, repo and ref must be empty or must be set
    37  	ownerEmpty := len(p.Owner) == 0
    38  	repoEmpty := len(p.Repo) == 0
    39  	refLen := len(p.Ref) == 0
    40  	if ownerEmpty != repoEmpty || repoEmpty != refLen {
    41  		return false
    42  	}
    43  
    44  	switch p.State {
    45  	case GithubStatePending, GithubStateSuccess, GithubStateError, GithubStateFailure:
    46  	default:
    47  		return false
    48  	}
    49  
    50  	_, err := url.Parse(p.URL)
    51  	if err != nil || len(p.Context) == 0 {
    52  		return false
    53  	}
    54  
    55  	return true
    56  }
    57  
    58  type githubStatusMessage struct {
    59  	raw GithubStatus
    60  	str string
    61  
    62  	Base `bson:"metadata" json:"metadata" yaml:"metadata"`
    63  }
    64  
    65  // NewGithubStatusMessageWithRepo creates a composer for sending payloads to the Github Status
    66  // API, with the repository and ref stored in the composer
    67  func NewGithubStatusMessageWithRepo(p level.Priority, status GithubStatus) Composer {
    68  	s := MakeGithubStatusMessageWithRepo(status)
    69  	_ = s.SetPriority(p)
    70  
    71  	return s
    72  }
    73  
    74  // MakeGithubStatusMessageWithRepo creates a composer for sending payloads to the Github Status
    75  // API, with the repository and ref stored in the composer
    76  func MakeGithubStatusMessageWithRepo(status GithubStatus) Composer {
    77  	return &githubStatusMessage{
    78  		raw: status,
    79  	}
    80  }
    81  
    82  // NewGithubStatusMessage creates a composer for sending payloads to the Github Status
    83  // API.
    84  func NewGithubStatusMessage(p level.Priority, context string, state GithubState, URL, description string) Composer {
    85  	s := MakeGithubStatusMessage(context, state, URL, description)
    86  	_ = s.SetPriority(p)
    87  
    88  	return s
    89  }
    90  
    91  // MakeGithubStatusMessage creates a composer for sending payloads to the Github Status
    92  // API without setting a priority
    93  func MakeGithubStatusMessage(context string, state GithubState, URL, description string) Composer {
    94  	return &githubStatusMessage{
    95  		raw: GithubStatus{
    96  			Context:     context,
    97  			State:       state,
    98  			URL:         URL,
    99  			Description: description,
   100  		},
   101  	}
   102  }
   103  
   104  func (c *githubStatusMessage) Loggable() bool {
   105  	return c.raw.Valid()
   106  }
   107  
   108  func (c *githubStatusMessage) String() string {
   109  	if len(c.str) != 0 {
   110  		return c.str
   111  	}
   112  
   113  	base := c.raw.Ref
   114  	if len(c.raw.Owner) > 0 {
   115  		base = fmt.Sprintf("%s/%s@%s ", c.raw.Owner, c.raw.Repo, c.raw.Ref)
   116  	}
   117  	if len(c.raw.Description) == 0 {
   118  		// looks like: evergreen failed (https://evergreen.mongodb.com)
   119  		c.str = base + fmt.Sprintf("%s %s (%s)", c.raw.Context, string(c.raw.State), c.raw.URL)
   120  	} else {
   121  		// looks like: evergreen failed: 1 task failed (https://evergreen.mongodb.com)
   122  		c.str = base + fmt.Sprintf("%s %s: %s (%s)", c.raw.Context, string(c.raw.State), c.raw.Description, c.raw.URL)
   123  	}
   124  
   125  	return c.str
   126  }
   127  
   128  func (c *githubStatusMessage) Raw() interface{} {
   129  	return &c.raw
   130  }