gitdeploy/internal/webhooks/github/github.go

116 lines
3.1 KiB
Go
Raw Normal View History

2020-09-28 23:39:05 +00:00
package github
2020-09-28 09:43:30 +00:00
import (
"fmt"
"io/ioutil"
"net/http"
"os"
2020-09-29 03:15:30 +00:00
"strings"
2020-09-28 09:43:30 +00:00
2020-12-01 00:48:09 +00:00
"git.rootprojects.org/root/gitdeploy/internal/log"
2020-10-09 09:22:06 +00:00
"git.rootprojects.org/root/gitdeploy/internal/options"
"git.rootprojects.org/root/gitdeploy/internal/webhooks"
2020-09-28 23:39:05 +00:00
2020-09-28 09:43:30 +00:00
"github.com/go-chi/chi"
2020-09-29 08:08:35 +00:00
// TODO nix this dependency in favor of a lightweight X-Hub-Signature
// and JSON-to-Go-struct approach
2021-02-22 22:48:33 +00:00
"github.com/google/go-github/v33/github"
2020-09-28 09:43:30 +00:00
)
func init() {
var githubSecrets string
2020-09-28 23:39:05 +00:00
options.ServerFlags.StringVar(
&githubSecrets, "github-secret", "",
2020-09-28 23:39:05 +00:00
"secret for github webhooks (same as GITHUB_SECRET=)",
)
webhooks.AddProvider("github", InitWebhook("github", &githubSecrets, "GITHUB_SECRET"))
2020-09-28 09:43:30 +00:00
}
func InitWebhook(providername string, secretList *string, envname string) func() {
2020-09-28 09:43:30 +00:00
return func() {
secrets := webhooks.ParseSecrets(providername, *secretList, envname)
if 0 == len(secrets) {
fmt.Fprintf(os.Stderr, "skipped route for missing %q\n", envname)
2020-09-28 09:43:30 +00:00
return
}
2020-09-28 23:39:05 +00:00
webhooks.AddRouteHandler(providername, func(router chi.Router) {
2020-09-28 09:43:30 +00:00
router.Post("/", func(w http.ResponseWriter, r *http.Request) {
2020-09-29 09:57:49 +00:00
r.Body = http.MaxBytesReader(w, r.Body, options.DefaultMaxBodySize)
2020-09-28 09:43:30 +00:00
payload, err := ioutil.ReadAll(r.Body)
if err != nil {
// if there's a read error, it should have been handled already by the MaxBytesReader
return
}
sig := r.Header.Get("X-Hub-Signature")
for _, secret := range secrets {
if err = github.ValidateSignature(sig, payload, secret); nil != err {
continue
}
// err = nil
break
}
if nil != err {
log.Printf("invalid %q signature: error: %s\n", providername, err)
http.Error(w, fmt.Sprintf("invalid %q signature", providername), http.StatusBadRequest)
2020-09-28 09:43:30 +00:00
return
}
hookType := github.WebHookType(r)
event, err := github.ParseWebHook(hookType, payload)
if err != nil {
log.Printf("invalid github webhook payload: error: %s\n", err)
http.Error(w, "invalid github webhook payload", http.StatusBadRequest)
return
}
switch e := event.(type) {
case *github.PushEvent:
2020-09-29 03:15:30 +00:00
var branch string
var tag string
2020-09-28 09:43:30 +00:00
ref := e.GetRef() // *e.Ref
2020-09-29 03:15:30 +00:00
parts := strings.Split(ref, "/")
refType := parts[1]
prefixLen := len("refs/") + len(refType) + len("/")
refName := ref[prefixLen:]
switch refType {
case "tags":
refType = "tag"
tag = refName
case "heads":
refType = "branch"
branch = refName
}
2020-09-28 23:39:05 +00:00
webhooks.Hook(webhooks.Ref{
2020-09-29 03:15:30 +00:00
HTTPSURL: e.GetRepo().GetCloneURL(),
SSHURL: e.GetRepo().GetSSHURL(),
Rev: e.GetAfter(), // *e.After
Ref: ref,
RefType: refType,
RefName: refName,
Branch: branch,
Tag: tag,
Repo: e.GetRepo().GetName(), // *e.Repo.Name
Owner: e.GetRepo().GetOwner().GetLogin(),
2020-09-28 23:39:05 +00:00
})
2020-09-28 09:43:30 +00:00
/*
case *github.PullRequestEvent:
// probably doesn't matter
case *github.StatusEvent:
// probably doesn't matter
case *github.WatchEvent:
// probably doesn't matter
*/
default:
log.Printf("unknown event type %s\n", hookType)
return
}
})
2020-09-28 23:39:05 +00:00
})
2020-09-28 09:43:30 +00:00
}
}