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 },
40 Commands: []*cli.Command{
41 {
42 Name: "post-recieve",
43 Usage: "sends a post-recieve hook to the knot (waits for stdin)",
44 Action: postRecieve,
45 },
46 },
47 }
48}
49
50func postRecieve(ctx context.Context, cmd *cli.Command) error {
51 gitDir := cmd.String("git-dir")
52 userDid := cmd.String("user-did")
53 userHandle := cmd.String("user-handle")
54 endpoint := cmd.String("internal-api")
55
56 payloadReader := bufio.NewReader(os.Stdin)
57 payload, _ := payloadReader.ReadString('\n')
58
59 client := &http.Client{}
60
61 req, err := http.NewRequest("POST", "http://"+endpoint+"/hooks/post-receive", strings.NewReader(payload))
62 if err != nil {
63 return fmt.Errorf("failed to create request: %w", err)
64 }
65
66 req.Header.Set("Content-Type", "text/plain")
67 req.Header.Set("X-Git-Dir", gitDir)
68 req.Header.Set("X-Git-User-Did", userDid)
69 req.Header.Set("X-Git-User-Handle", userHandle)
70
71 resp, err := client.Do(req)
72 if err != nil {
73 return fmt.Errorf("failed to execute request: %w", err)
74 }
75 defer resp.Body.Close()
76
77 if resp.StatusCode != http.StatusOK {
78 return fmt.Errorf("unexpected status code: %d", resp.StatusCode)
79 }
80
81 return nil
82}