mirror of
https://github.com/adnanh/webhook.git
synced 2025-05-15 10:04:44 +00:00
commit
86cef3e421
6 changed files with 56 additions and 33 deletions
29
Makefile
Normal file
29
Makefile
Normal file
|
@ -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
|
|
@ -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)
|
||||||
|
@ -521,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"`
|
|
||||||
}
|
|
||||||
|
|
|
@ -179,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 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
30
webhook.go
30
webhook.go
|
@ -21,7 +21,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
version = "2.4.0"
|
version = "2.5.0"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -222,8 +222,15 @@ func hookHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if matchedHook.CaptureCommandOutput {
|
if matchedHook.CaptureCommandOutput {
|
||||||
response := handleHook(matchedHook, &headers, &query, &payload, &body)
|
response, err := handleHook(matchedHook, &headers, &query, &payload, &body)
|
||||||
fmt.Fprintf(w, response)
|
|
||||||
|
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 {
|
} else {
|
||||||
go handleHook(matchedHook, &headers, &query, &payload, &body)
|
go handleHook(matchedHook, &headers, &query, &payload, &body)
|
||||||
fmt.Fprintf(w, matchedHook.ResponseMessage)
|
fmt.Fprintf(w, matchedHook.ResponseMessage)
|
||||||
|
@ -241,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)
|
||||||
|
@ -261,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() {
|
||||||
|
|
|
@ -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.`},
|
||||||
|
|
Loading…
Add table
Reference in a new issue