Repository: reviewdog/reviewdog
Pull request #208 (2019-03-24 15:40:20)

Introduce go mod & Upgrade AppEngine runtime to go1.11


Patch:
diff --git a/.gitmodules b/.gitmodules
deleted file mode 100644
index e69de29b..00000000
diff --git a/.travis.yml b/.travis.yml
index c985c5f8..b19653c8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,7 +2,7 @@ language: go
 
 go:
   - "1.12.x"
-  - "1.9.x" # for doghouse server which runs on AppEngine with Go 1.9
+  - "1.11.x" # for doghouse server which runs on AppEngine with Go 1.11
   - master
 
 matrix:
@@ -13,11 +13,9 @@ matrix:
 env:
   global:
     - secure: "F1MWBFOxaa1vcb0bnjVTuVEzzaqxQykwHVzdeevKGG6qGwBqDoKjzDym1XbWdZkfsu6N2sEz6Xo9wAMQwc1nhBJTufQOKjwqy0zDXsKMF5aouvswqe4eEZ95IU8Ww30jGiw1E4d6RfvTvYOwZszB+vIvqJ7gs8msFr0wJaQUpJk+Qpd5TtNb8poY7J0qQH0GevlNIY5SieM52BbQKodEC9aUUTFYOvoZEOAiLPX/6qS1hvfOIwHEFxXo9jrUSiSyqYZTfEN9CExsO3M5iJQz1ZVvtylXpATcZ6Imo3Q5eL288wTx4VUjL/lrnS1vIkmgG0HWyOYg4FGl9l4TsANGf3EnByBtZmFJ/MLjmqtWQzodvU2wMCseVJ/MQzi6iOkunXccUCLzoh9F3rzbus8lP6io7yknaB/AqKyTj9oBY7AXT9r1wnEmO56XNQu11PK1qu2JeCOzkF52784vh+XNBfPTvJYmJy1c7m1Sys0rta2m6F9c3bZV24ZWPaY7DkfwcT6ytXJP44D6NI1k1cOOwmJ8oJfNkrgNBUTUfd8rKu4alKAG0VB59imTVH25ZYzUdxqiiG+tuXJ4ZG8bvreyfk4qTiF5BqdU0/iqGgEkdn2px7UZd656svLGI9qRodSCFhd7pCHw2UfGakGweRG9cW4GEYdDwHnEx+l2g8vc6EQ="
+    - GO111MODULE=on
 
 install:
-  # Install reviewdog.
-  - go get -u github.com/golang/dep/...
-  - dep ensure
   - go install ./cmd/reviewdog
   # Install CI tools.
   - go get github.com/haya14busa/goverage
