Skip to content

Commit

Permalink
Fix jsonschema, add preview tpl
Browse files Browse the repository at this point in the history
  • Loading branch information
mszostok committed Aug 9, 2023
1 parent 374a49c commit 0649b39
Show file tree
Hide file tree
Showing 9 changed files with 198 additions and 121 deletions.
21 changes: 1 addition & 20 deletions internal/executor/flux/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,24 +178,6 @@ func jsonSchema() api.JSONSchema {
"description": "%s",
"type": "object",
"properties": {
"logger": {
"title": "Logger",
"type": "object",
"properties": {
"level": {
"title": "Level",
"type": "string"
},
"disableColors": {
"title": "Disable Colors",
"type": "boolean"
},
"formatter": {
"title": "Formatter",
"type": "string"
}
}
},
"github": {
"title": "GitHub",
"type": "object",
Expand All @@ -209,8 +191,7 @@ func jsonSchema() api.JSONSchema {
"description": "The GitHub access token. When not provided, some functionality may not work. For example, adding a comment under a pull request.",
"type": "string"
}
},
"required": []
}
}
}
}
Expand Down
27 changes: 17 additions & 10 deletions internal/source/github_events/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,17 @@ type (
// GitHub configuration.
GitHub gh.ClientConfig `yaml:"github"`

// RefreshTime defines how often we should call GitHub REST API to check repository events.
// RefreshDuration defines how often we should call GitHub REST API to check repository events.
// It's the same for all configured repositories. For example, if you configure 5s refresh time, and you have 3 repositories registered,
// we will execute maximum 2160 calls which easily fits into PAT rate limits. You need to consider when you configure this plugin.
// You can create multiple plugins configuration with dedicated tokens to split have the rate limits increased.
// we will execute maximum 2160 calls which easily fits into PAT rate limits.
// You can create multiple plugins configuration with dedicated tokens to have the rate limits increased.
//
// NOTE:
// - we use conditional requests (https://docs.github.com/en/rest/overview/resources-in-the-rest-api?apiVersion=2022-11-28#conditional-requests), so if there are no events the call doesn't count against your rate limits.
// - if you configure file pattern matcher for merged pull request events we execute one more additional call to check which files were changed in the context of a given pull request
//
// Rate limiting: https://docs.github.com/en/rest/overview/resources-in-the-rest-api?apiVersion=2022-11-28#rate-limiting
//
// Defaults: 5s
RefreshTime time.Duration `yaml:"refreshTime"`
RefreshDuration time.Duration `yaml:"refreshDuration"`

// List of repository configurations.
Repositories []RepositoryConfig `yaml:"repositories"`
Expand Down Expand Up @@ -66,18 +64,24 @@ type (

// ExtraButton represents the extra button configuration in notification templates.
ExtraButton struct {
// Display name for the extra button.
// DisplayName for the extra button.
DisplayName string `yaml:"displayName"`

// Command template for the extra button.
// CommandTpl template for the extra button.
CommandTpl string `yaml:"commandTpl"`
Style string `yaml:"style"`

// URL to open. If specified CommandTpl is ignored.
URL string `yaml:"url"`

// Style for button.
Style string `yaml:"style"`
}

// NotificationTemplate represents the notification template configuration.
NotificationTemplate struct {
// Extra buttons in the notification template.
ExtraButtons []ExtraButton `yaml:"extraButtons"`
PreviewTpl string `yaml:"previewTpl"`
}

// RepositoryConfig represents the configuration for repositories.
Expand Down Expand Up @@ -117,6 +121,9 @@ type (

func (t NotificationTemplate) ToOptions() []templates.MessageMutatorOption {
var out []templates.MessageMutatorOption
if t.PreviewTpl != "" {
out = append(out, WithCustomPreview(t.PreviewTpl))
}
if len(t.ExtraButtons) > 0 {
out = append(out, WithExtraButtons(t.ExtraButtons))
}
Expand Down Expand Up @@ -186,7 +193,7 @@ func MergeConfigs(configs []*source.Config) (Config, error) {
Log: config.Logger{
Level: "info",
},
RefreshTime: 5 * time.Second,
RefreshDuration: 5 * time.Second,
GitHub: gh.ClientConfig{
BaseURL: "https://api.github.com/",
UploadURL: "https://uploads.github.com/",
Expand Down
File renamed without changes.
10 changes: 5 additions & 5 deletions internal/source/github_events/gh/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type (
// Default: https://api.github.com/
BaseURL string `yaml:"baseUrl"`

// The GitHub upload URL for uploading files. It is taken into account only when the GITHUB_BASE_URL is also set. If only the GITHUB_BASE_URL is provided then this parameter defaults to the GITHUB_BASE_URL value.
// The GitHub upload URL for uploading files. It is taken into account only when the BaseURL is also set. If only the BaseURL is provided then this parameter defaults to the BaseURL value.
// Default: https://uploads.github.com/
UploadURL string `yaml:"uploadUrl"`
}
Expand All @@ -38,19 +38,19 @@ type (
AccessToken string `yaml:"accessToken"`

// AppConfig represents the GitHub App configuration.
// This replaces the AccessToken
App AppConfig `yaml:"app"`
}

// AppConfig represents the GitHub App configuration.
AppConfig struct {
// GitHub App ID for authentication. This replaces the GITHUB_ACCESS_TOKEN.
// Instruction for creating a GitHub App can be found here: https://github.com/mszostok/codeowners-validator/blob/main/docs/gh-token.md
// GitHub App ID for authentication.
ID int64 `yaml:"id"`

// GitHub App Installation ID. Required when GITHUB_APP_ID is set.
// GitHub App Installation ID.
InstallationID int64 `yaml:"installationId"`

// GitHub App private key in PEM format. Required when GITHUB_APP_ID is set.
// GitHub App private key in PEM format.
PrivateKey string `yaml:"privateKey"`
}
)
Expand Down
59 changes: 43 additions & 16 deletions internal/source/github_events/github_events.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,22 @@ type Watcher struct {
cli *github.Client
log logrus.FieldLogger
cfg []RepositoryConfig
refreshTime time.Duration
refreshDuration time.Duration
lastProcessTime map[string]time.Time
repos map[string]matchCriteria
prMatcher *PullRequestMatcher
jsonPathMatcher *JSONPathMatcher
}

// NewWatcher returns a new Watcher instance.
func NewWatcher(refreshTime time.Duration, repositories []RepositoryConfig, cli *github.Client, log logrus.FieldLogger) (*Watcher, error) {
func NewWatcher(refreshDuration time.Duration, repositories []RepositoryConfig, cli *github.Client, log logrus.FieldLogger) (*Watcher, error) {
repos, lastProcessTime, err := normalizeRepos(repositories)
if err != nil {
return nil, err
}

return &Watcher{
refreshTime: refreshTime,
refreshDuration: refreshDuration,
cfg: repositories,
repos: repos,
cli: cli,
Expand Down Expand Up @@ -91,7 +91,7 @@ func normalizeRepos(in []RepositoryConfig) (map[string]matchCriteria, map[string

func (w *Watcher) AsyncConsumeEvents(ctx context.Context, stream *source.StreamOutput) {
go func() {
timer := time.NewTimer(w.refreshTime)
timer := time.NewTimer(w.refreshDuration)
defer timer.Stop()

defer close(stream.Event)
Expand All @@ -114,10 +114,10 @@ func (w *Watcher) AsyncConsumeEvents(ctx context.Context, stream *source.StreamO
return nil
})
if err != nil {
w.log.WithError(err).Errorf("while processing events, next retry in %d", w.refreshTime)
w.log.WithError(err).Errorf("while processing events, next retry in %d", w.refreshDuration)
}

timer.Reset(w.refreshTime)
timer.Reset(w.refreshDuration)
}
}
}()
Expand Down Expand Up @@ -154,8 +154,13 @@ func (w *Watcher) emitMatchingEvent(ctx context.Context, stream *source.StreamOu
continue
}

msg, err := messageRenderer(ev.GetEvent(), payload, criteria.NotificationTemplate.ToOptions()...)
if err != nil {
log.WithError(err).Errorf("while rendering event %q from %s/%s", ev.Type(), repo.RepoOwner, repo.RepoName)
continue // let's check other events
}
stream.Event <- source.Event{
Message: messageRenderer(ev.GetEvent(), payload, criteria.NotificationTemplate.ToOptions()...),
Message: msg,
}
}
default:
Expand All @@ -179,8 +184,13 @@ func (w *Watcher) emitMatchingEvent(ctx context.Context, stream *source.StreamOu
continue
}

msg, err := messageRenderer(ev.GetEvent(), payload, criteria.NotificationTemplate.ToOptions()...)
if err != nil {
log.WithError(err).Errorf("while rendering event %q from %s/%s", ev.Type(), repo.RepoOwner, repo.RepoName)
continue // let's check other events
}
stream.Event <- source.Event{
Message: messageRenderer(ev.GetEvent(), payload, criteria.NotificationTemplate.ToOptions()...),
Message: msg,
}
}

Expand Down Expand Up @@ -303,28 +313,45 @@ func addOptions(s string, opts interface{}) (string, error) {
// source: https://docs.github.com/en/rest/activity/events?apiVersion=2022-11-28#list-repository-events
func (w *Watcher) listRepositoryEvents(ctx context.Context, repo matchCriteria) ([]CommonEvent, error) {
w.log.Debugf("Listing all %d last emitted github events", perPageItems)
events, r, err := w.cli.Activity.ListRepositoryEvents(ctx, repo.RepoOwner, repo.RepoName, &github.ListOptions{

var events []*github.Event
opts := github.ListOptions{
PerPage: perPageItems,
})
if err != nil {
return nil, fmt.Errorf("while listing repository events: %w", err)
}
if r.StatusCode >= 400 {
return nil, fmt.Errorf("got unexpected status code: %d", r.StatusCode)
for {
resultPage, r, err := w.cli.Activity.ListRepositoryEvents(ctx, repo.RepoOwner, repo.RepoName, &opts)
if err != nil {
return nil, fmt.Errorf("while listing repository events: %w", err)
}
if r.StatusCode >= 400 {
return nil, fmt.Errorf("got unexpected status code: %d", r.StatusCode)
}

events = append(events, resultPage...)
if r.NextPage == 0 {
break
}
opts.Page = r.NextPage
}

var eventsToProcess []CommonEvent
for _, e := range events {
if e == nil || e.CreatedAt.Before(w.lastProcessTime[repoKey(repo)]) {
fmt.Println(e.GetType())
if e == nil || e.GetCreatedAt().Before(w.lastProcessTime[repoKey(repo)]) {
w.log.WithField("eventType", e.GetType()).Debug("Ignoring old events")
continue
}
if e.GetType() == prEventName {
w.log.Debug("Ignore PullRequestEvent as we list them on our own")
w.log.Debugf("Ignore %s as we list them on our own", prEventName)
continue
}
w.log.WithFields(logrus.Fields{
"eventType": e.GetType(),
"eventCreatedAt": e.GetCreatedAt().String(),
}).Debug()
eventsToProcess = append(eventsToProcess, &GitHubEvent{e})
}

return eventsToProcess, nil
}

Expand Down
Loading

0 comments on commit 0649b39

Please sign in to comment.