hooker/hooker.go

155 lines
3.3 KiB
Go

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)
}
}