forked from tangled.org/core
Monorepo for Tangled — https://tangled.org
1package hook 2 3import ( 4 "bufio" 5 "context" 6 "fmt" 7 "net/http" 8 "os" 9 "strings" 10 11 "github.com/urfave/cli/v3" 12) 13 14// The hook command is nested like so: 15// 16// knot hook --[flags] [hook] 17func Command() *cli.Command { 18 return &cli.Command{ 19 Name: "hook", 20 Usage: "run git hooks", 21 Flags: []cli.Flag{ 22 &cli.StringFlag{ 23 Name: "git-dir", 24 Usage: "base directory for git repos", 25 }, 26 &cli.StringFlag{ 27 Name: "user-did", 28 Usage: "git user's did", 29 }, 30 &cli.StringFlag{ 31 Name: "user-handle", 32 Usage: "git user's handle", 33 }, 34 &cli.StringFlag{ 35 Name: "internal-api", 36 Usage: "endpoint for the internal API", 37 Value: "http://localhost:5444", 38 }, 39 &cli.StringSliceFlag{ 40 Name: "push-option", 41 Usage: "any push option from git", 42 }, 43 }, 44 Commands: []*cli.Command{ 45 { 46 Name: "post-recieve", 47 Usage: "sends a post-recieve hook to the knot (waits for stdin)", 48 Action: postRecieve, 49 }, 50 }, 51 } 52} 53 54func postRecieve(ctx context.Context, cmd *cli.Command) error { 55 gitDir := cmd.String("git-dir") 56 userDid := cmd.String("user-did") 57 userHandle := cmd.String("user-handle") 58 endpoint := cmd.String("internal-api") 59 pushOptions := cmd.StringSlice("push-option") 60 61 payloadReader := bufio.NewReader(os.Stdin) 62 payload, _ := payloadReader.ReadString('\n') 63 64 client := &http.Client{} 65 66 req, err := http.NewRequest("POST", "http://"+endpoint+"/hooks/post-receive", strings.NewReader(payload)) 67 if err != nil { 68 return fmt.Errorf("failed to create request: %w", err) 69 } 70 71 req.Header.Set("Content-Type", "text/plain; charset=utf-8") 72 req.Header.Set("X-Git-Dir", gitDir) 73 req.Header.Set("X-Git-User-Did", userDid) 74 req.Header.Set("X-Git-User-Handle", userHandle) 75 if pushOptions != nil { 76 for _, option := range pushOptions { 77 req.Header.Add("X-Git-Push-Option", option) 78 } 79 } 80 81 resp, err := client.Do(req) 82 if err != nil { 83 return fmt.Errorf("failed to execute request: %w", err) 84 } 85 defer resp.Body.Close() 86 87 if resp.StatusCode != http.StatusOK { 88 return fmt.Errorf("unexpected status code: %d", resp.StatusCode) 89 } 90 91 return nil 92}