I'm Parker.


Source Code: https://github.com/parkr/auto-reply
Godoc: https://godoc.org/byparker.com/go/auto-reply

GitHub provides webhooks as a way to be notified when a particular event happens. They’re used for all kinds of integrations and they make it easy to automate tasks based on user actions.

In an effort to automate all sorts of tasks for the Jekyll project, I created a little server which accepts webhooks and performs actions. In an effort to think ahead, I created a framework for getting up and running with webhooks quickly and easily. The details of event type and accepting the webhook and firing off the appropriate actions is all taken care of.

Every action you write has the following signature:

func(*ctx.Context, interface{}) error

This makes it very easy to construct actions, and to allow them to accept multiple inputs. For example:

// Keep track of how many failed CI statuses the project gets.
// The 'ctx' package is github.com/parkr/auto-reply/ctx.
func statStatus(context *ctx.Context, payload interface{}) error {
    status, ok := payload.(*github.StatusEvent)
    if !ok {
        return context.NewError("statStatus: not an status event")

    context.SetIssue(*status.Repo.Owner.Login, *status.Repo.Name, -1)

    // context.Statsd uses the dogstats series of features, and therefore
    // has some added features like tags.
    if context.Statsd != nil {
        statName := fmt.Sprintf("status.%s", *status.State)
        return context.Statsd.Incr(
                "context:" + *status.Context, // e.g. 'travis-ci/pull'
                "repo:" + context.Issue.String(), // e.g. 'octocat/hacks'
            float64(1.0), // rate
    return nil

// The 'hooks' package is github.com/parkr/auto-reply/hooks.
func newGitHubHandler(context *ctx.Context) *hooks.GlobalHandler {
    myHandlers := hooks.EventHandlerMap{}
    myHandlers.AddHandler(hooks.StatusEvent, statStatus)
    return &hooks.GlobalHandler{
        Context:       context,
        EventHandlers: myHandlers,

If you want to spin up a web server, no problem! hooks.GlobalHandler implements net/http.Handler:

func main() {
    context = ctx.NewDefaultContext()
    http.Handle("/webhooks", myGitHubHandler(context))

    port := "8080"
    log.Printf("Listening on :%s", port)
    log.Fatal(http.ListenAndServe(":"+port, nil))

Check out the README for auto-reply if you’re interested in learning more about how you can use this tool for your projects.


auto-reply is licensed under the MIT License, copyright Parker Moore.