From 2189ee511c0030bb8b934becf3c891f5992bd48f Mon Sep 17 00:00:00 2001 From: Alvie Rahman Date: Wed, 4 Aug 2021 11:51:40 +0100 Subject: [PATCH] Allow executed script to have arguments --- config.json | 9 ++++++--- example.sh | 1 + main.go | 49 ++++++++++++++++++++++++++++++++----------------- readme.md | 21 +++++++++++++++------ 4 files changed, 54 insertions(+), 26 deletions(-) diff --git a/config.json b/config.json index 7cb906e..15865c4 100644 --- a/config.json +++ b/config.json @@ -2,13 +2,16 @@ "ListenAddress": "127.0.0.1:8654", "Services": { "test": { - "Script": "./example.sh", + "Script": { + "Program": "./example.sh", + "AppendPayload": true + }, "Secret": "THISISVERYSECRET", "SignatureHeader": "X-Gitea-Signature", "Tests": [ { - "Command": "git", - "Arguments": [ "pull" ] + "Program": "echo", + "Arguments": [ "test" ] } ] } diff --git a/example.sh b/example.sh index 517a5c2..2216ed7 100755 --- a/example.sh +++ b/example.sh @@ -1,2 +1,3 @@ #!/usr/bin/bash date >> test_output +echo "$1" >> test_output diff --git a/main.go b/main.go index 5b0e3cb..5f0fabf 100644 --- a/main.go +++ b/main.go @@ -24,6 +24,14 @@ func main() { r := mux.NewRouter() r.HandleFunc("/webhooks/{service}", webhookHandler) + if p, ok := os.LookupEnv("CONFIG"); ok { + config_filename = p + } + + if p, ok := os.LookupEnv("NO_SIGNATURE_CHECK"); ok { + checkSignature = p != "true" + } + raw_config, err := ioutil.ReadFile(config_filename) if err != nil { panic(err.Error()) @@ -34,13 +42,6 @@ func main() { panic(err.Error()) } - if p, ok := os.LookupEnv("CONFIG"); ok { - config_filename = p - } - - if p, ok := os.LookupEnv("NO_SIGNATURE_CHECK"); ok { - checkSignature = p != "true" - } log.Fatal(http.ListenAndServe(config.ListenAddress, r)) } @@ -73,15 +74,15 @@ func webhookHandler(w http.ResponseWriter, r *http.Request) { // Run tests, immediately stop if one fails for _, test := range service.Tests { - if _, err := exec.Command(test.Command, test.Arguments...).Output(); err != nil { + if _, err := test.Execute(payload); err != nil { writeResponse(w, 409, - fmt.Sprintf("409 Conflict: Test failed: %v", err.Error()), + fmt.Sprintf("Conflict: Test failed: %v", err.Error()), ) return } } - if stdout, err := exec.Command(service.Script, payload).Output(); err != nil { + if stdout, err := service.Script.Execute(payload); err != nil { writeResponse(w, 500, err.Error()) return } else { @@ -106,9 +107,12 @@ func (c Config) Validate() error { return requiredFieldError{"ListenAddress", ""} } + jsonbytes, _ := json.MarshalIndent(c, "", " ") + fmt.Println(string(jsonbytes)) + for serviceName, service := range c.Services { - if service.Script == "" { - return requiredFieldError{"Script", serviceName} + if service.Script.Program == "" { + return requiredFieldError{"Script.Program", serviceName} } if service.SignatureHeader == "" { return requiredFieldError{"SignatureHeader", serviceName} @@ -121,16 +125,27 @@ func (c Config) Validate() error { return nil } -type Test struct { - Command string - Arguments []string +func (c Command) Execute(payload string) ([]byte, error) { + arguments := make([]string, 0) + copy(c.Arguments, arguments) + if c.AppendPayload { + arguments = append(arguments, payload) + } + + return exec.Command(c.Program, arguments...).Output() +} + +type Command struct { + Program string + Arguments []string + AppendPayload bool } type Service struct { - Script string + Script Command Secret string SignatureHeader string - Tests []Test + Tests []Command } type Config struct { diff --git a/readme.md b/readme.md index 54e0d6f..ceb3b9a 100644 --- a/readme.md +++ b/readme.md @@ -27,7 +27,13 @@ You should also specify a shared secret in the `Secret` key. You can disable signature verification altogether by setting environment variable `NO_SIGNATURE_VERIFICATION` to `true`. -## Tests +## Writing Commands + +gohookr doesn't care what the command is as long as the `Program` is executable. +You can specify extra arguments with the `Arguments` field. +You can ask it to put the payload as the last argument by setting `AppendPayload` to true. + +## Writing Tests gohookr can run test before running your script. Tests must be in the form of bash scripts. @@ -35,13 +41,13 @@ A non-zero return code is considered a fail and gohookr will run no further test deploy. Tests are run in the order they're listed so any actions that need to be done before -real tests are run can simply be put before the tests. +tests are run can simply be put in this section before the tests. ## Example Config Required config keys are `ListenAddress` and `Services`. -Requried keys per service are `Script`, `Secret`, `SignatureHeader`. +Requried keys per service are `Script.Program`, `Secret`, `SignatureHeader`. An example config file can be found [here](./config.json) but also below: @@ -50,13 +56,16 @@ An example config file can be found [here](./config.json) but also below: "ListenAddress": "127.0.0.1:8654", "Services": { "test": { - "Script": "./example.sh", + "Script": { + "Program": "./example.sh", + "AppendPayload": true + }, "Secret": "THISISVERYSECRET", "SignatureHeader": "X-Gitea-Signature", "Tests": [ { - "Command": "git", - "Arguments": [ "pull" ] + "Program": "echo", + "Arguments": [ "test" ] } ] }