Skip to content

Commit

Permalink
feat(hook): add default extension parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
ncarlier committed Dec 22, 2023
1 parent bc846f4 commit 8ea4262
Show file tree
Hide file tree
Showing 8 changed files with 21 additions and 21 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ All configuration variables are described in [etc/default/webhookd.env](./etc/de
Webhooks are simple scripts within a directory structure.

By default inside the `./scripts` directory.
You can override the default using the `WHD_SCRIPTS` environment variable or `-script` parameter.
You can change the default directory using the `WHD_SCRIPTS` environment variable or `-script` parameter.

*Example:*

Expand All @@ -87,7 +87,8 @@ In particular, examples of integration with Gitlab and Github.

The directory structure define the webhook URL.

You can omit the script extension. If you do, webhookd will search for a `.sh` file.
You can omit the script extension. If you do, webhookd will search by default for a `.sh` file.
You can change the default extension using the `WHD_HOOK_DEFAULT_EXT` environment variable or `-hook-default-ext` parameter.
If the script exists, the output the will be streamed to the HTTP response.

The streaming technology depends on the HTTP request:
Expand Down
10 changes: 6 additions & 4 deletions pkg/api/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (

var (
defaultTimeout int
defaultExt string
scriptDir string
outputDir string
)
Expand All @@ -32,6 +33,7 @@ func atoiFallback(str string, fallback int) int {
// index is the main handler of the API.
func index(conf *config.Config) http.Handler {
defaultTimeout = conf.HookTimeout
defaultExt = conf.HookDefaultExt
scriptDir = conf.ScriptDir
outputDir = conf.HookLogDir
return http.HandlerFunc(webhookHandler)
Expand Down Expand Up @@ -61,7 +63,7 @@ func triggerWebhook(w http.ResponseWriter, r *http.Request) {
infoHandler(w, r)
return
}
_, err := hook.ResolveScript(scriptDir, hookName)
script, err := hook.ResolveScript(scriptDir, hookName, defaultExt)
if err != nil {
slog.Error("hooke not found", "err", err.Error())
http.Error(w, "hook not found", http.StatusNotFound)
Expand Down Expand Up @@ -92,15 +94,15 @@ func triggerWebhook(w http.ResponseWriter, r *http.Request) {
params := HTTPParamsToShellVars(r.Form)
params = append(params, HTTPParamsToShellVars(r.Header)...)

// Create work
// Create hook job
timeout := atoiFallback(r.Header.Get("X-Hook-Timeout"), defaultTimeout)
job, err := hook.NewHookJob(&hook.Request{
Name: hookName,
Script: script,
Method: r.Method,
Payload: string(body),
Args: params,
Timeout: timeout,
BaseDir: scriptDir,
OutputDir: outputDir,
})
if err != nil {
Expand Down Expand Up @@ -146,7 +148,7 @@ func getWebhookLog(w http.ResponseWriter, r *http.Request) {

// Get script location
hookName := path.Dir(strings.TrimPrefix(r.URL.Path, "/"))
_, err := hook.ResolveScript(scriptDir, hookName)
_, err := hook.ResolveScript(scriptDir, hookName, defaultExt)
if err != nil {
slog.Error(err.Error())
http.Error(w, err.Error(), http.StatusNotFound)
Expand Down
1 change: 1 addition & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ type Config struct {
TLSKeyFile string `flag:"tls-key-file" desc:"TLS key file" default:"server.key"`
TLSDomain string `flag:"tls-domain" desc:"TLS domain name used by ACME"`
NbWorkers int `flag:"nb-workers" desc:"Number of workers to start" default:"2"`
HookDefaultExt string `flag:"hook-default-ext" desc:"Default extension for hook scripts" default:"sh"`
HookTimeout int `flag:"hook-timeout" desc:"Maximum hook execution time in second" default:"10"`
HookLogDir string `flag:"hook-log-dir" desc:"Hook execution logs location" default:""`
ScriptDir string `flag:"scripts" desc:"Scripts location" default:"scripts"`
Expand Down
4 changes: 2 additions & 2 deletions pkg/hook/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import (
)

// ResolveScript is resolving the target script.
func ResolveScript(dir, name string) (string, error) {
func ResolveScript(dir, name, defaultExt string) (string, error) {
if path.Ext(name) == "" {
name += ".sh"
name += "." + defaultExt
}
script := path.Clean(path.Join(dir, name))
if !strings.HasPrefix(script, dir) {
Expand Down
6 changes: 1 addition & 5 deletions pkg/hook/job.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,10 @@ type Job struct {

// NewHookJob creates new hook job
func NewHookJob(request *Request) (*Job, error) {
script, err := ResolveScript(request.BaseDir, request.Name)
if err != nil {
return nil, err
}
job := &Job{
id: atomic.AddUint64(&hookID, 1),
name: request.Name,
script: script,
script: request.Script,
method: request.Method,
payload: request.Payload,
args: request.Args,
Expand Down
8 changes: 4 additions & 4 deletions pkg/hook/test/helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,25 @@ import (
)

func TestResolveScript(t *testing.T) {
script, err := hook.ResolveScript("../../../scripts", "../scripts/echo")
script, err := hook.ResolveScript("../../../scripts", "../scripts/echo", "sh")
assert.Nil(t, err, "")
assert.Equal(t, "../../../scripts/echo.sh", script, "")
}

func TestNotResolveScript(t *testing.T) {
_, err := hook.ResolveScript("../../scripts", "foo")
_, err := hook.ResolveScript("../../scripts", "foo", "sh")
assert.NotNil(t, err, "")
assert.Equal(t, "Script not found: ../../scripts/foo.sh", err.Error(), "")
}

func TestResolveBadScript(t *testing.T) {
_, err := hook.ResolveScript("../../scripts", "../tests/test_simple")
_, err := hook.ResolveScript("../../scripts", "../tests/test_simple", "sh")
assert.NotNil(t, err, "")
assert.Equal(t, "Invalid script path: ../tests/test_simple.sh", err.Error(), "")
}

func TestResolveScriptWithExtension(t *testing.T) {
_, err := hook.ResolveScript("../../scripts", "node.js")
_, err := hook.ResolveScript("../../scripts", "node.js", "sh")
assert.NotNil(t, err, "")
assert.Equal(t, "Script not found: ../../scripts/node.js", err.Error(), "")
}
6 changes: 3 additions & 3 deletions pkg/hook/test/job_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ func printJobMessages(job *hook.Job) {
func TestHookJob(t *testing.T) {
req := &hook.Request{
Name: "test_simple",
Script: "../test/test_simple.sh",
Method: "GET",
Payload: "{\"foo\": \"bar\"}",
Args: []string{
"name=foo",
"user_agent=test",
},
Timeout: 5,
BaseDir: "../test",
OutputDir: os.TempDir(),
}
job, err := hook.NewHookJob(req)
Expand All @@ -55,11 +55,11 @@ func TestHookJob(t *testing.T) {
func TestWorkRunnerWithError(t *testing.T) {
req := &hook.Request{
Name: "test_error",
Script: "../test/test_error.sh",
Method: "POST",
Payload: "",
Args: []string{},
Timeout: 5,
BaseDir: "../test",
OutputDir: os.TempDir(),
}
job, err := hook.NewHookJob(req)
Expand All @@ -75,11 +75,11 @@ func TestWorkRunnerWithError(t *testing.T) {
func TestWorkRunnerWithTimeout(t *testing.T) {
req := &hook.Request{
Name: "test_timeout",
Script: "../test/test_timeout.sh",
Method: "POST",
Payload: "",
Args: []string{},
Timeout: 1,
BaseDir: "../test",
OutputDir: os.TempDir(),
}
job, err := hook.NewHookJob(req)
Expand Down
2 changes: 1 addition & 1 deletion pkg/hook/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ const (
// Request is a hook request
type Request struct {
Name string
Script string
Method string
Payload string
Args []string
Timeout int
BaseDir string
OutputDir string
}

0 comments on commit 8ea4262

Please sign in to comment.