githubapp

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 7, 2020 License: Apache-2.0 Imports: 18 Imported by: 0

Documentation

Overview

Package githubapp implements an http.Handler for GitHub events and provides utilities for building GitHub applications. Most users will create implementations of githubapp.EventHandler to handle different webhook event types and register them with the event dispatcher.

Many functions are instrumented with optional logging and metrics collection. The package also defines functions to create authenticated GitHub clients and manage application installations.

Index

Constants

View Source
const (
	LogKeyEventType       string = "github_event_type"
	LogKeyDeliveryID      string = "github_delivery_id"
	LogKeyRepositoryName  string = "github_repository_name"
	LogKeyRepositoryOwner string = "github_repository_owner"
	LogKeyPRNum           string = "github_pr_num"
	LogKeyInstallationID  string = "github_installation_id"
)
View Source
const (
	MetricsKeyRequests    = "github.requests"
	MetricsKeyRequests2xx = "github.requests.2xx"
	MetricsKeyRequests3xx = "github.requests.3xx"
	MetricsKeyRequests4xx = "github.requests.4xx"
	MetricsKeyRequests5xx = "github.requests.5xx"

	MetricsKeyRequestsCached = "github.requests.cached"

	MetricsKeyRateLimit          = "github.rate.limit"
	MetricsKeyRateLimitRemaining = "github.rate.remaining"
)
View Source
const (
	DefaultCachingClientCapacity = 64
)
View Source
const (
	DefaultWebhookRoute string = "/api/github/hook"
)

Variables

This section is empty.

Functions

func DefaultErrorCallback

func DefaultErrorCallback(w http.ResponseWriter, r *http.Request, err error)

DefaultErrorCallback logs errors and responds with a 500 status code.

func DefaultResponseCallback

func DefaultResponseCallback(w http.ResponseWriter, r *http.Request, event string, handled bool)

DefaultResponseCallback responds with a 200 OK for handled events and a 202 Accepted status for all other events. By default, responses are empty. Event handlers may send custom responses by calling the SetResponder function before returning.

func GetInstallationIDFromEvent

func GetInstallationIDFromEvent(event InstallationSource) int64

GetInstallationIDFromEvent returns the installation ID from a GitHub webhook event payload.

func GetResponder

func GetResponder(ctx context.Context) func(http.ResponseWriter, *http.Request)

GetResponder returns the response function that was set by an event handler. If no response function exists, it returns nil. There is usually no reason to call this outside of a response callback implementation.

func InitializeResponder

func InitializeResponder(ctx context.Context) context.Context

InitializeResponder prepares the context to work with SetResponder and GetResponder. It is used to test handlers that call SetResponder or to implement custom event dispatchers that support responders.

func NewDefaultEventDispatcher

func NewDefaultEventDispatcher(c Config, handlers ...EventHandler) http.Handler

NewDefaultEventDispatcher is a convenience method to create an event dispatcher from configuration using the default error and response callbacks.

func NewEventDispatcher

func NewEventDispatcher(handlers []EventHandler, secret string, opts ...DispatcherOption) http.Handler

NewEventDispatcher creates an http.Handler that dispatches GitHub webhook requests to the appropriate event handlers. It validates payload integrity using the given secret value.

Responses are controlled by optional error and response callbacks. If these options are not provided, default callbacks are used.

func PreparePRContext

func PreparePRContext(ctx context.Context, installationID int64, repo *github.Repository, number int) (context.Context, zerolog.Logger)

PreparePRContext adds information about a pull request to the logger in a context and returns the modified context and logger.

func PrepareRepoContext

func PrepareRepoContext(ctx context.Context, installationID int64, repo *github.Repository) (context.Context, zerolog.Logger)

PrepareRepoContext adds information about a repository to the logger in a context and returns the modified context and logger.

func SetResponder

func SetResponder(ctx context.Context, responder func(http.ResponseWriter, *http.Request))

SetResponder sets a function that sends a response to GitHub after event processing completes. The context must be initialized by InitializeResponder. The event dispatcher does this automatically before calling a handler.

Customizing individual handler responses should be rare. Applications that want to modify the standard responses should consider registering a response callback before using this function.

Types

type ClientCreator

