package main import ( "fmt" "log" "net/http" "os" "strconv" "sync" "time" "github.com/urfave/cli/v2" ) /* Listen for git web hooks and then execute a script. */ var verbose bool type TaskDefErr struct { message string } func (e *TaskDefErr) Error() string { return e.message } type TaskManifest struct { Owner string RepoID uint64 Auth string Command string // Path to executable Lock *sync.Mutex } var httpServer http.Server var task TaskManifest func InitHTTPHandler(handler *http.ServeMux) *LoggingHTTPHandler { auth := NewAuth(handler) loggingHandler := NewLogger(&auth) return &loggingHandler } // Try to get an env var, if not set, panic or fatal func getEnv(name string) string { varVal := os.Getenv(name) if varVal == "" { panic(fmt.Sprintf("required %s env variable is not set", name)) } return varVal } func InitTask() TaskManifest { RepoID := getEnv("REPO_ID") repoID, err := strconv.ParseUint(RepoID, 10, 64) if err != nil { panic("REPO_ID is not a valid int") } return TaskManifest{ Command: getEnv("CMD"), Owner: getEnv("OWNER"), Auth: getEnv("AUTH"), RepoID: repoID, Lock: &sync.Mutex{}, } } func init() { mux := http.NewServeMux() mux.HandleFunc("/", handleRoot) handler := InitHTTPHandler(mux) httpServer = http.Server{ ReadTimeout: time.Second * 5, WriteTimeout: time.Second * 5, Addr: ":4184", Handler: handler, } } func runServer() error { log.Println("Task", task) log.Printf("Listening on %s", httpServer.Addr) log.Fatal(httpServer.ListenAndServe()) log.Println("Server Stopped") return nil } func main() { app := cli.App{ Name: "hooker", Description: "Listen for git web hooks and then execute a script or executable", Authors: []*cli.Author{ { Name: "Hesham T. Banafa", Email: "hishaminv@gmail.com", }, }, Flags: []cli.Flag{ &cli.Uint64Flag{ Name: "repo_id", Usage: "Target Repo ID reported by git webhook", Destination: &task.RepoID, Required: true, }, &cli.StringFlag{ Name: "owner", Usage: "Repo Owner username", Destination: &task.Owner, Required: true, }, &cli.StringFlag{ Name: "auth", Usage: "Auth Secret", Destination: &task.Auth, Required: true, }, &cli.StringFlag{ Name: "command", Aliases: []string{"c"}, Usage: "Command is the script or executable to be run upon webhook", Destination: &task.Command, Required: true, }, &cli.BoolFlag{ Name: "verbose", Aliases: []string{"v"}, Value: false, Usage: "Produce more verbose output", Destination: &verbose, }, }, Action: func(ctx *cli.Context) error { err := runServer() return err }, } if err := app.Run(os.Args); err != nil { log.Fatal(err) } }