wip
This commit is contained in:
parent
d4dacd6f8e
commit
4f1089495d
@ -32,7 +32,7 @@ Hooks are defined as objects in the JSON or YAML hooks configuration file. Pleas
|
|||||||
* `query` - object with query parameters and their respective values
|
* `query` - object with query parameters and their respective values
|
||||||
* `headers` - object with headers and their respective values
|
* `headers` - object with headers and their respective values
|
||||||
* `base64EncodedBody` - base64 encoded request body
|
* `base64EncodedBody` - base64 encoded request body
|
||||||
* Output of this command __MUST__ be valid JSON string which will be parsed by the webhook and accessible using the `context` as source when referencing values.
|
* Output of this command __MUST__ be valid JSON string which will be parsed by the webhook and accessible using the `pre-hook` as source when referencing values.
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
Check out [Hook examples page](Hook-Examples.md) for more complex examples of hooks.
|
Check out [Hook examples page](Hook-Examples.md) for more complex examples of hooks.
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
# Referencing request values
|
# Referencing request values
|
||||||
There are four types of request values:
|
There are four types of request values:
|
||||||
|
|
||||||
1. Context values
|
1. Pre-hook values
|
||||||
These are the values provided by the `pre-hook-command` output.
|
These are the values provided by the `pre-hook-command` output.
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"source": "context",
|
"source": "pre-hook",
|
||||||
"name": "parameter-name"
|
"name": "parameter-name"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
13
hooks.json
Normal file
13
hooks.json
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "test",
|
||||||
|
"pre-hook-command": "/home/adnan/test.sh",
|
||||||
|
"execute-command": "/bin/echo",
|
||||||
|
"pass-arguments-to-command": [
|
||||||
|
{
|
||||||
|
"source": "payload",
|
||||||
|
"name": "root"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
@ -35,7 +35,7 @@ const (
|
|||||||
SourceQuery string = "url"
|
SourceQuery string = "url"
|
||||||
SourceQueryAlias string = "query"
|
SourceQueryAlias string = "query"
|
||||||
SourcePayload string = "payload"
|
SourcePayload string = "payload"
|
||||||
SourceContext string = "context"
|
SourcePreHook string = "pre-hook"
|
||||||
SourceString string = "string"
|
SourceString string = "string"
|
||||||
SourceEntirePayload string = "entire-payload"
|
SourceEntirePayload string = "entire-payload"
|
||||||
SourceEntireQuery string = "entire-query"
|
SourceEntireQuery string = "entire-query"
|
||||||
@ -443,8 +443,8 @@ func (ha *Argument) Get(r *Request) (string, error) {
|
|||||||
source = &r.Query
|
source = &r.Query
|
||||||
case SourcePayload:
|
case SourcePayload:
|
||||||
source = &r.Payload
|
source = &r.Payload
|
||||||
case SourceContext:
|
case SourcePreHook:
|
||||||
source = &r.Context
|
source = &r.PreHook
|
||||||
case SourceString:
|
case SourceString:
|
||||||
return ha.Name, nil
|
return ha.Name, nil
|
||||||
case SourceEntirePayload:
|
case SourceEntirePayload:
|
||||||
@ -591,8 +591,8 @@ func (h *Hook) ParseJSONParameters(r *Request) []error {
|
|||||||
source = &r.Headers
|
source = &r.Headers
|
||||||
case SourcePayload:
|
case SourcePayload:
|
||||||
source = &r.Payload
|
source = &r.Payload
|
||||||
case SourceContext:
|
case SourcePreHook:
|
||||||
source = &r.Context
|
source = &r.PreHook
|
||||||
case SourceQuery, SourceQueryAlias:
|
case SourceQuery, SourceQueryAlias:
|
||||||
source = &r.Query
|
source = &r.Query
|
||||||
}
|
}
|
||||||
|
@ -254,21 +254,21 @@ func TestExtractParameter(t *testing.T) {
|
|||||||
|
|
||||||
var argumentGetTests = []struct {
|
var argumentGetTests = []struct {
|
||||||
source, name string
|
source, name string
|
||||||
headers, query, payload, context map[string]interface{}
|
headers, query, payload, prehook map[string]interface{}
|
||||||
value string
|
value string
|
||||||
ok bool
|
ok bool
|
||||||
}{
|
}{
|
||||||
{"header", "a", map[string]interface{}{"A": "z"}, nil, nil, nil, "z", true},
|
{"header", "a", map[string]interface{}{"A": "z"}, nil, nil, nil, "z", true},
|
||||||
{"url", "a", nil, map[string]interface{}{"a": "z"}, nil, nil, "z", true},
|
{"url", "a", nil, map[string]interface{}{"a": "z"}, nil, nil, "z", true},
|
||||||
{"payload", "a", nil, nil, map[string]interface{}{"a": "z"}, nil, "z", true},
|
{"payload", "a", nil, nil, map[string]interface{}{"a": "z"}, nil, "z", true},
|
||||||
{"context", "a", nil, nil, nil, map[string]interface{}{"a": "z"}, "z", true},
|
{"prehook", "a", nil, nil, nil, map[string]interface{}{"a": "z"}, "z", true},
|
||||||
{"string", "a", nil, nil, nil, nil, "a", true},
|
{"string", "a", nil, nil, nil, nil, "a", true},
|
||||||
// failures
|
// failures
|
||||||
{"header", "a", nil, map[string]interface{}{"a": "z"}, map[string]interface{}{"a": "z"}, nil, "", false}, // nil headers
|
{"header", "a", nil, map[string]interface{}{"a": "z"}, map[string]interface{}{"a": "z"}, nil, "", false}, // nil headers
|
||||||
{"url", "a", map[string]interface{}{"A": "z"}, nil, map[string]interface{}{"a": "z"}, nil, "", false}, // nil query
|
{"url", "a", map[string]interface{}{"A": "z"}, nil, map[string]interface{}{"a": "z"}, nil, "", false}, // nil query
|
||||||
{"payload", "a", map[string]interface{}{"A": "z"}, map[string]interface{}{"a": "z"}, nil, nil, "", false}, // nil payload
|
{"payload", "a", map[string]interface{}{"A": "z"}, map[string]interface{}{"a": "z"}, nil, nil, "", false}, // nil payload
|
||||||
{"context", "a", nil, nil, nil, nil, "", false}, // nil context
|
{"prehook", "a", nil, nil, nil, nil, "", false}, // nil prehook
|
||||||
{"foo", "a", map[string]interface{}{"A": "z"}, nil, nil, nil, "", false}, // invalid source
|
{"foo", "a", map[string]interface{}{"A": "z"}, nil, nil, nil, "", false}, // invalid source
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestArgumentGet(t *testing.T) {
|
func TestArgumentGet(t *testing.T) {
|
||||||
@ -278,7 +278,7 @@ func TestArgumentGet(t *testing.T) {
|
|||||||
Headers: tt.headers,
|
Headers: tt.headers,
|
||||||
Query: tt.query,
|
Query: tt.query,
|
||||||
Payload: tt.payload,
|
Payload: tt.payload,
|
||||||
Context: tt.context,
|
PreHook: tt.prehook,
|
||||||
}
|
}
|
||||||
value, err := a.Get(r)
|
value, err := a.Get(r)
|
||||||
if (err == nil) != tt.ok || value != tt.value {
|
if (err == nil) != tt.ok || value != tt.value {
|
||||||
@ -289,14 +289,14 @@ func TestArgumentGet(t *testing.T) {
|
|||||||
|
|
||||||
var hookParseJSONParametersTests = []struct {
|
var hookParseJSONParametersTests = []struct {
|
||||||
params []Argument
|
params []Argument
|
||||||
headers, query, payload, context map[string]interface{}
|
headers, query, payload, prehook map[string]interface{}
|
||||||
rheaders, rquery, rpayload, rcontext map[string]interface{}
|
rheaders, rquery, rpayload, rprehook map[string]interface{}
|
||||||
ok bool
|
ok bool
|
||||||
}{
|
}{
|
||||||
{[]Argument{Argument{"header", "a", "", false}}, map[string]interface{}{"A": `{"b": "y"}`}, nil, nil, nil, map[string]interface{}{"A": map[string]interface{}{"b": "y"}}, nil, nil, nil, true},
|
{[]Argument{Argument{"header", "a", "", false}}, map[string]interface{}{"A": `{"b": "y"}`}, nil, nil, nil, map[string]interface{}{"A": map[string]interface{}{"b": "y"}}, nil, nil, nil, true},
|
||||||
{[]Argument{Argument{"url", "a", "", false}}, nil, map[string]interface{}{"a": `{"b": "y"}`}, nil, nil, nil, map[string]interface{}{"a": map[string]interface{}{"b": "y"}}, nil, nil, true},
|
{[]Argument{Argument{"url", "a", "", false}}, nil, map[string]interface{}{"a": `{"b": "y"}`}, nil, nil, nil, map[string]interface{}{"a": map[string]interface{}{"b": "y"}}, nil, nil, true},
|
||||||
{[]Argument{Argument{"payload", "a", "", false}}, nil, nil, map[string]interface{}{"a": `{"b": "y"}`}, nil, nil, nil, map[string]interface{}{"a": map[string]interface{}{"b": "y"}}, nil, true},
|
{[]Argument{Argument{"payload", "a", "", false}}, nil, nil, map[string]interface{}{"a": `{"b": "y"}`}, nil, nil, nil, map[string]interface{}{"a": map[string]interface{}{"b": "y"}}, nil, true},
|
||||||
{[]Argument{Argument{"context", "a", "", false}}, nil, nil, nil, map[string]interface{}{"a": `{"b": "y"}`}, nil, nil, nil, map[string]interface{}{"a": map[string]interface{}{"b": "y"}}, true},
|
{[]Argument{Argument{"prehook", "a", "", false}}, nil, nil, nil, map[string]interface{}{"a": `{"b": "y"}`}, nil, nil, nil, map[string]interface{}{"a": map[string]interface{}{"b": "y"}}, true},
|
||||||
{[]Argument{Argument{"header", "z", "", false}}, map[string]interface{}{"Z": `{}`}, nil, nil, nil, map[string]interface{}{"Z": map[string]interface{}{}}, nil, nil, nil, true},
|
{[]Argument{Argument{"header", "z", "", false}}, map[string]interface{}{"Z": `{}`}, nil, nil, nil, map[string]interface{}{"Z": map[string]interface{}{}}, nil, nil, nil, true},
|
||||||
// failures
|
// failures
|
||||||
{[]Argument{Argument{"header", "z", "", false}}, map[string]interface{}{"Z": ``}, nil, nil, nil, map[string]interface{}{"Z": ``}, nil, nil, nil, false}, // empty string
|
{[]Argument{Argument{"header", "z", "", false}}, map[string]interface{}{"Z": ``}, nil, nil, nil, map[string]interface{}{"Z": ``}, nil, nil, nil, false}, // empty string
|
||||||
@ -311,7 +311,7 @@ func TestHookParseJSONParameters(t *testing.T) {
|
|||||||
Headers: tt.headers,
|
Headers: tt.headers,
|
||||||
Query: tt.query,
|
Query: tt.query,
|
||||||
Payload: tt.payload,
|
Payload: tt.payload,
|
||||||
Context: tt.context,
|
PreHook: tt.prehook,
|
||||||
}
|
}
|
||||||
err := h.ParseJSONParameters(r)
|
err := h.ParseJSONParameters(r)
|
||||||
if (err == nil) != tt.ok || !reflect.DeepEqual(tt.headers, tt.rheaders) {
|
if (err == nil) != tt.ok || !reflect.DeepEqual(tt.headers, tt.rheaders) {
|
||||||
@ -323,7 +323,7 @@ func TestHookParseJSONParameters(t *testing.T) {
|
|||||||
var hookExtractCommandArgumentsTests = []struct {
|
var hookExtractCommandArgumentsTests = []struct {
|
||||||
exec string
|
exec string
|
||||||
args []Argument
|
args []Argument
|
||||||
headers, query, payload, context map[string]interface{}
|
headers, query, payload, prehook map[string]interface{}
|
||||||
value []string
|
value []string
|
||||||
ok bool
|
ok bool
|
||||||
}{
|
}{
|
||||||
@ -339,7 +339,7 @@ func TestHookExtractCommandArguments(t *testing.T) {
|
|||||||
Headers: tt.headers,
|
Headers: tt.headers,
|
||||||
Query: tt.query,
|
Query: tt.query,
|
||||||
Payload: tt.payload,
|
Payload: tt.payload,
|
||||||
Context: tt.context,
|
PreHook: tt.prehook,
|
||||||
}
|
}
|
||||||
value, err := h.ExtractCommandArguments(r)
|
value, err := h.ExtractCommandArguments(r)
|
||||||
if (err == nil) != tt.ok || !reflect.DeepEqual(value, tt.value) {
|
if (err == nil) != tt.ok || !reflect.DeepEqual(value, tt.value) {
|
||||||
@ -370,7 +370,7 @@ func TestHookExtractCommandArguments(t *testing.T) {
|
|||||||
var hookExtractCommandArgumentsForEnvTests = []struct {
|
var hookExtractCommandArgumentsForEnvTests = []struct {
|
||||||
exec string
|
exec string
|
||||||
args []Argument
|
args []Argument
|
||||||
headers, query, payload, context map[string]interface{}
|
headers, query, payload, prehook map[string]interface{}
|
||||||
value []string
|
value []string
|
||||||
ok bool
|
ok bool
|
||||||
}{
|
}{
|
||||||
@ -406,7 +406,7 @@ func TestHookExtractCommandArgumentsForEnv(t *testing.T) {
|
|||||||
Headers: tt.headers,
|
Headers: tt.headers,
|
||||||
Query: tt.query,
|
Query: tt.query,
|
||||||
Payload: tt.payload,
|
Payload: tt.payload,
|
||||||
Context: tt.context,
|
PreHook: tt.prehook,
|
||||||
}
|
}
|
||||||
value, err := h.ExtractCommandArgumentsForEnv(r)
|
value, err := h.ExtractCommandArgumentsForEnv(r)
|
||||||
if (err == nil) != tt.ok || !reflect.DeepEqual(value, tt.value) {
|
if (err == nil) != tt.ok || !reflect.DeepEqual(value, tt.value) {
|
||||||
@ -486,7 +486,7 @@ func TestHooksMatch(t *testing.T) {
|
|||||||
var matchRuleTests = []struct {
|
var matchRuleTests = []struct {
|
||||||
typ, regex, secret, value, ipRange string
|
typ, regex, secret, value, ipRange string
|
||||||
param Argument
|
param Argument
|
||||||
headers, query, payload, context map[string]interface{}
|
headers, query, payload, prehook map[string]interface{}
|
||||||
body []byte
|
body []byte
|
||||||
remoteAddr string
|
remoteAddr string
|
||||||
ok bool
|
ok bool
|
||||||
@ -533,7 +533,7 @@ func TestMatchRule(t *testing.T) {
|
|||||||
Headers: tt.headers,
|
Headers: tt.headers,
|
||||||
Query: tt.query,
|
Query: tt.query,
|
||||||
Payload: tt.payload,
|
Payload: tt.payload,
|
||||||
Context: tt.context,
|
PreHook: tt.prehook,
|
||||||
Body: tt.body,
|
Body: tt.body,
|
||||||
RawRequest: &http.Request{
|
RawRequest: &http.Request{
|
||||||
RemoteAddr: tt.remoteAddr,
|
RemoteAddr: tt.remoteAddr,
|
||||||
@ -549,7 +549,7 @@ func TestMatchRule(t *testing.T) {
|
|||||||
var andRuleTests = []struct {
|
var andRuleTests = []struct {
|
||||||
desc string // description of the test case
|
desc string // description of the test case
|
||||||
rule AndRule
|
rule AndRule
|
||||||
headers, query, payload, context map[string]interface{}
|
headers, query, payload, prehook map[string]interface{}
|
||||||
body []byte
|
body []byte
|
||||||
ok bool
|
ok bool
|
||||||
err bool
|
err bool
|
||||||
@ -614,7 +614,7 @@ func TestAndRule(t *testing.T) {
|
|||||||
Headers: tt.headers,
|
Headers: tt.headers,
|
||||||
Query: tt.query,
|
Query: tt.query,
|
||||||
Payload: tt.payload,
|
Payload: tt.payload,
|
||||||
Context: tt.context,
|
PreHook: tt.prehook,
|
||||||
Body: tt.body,
|
Body: tt.body,
|
||||||
}
|
}
|
||||||
ok, err := tt.rule.Evaluate(r)
|
ok, err := tt.rule.Evaluate(r)
|
||||||
@ -627,7 +627,7 @@ func TestAndRule(t *testing.T) {
|
|||||||
var orRuleTests = []struct {
|
var orRuleTests = []struct {
|
||||||
desc string // description of the test case
|
desc string // description of the test case
|
||||||
rule OrRule
|
rule OrRule
|
||||||
headers, query, payload, context map[string]interface{}
|
headers, query, payload, prehook map[string]interface{}
|
||||||
body []byte
|
body []byte
|
||||||
ok bool
|
ok bool
|
||||||
err bool
|
err bool
|
||||||
@ -676,7 +676,7 @@ func TestOrRule(t *testing.T) {
|
|||||||
Headers: tt.headers,
|
Headers: tt.headers,
|
||||||
Query: tt.query,
|
Query: tt.query,
|
||||||
Payload: tt.payload,
|
Payload: tt.payload,
|
||||||
Context: tt.context,
|
PreHook: tt.prehook,
|
||||||
Body: tt.body,
|
Body: tt.body,
|
||||||
}
|
}
|
||||||
ok, err := tt.rule.Evaluate(r)
|
ok, err := tt.rule.Evaluate(r)
|
||||||
@ -689,7 +689,7 @@ func TestOrRule(t *testing.T) {
|
|||||||
var notRuleTests = []struct {
|
var notRuleTests = []struct {
|
||||||
desc string // description of the test case
|
desc string // description of the test case
|
||||||
rule NotRule
|
rule NotRule
|
||||||
headers, query, payload, context map[string]interface{}
|
headers, query, payload, prehook map[string]interface{}
|
||||||
body []byte
|
body []byte
|
||||||
ok bool
|
ok bool
|
||||||
err bool
|
err bool
|
||||||
@ -704,7 +704,7 @@ func TestNotRule(t *testing.T) {
|
|||||||
Headers: tt.headers,
|
Headers: tt.headers,
|
||||||
Query: tt.query,
|
Query: tt.query,
|
||||||
Payload: tt.payload,
|
Payload: tt.payload,
|
||||||
Context: tt.context,
|
PreHook: tt.prehook,
|
||||||
Body: tt.body,
|
Body: tt.body,
|
||||||
}
|
}
|
||||||
ok, err := tt.rule.Evaluate(r)
|
ok, err := tt.rule.Evaluate(r)
|
||||||
|
@ -31,8 +31,8 @@ type Request struct {
|
|||||||
// Payload is a map of the parsed payload.
|
// Payload is a map of the parsed payload.
|
||||||
Payload map[string]interface{}
|
Payload map[string]interface{}
|
||||||
|
|
||||||
// Context is a map of the parsed pre-hook command result
|
// PreHook is a map of the parsed pre-hook command result
|
||||||
Context map[string]interface{}
|
PreHook map[string]interface{}
|
||||||
|
|
||||||
// The underlying HTTP request.
|
// The underlying HTTP request.
|
||||||
RawRequest *http.Request
|
RawRequest *http.Request
|
||||||
|
121
webhook.go
121
webhook.go
@ -473,14 +473,14 @@ func hookHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
if matchedHook.PreHookCommand != "" {
|
if matchedHook.PreHookCommand != "" {
|
||||||
// check the command exists
|
// check the command exists
|
||||||
var lookpath string
|
var searchPath string
|
||||||
if filepath.IsAbs(matchedHook.PreHookCommand) || matchedHook.CommandWorkingDirectory == "" {
|
if filepath.IsAbs(matchedHook.PreHookCommand) || matchedHook.CommandWorkingDirectory == "" {
|
||||||
lookpath = matchedHook.PreHookCommand
|
searchPath = matchedHook.PreHookCommand
|
||||||
} else {
|
} else {
|
||||||
lookpath = filepath.Join(matchedHook.CommandWorkingDirectory, matchedHook.PreHookCommand)
|
searchPath = filepath.Join(matchedHook.CommandWorkingDirectory, matchedHook.PreHookCommand)
|
||||||
}
|
}
|
||||||
|
|
||||||
preHookCommandPath, err := exec.LookPath(lookpath)
|
preHookCommandPath, err := exec.LookPath(searchPath)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("[%s] unable to locate pre-hook command: '%s', %+v\n", req.ID, matchedHook.PreHookCommand, err)
|
log.Printf("[%s] unable to locate pre-hook command: '%s', %+v\n", req.ID, matchedHook.PreHookCommand, err)
|
||||||
@ -489,48 +489,85 @@ func hookHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
s := strings.Fields(matchedHook.PreHookCommand)[0]
|
s := strings.Fields(matchedHook.PreHookCommand)[0]
|
||||||
log.Printf("[%s] please use a wrapper script to provide arguments to pre-hook command for '%s'\n", req.ID, s)
|
log.Printf("[%s] please use a wrapper script to provide arguments to pre-hook command for '%s'\n", req.ID, s)
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
preHookCommandStdin := hook.PreHookContext{
|
|
||||||
HookID: matchedHook.ID,
|
|
||||||
Method: r.Method,
|
|
||||||
Base64EncodedBody: base64.StdEncoding.EncodeToString(req.Body),
|
|
||||||
RemoteAddr: r.RemoteAddr,
|
|
||||||
URI: r.RequestURI,
|
|
||||||
Host: r.Host,
|
|
||||||
Headers: r.Header,
|
|
||||||
Query: r.URL.Query(),
|
|
||||||
}
|
|
||||||
|
|
||||||
if preHookCommandStdinJSONString, err := json.Marshal(preHookCommandStdin); err != nil {
|
writeHttpResponseCode(w, req.ID, matchedHook.ID, http.StatusInternalServerError)
|
||||||
log.Printf("[%s] unable to encode pre-hook context as JSON string for the pre-hook command: %+v\n", req.ID, err)
|
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
||||||
} else {
|
fmt.Fprint(w, "Error occurred while executing the hook's pre-hook command. Please check your logs for more details.")
|
||||||
preHookCommand := exec.Command(preHookCommandPath)
|
return
|
||||||
preHookCommand.Dir = matchedHook.CommandWorkingDirectory
|
}
|
||||||
preHookCommand.Env = append(os.Environ())
|
|
||||||
|
|
||||||
if preHookCommandStdinPipe, err := preHookCommand.StdinPipe(); err != nil {
|
preHookCommandStdin := hook.PreHookContext{
|
||||||
log.Printf("[%s] unable to acquire stdin pipe for the pre-hook command: %+v\n", req.ID, err)
|
HookID: matchedHook.ID,
|
||||||
} else {
|
Method: r.Method,
|
||||||
_, err := io.WriteString(preHookCommandStdinPipe, string(preHookCommandStdinJSONString))
|
Base64EncodedBody: base64.StdEncoding.EncodeToString(req.Body),
|
||||||
preHookCommandStdinPipe.Close()
|
RemoteAddr: r.RemoteAddr,
|
||||||
if err != nil {
|
URI: r.RequestURI,
|
||||||
log.Printf("[%s] unable to write to pre-hook command stdin: %+v\n", req.ID, err)
|
Host: r.Host,
|
||||||
} else {
|
Headers: r.Header,
|
||||||
log.Printf("[%s] executing pre-hook command %s (%s) using %s as cwd\n", req.ID, matchedHook.PreHookCommand, preHookCommand.Path, preHookCommand.Dir)
|
Query: r.URL.Query(),
|
||||||
|
}
|
||||||
|
|
||||||
if preHookCommandOutput, err := preHookCommand.CombinedOutput(); err != nil {
|
preHookCommandStdinJSONString, err := json.Marshal(preHookCommandStdin)
|
||||||
log.Printf("[%s] unable to execute pre-hook command: %+v\n", req.ID, err)
|
|
||||||
} else {
|
|
||||||
JSONDecoder := json.NewDecoder(strings.NewReader(string(preHookCommandOutput)))
|
|
||||||
JSONDecoder.UseNumber()
|
|
||||||
|
|
||||||
if err := JSONDecoder.Decode(&req.Context); err != nil {
|
if err != nil {
|
||||||
log.Printf("[%s] unable to parse pre-hook command output: %+v\npre-hook command output was: %+v\n", req.ID, err, string(preHookCommandOutput))
|
log.Printf("[%s] unable to encode pre-hook context as JSON string for the pre-hook command: %+v\n", req.ID, err)
|
||||||
}
|
|
||||||
}
|
writeHttpResponseCode(w, req.ID, matchedHook.ID, http.StatusInternalServerError)
|
||||||
}
|
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
||||||
}
|
fmt.Fprint(w, "Error occurred while executing the hook's pre-hook command. Please check your logs for more details.")
|
||||||
}
|
return
|
||||||
|
}
|
||||||
|
preHookCommand := exec.Command(preHookCommandPath)
|
||||||
|
preHookCommand.Dir = matchedHook.CommandWorkingDirectory
|
||||||
|
preHookCommand.Env = append(os.Environ())
|
||||||
|
|
||||||
|
preHookCommandStdinPipe, err := preHookCommand.StdinPipe()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[%s] unable to acquire stdin pipe for the pre-hook command: %+v\n", req.ID, err)
|
||||||
|
|
||||||
|
writeHttpResponseCode(w, req.ID, matchedHook.ID, http.StatusInternalServerError)
|
||||||
|
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
||||||
|
fmt.Fprint(w, "Error occurred while executing the hook's pre-hook command. Please check your logs for more details.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = io.WriteString(preHookCommandStdinPipe, string(preHookCommandStdinJSONString))
|
||||||
|
|
||||||
|
preHookCommandStdinPipe.Close()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[%s] unable to write to pre-hook command stdin: %+v\n", req.ID, err)
|
||||||
|
|
||||||
|
writeHttpResponseCode(w, req.ID, matchedHook.ID, http.StatusInternalServerError)
|
||||||
|
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
||||||
|
fmt.Fprint(w, "Error occurred while executing the hook's pre-hook command. Please check your logs for more details.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("[%s] executing pre-hook command %s (%s) using %s as cwd\n", req.ID, matchedHook.PreHookCommand, preHookCommand.Path, preHookCommand.Dir)
|
||||||
|
|
||||||
|
preHookCommandOutput, err := preHookCommand.CombinedOutput()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("[%s] unable to execute pre-hook command: %+v\n", req.ID, err)
|
||||||
|
|
||||||
|
writeHttpResponseCode(w, req.ID, matchedHook.ID, http.StatusInternalServerError)
|
||||||
|
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
||||||
|
fmt.Fprint(w, "Error occurred while executing the hook's pre-hook command. Please check your logs for more details.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONDecoder := json.NewDecoder(strings.NewReader(string(preHookCommandOutput)))
|
||||||
|
JSONDecoder.UseNumber()
|
||||||
|
|
||||||
|
if err := JSONDecoder.Decode(&req.PreHook); err != nil {
|
||||||
|
log.Printf("[%s] unable to parse pre-hook command output: %+v\npre-hook command output was: %+v\n", req.ID, err, string(preHookCommandOutput))
|
||||||
|
|
||||||
|
writeHttpResponseCode(w, req.ID, matchedHook.ID, http.StatusInternalServerError)
|
||||||
|
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
||||||
|
fmt.Fprint(w, "Error occurred while executing the hook's pre-hook command. Please check your logs for more details.")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user