type ClientCreator interface {
	// NewAppClient returns a new github.Client that performs app authentication for
	// the GitHub app with a specific integration ID and private key. The returned
	// client makes all calls using the application's authorization token. The
	// client gets that token by creating and signing a JWT for the application and
	// requesting a token using it. The token is cached by the client and is
	// refreshed as needed if it expires.
	//
	// Used for performing app-level operations that are not associated with a
	// specific installation.
	//
	// See the following for more information:
	//  * https://developer.github.com/apps/building-github-apps/authenticating-with-github-apps/#authenticating-as-a-github-app
	//
	// Authenticating as a GitHub App lets you do a couple of things:
	//  * You can retrieve high-level management information about your GitHub App.
	//  * You can request access tokens for an installation of the app.
	//
	// Tips for determining the arguments for this function:
	//  * the integration ID is listed as "ID" in the "About" section of the app's page
	//  * the key bytes must be a PEM-encoded PKCS1 or PKCS8 private key for the application
	NewAppClient() (*github.Client, error)

	// NewAppV4Client returns an app-authenticated v4 API client, similar to NewAppClient.
	NewAppV4Client() (*githubv4.Client, error)

	// NewInstallationClient returns a new github.Client that performs app
	// authentication for the GitHub app with the a specific integration ID, private
	// key, and the given installation ID. The returned client makes all calls using
	// the application's authorization token. The client gets that token by creating
	// and signing a JWT for the application and requesting a token using it. The
	// token is cached by the client and is refreshed as needed if it expires.
	//
	// See the following for more information:
	//  * https://developer.github.com/apps/building-github-apps/authenticating-with-github-apps/#authenticating-as-an-installation
	//
	// Authenticating as an installation of a Github App lets you perform the following:
	//  * https://developer.github.com/v3/apps/available-endpoints/
	//
	// Tips for determining the arguments for this function:
	//  * the integration ID is listed as "ID" in the "About" section of the app's page
	//  * the installation ID is the ID that is shown in the URL of https://{githubURL}/settings/installations/{#}
	//      (navigate to the "installations" page without the # and go to the app's page to see the number)
	//  * the key bytes must be a PEM-encoded PKCS1 or PKCS8 private key for the application
	NewInstallationClient(installationID int64) (*github.Client, error)

	// NewInstallationV4Client returns an installation-authenticated v4 API client, similar to NewInstallationClient.
	NewInstallationV4Client(installationID int64) (*githubv4.Client, error)

	// NewTokenClient returns a *github.Client that uses the passed in OAuth token for authentication.
	NewTokenClient(token string) (*github.Client, error)

	// NewTokenV4Client returns a *githubv4.Client that uses the passed in OAuth token for authentication.
	NewTokenV4Client(token string) (*githubv4.Client, error)
}

func NewCachingClientCreator

func NewCachingClientCreator(delegate ClientCreator, capacity int) (ClientCreator, error)

NewCachingClientCreator returns a ClientCreator that creates a GitHub client for installations of the app specified by the provided arguments. It uses an LRU cache of the provided capacity to store clients created for installations and returns cached clients when a cache hit exists.

func NewClientCreator

func NewClientCreator(v3BaseURL, v4BaseURL string, integrationID int, privKeyBytes []byte, opts ...ClientOption) ClientCreator

NewClientCreator returns a ClientCreator that creates a GitHub client for installations of the app specified by the provided arguments.

func NewDefaultCachingClientCreator

func NewDefaultCachingClientCreator(c Config, opts ...ClientOption) (ClientCreator, error)

NewDefaultCachingClientCreator returns a ClientCreator using values from the configuration or other defaults.

type ClientMiddleware

type ClientMiddleware func(http.RoundTripper) http.RoundTripper

ClientMiddleware modifies the transport of a GitHub client to add common functionality, like logging or metrics collection.

func ClientLogging

func ClientLogging(lvl zerolog.Level) ClientMiddleware

ClientLogging creates client middleware that logs request and response information at the given level. If the request fails without creating a response, it is logged with a status code of -1. The middleware uses a logger from the request context.

func ClientMetrics

func ClientMetrics(registry metrics.Registry) ClientMiddleware

ClientMetrics creates client middleware that records metrics about all requests. It also defines the metrics in the provided registry.

type ClientOption

type ClientOption func(c *clientCreator)

func WithClientCaching

func WithClientCaching(alwaysValidate bool, cache func() httpcache.Cache) ClientOption

WithClientCaching sets an HTTP cache for all created clients using the provided cache implementation If alwaysValidate is true, the cache validates all saved responses before returning them. Otherwise, it respects the caching headers returned by GitHub. https://developer.github.com/v3/#conditional-requests

