Allow executed script to have arguments

This commit is contained in:
Akbar Rahman 2021-08-04 11:51:40 +01:00
parent a2d4153c64
commit 2189ee511c
4 changed files with 54 additions and 26 deletions

View File

@ -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" ]
}
]
}

View File

@ -1,2 +1,3 @@
#!/usr/bin/bash
date >> test_output
echo "$1" >> test_output

49
main.go
View File

@ -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 {

View File

@ -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" ]
}
]
}