mirror of
https://github.com/adnanh/webhook.git
synced 2026-07-26 17:19:17 +08:00
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 86cef3e421 | |||
| 75cf8952be | |||
| c53596df59 | |||
| cc0d9b2cba | |||
| c6530b17e7 | |||
| 1943c5311f | |||
| 3b59539a33 | |||
| 923b0c6daa | |||
| 8530255ae6 | |||
| 032c74451f | |||
| 1c50853d8d | |||
| b5ed4cbea7 | |||
| b6d176705e | |||
| 421fc2cbcd | |||
| 10d65dd2fd | |||
| 54a9dbe1d6 | |||
| 30baec91df |
@@ -0,0 +1,29 @@
|
|||||||
|
OS = darwin freebsd linux openbsd windows
|
||||||
|
ARCHS = 386 arm amd64 arm64
|
||||||
|
|
||||||
|
all: build release
|
||||||
|
|
||||||
|
build: deps
|
||||||
|
go build
|
||||||
|
|
||||||
|
release: clean deps
|
||||||
|
@for arch in $(ARCHS);\
|
||||||
|
do \
|
||||||
|
for os in $(OS);\
|
||||||
|
do \
|
||||||
|
echo "Building $$os-$$arch"; \
|
||||||
|
mkdir -p build/webhook-$$os-$$arch/; \
|
||||||
|
GOOS=$$os GOARCH=$$arch go build -o build/webhook-$$os-$$arch/webhook; \
|
||||||
|
tar cz -C build -f build/webhook-$$os-$$arch.tar.gz webhook-$$os-$$arch; \
|
||||||
|
done \
|
||||||
|
done
|
||||||
|
|
||||||
|
test: deps
|
||||||
|
go test ./...
|
||||||
|
|
||||||
|
deps:
|
||||||
|
go get -d -v -t ./...
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf build
|
||||||
|
rm -f webhook
|
||||||
+2
-26
@@ -93,7 +93,7 @@ func CheckPayloadSignature(payload []byte, secret string, signature string) (str
|
|||||||
expectedMAC := hex.EncodeToString(mac.Sum(nil))
|
expectedMAC := hex.EncodeToString(mac.Sum(nil))
|
||||||
|
|
||||||
if !hmac.Equal([]byte(signature), []byte(expectedMAC)) {
|
if !hmac.Equal([]byte(signature), []byte(expectedMAC)) {
|
||||||
return expectedMAC, &SignatureError{expectedMAC}
|
return expectedMAC, &SignatureError{signature}
|
||||||
}
|
}
|
||||||
return expectedMAC, err
|
return expectedMAC, err
|
||||||
}
|
}
|
||||||
@@ -367,7 +367,7 @@ func (h *Hook) ExtractCommandArgumentsForEnv(headers, query, payload *map[string
|
|||||||
if arg, ok := h.PassEnvironmentToCommand[i].Get(headers, query, payload); ok {
|
if arg, ok := h.PassEnvironmentToCommand[i].Get(headers, query, payload); ok {
|
||||||
if h.PassEnvironmentToCommand[i].EnvName != "" {
|
if h.PassEnvironmentToCommand[i].EnvName != "" {
|
||||||
// first try to use the EnvName if specified
|
// first try to use the EnvName if specified
|
||||||
args = append(args, EnvNamespace+h.PassEnvironmentToCommand[i].EnvName+"="+arg)
|
args = append(args, h.PassEnvironmentToCommand[i].EnvName+"="+arg)
|
||||||
} else {
|
} else {
|
||||||
// then fallback on the name
|
// then fallback on the name
|
||||||
args = append(args, EnvNamespace+h.PassEnvironmentToCommand[i].Name+"="+arg)
|
args = append(args, EnvNamespace+h.PassEnvironmentToCommand[i].Name+"="+arg)
|
||||||
@@ -412,23 +412,6 @@ func (h *Hooks) Match(id string) *Hook {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// MatchAll iterates through Hooks and returns all of the hooks that match the
|
|
||||||
// given ID, if no hook matches the given ID, nil is returned
|
|
||||||
func (h *Hooks) MatchAll(id string) []*Hook {
|
|
||||||
var matchedHooks []*Hook
|
|
||||||
for i := range *h {
|
|
||||||
if (*h)[i].ID == id {
|
|
||||||
matchedHooks = append(matchedHooks, &(*h)[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(matchedHooks) > 0 {
|
|
||||||
return matchedHooks
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rules is a structure that contains one of the valid rule types
|
// Rules is a structure that contains one of the valid rule types
|
||||||
type Rules struct {
|
type Rules struct {
|
||||||
And *AndRule `json:"and,omitempty"`
|
And *AndRule `json:"and,omitempty"`
|
||||||
@@ -538,10 +521,3 @@ func (r MatchRule) Evaluate(headers, query, payload *map[string]interface{}, bod
|
|||||||
}
|
}
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CommandStatusResponse type encapsulates the executed command exit code, message, stdout and stderr
|
|
||||||
type CommandStatusResponse struct {
|
|
||||||
ResponseMessage string `json:"message,omitempty"`
|
|
||||||
Output string `json:"output,omitempty"`
|
|
||||||
Error string `json:"error,omitempty"`
|
|
||||||
}
|
|
||||||
|
|||||||
+6
-1
@@ -2,6 +2,7 @@ package hook
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -25,6 +26,10 @@ func TestCheckPayloadSignature(t *testing.T) {
|
|||||||
if (err == nil) != tt.ok || mac != tt.mac {
|
if (err == nil) != tt.ok || mac != tt.mac {
|
||||||
t.Errorf("failed to check payload signature {%q, %q, %q}:\nexpected {mac:%#v, ok:%#v},\ngot {mac:%#v, ok:%#v}", tt.payload, tt.secret, tt.signature, tt.mac, tt.ok, mac, (err == nil))
|
t.Errorf("failed to check payload signature {%q, %q, %q}:\nexpected {mac:%#v, ok:%#v},\ngot {mac:%#v, ok:%#v}", tt.payload, tt.secret, tt.signature, tt.mac, tt.ok, mac, (err == nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err != nil && strings.Contains(err.Error(), tt.mac) {
|
||||||
|
t.Errorf("error message should not disclose expected mac: %s", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,7 +179,7 @@ var hookExtractCommandArgumentsForEnvTests = []struct {
|
|||||||
"test",
|
"test",
|
||||||
[]Argument{Argument{"header", "a", "MYKEY"}},
|
[]Argument{Argument{"header", "a", "MYKEY"}},
|
||||||
&map[string]interface{}{"a": "z"}, nil, nil,
|
&map[string]interface{}{"a": "z"}, nil, nil,
|
||||||
[]string{"HOOK_MYKEY=z"},
|
[]string{"MYKEY=z"},
|
||||||
true,
|
true,
|
||||||
},
|
},
|
||||||
// failures
|
// failures
|
||||||
|
|||||||
@@ -57,7 +57,7 @@
|
|||||||
"id": "bitbucket",
|
"id": "bitbucket",
|
||||||
"execute-command": "{{ .Hookecho }}",
|
"execute-command": "{{ .Hookecho }}",
|
||||||
"command-working-directory": "/",
|
"command-working-directory": "/",
|
||||||
"include-command-output-in-response": true,
|
"include-command-output-in-response": false,
|
||||||
"response-message": "success",
|
"response-message": "success",
|
||||||
"parse-parameters-as-json": [
|
"parse-parameters-as-json": [
|
||||||
{
|
{
|
||||||
@@ -136,4 +136,3 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
+71
-68
@@ -21,11 +21,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
version = "2.3.9"
|
version = "2.5.0"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ip = flag.String("ip", "", "ip the webhook should serve hooks on")
|
ip = flag.String("ip", "0.0.0.0", "ip the webhook should serve hooks on")
|
||||||
port = flag.Int("port", 9000, "port the webhook should serve hooks on")
|
port = flag.Int("port", 9000, "port the webhook should serve hooks on")
|
||||||
verbose = flag.Bool("verbose", false, "show verbose output")
|
verbose = flag.Bool("verbose", false, "show verbose output")
|
||||||
noPanic = flag.Bool("nopanic", false, "do not panic if hooks cannot be loaded when webhook is not running in verbose mode")
|
noPanic = flag.Bool("nopanic", false, "do not panic if hooks cannot be loaded when webhook is not running in verbose mode")
|
||||||
@@ -76,10 +76,16 @@ func main() {
|
|||||||
|
|
||||||
log.Printf("couldn't load hooks from file! %+v\n", err)
|
log.Printf("couldn't load hooks from file! %+v\n", err)
|
||||||
} else {
|
} else {
|
||||||
log.Printf("loaded %d hook(s) from file\n", len(hooks))
|
seenHooksIds := make(map[string]bool)
|
||||||
|
|
||||||
|
log.Printf("found %d hook(s) in file\n", len(hooks))
|
||||||
|
|
||||||
for _, hook := range hooks {
|
for _, hook := range hooks {
|
||||||
log.Printf("\t> %s\n", hook.ID)
|
if seenHooksIds[hook.ID] == true {
|
||||||
|
log.Fatalf("error: hook with the id %s has already been loaded!\nplease check your hooks file for duplicate hooks ids!\n", hook.ID)
|
||||||
|
}
|
||||||
|
seenHooksIds[hook.ID] = true
|
||||||
|
log.Printf("\tloaded: %s\n", hook.ID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,10 +111,10 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
l := negroni.NewLogger()
|
l := negroni.NewLogger()
|
||||||
l.Logger = log.New(os.Stderr, "[webhook] ", log.Ldate|log.Ltime)
|
l.ALogger = log.New(os.Stderr, "[webhook] ", log.Ldate|log.Ltime)
|
||||||
|
|
||||||
negroniRecovery := &negroni.Recovery{
|
negroniRecovery := &negroni.Recovery{
|
||||||
Logger: l.Logger,
|
Logger: l.ALogger,
|
||||||
PrintStack: true,
|
PrintStack: true,
|
||||||
StackAll: false,
|
StackAll: false,
|
||||||
StackSize: 1024 * 8,
|
StackSize: 1024 * 8,
|
||||||
@@ -131,10 +137,10 @@ func main() {
|
|||||||
n.UseHandler(router)
|
n.UseHandler(router)
|
||||||
|
|
||||||
if *secure {
|
if *secure {
|
||||||
log.Printf("starting secure (https) webhook on %s:%d", *ip, *port)
|
log.Printf("serving hooks on https://%s:%d%s", *ip, *port, hooksURL)
|
||||||
log.Fatal(http.ListenAndServeTLS(fmt.Sprintf("%s:%d", *ip, *port), *cert, *key, n))
|
log.Fatal(http.ListenAndServeTLS(fmt.Sprintf("%s:%d", *ip, *port), *cert, *key, n))
|
||||||
} else {
|
} else {
|
||||||
log.Printf("starting insecure (http) webhook on %s:%d", *ip, *port)
|
log.Printf("serving hooks on http://%s:%d%s", *ip, *port, hooksURL)
|
||||||
log.Fatal(http.ListenAndServe(fmt.Sprintf("%s:%d", *ip, *port), n))
|
log.Fatal(http.ListenAndServe(fmt.Sprintf("%s:%d", *ip, *port), n))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,10 +153,8 @@ func hookHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
id := mux.Vars(r)["id"]
|
id := mux.Vars(r)["id"]
|
||||||
|
|
||||||
matchedHooks := hooks.MatchAll(id)
|
if matchedHook := hooks.Match(id); matchedHook != nil {
|
||||||
|
log.Printf("%s got matched\n", id)
|
||||||
if matchedHooks != nil {
|
|
||||||
log.Printf("%s got matched (%d time(s))\n", id, len(matchedHooks))
|
|
||||||
|
|
||||||
body, err := ioutil.ReadAll(r.Body)
|
body, err := ioutil.ReadAll(r.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -187,53 +191,55 @@ func hookHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle hook
|
// handle hook
|
||||||
for _, h := range matchedHooks {
|
if err = matchedHook.ParseJSONParameters(&headers, &query, &payload); err != nil {
|
||||||
|
msg := fmt.Sprintf("error parsing JSON parameters: %s", err)
|
||||||
|
log.Printf(msg)
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
fmt.Fprintf(w, "Unable to parse JSON parameters.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
err := h.ParseJSONParameters(&headers, &query, &payload)
|
var ok bool
|
||||||
|
|
||||||
|
if matchedHook.TriggerRule == nil {
|
||||||
|
ok = true
|
||||||
|
} else {
|
||||||
|
ok, err = matchedHook.TriggerRule.Evaluate(&headers, &query, &payload, &body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := fmt.Sprintf("error parsing JSON: %s", err)
|
msg := fmt.Sprintf("error evaluating hook: %s", err)
|
||||||
log.Printf(msg)
|
log.Printf(msg)
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
fmt.Fprintf(w, msg)
|
fmt.Fprintf(w, "Error occurred while evaluating hook rules.")
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var ok bool
|
|
||||||
|
|
||||||
if h.TriggerRule == nil {
|
|
||||||
ok = true
|
|
||||||
} else {
|
|
||||||
ok, err = h.TriggerRule.Evaluate(&headers, &query, &payload, &body)
|
|
||||||
if err != nil {
|
|
||||||
msg := fmt.Sprintf("error evaluating hook: %s", err)
|
|
||||||
log.Printf(msg)
|
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
|
||||||
fmt.Fprintf(w, msg)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ok {
|
|
||||||
log.Printf("%s hook triggered successfully\n", h.ID)
|
|
||||||
|
|
||||||
for _, responseHeader := range h.ResponseHeaders {
|
|
||||||
w.Header().Set(responseHeader.Name, responseHeader.Value)
|
|
||||||
}
|
|
||||||
|
|
||||||
if h.CaptureCommandOutput {
|
|
||||||
response := handleHook(h, &headers, &query, &payload, &body)
|
|
||||||
fmt.Fprintf(w, response)
|
|
||||||
} else {
|
|
||||||
go handleHook(h, &headers, &query, &payload, &body)
|
|
||||||
fmt.Fprintf(w, h.ResponseMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ok {
|
||||||
|
log.Printf("%s hook triggered successfully\n", matchedHook.ID)
|
||||||
|
|
||||||
|
for _, responseHeader := range matchedHook.ResponseHeaders {
|
||||||
|
w.Header().Set(responseHeader.Name, responseHeader.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
if matchedHook.CaptureCommandOutput {
|
||||||
|
response, err := handleHook(matchedHook, &headers, &query, &payload, &body)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
fmt.Fprintf(w, "Error occurred while executing the hook's command. Please check your logs for more details.")
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(w, response)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
go handleHook(matchedHook, &headers, &query, &payload, &body)
|
||||||
|
fmt.Fprintf(w, matchedHook.ResponseMessage)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// if none of the hooks got triggered
|
// if none of the hooks got triggered
|
||||||
log.Printf("%s got matched (%d time(s)), but didn't get triggered because the trigger rules were not satisfied\n", matchedHooks[0].ID, len(matchedHooks))
|
log.Printf("%s got matched, but didn't get triggered because the trigger rules were not satisfied\n", matchedHook.ID)
|
||||||
|
|
||||||
fmt.Fprintf(w, "Hook rules were not satisfied.")
|
fmt.Fprintf(w, "Hook rules were not satisfied.")
|
||||||
} else {
|
} else {
|
||||||
@@ -242,7 +248,7 @@ func hookHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleHook(h *hook.Hook, headers, query, payload *map[string]interface{}, body *[]byte) string {
|
func handleHook(h *hook.Hook, headers, query, payload *map[string]interface{}, body *[]byte) (string, error) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
cmd := exec.Command(h.ExecuteCommand)
|
cmd := exec.Command(h.ExecuteCommand)
|
||||||
@@ -262,28 +268,17 @@ func handleHook(h *hook.Hook, headers, query, payload *map[string]interface{}, b
|
|||||||
|
|
||||||
log.Printf("executing %s (%s) with arguments %q and environment %s using %s as cwd\n", h.ExecuteCommand, cmd.Path, cmd.Args, envs, cmd.Dir)
|
log.Printf("executing %s (%s) with arguments %q and environment %s using %s as cwd\n", h.ExecuteCommand, cmd.Path, cmd.Args, envs, cmd.Dir)
|
||||||
|
|
||||||
out, err := cmd.CombinedOutput()
|
out, err := cmd.Output()
|
||||||
|
|
||||||
log.Printf("command output: %s\n", out)
|
log.Printf("command output: %s\n", out)
|
||||||
|
|
||||||
var errorResponse string
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("error occurred: %+v\n", err)
|
log.Printf("error occurred: %+v\n", err)
|
||||||
errorResponse = fmt.Sprintf("%+v", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("finished handling %s\n", h.ID)
|
log.Printf("finished handling %s\n", h.ID)
|
||||||
|
|
||||||
var response []byte
|
return string(out), err
|
||||||
response, err = json.Marshal(&hook.CommandStatusResponse{ResponseMessage: h.ResponseMessage, Output: string(out), Error: errorResponse})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("error marshalling response: %+v", err)
|
|
||||||
return h.ResponseMessage
|
|
||||||
}
|
|
||||||
|
|
||||||
return string(response)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func reloadHooks() {
|
func reloadHooks() {
|
||||||
@@ -297,10 +292,18 @@ func reloadHooks() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("couldn't load hooks from file! %+v\n", err)
|
log.Printf("couldn't load hooks from file! %+v\n", err)
|
||||||
} else {
|
} else {
|
||||||
log.Printf("loaded %d hook(s) from file\n", len(hooks))
|
seenHooksIds := make(map[string]bool)
|
||||||
|
|
||||||
for _, hook := range hooks {
|
log.Printf("found %d hook(s) in file\n", len(newHooks))
|
||||||
log.Printf("\t> %s\n", hook.ID)
|
|
||||||
|
for _, hook := range newHooks {
|
||||||
|
if seenHooksIds[hook.ID] == true {
|
||||||
|
log.Printf("error: hook with the id %s has already been loaded!\nplease check your hooks file for duplicate hooks ids!", hook.ID)
|
||||||
|
log.Println("reverting hooks back to the previous configuration")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
seenHooksIds[hook.ID] = true
|
||||||
|
log.Printf("\tloaded: %s\n", hook.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
hooks = newHooks
|
hooks = newHooks
|
||||||
|
|||||||
+11
-5
@@ -372,7 +372,9 @@ var hookHandlerTests = []struct {
|
|||||||
}`,
|
}`,
|
||||||
false,
|
false,
|
||||||
http.StatusOK,
|
http.StatusOK,
|
||||||
`{"output":"arg: 1481a2de7b2a7d02428ad93446ab166be7793fbb lolwut@noway.biz\nenv: HOOK_head_commit.timestamp=2013-03-12T08:14:29-07:00\n"}`,
|
`arg: 1481a2de7b2a7d02428ad93446ab166be7793fbb lolwut@noway.biz
|
||||||
|
env: HOOK_head_commit.timestamp=2013-03-12T08:14:29-07:00
|
||||||
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"bitbucket", // bitbucket sends their payload using uriencoded params.
|
"bitbucket", // bitbucket sends their payload using uriencoded params.
|
||||||
@@ -381,7 +383,7 @@ var hookHandlerTests = []struct {
|
|||||||
`payload={"canon_url": "https://bitbucket.org","commits": [{"author": "marcus","branch": "master","files": [{"file": "somefile.py","type": "modified"}],"message": "Added some more things to somefile.py\n","node": "620ade18607a","parents": ["702c70160afc"],"raw_author": "Marcus Bertrand <marcus@somedomain.com>","raw_node": "620ade18607ac42d872b568bb92acaa9a28620e9","revision": null,"size": -1,"timestamp": "2012-05-30 05:58:56","utctimestamp": "2014-11-07 15:19:02+00:00"}],"repository": {"absolute_url": "/webhook/testing/","fork": false,"is_private": true,"name": "Project X","owner": "marcus","scm": "git","slug": "project-x","website": "https://atlassian.com/"},"user": "marcus"}`,
|
`payload={"canon_url": "https://bitbucket.org","commits": [{"author": "marcus","branch": "master","files": [{"file": "somefile.py","type": "modified"}],"message": "Added some more things to somefile.py\n","node": "620ade18607a","parents": ["702c70160afc"],"raw_author": "Marcus Bertrand <marcus@somedomain.com>","raw_node": "620ade18607ac42d872b568bb92acaa9a28620e9","revision": null,"size": -1,"timestamp": "2012-05-30 05:58:56","utctimestamp": "2014-11-07 15:19:02+00:00"}],"repository": {"absolute_url": "/webhook/testing/","fork": false,"is_private": true,"name": "Project X","owner": "marcus","scm": "git","slug": "project-x","website": "https://atlassian.com/"},"user": "marcus"}`,
|
||||||
true,
|
true,
|
||||||
http.StatusOK,
|
http.StatusOK,
|
||||||
`{"message":"success"}`,
|
`success`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"gitlab",
|
"gitlab",
|
||||||
@@ -431,7 +433,8 @@ var hookHandlerTests = []struct {
|
|||||||
}`,
|
}`,
|
||||||
false,
|
false,
|
||||||
http.StatusOK,
|
http.StatusOK,
|
||||||
`{"message":"success","output":"arg: b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327 John Smith john@example.com\n"}`,
|
`arg: b6568db1bc1dcd7f8b4d5a946b0b91f9dacd7327 John Smith john@example.com
|
||||||
|
`,
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -469,7 +472,9 @@ var hookHandlerTests = []struct {
|
|||||||
}`,
|
}`,
|
||||||
false,
|
false,
|
||||||
http.StatusOK,
|
http.StatusOK,
|
||||||
`{"output":"arg: 1481a2de7b2a7d02428ad93446ab166be7793fbb lolwut@noway.biz\nenv: HOOK_head_commit.timestamp=2013-03-12T08:14:29-07:00\n"}`,
|
`arg: 1481a2de7b2a7d02428ad93446ab166be7793fbb lolwut@noway.biz
|
||||||
|
env: HOOK_head_commit.timestamp=2013-03-12T08:14:29-07:00
|
||||||
|
`,
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -506,7 +511,8 @@ var hookHandlerTests = []struct {
|
|||||||
}`,
|
}`,
|
||||||
false,
|
false,
|
||||||
http.StatusOK,
|
http.StatusOK,
|
||||||
`{"output":"arg: 1481a2de7b2a7d02428ad93446ab166be7793fbb lolwut@noway.biz\n"}`,
|
`arg: 1481a2de7b2a7d02428ad93446ab166be7793fbb lolwut@noway.biz
|
||||||
|
`,
|
||||||
},
|
},
|
||||||
|
|
||||||
{"empty payload", "github", nil, `{}`, false, http.StatusOK, `Hook rules were not satisfied.`},
|
{"empty payload", "github", nil, `{}`, false, http.StatusOK, `Hook rules were not satisfied.`},
|
||||||
|
|||||||
Reference in New Issue
Block a user