diff --git a/Gopkg.lock b/Gopkg.lock
deleted file mode 100644
index 47b09a4d..00000000
--- a/Gopkg.lock
+++ /dev/null
@@ -1,193 +0,0 @@
-# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
-
-
-[[projects]]
-  digest = "1:8a527a9a281d4bd2e09539f503ad99ee9cc4c0ae768243e706683ddca997d556"
-  name = "github.com/bradleyfalzon/ghinstallation"
-  packages = ["."]
-  pruneopts = ""
-  revision = "3f4e9b1898e6b65e31827d5dccb97d91d59feaa3"
-  version = "v0.1.2"
-
-[[projects]]
-  digest = "1:6098222470fe0172157ce9bbef5d2200df4edde17ee649c5d6e48330e4afa4c6"
-  name = "github.com/dgrijalva/jwt-go"
-  packages = ["."]
-  pruneopts = ""
-  revision = "06ea1031745cb8b3dab3f6a236daf2b0aa468b7e"
-  version = "v3.2.0"
-
-[[projects]]
-  digest = "1:529d738b7976c3848cae5cf3a8036440166835e389c1f617af701eeb12a0518d"
-  name = "github.com/golang/protobuf"
-  packages = ["proto"]
-  pruneopts = ""
-  revision = "b5d812f8a3706043e23a9cd5babf2e5423744d30"
-  version = "v1.3.1"
-
-[[projects]]
-  digest = "1:f9f45f75f332e03fc7e9fe9188ea4e1ce4d14779ef34fa1b023da67518e36327"
-  name = "github.com/google/go-cmp"
-  packages = [
-    "cmp",
-    "cmp/internal/diff",
-    "cmp/internal/function",
-    "cmp/internal/value",
-  ]
-  pruneopts = ""
-  revision = "3af367b6b30c263d47e8895973edcca9a49cf029"
-  version = "v0.2.0"
-
-[[projects]]
-  digest = "1:e38ad2825940d58bd8425be40bcd4211099d0c1988c158c35828197413b3cf85"
-  name = "github.com/google/go-github"
-  packages = ["github"]
-  pruneopts = ""
-  revision = "7462feb2032c2da9e3b85e9b04e6853a6e9e14ca"
-  version = "v24.0.1"
-
-[[projects]]
-  digest = "1:cea4aa2038169ee558bf507d5ea02c94ca85bcca28a4c7bb99fd59b31e43a686"
-  name = "github.com/google/go-querystring"
-  packages = ["query"]
-  pruneopts = ""
-  revision = "44c6ddd0a2342c386950e880b658017258da92fc"
-  version = "v1.0.0"
-
-[[projects]]
-  branch = "master"
-  digest = "1:825151fc1df14d134ca4e18bac531030ab718b329ef2464846bbe004547d5220"
-  name = "github.com/reviewdog/errorformat"
-  packages = [
-    ".",
-    "fmts",
-  ]
-  pruneopts = ""
-  revision = "689b7d67b7a82a9cae3d8bfcfa0f6f4b5790b88a"
-
-[[projects]]
-  branch = "master"
-  digest = "1:c1cc4d39fa7ef04a2e11fdcf4b366a8e3b8a4960e524f7d364c1bf9312b36947"
-  name = "github.com/haya14busa/secretbox"
-  packages = ["."]
-  pruneopts = ""
-  revision = "07c7ecf409f5fff9b029e7ea44309226d25dd936"
-
-[[projects]]
-  branch = "master"
-  digest = "1:7f2188c32f0bbe2ffb81609dd97fc227e3269b193b68d510f06ea07329ec1f9f"
-  name = "github.com/justinas/nosurf"
-  packages = ["."]
-  pruneopts = ""
-  revision = "6453469bdcc9a5da46b528edb797565bbd21c356"
-
-[[projects]]
-  branch = "master"
-  digest = "1:ee97ec8a00b2424570c1ce53d7b410e96fbd4c241b29df134276ff6aa3750335"
-  name = "github.com/kylelemons/godebug"
-  packages = [
-    "diff",
-    "pretty",
-  ]
-  pruneopts = ""
-  revision = "d65d576e9348f5982d7f6d83682b694e731a45c6"
-
-[[projects]]
-  digest = "1:0093a7c66d5b9e0cdaf4be5c20e0a9b889d1d839148eeed1d587e99b4cfd90ff"
-  name = "github.com/mattn/go-shellwords"
-  packages = ["."]
-  pruneopts = ""
-  revision = "a72fbe27a1b0ed0df2f02754945044ce1456608b"
-  version = "v1.0.5"
-
-[[projects]]
-  digest = "1:9e0446b86e11cb3e483eaf46cd534386da799502d403f9d06143b27231e4ec69"
-  name = "github.com/xanzy/go-gitlab"
-  packages = ["."]
-  pruneopts = ""
-  revision = "be70cf752294cc5c6ee89a18d6ba0caca08aa5c7"
-  version = "v0.16.1"
-
-[[projects]]
-  branch = "master"
-  digest = "1:ab3e9a81a5ec54c5d1ed41d0d6898ba88c6799fa401b784b06bdee8e432d872b"
-  name = "golang.org/x/crypto"
-  packages = [
-    "internal/subtle",
-    "nacl/secretbox",
-    "poly1305",
-    "salsa20/salsa",
-  ]
-  pruneopts = ""
-  revision = "a1f597ede03a7bef967a422b5b3a5bd08805a01e"
-
-[[projects]]
-  branch = "master"
-  digest = "1:73e6624a8569db94b0d8f9b34052f73ef9598c380edbce36d89dbbc00941e976"
-  name = "golang.org/x/net"
-  packages = [
-    "context",
-    "context/ctxhttp",
-  ]
-  pruneopts = ""
-  revision = "d196dffd7c2beec1957382065df08bcc353b9706"
-
-[[projects]]
-  branch = "master"
-  digest = "1:ffae4a89b63a2c845533a393b3340f8696898b11b71da1b187f82f08135c23a0"
-  name = "golang.org/x/oauth2"
-  packages = [
-    ".",
-    "internal",
-  ]
-  pruneopts = ""
-  revision = "e64efc72b421e893cbf63f17ba2221e7d6d0b0f3"
-
-[[projects]]
-  branch = "master"
-  digest = "1:0142c968b74c157abbb0220c05fa2bdde8a3a4509d6134b35ef75d5b58afb721"
-  name = "golang.org/x/sync"
-  packages = ["errgroup"]
-  pruneopts = ""
-  revision = "e225da77a7e68af35c70ccbf71af2b83e6acac3c"
-
-[[projects]]
-  branch = "master"
-  digest = "1:ff0bd364800b7ec504f142151d0c2fbe68841cd1dc1a506fae10eeddcae42e60"
-  name = "golang.org/x/sys"
-  packages = [
-    "cpu",
-    "unix",
-  ]
-  pruneopts = ""
-  revision = "6c81ef8f67ca3f42fc9cd71dfbd5f35b0c4b5771"
-
-[[projects]]
-  digest = "1:cedccf16b71e86db87a24f8d4c70b0a855872eb967cb906a66b95de56aefbd0d"
-  name = "gopkg.in/yaml.v2"
-  packages = ["."]
-  pruneopts = ""
-  revision = "51d6538a90f86fe93ac480b35f37b2be17fef232"
-  version = "v2.2.2"
-
-[solve-meta]
-  analyzer-name = "dep"
-  analyzer-version = 1
-  input-imports = [
-    "github.com/bradleyfalzon/ghinstallation",
-    "github.com/google/go-cmp/cmp",
-    "github.com/google/go-github/github",
-    "github.com/reviewdog/errorformat",
-    "github.com/reviewdog/errorformat/fmts",
-    "github.com/haya14busa/secretbox",
-    "github.com/justinas/nosurf",
-    "github.com/kylelemons/godebug/pretty",
-    "github.com/mattn/go-shellwords",
-    "github.com/xanzy/go-gitlab",
-    "golang.org/x/net/context",
-    "golang.org/x/oauth2",
-    "golang.org/x/sync/errgroup",
-    "gopkg.in/yaml.v2",
-  ]
-  solver-name = "gps-cdcl"
-  solver-version = 1
diff --git a/Gopkg.toml b/Gopkg.toml
deleted file mode 100644
index 77028df6..00000000
--- a/Gopkg.toml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-# Example:
-# [[dependencies]]
-# source = "https://github.com/myfork/package.git"
-# branch = "master"
-# name = "github.com/vendor/package"
-# Note: revision will depend on your repository type, i.e git, svc, bzr etc...
-# revision = "abc123"
-# version = "1.0.0"
diff --git a/cmd/reviewdog/main.go b/cmd/reviewdog/main.go
index 1db20f66..ffbfb226 100644
--- a/cmd/reviewdog/main.go
+++ b/cmd/reviewdog/main.go
@@ -18,7 +18,7 @@ import (
 
 	"golang.org/x/oauth2"
 
-	"github.com/google/go-github/github"
+	"github.com/google/go-github/v24/github"
 	"github.com/reviewdog/errorformat/fmts"
 	shellwords "github.com/mattn/go-shellwords"
 	"github.com/reviewdog/reviewdog"
diff --git a/doghouse/appengine/.gcloudignore b/doghouse/appengine/.gcloudignore
new file mode 100644
index 00000000..964115ef
--- /dev/null
+++ b/doghouse/appengine/.gcloudignore
@@ -0,0 +1,13 @@
+# This file specifies files that are *not* uploaded to Google Cloud Platform
+# using gcloud. It follows the same syntax as .gitignore, with the addition of
+# "#!include" directives (which insert the entries of the given .gitignore-style
+# file at that point).
+#
+# For more information, run:
+#   $ gcloud topic gcloudignore
+#
+
+# To prevent error of gloud SDK which cannot decode Unicode properly.
+/diff/testdata
+
+node_modules/
diff --git a/doghouse/appengine/app.yaml b/doghouse/appengine/app.yaml
index 8ec0671b..eb40fc3b 100644
--- a/doghouse/appengine/app.yaml
+++ b/doghouse/appengine/app.yaml
@@ -1,8 +1,7 @@
 # reviewdog app config: https://github.com/settings/apps/reviewdog
 
 # https://cloud.google.com/appengine/docs/standard/go/config/appref
-runtime: go
-api_version: go1.9
+runtime: go111
 
 # https://cloud.google.com/appengine/docs/standard/go/warmup-requests/configuring
 inbound_services:
diff --git a/doghouse/appengine/app_dev.yaml b/doghouse/appengine/app_dev.yaml
index cff9b9e8..2e48f0be 100644
--- a/doghouse/appengine/app_dev.yaml
+++ b/doghouse/appengine/app_dev.yaml
@@ -1,8 +1,7 @@
 # reviewdog-dev app config: https://github.com/settings/apps/reviewdog-dev
 
 # https://cloud.google.com/appengine/docs/standard/go/config/appref
-runtime: go
-api_version: go1.9
+runtime: go111
 
 # https://cloud.google.com/appengine/docs/standard/go/warmup-requests/configuring
 inbound_services:
diff --git a/doghouse/appengine/github.go b/doghouse/appengine/github.go
index 3b48482d..fb4e257b 100644
--- a/doghouse/appengine/github.go
+++ b/doghouse/appengine/github.go
@@ -7,18 +7,17 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
-	"html/template"
 	"io"
 	"io/ioutil"
 	"net/http"
 	"net/url"
 	"strings"
 
-	"github.com/google/go-github/github"
+	"github.com/google/go-github/v24/github"
+	"github.com/justinas/nosurf"
 	"github.com/reviewdog/reviewdog/doghouse/server"
 	"github.com/reviewdog/reviewdog/doghouse/server/cookieman"
 	"github.com/reviewdog/reviewdog/doghouse/server/storage"
-	"github.com/justinas/nosurf"
 	"golang.org/x/oauth2"
 	"google.golang.org/appengine"
 	"google.golang.org/appengine/log"
@@ -52,20 +51,6 @@ func NewGitHubHandler(clientID, clientSecret string, c *cookieman.CookieMan, pri
 	}
 }
 
