blob: 929674941e1747a57867b86f06c4e77c15d0e0e1 [file] [log] [blame]
gio0eaf2712024-04-14 13:08:46 +04001package main
2
3import (
4 "encoding/json"
5 "flag"
6 "fmt"
gio5e4d1a72024-10-09 15:25:29 +04007 "log"
gio0eaf2712024-04-14 13:08:46 +04008 "net"
9 "os"
10
11 "golang.org/x/crypto/ssh"
12
13 "github.com/go-git/go-billy/v5/osfs"
14 "github.com/go-git/go-git/v5"
gio2b1157a2024-10-24 08:45:07 +040015 "github.com/go-git/go-git/v5/plumbing"
gio0eaf2712024-04-14 13:08:46 +040016 gitssh "github.com/go-git/go-git/v5/plumbing/transport/ssh"
17 "github.com/go-git/go-git/v5/storage/memory"
18)
19
20var port = flag.Int("port", 3000, "Port to listen on")
gio266c04f2024-07-03 14:18:45 +040021var appId = flag.String("app-id", "", "Application ID")
gio0eaf2712024-04-14 13:08:46 +040022var repoAddr = flag.String("repo-addr", "", "Git repository address")
gio2b1157a2024-10-24 08:45:07 +040023var branch = flag.String("branch", "", "Name of the branch to process")
gio0eaf2712024-04-14 13:08:46 +040024var sshKey = flag.String("ssh-key", "", "Private SSH key to access Git repository")
25var appDir = flag.String("app-dir", "", "Path to store application repository locally")
26var runCfg = flag.String("run-cfg", "", "Run configuration")
gioa60f0de2024-07-08 10:49:48 +040027var managerAddr = flag.String("manager-addr", "", "Address of the manager")
gio0eaf2712024-04-14 13:08:46 +040028
29type Command struct {
30 Bin string `json:"bin"`
31 Args []string `json:"args"`
gio1364e432024-06-29 11:39:18 +040032 Env []string `json:"env"`
gio0eaf2712024-04-14 13:08:46 +040033}
34
gio2b1157a2024-10-24 08:45:07 +040035func CloneRepositoryBranch(addr, branch string, signer ssh.Signer, path string) error {
36 ref := fmt.Sprintf("refs/heads/%s", branch)
giof5ffedb2024-06-19 14:14:43 +040037 c, err := git.Clone(memory.NewStorage(), osfs.New(path, osfs.WithBoundOS()), &git.CloneOptions{
gio0eaf2712024-04-14 13:08:46 +040038 URL: addr,
39 Auth: &gitssh.PublicKeys{
40 User: "git",
41 Signer: signer,
42 HostKeyCallbackHelper: gitssh.HostKeyCallbackHelper{
43 HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
44 // TODO(giolekva): verify server public key
45 fmt.Printf("--- %+v\n", ssh.MarshalAuthorizedKey(key))
46 return nil
47 },
48 },
49 },
giof5ffedb2024-06-19 14:14:43 +040050 RemoteName: "origin",
gio2b1157a2024-10-24 08:45:07 +040051 ReferenceName: plumbing.ReferenceName(ref),
giof5ffedb2024-06-19 14:14:43 +040052 SingleBranch: true,
53 Depth: 1,
54 InsecureSkipTLS: true,
55 Progress: os.Stdout,
gio0eaf2712024-04-14 13:08:46 +040056 })
giof5ffedb2024-06-19 14:14:43 +040057 if err != nil {
58 return err
59 }
60 wt, err := c.Worktree()
61 if err != nil {
62 return err
63 }
64 sb, err := wt.Submodules()
65 if err != nil {
66 return err
67 }
68 if err := sb.Init(); err != nil {
69 return err
70 }
71 if err := sb.Update(&git.SubmoduleUpdateOptions{
72 Depth: 1,
73 }); err != nil {
74 return err
75 }
gio0eaf2712024-04-14 13:08:46 +040076 return err
77}
78
79func main() {
80 flag.Parse()
81 self, ok := os.LookupEnv("SELF_IP")
82 if !ok {
83 panic("no SELF_IP")
84 }
85 key, err := os.ReadFile(*sshKey)
86 if err != nil {
87 panic(err)
88 }
89 signer, err := ssh.ParsePrivateKey(key)
90 if err != nil {
91 panic(err)
92 }
gio2b1157a2024-10-24 08:45:07 +040093 if err := CloneRepositoryBranch(*repoAddr, *branch, signer, *appDir); err != nil {
gio0eaf2712024-04-14 13:08:46 +040094 panic(err)
95 }
96 r, err := os.Open(*runCfg)
97 if err != nil {
98 panic(err)
99 }
100 defer r.Close()
101 var cmds []Command
102 if err := json.NewDecoder(r).Decode(&cmds); err != nil {
103 panic(err)
104 }
gio2b1157a2024-10-24 08:45:07 +0400105 s := NewServer(*port, *appId, *repoAddr, *branch, signer, *appDir, cmds, self, *managerAddr)
gio5e4d1a72024-10-09 15:25:29 +0400106 if err := s.Start(); err != nil {
107 log.Fatal(err)
108 }
gio0eaf2712024-04-14 13:08:46 +0400109}