func WithClientMiddleware

func WithClientMiddleware(middleware ...ClientMiddleware) ClientOption

WithClientMiddleware adds middleware that is applied to all created clients.

func WithClientUserAgent

func WithClientUserAgent(agent string) ClientOption

WithClientUserAgent sets the base user agent for all created clients.

type Config

type Config struct {
	WebURL   string `yaml:"web_url" json:"webUrl"`
	V3APIURL string `yaml:"v3_api_url" json:"v3ApiUrl"`
	V4APIURL string `yaml:"v4_api_url" json:"v4ApiUrl"`

	App struct {
		IntegrationID int    `yaml:"integration_id" json:"integrationId"`
		WebhookSecret string `yaml:"webhook_secret" json:"webhookSecret"`
		PrivateKey    string `yaml:"private_key" json:"privateKey"`
	} `yaml:"app" json:"app"`

	OAuth struct {
		ClientID     string `yaml:"client_id" json:"clientId"`
		ClientSecret string `yaml:"client_secret" json:"clientSecret"`
	} `yaml:"oauth" json:"oauth"`
}

func (*Config) SetValuesFromEnv

func (c *Config) SetValuesFromEnv(prefix string)

SetValuesFromEnv sets values in the configuration from coresponding environment variables, if they exist. The optional prefix is added to the start of the environment variable names.

type DispatcherOption

type DispatcherOption func(*eventDispatcher)

DispatcherOption configures properties of an event dispatcher.

func WithErrorCallback

func WithErrorCallback(onError ErrorCallback) DispatcherOption

WithErrorCallback sets the error callback for an event dispatcher.

func WithResponseCallback

func WithResponseCallback(onResponse ResponseCallback) DispatcherOption

WithResponseCallback sets the response callback for an event dispatcher.

type ErrorCallback

type ErrorCallback func(w http.ResponseWriter, r *http.Request, err error)

ErrorCallback is called when an event handler returns an error. The error from the handler is passed directly as the final argument.

type EventHandler

type EventHandler interface {
	// Handles returns a list of GitHub events that this handler handles
	// See https://developer.github.com/v3/activity/events/types/
	Handles() []string

	// Handle processes the GitHub event "eventType" with the given delivery ID
	// and payload. The EventDispatcher guarantees that the Handle method will
	// only be called for the events returned by Handles().
	//
	// If Handle returns an error, processing stops and the error is passed
	// directly to the configured error handler.
	Handle(ctx context.Context, eventType, deliveryID string, payload []byte) error
}

type Installation

type Installation struct {
	ID      int64
	Owner   string
	OwnerID int64
}

Installation is a minimal representation of a GitHub app installation.

type InstallationNotFound

type InstallationNotFound string

InstallationNotFound is returned when no installation exists for a specific owner or repository.

func (InstallationNotFound) Error

func (err InstallationNotFound) Error() string

type InstallationSource

type InstallationSource interface {
	GetInstallation() *github.Installation
}

InstallationSource is implemented by GitHub webhook event payload types.

type InstallationsService

type InstallationsService interface {
	// ListAll returns all installations for this app.
	ListAll(ctx context.Context) ([]Installation, error)

	// GetByOwner returns the installation for an owner (user or organization).
	// It returns an InstallationNotFound error if no installation exists for
	// the owner.
	GetByOwner(ctx context.Context, owner string) (Installation, error)
}

InstallationsService retrieves installation information for a given app. Implementations may chose how to retrieve, store, or cache these values.

This service is useful for background processes that do not respond directly to webhooks, since webhooks provide installation IDs in their payloads.

func NewInstallationsService

func NewInstallationsService(appClient *github.Client) InstallationsService

NewInstallationsService returns an InstallationsService that always queries GitHub. It should be created with a client that authenticates as the target application.

type ResponseCallback

type ResponseCallback func(w http.ResponseWriter, r *http.Request, event string, handled bool)

ResponseCallback is called to send a response to GitHub after an event is handled. It is passed the event type and a flag indicating if an event handler was called for the event.

type ValidationError

type ValidationError struct {
	EventType  string
	DeliveryID string
	Cause      error
}

ValidationError is passed to error callbacks when the webhook payload fails validation.

func (ValidationError) Error

func (ve ValidationError) Error() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL