Skip to content
The code that runs @jekyllbot
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.
chlog Update the import paths Apr 23, 2019
cmd freeze-ancient-issues: parse issue repo from URL Apr 23, 2019
ctx ctx: Add Context.CurrentlyAuthedGitHubUser() Dec 2, 2017
search Update the import paths Apr 23, 2019


An open source gardener. This is a technology for powering GitHub bots. It's really rough around the edges but it currently powers @jekyllbot.

Build Status


If you want to configure a secret to validate your payload from GitHub, then set it as the environment variable GITHUB_WEBHOOK_SECRET. This is the same value you enter in the web interface when setting up the "Secret" for your webhook.

I could use your thoughts on this! Currently, it's a hodge-podge. The documentation for each package will provide more details on this. Currently we have the following packages, with varying levels of configuration:

  • affinity – assigns issues based on team mentions and those team captains. See Jekyll's docs for more info.
  • autopull – detects pushes to branches which start with pull/ and automatically creates a PR for them
  • chlog – creates GitHub releases when a new tag is pushed, and powers "@jekyllbot: merge (+category)"
  • jekyll/deprecate – comments on and closes issues to issues on certain repos with a per-repo stock message
  • jekyll/issuecomment – provides handlers for removing pending-feedback and stale labels when a comment comes through
  • labeler – removes pending-rebase label when a PR is pushed to and is mergeable (and helper functions for manipulating labels)
  • lgtm – adds a jekyllbot/lgtm CI status and handles LGTM counting


This is intended for use with servers, so you'd do something like:

package main

import (


var context *ctx.Context

func main() {
	var port string
	flag.StringVar(&port, "port", "8080", "The port to serve to")
	context = ctx.NewDefaultContext()

	http.HandleFunc("/_ping", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "text/plain")

	// Add your event handlers. Check out the documentation for the
	// package to see all supported events.
	eventHandlers := hooks.EventHandlerMap{}

	// Build the affinity handler.
	aff := &affinity.Handler{}
	aff.AddRepo("myorg", "myproject")
	aff.AddTeam(context, 123) // @myorg/performance
	aff.AddTeam(context, 456) // @myorg/documentation

	// Add the affinity handler's various event handlers to the event handlers map :)
	eventHandlers.AddHandler(hooks.IssuesEvent, aff.AssignIssueToAffinityTeamCaptain)
	eventHandlers.AddHandler(hooks.IssueCommentEvent, aff.AssignIssueToAffinityTeamCaptainFromComment)
	eventHandlers.AddHandler(hooks.PullRequestEvent, aff.RequestReviewFromAffinityTeamCaptain)

	// Create the webhook handler. GlobalHandler takes the list of event handlers from
	// its configuration and fires each of them based on the X-GitHub-Event header from
	// the webhook payload.
	myOrgHandler := &hooks.GlobalHandler{
		Context:       context,
		EventHandlers: eventHandlers,
	http.Handle("/_github/myproject", myOrgHandler)

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

Writing Custom Handlers

For now, all you have to do is write a function which satisfies the hooks.EventHandler type. At the moment, each handler can accept only one type of event. If you want to accept the issue_comment event, then you should be able to perform a successful type assertion:

func MyIssueCommentHandler(context *ctx.Context, payload interface{}) error {
    event, err := payload.(*github.IssueCommentEvent)
    if err != nil {
        return context.NewError("MyIssueCommentHandler: hm, didn't get an IssueCommentEvent: %v", err)

    // Handle your issue comment event in a type-safe way here.

Then you register that with your project. Taking the two examples above, you'd add MyIssueCommentHandler to the eventHandlers[hooks.IssueCommentEvent] array:

eventHandlers := hooks.EventHandlerMap{}
eventHandlers.AddHandler(hooks.IssueCommentEvent, MyIssueCommentHandler)

And it should work!

Optional: Mark-and-sweep Stale Issues

One big issue we have in Jekyll is "stale" issues, that is, issues which were opened and abandoned after a few months of activity. The code in cmd/mark-and-sweep-stale-issues is still Jekyll-specific but I'd love a PR which abstracts out the configuration into a file or something!


This code is licensed under BSD 3-clause as specified in the LICENSE file in this repository.

You can’t perform that action at this time.