-var ghTopTmpl = template.Must(
-	template.ParseFiles(
-		"tmpl/gh/base.html",
-		"tmpl/gh/header.html",
-		"tmpl/gh/top.html",
-	))
-
-var ghRepoTmpl = template.Must(
-	template.ParseFiles(
-		"tmpl/gh/base.html",
-		"tmpl/gh/header.html",
-		"tmpl/gh/repo.html",
-	))
-
 type ghTopTmplData struct {
 	Title string
 	User  tmplUser
diff --git a/doghouse/appengine/github_webhook.go b/doghouse/appengine/github_webhook.go
index fc53c645..c76d7baf 100644
--- a/doghouse/appengine/github_webhook.go
+++ b/doghouse/appengine/github_webhook.go
@@ -7,7 +7,7 @@ import (
 	"io/ioutil"
 	"net/http"
 
-	"github.com/google/go-github/github"
+	"github.com/google/go-github/v24/github"
 	"github.com/reviewdog/reviewdog/doghouse/server/storage"
 	"google.golang.org/appengine"
 )
diff --git a/doghouse/appengine/handlers.yaml b/doghouse/appengine/handlers.yaml
index 3a854711..2e509700 100644
--- a/doghouse/appengine/handlers.yaml
+++ b/doghouse/appengine/handlers.yaml
@@ -1,15 +1,15 @@
 handlers:
 - url: /secret/*
   secure: always
-  script: _go_app
+  script: auto
 
 - url: /static
   static_dir: static
 
 - url: /.*
-  script: _go_app
+  script: auto
 
 - url: /_ah/warmup
-  script: _go_app
+  script: auto
   login: admin
 
diff --git a/doghouse/appengine/main.go b/doghouse/appengine/main.go
index 3b6c0f9d..c7463334 100644
--- a/doghouse/appengine/main.go
+++ b/doghouse/appengine/main.go
@@ -1,17 +1,16 @@
 package main
 
 import (
-	"html/template"
 	"io/ioutil"
 	"log"
 	"net/http"
 	"os"
 	"strconv"
 
-	"github.com/reviewdog/reviewdog/doghouse/server/cookieman"
-	"github.com/reviewdog/reviewdog/doghouse/server/storage"
 	"github.com/haya14busa/secretbox"
 	"github.com/justinas/nosurf"
+	"github.com/reviewdog/reviewdog/doghouse/server/cookieman"
+	"github.com/reviewdog/reviewdog/doghouse/server/storage"
 	"google.golang.org/appengine"
 )
 
@@ -62,6 +61,8 @@ func mustIntEnv(name string) int {
 }
 
 func main() {
+	initTemplates()
+
 	integrationID := mustIntEnv("GITHUB_INTEGRATION_ID")
 	ghPrivateKey := mustGitHubAppsPrivateKey()
 
@@ -104,12 +105,6 @@ func main() {
 	appengine.Main()
 }
 
-var topTmpl = template.Must(
-	template.ParseFiles(
-		"tmpl/base.html",
-		"tmpl/index.html",
-	))
-
 func handleTop(w http.ResponseWriter, r *http.Request) {
 	var data struct {
 		Title string
diff --git a/doghouse/appengine/statik/statik.go b/doghouse/appengine/statik/statik.go
new file mode 100644
index 00000000..fb621593
--- /dev/null
+++ b/doghouse/appengine/statik/statik.go
@@ -0,0 +1,13 @@
+// Code generated by statik. DO NOT EDIT.
+
+// Package statik contains static assets.
+package statik
+
+import (
+	"github.com/rakyll/statik/fs"
+)
+
+func init() {
+	data := "PK\x03\x04\x14\x00\x08\x00\x08\x00Y\x94xN\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00	\x00	\x00base.htmlUT\x05\x00\x01\xcb\xcd\x97\\t\x91\xe1\xaa\xdc \x10\x85\xff\xe7)\xac\xbfw\xd5\xcbmi\xb9\xc4\xed;\x94\xbe\xc0D'\xc9PuB\x9c\xbb\xdb\x10\xf2\xee\xc5\x86\xa5\xd0\xd2_\xea\x9c\xe3\x99\x03\xdf\xbeG\x1c\xa9\xa0\xd2\x03T\xd4\xc7\xd1\xf5\x1f\"\x07\xd9\x16T\xb3\xe4t\xeb\xfav\xa8\x04e\xf2\x1a\x8bn\x03\x84x\xeb\x94\xea3\n\xa80\xc3ZQ\xbc~\x97\xf1\xfaE\xff\x11\nd\xf4\xfaN\xf8Xx\x15\xad\x02\x17\xc1\"^?(\xca\xec#\xde)\xe0\xf5\xf7\xe3\xa2\xa8\x90\x10\xa4k\x0d\x90\xd0\xbf\x18w\x06%*?\xd4\x8a\xc9\xeb:\xf3*\xe1]\x14\x05.Z\xb5\x82^S\x86	-\x05\xd6j^q\xf4\xdaV\x01\xa1`G\xb87\x9fi\x92\xfd;I\xb6\x84uF\x94\xe7\xafYd\xa9o\xd6\x8e\\\xa4\x9a\x89yJ\x08\x0bU\x138\xdbP\xeb\xd7\x112\xa5\xcd\x7f\xe3\x81\x85\xdf^\x9d\xbb|t\xee\xf2\xc9\xb9\xcbg\xe7\x9ee\x04\x7fJs\xff\xd3\xfc\xbf\xfb\x02G4\x13J\x8e\xc9\x10\xdb\x17\xf3j\x9c\xcd \xb8\x12$3\xac\xfc(W^\xa1Lh2\x15\xd3\xb2\x95\xbdu-^H\x12\xde\xf6\xdd|o\x97\xe3\xe8\xed9\xe9z{\xe2\xe9\x07\x8e[k\xb2\xef\x82yI \x8d1\xc7M+\xd3(\xdbS\xef\xedIy\xdf\xb1\xc4\xe3\xe8~\x05\x00\x00\xff\xffPK\x07\x08\xc1\x1e\x08\x9cJ\x01\x00\x00\x10\x02\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00-:xN\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0c\x00	\x00gh/base.htmlUT\x05\x00\x01\x06/\x97\\\x94\x93?o\xdc<\x0c\xc6w\x7f\n\xbeZ\xdf\xb3\xe4 \x0dZ\xa4\xf6u\xee\xd0\xa5\xe8\x1e\xe8$\xdaf\xaa?\x86\xc4\\\xee`\xf8\xbb\x17\xb2\xef\x9a\xa6Y\xd2\xc9\x14I\xff\x9e\x87\x844\xcf\x16{\n\x08\xe2\xa03\x8ae\xa9\xda\xffl4|\x9e\x10F\xf6n_\xb5\xe5\x03N\x87\xa1\x13\x18DI\xa0\xb6\xfb\n\xa0\xf5\xc8\x1a\xcc\xa8SF\xee\xc4\x13\xf7\xf5'\xf1R\x08\xdac'\x8e\x84\xcfSL,\xc0\xc4\xc0\x18\xb8\x13\xcfdy\xec,\x1e\xc9`\xbd\x1ev@\x81\x98\xb4\xab\xb3\xd1\x0e\xbb\x1b\xd9l G\xe1'$t\x9d\xc8cLl\x9e\x18\xc8\xc4 \xa0\x18\xec\x04y=\xa0\"\x13\x05\x8c	\xfbN\xa8\xcc\x9a\xc9\xa8^\x1fK\x9f,%\xb5\xaf\n\x8a\x89\x1d\xee\xe7Y\xfe(\xc1\xb2\xb4j\xcbT\x7f\xe9\xf0\xd9a\x1e\x11\xf9\xca\x1c\x99\xa7|\xafT\x1f\x03g9\xc488\xd4\x13ei\xa2/\xda\xe1K\xaf=\xb9s\xf7M3&\xd2\xee\xff\xaf&\x86\xfcf\x80\x7f\x03\x9b\x9c\xaf\xdc\xef\xf1\x109\xde\xdf6\xcd\xeeC\xd3\xec\xee\x9af\xf7\xb1i\xae;`<q\xe9~\xbf\x9e\x89\x16\xe5\x80\xec\xad\x93\x14\xd5\x8d\xbc\x95\x8d\xf2\x17\xf3\xf2\x90\xe2s\xa8c\xd2a@\xe9)\xc8\xc2\x86\xcb\x12\xb3I41X\xec1AN\xe6\xbd\xd0\xc2y\xccb\xdf\xaa\x8d\xb0\xafZ\xb5]\xa3\xf6\x10\xedy\xb5n\xe9\x08\xc6\xe9\x9c;\xe1\xad\xab\x9d>\xc7'\x86\x12>\xe6?O[X\xd7=\x9d\xd0\xd6\x85\x82i\x1d\x1e`\x9e\x19\xfd\xe44#\x88K\x01\xe4\xb2\xac\xb5\xd6k\no\x05\x1e\x1e.\xf7\xf2\x82xmd\xd2\x03\xd6\xd7\x06XWZ\x92\xd6R\x18\xee\xe1n:}\xfe\xfd\xdbk\xf52\xd5\x8b6@\xab,\x1d\xb7\xd6V\x15'\xeb\xc8[\xb2U\xdb\x0eZ\xb5\xbd\xb8y\xc6`\x97\xa5\xaa~\x05\x00\x00\xff\xffPK\x07\x08\xca\x11\x96\xf1\xd1\x01\x00\x00\x9d\x03\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00-:xN\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00	\x00gh/header.htmlUT\x05\x00\x01\x06/\x97\\\xc4S\xcd\x8e\xdb \x10\xbe\xfb)\xa6H\xbd\x95\x90\\zH\x88\xa5\x9e\xdaJ\xab\x1eV\xdds\x84\xcd\xd8f\x8b\xc128id\xf9\xdd+l\x12\xd3ms\xde\xdb0\xfa\xe6\xfb\x19\x0d\xe3(\xb1R\x06\x814($\xf6d\x9a\xb2\x8c/5\x94Z8w$\xad\xd4T\x8b\xab\x1d\xfc\xe9\x14Qy\x06\xc0\xa5:?\x86\xd0\xde^\x088\x7f\xd5x$\x9d\x90R\x99\x9aj\xac\xfc\x1ev\xdb\xee\xf7a\xa6\x00\xe0\x1f(\x85\x9f\xcak\x04Jc\xcbu\xc2\xfcKL}@\x91|\x1ca\xb3\x0cL\x13g\x01\x9b0}\x91\x12\\'J\xec?\x81\xb7 \xb4\xaa\x0d\x18qV\xb5\xf0\xca\x9a\xd0\xf3\x0dB\xaf\xea\xc6\xaf\x82\xff\x0dB\x17\x1e\x92s&\xd59\xd1\xf8q\xa7\xdb\xac\x14F\xfcE\xb1J\xc6\x9cq\xf6y\x16\x9em\xa1\x84\x16\xcd\x00\x05j{\x81b\xf0\xde\x9a;\x1f\x00\x8f\x1d%\x8fDbki\x00Sm/a\xb5\x81\x85D \xa4\xbaq(\x94\xaf.}-%\xa5\xaaL,\x01p\xd5\xd6\xe0\xfa\xf2H\xc2Z_\x1c\xf6\x9b\xef\xa55/\xcfO0M\x04\x1a\x0cJG\xb2\xdbn?\xaeA\xd8B\x96g\xb7\xc6\xa0S\x0fs\xaa[Aia\xbd\xb7\xed\xe2\xf9f\xec\x0eyu\xb4W]\xa7\x91bUa\x99\x84\xaal\xff(xb_\xab\xb7\xca\xa7\x93\xf2\xd8\xbe\xbd\xbc=l\x0f\xc9\x1c\x00\x177\x84T\xae\xd3\xe2\xba\x87B\xdb\xf2\xd7\x01\xd6	\xd8}\x0e\x87\nM\x8fU\xb2\xa0\xaf\xca\x7f\x1b\x8a\xb8\xa2|yq&\x12WL\xab\xf7\xf1\xc8\xea\xe6\xc4\xb4\xad\xed\xe0I\xfedk\xb0\x83\x7fh\x8d\xb3A\xc7\xebeF\xcc\x17\x1eO\x9d\xb3\xe5\x0f\xe7Y6\x8eh\xe44e\x7f\x02\x00\x00\xff\xffPK\x07\x08m{(\xef\xb2\x01\x00\x00(\x04\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00-:xN\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0c\x00	\x00gh/repo.htmlUT\x05\x00\x01\x06/\x97\\\x8cQ]o\x9b<\x14\xbe\xe7W\x1c\xf9}w\xe9\xd0U\xea\xd4\x11\xe8M\xd7M\xd5\xa4fJ\xa3\xed22\xf8\x00^\xc1\xf6\x8e\x0dI\x86\xf8\xef\x13\x01\xdatj\xa4\xc9\x17\xfe\xd0s\x9e/w\x9d\xc4\\i\x04\x96\x1ay`}\x1f\x04\xb1T-d\x95p.a\xb5\xacx&H\xc2pp\xa5\x90f\xc7\xf9\xa5\xb4\x0c\x9c?T\x98\xb0\x9d\x92\xbe\x8c\xe0\xc3\xc5\x85\xdd/\xa1\x16{>\xbd|\xbc~\xb7d7\x01\xc0[t\xdb\xadW\xbeB\x98\xef\x9c\xa7\x86$\xd2q\x00 ./\xcfLp\x8f{\xcfn\xd6w\xdf\xef\xef~|Z}\xd9nV_\xef\x1e\xe2\xb0\xbc<J\x85R\xb5\xe75]c\xad!\xaft1\xd1\x8cb\x96pN\x93\x1b\xed\xb9S\xbf1\x82\xf7\x8b+\xc2z	\xa9\xc8\x9e\n2\x8d\x96<3\x95\xa1\x08\xfe\xcb\xaf\x87\xb5\x04+\xa4T\xba\x88\xe0j\xccN\x85\xd2\xdc\x1b\x1b\xc1\xc5\x92\xdd\xb0\xae\x83\xc5\xc6<\xa1\x86\xbegqh	g\xc1q\x07xD\x0fJ\xc3\xc14\x04\xa8[EF\xd7\xa8=\xb4\x82\x94H+t\x13.>\xce\xfe\x0f\xb8\x1f\xfc\xc3_\xe9\x93\xd7J\xf3\xcc\x8b \xc0\x83\xf1\x18\xc1\x08\xd1\xc6\x03\xe1\xafF\x11JP\xf9\xa0\x0e\xd4h l\x15\xee\xa4)\x06K\x1b\x12\xadrp{\xbf\x08&\xb2\x7f\xe8Wd^\x19\xed\xce\xfejn\xa8\x86\x11\x94\xb0\xb0(\xc3\xc1\xf7\x1a\xadY\xacv\x1a	\xfa\xfe\xe5\xe5A\xd48\xa4\x81\x1a}id\xc2\xbe\xad\x1e7l\xce\x13+m\x1b\x0f\xfe`1a\xaeIk\xe5\xe7\xdc'\xae\xd2\xc6{\xa3\x8fv~\xba\xd3\xdbx\xe4\x9c\x84r(g\x00)k+\xe4\x98\xe7\x98\xf9W8\x91e\xa8\x9f\x15ZQ5\x98\xb05\x16\xa8\x91\x84\xc7\xb1\xd8\xb7\xcd\x95JJ\xd4\x0c\xb4\xa81a\x99\xa3|\xeb\x8f\xe8\x99fH|\xfb\xb8\xfe\xfc\xfc\x7fSY\xe1\xd0\xd6I\xe9\xd3\x16t\x1dj\xd9\xf7\xc1\x9f\x00\x00\x00\xff\xffPK\x07\x08E=r\x08\xe9\x01\x00\x00\xb9\x03\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00/:xN\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0b\x00	\x00gh/top.htmlUT\x05\x00\x01\n/\x97\\|\x93_k\xe38\x14\xc5\xdf\xfd)\x0e\xde\xb2mam/-\xdd\x07\xc71\x94n\xe9\x86\xedL\xa0\xd3\x99y,\xb2tc\x8b:\x92\x90\x94\x7fc\xfc\xdd\x07\xe7\x9f\x9dB\ny\xb8R\xee=\xf7w\x8e\x92\xa6\x114\x93\x8a\x10\x16Zl\xc2\xb6\x0d\x82\xac\xba\xcd'\xcayV\xd7$p\xcf\xb9^(\xef\xf0'\xa6\xb6tYR\xdd\xe6A\x90	\xb9\x84\xf3\x9b\x9a\xc6\xa1\x90\xce\xd4l\x93bV\xd3z\x14\xe6\x01\xd04\x96\xa9\x92p!w:\xccK\xad\x90\x8e\x11O\x06\x17\xaem\x03\x00\xd8\x8a\xf1\x9a97\x0e\xe7\xa2\x8e8\xb3\x02]\xe1*&\xf4*\x8an\x84	\xb7\x9d8\xec\\I\xe1\xab\x147w\xff\x98\xf5\x08\x15\xc9\xb2\xf2\xc7c\xc1\xf8{i\xf5B\x89\x14\x0b[_]6\xcd)I\xbc75\xe1Z}\x7fyF\xdb^^\x83\x93\xf2d\x91\x80\xeb%\xd9\x11\xe6\xcc\x96R\xa5\xb83{S\xe7P\xdf\xde\xbc\xf45\xe1p\x8e\"Z\x1b\xa6D\x98g\x89\x90\xcb\xcfG\x19\xdf&1\x18.\xb4\x15d\x0f~\x8f\x8e\x87\xa6lY\xb0\xab\xbf\xff\xc2\xfe\x13\xdf\\\x8fp\xfa\n(\xf4:r\xf2\x97Te\xba\x13\x8c\n\xbd\x1e\x81\xd5\xb2T\x91\xf44w\xe9\xdeqo\x0e\xc8\x18*K\xb3qx.\xb1\xff^\xbf<\xef\x12\x0b\x0f`\\\xd7\xda\xa6\xf8\x83\x88F\xf0\xb4\xf6\x91 \xae\xedv,\x85\xd2\x8aFa~N\x0fm\x9b%l\x00\xf0!\xa4\x9am\xf4\xc2G\xce0N\xf6C\xa0\x9f\xe1\x0e8\xfbv \x93Gq\xe6\xc9JVG\x92k\xe5\xc2\xdc\x91\xf7Ru\xbfo9\xd0\xef\xd1\x06\x9b\x8fe\xd3\x90\x12m\x1b\xec/2\xd3]>ix}B\x16\xdf\x1bs\x02di)i%t	f\x0c\xfa\xcd,\xefF\xf7>\x02\xe0\xb4\xcfkh_\x91\x05\xdb\xff#\xe3 K\xcc\xe9\xda\xca{\xe3\xd2$9N\xc6\xcc\x98\xa4\xac\x92F\xaf\x14\xd96i,\x19\xddv\xad%y\xbc<\xfe\x98<\xfe\xfcw\xfa\xf4\xf6:\xfd\xff\xf1k\x1c\x00Ya;\xb9\xa9\xed\xeb\x97\x85:\xa2p<<O0\xb3z\x8eW\xcb\x96\xd2\xe1a\x82\x95\xf4\x95^\x9c\x97\x1b`f\xc6R\x1e\\\x0c\xacE\\\xab\xd98\xee\x897\xf3\x1aQ\x87i=\xd9q)}\xb5(\"c#^\x11\x7f\xef$\x92\xad\x06\xf0\x8d\x08\xacv\x83\xb0\x0f\xf6wC1\xd7\xf3>\x89\xbe\n\xf3\xcf\xbf\xdf\xbe\xfa\x969\x08\x0eO\x1c\xfc\x0e\x00\x00\xff\xffPK\x07\x08U/\x11\xccf\x02\x00\x00(\x05\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00/:xN\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00	\x00index.htmlUT\x05\x00\x01\n/\x97\\\x84Q\xc1\n\x131\x10\xbd\xefW\x0c\xb9osh\xbd\xd4tA\xb0\xacE\xb1\xa0\xa2G\xc9&\xb3Id\x9b\x84d\xb6\xb5,\xfb\xef\xd2m]\xda\n\xf5\x96\xcc{o\xde\x9b\x99a\xd0\xd8:\x8f\xc0\x9a\xa0\xcfl\x1c\x8bBhw\x84L\xe7\x0e7,J\xad\x9d7kx\x13\x7f\xbfeU\x01 \xec\xb2Jxtx\xd2\xc1\x08n\x97U1UW\xd5\xceg\x92]'\xc9\x05/\xb8]]\x81x\x11\x01\xdc@\x98\xa4:\x18x\x17c\x866\x85\x03\x08	6a\xbba\x96(\xe65\xe7\xc6\x91\xed\x9b\x85\n\x07.c\xcc|\xb6c\xd5\x7f)\x82\xcb)%\x8fs\xae\x1a	\xbel\xbf\xef\xb6?\xde\xef\xeb\x9f\xdf\xf6\x1f\xb7\x9f\xff\x89W\x07\xa0\x00B\x05\x8d\xb3\xc7\xdcs!c\xe4\xc6\xf2!\x9c<\xa6\x91\x0f	c\x18\x05\x9f\xd8\x17\x9dA\x9a\xba<\xb9,\xa6\xa2h\xd2\xd5c\x9e\x93\x1b\xcb@u2\xe7\x0d;\xe8\xaelz\xa2\xe0\xe1\xf2\xfc\x95\xef\x7f\xd7gY&\xe92\xea\xbf\x84\xe4b\xec\xb0\xc4\xb6EE\x0f<\xa9\x14zb\xd5\xa7`\x9c\x87\x93#\x0b\xb5\xa3\x0f}\x03R\xa9\xd0{z\xde\xcem\xfa\xaf\x88 \xbb\x1c^\x9eb^\xc7\xfd=^\xe3\x0fv\x82kw\xac\x8ab\x18\xd0\xebq,\xfe\x04\x00\x00\xff\xffPK\x07\x08\xb2\xe8j{E\x01\x00\x00z\x02\x00\x00PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00Y\x94xN\xc1\x1e\x08\x9cJ\x01\x00\x00\x10\x02\x00\x00	\x00	\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb4\x81\x00\x00\x00\x00base.htmlUT\x05\x00\x01\xcb\xcd\x97\\PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00-:xN\xca\x11\x96\xf1\xd1\x01\x00\x00\x9d\x03\x00\x00\x0c\x00	\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb4\x81\x8a\x01\x00\x00gh/base.htmlUT\x05\x00\x01\x06/\x97\\PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00-:xNm{(\xef\xb2\x01\x00\x00(\x04\x00\x00\x0e\x00	\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb4\x81\x9e\x03\x00\x00gh/header.htmlUT\x05\x00\x01\x06/\x97\\PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00-:xNE=r\x08\xe9\x01\x00\x00\xb9\x03\x00\x00\x0c\x00	\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb4\x81\x95\x05\x00\x00gh/repo.htmlUT\x05\x00\x01\x06/\x97\\PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00/:xNU/\x11\xccf\x02\x00\x00(\x05\x00\x00\x0b\x00	\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb4\x81\xc1\x07\x00\x00gh/top.htmlUT\x05\x00\x01\n/\x97\\PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00/:xN\xb2\xe8j{E\x01\x00\x00z\x02\x00\x00\n\x00	\x00\x00\x00\x00\x00\x00\x00\x00\x00\xb4\x81i\n\x00\x00index.htmlUT\x05\x00\x01\n/\x97\\PK\x05\x06\x00\x00\x00\x00\x06\x00\x06\x00\x8e\x01\x00\x00\xef\x0b\x00\x00\x00\x00"
+	fs.Register(data)
+}
diff --git a/doghouse/appengine/template.go b/doghouse/appengine/template.go
new file mode 100644
index 00000000..1c13e5fd
--- /dev/null
+++ b/doghouse/appengine/template.go
@@ -0,0 +1,70 @@
+//go:generate statik -src=./tmpl
+package main
+
+import (
+	"html/template"
+	"log"
+	"net/http"
+
+	"github.com/rakyll/statik/fs"
+	_ "github.com/reviewdog/reviewdog/doghouse/appengine/statik"
+)
+
+var tmplFiles http.FileSystem
+
+func mustParseTemplatesFiles(filenames ...string) *template.Template {
+	t, err := parseTempaltesFiles(filenames...)
+	if err != nil {
+		log.Fatal(err)
+	}
+	return t
+}
+
+func parseTempaltesFiles(filenames ...string) (*template.Template, error) {
+	var t *template.Template
+	for _, filename := range filenames {
+		if t == nil {
+			t = template.New(filename)
+		}
+		text, err := fs.ReadFile(tmplFiles, filename)
+		if err != nil {
+			return nil, err
+		}
+		t, err = t.Parse(string(text))
+		if err != nil {
+			return nil, err
+		}
+	}
+	return t, nil
+}
+
+var (
+	topTmpl    *template.Template
+	ghTopTmpl  *template.Template
+	ghRepoTmpl *template.Template
+)
+
+func initTemplates() {
+	var err error
+	tmplFiles, err = fs.New()
+	if err != nil {
+		log.Fatal(err)
+	}
+
+	topTmpl = mustParseTemplatesFiles(
+		"/base.html",
+		"/index.html",
+	)
+
+	ghTopTmpl = mustParseTemplatesFiles(
+		"/gh/base.html",
+		"/gh/header.html",
+		"/gh/top.html",
+	)
+
+	ghRepoTmpl = mustParseTemplatesFiles(
+		"/gh/base.html",
+		"/gh/header.html",
+		"/gh/repo.html",
+	)
+}
diff --git a/doghouse/server/doghouse.go b/doghouse/server/doghouse.go
index 649d6106..3446b198 100644
--- a/doghouse/server/doghouse.go
+++ b/doghouse/server/doghouse.go
@@ -7,7 +7,7 @@ import (
 	"strings"
 	"time"
 
-	"github.com/google/go-github/github"
+	"github.com/google/go-github/v24/github"
 	"github.com/reviewdog/reviewdog"
 	"github.com/reviewdog/reviewdog/diff"
 	"github.com/reviewdog/reviewdog/doghouse"
diff --git a/doghouse/server/github.go b/doghouse/server/github.go
index 4b04f6f5..53e55917 100644
--- a/doghouse/server/github.go
+++ b/doghouse/server/github.go
@@ -7,7 +7,7 @@ import (
 	"net/http"
 
 	"github.com/bradleyfalzon/ghinstallation"
-	"github.com/google/go-github/github"
+	"github.com/google/go-github/v24/github"
 	"github.com/reviewdog/reviewdog/doghouse/server/storage"
 )
 
diff --git a/doghouse/server/github_checker.go b/doghouse/server/github_checker.go
index 7ad22503..6012a8ca 100644
--- a/doghouse/server/github_checker.go
+++ b/doghouse/server/github_checker.go
@@ -3,7 +3,7 @@ package server
 import (
 	"context"
 
-	"github.com/google/go-github/github"
+	"github.com/google/go-github/v24/github"
 )
 
 type checkerGitHubClientInterface interface {
diff --git a/go.mod b/go.mod
new file mode 100644
index 00000000..4cd75a96
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,22 @@
+module github.com/reviewdog/reviewdog
+
+go 1.12
+
+require (
+	github.com/bradleyfalzon/ghinstallation v0.1.2
+	github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
+	github.com/google/go-cmp v0.2.0
+	github.com/google/go-github/v24 v24.0.1
+	github.com/haya14busa/secretbox v0.0.0-20180525171038-07c7ecf409f5
+	github.com/justinas/nosurf v0.0.0-20190118163749-6453469bdcc9
+	github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348
+	github.com/mattn/go-shellwords v1.0.5
+	github.com/rakyll/statik v0.1.6
+	github.com/reviewdog/errorformat v0.0.0-20190324140416-e1294664b9b7
+	github.com/xanzy/go-gitlab v0.16.1
+	golang.org/x/net v0.0.0-20190322120337-addf6b3196f6
+	golang.org/x/oauth2 v0.0.0-20190319182350-c85d3e98c914
+	golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6
+	google.golang.org/appengine v1.5.0
+	gopkg.in/yaml.v2 v2.2.2
+)
diff --git a/go.sum b/go.sum
new file mode 100644
index 00000000..2deb97cd
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,66 @@
+cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+github.com/bradleyfalzon/ghinstallation v0.1.2 h1:9fdqVadlvEX/EUts5/aIGvx2ujKnGNIMcuCuUrM6s6Q=
+github.com/bradleyfalzon/ghinstallation v0.1.2/go.mod h1:VQsLlCoNa54/CNXcc2DuCfNZrZxqQcyPeqKUugF/2h8=
+github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
+github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
+github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
+github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
+github.com/google/go-github/v24 v24.0.1 h1:KCt1LjMJEey1qvPXxa9SjaWxwTsCWSq6p2Ju57UR4Q4=
+github.com/google/go-github/v24 v24.0.1/go.mod h1:CRqaW1Uns1TCkP0wqTpxYyRxRjxwvKU/XSS44u6X74M=
+github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
+github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
+github.com/haya14busa/secretbox v0.0.0-20180525171038-07c7ecf409f5 h1:ylgozezbuxA/i4uFtWCG/qGKYOZydsS8VUNNwfugn2Q=
+github.com/haya14busa/secretbox v0.0.0-20180525171038-07c7ecf409f5/go.mod h1:FGO/dXIFZnan7KvvUSFk1hYMnoVNzB6NTMPrmke8SSI=
+github.com/justinas/nosurf v0.0.0-20190118163749-6453469bdcc9 h1:gkVgl48ln8/fugpYy2jufQlEv5dYVPgQEMVJsw7j7t8=
+github.com/justinas/nosurf v0.0.0-20190118163749-6453469bdcc9/go.mod h1:Aucr5I5chr4OCuuVB4LTuHVrKHBuyRSo7vM2hqrcb7E=
+github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 h1:MtvEpTB6LX3vkb4ax0b5D2DHbNAUsen0Gx5wZoq3lV4=
+github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
+github.com/mattn/go-shellwords v1.0.5 h1:JhhFTIOslh5ZsPrpa3Wdg8bF0WI3b44EMblmU9wIsXc=
+github.com/mattn/go-shellwords v1.0.5/go.mod h1:3xCvwCdWdlDJUrvuMn7Wuy9eWs4pE8vqg+NOMyg4B2o=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/rakyll/statik v0.1.6 h1:uICcfUXpgqtw2VopbIncslhAmE5hwc4g20TEyEENBNs=
+github.com/rakyll/statik v0.1.6/go.mod h1:OEi9wJV/fMUAGx1eNjq75DKDsJVuEv1U0oYdX6GX8Zs=
+github.com/reviewdog/errorformat v0.0.0-20190324140416-e1294664b9b7 h1:ULSsf3u1yuXxjE6kbvl8lmI7C1Qctj3wU+OcI2rbX5o=
+github.com/reviewdog/errorformat v0.0.0-20190324140416-e1294664b9b7/go.mod h1:4luFKE7i+JWca3IkiS0pim24VEyZ4evpd2UXOuqqOhY=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/xanzy/go-gitlab v0.16.1 h1:kRHZ/wDsMkJHJvzfielqBTTrsbCtoxeEFrwiwtvVbZw=
+github.com/xanzy/go-gitlab v0.16.1/go.mod h1:LSfUQ9OPDnwRqulJk2HcWaAiFfCzaknyeGvjQI67MbE=
+golang.org/x/crypto v0.0.0-20180820150726-614d502a4dac/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181108082009-03003ca0c849/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190322120337-addf6b3196f6 h1:78jEq2G3J16aXneH23HSnTQQTCwMHoyO8VEiUH+bpPM=
+golang.org/x/net v0.0.0-20190322120337-addf6b3196f6/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.0.0-20190319182350-c85d3e98c914 h1:jIOcLT9BZzyJ9ce+IwwZ+aF9yeCqzrR+NrD68a/SHKw=
+golang.org/x/oauth2 v0.0.0-20190319182350-c85d3e98c914/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI=
+golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180824143301-4910a1d54f87/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a h1:1BGLXjeY4akVXGgbC9HugT3Jv3hCI0z56oJR5vAMgBU=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4c=
+google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
diff --git a/service/github/github.go b/service/github/github.go
index 29ae0423..0bc6eb23 100644
--- a/service/github/github.go
+++ b/service/github/github.go
@@ -6,7 +6,7 @@ import (
 	"path/filepath"
 	"sync"
 
-	"github.com/google/go-github/github"
+	"github.com/google/go-github/v24/github"
 	"github.com/reviewdog/reviewdog"
 	"github.com/reviewdog/reviewdog/service/serviceutil"
 )


Test patch:
diff --git a/doghouse/server/doghouse_test.go b/doghouse/server/doghouse_test.go
index 1b7ece52..8abee2ed 100644
--- a/doghouse/server/doghouse_test.go
+++ b/doghouse/server/doghouse_test.go
@@ -6,7 +6,7 @@ import (
 	"testing"
 
 	"github.com/google/go-cmp/cmp"
-	"github.com/google/go-github/github"
+	"github.com/google/go-github/v24/github"
 	"github.com/reviewdog/reviewdog/doghouse"
 )
 
diff --git a/service/github/github_test.go b/service/github/github_test.go
index 338c84fe..25ce551a 100644
--- a/service/github/github_test.go
+++ b/service/github/github_test.go
@@ -10,7 +10,7 @@ import (
 	"strings"
 	"testing"
 
-	"github.com/google/go-github/github"
+	"github.com/google/go-github/v24/github"
 	"github.com/kylelemons/godebug/pretty"
 	"github.com/reviewdog/reviewdog"
 	"github.com/reviewdog/reviewdog/service/serviceutil"