blob: b560c6c075dcfd42d4203478518edfd59ce234d9 [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"
gioa421b062025-04-21 09:45:04 +040010 "strings"
gio0eaf2712024-04-14 13:08:46 +040011
12 "golang.org/x/crypto/ssh"
13
14 "github.com/go-git/go-billy/v5/osfs"
15 "github.com/go-git/go-git/v5"
gio2b1157a2024-10-24 08:45:07 +040016 "github.com/go-git/go-git/v5/plumbing"
gio0eaf2712024-04-14 13:08:46 +040017 gitssh "github.com/go-git/go-git/v5/plumbing/transport/ssh"
18 "github.com/go-git/go-git/v5/storage/memory"
19)
20
21var port = flag.Int("port", 3000, "Port to listen on")
gio266c04f2024-07-03 14:18:45 +040022var appId = flag.String("app-id", "", "Application ID")
gio0eaf2712024-04-14 13:08:46 +040023var repoAddr = flag.String("repo-addr", "", "Git repository address")
gio2b1157a2024-10-24 08:45:07 +040024var branch = flag.String("branch", "", "Name of the branch to process")
giofc441e32024-11-11 16:26:14 +040025var rootDir = flag.String("root-dir", "/", "Path to the app code")
gio0eaf2712024-04-14 13:08:46 +040026var sshKey = flag.String("ssh-key", "", "Private SSH key to access Git repository")
27var appDir = flag.String("app-dir", "", "Path to store application repository locally")
28var runCfg = flag.String("run-cfg", "", "Run configuration")
gioa60f0de2024-07-08 10:49:48 +040029var managerAddr = flag.String("manager-addr", "", "Address of the manager")
gio0eaf2712024-04-14 13:08:46 +040030
31type Command struct {
32 Bin string `json:"bin"`
33 Args []string `json:"args"`
gio1364e432024-06-29 11:39:18 +040034 Env []string `json:"env"`
gio0eaf2712024-04-14 13:08:46 +040035}
36
giofc441e32024-11-11 16:26:14 +040037func CloneRepositoryBranch(addr, branch, rootDir string, signer ssh.Signer, path string) error {
gio2b1157a2024-10-24 08:45:07 +040038 ref := fmt.Sprintf("refs/heads/%s", branch)
giofc441e32024-11-11 16:26:14 +040039 opts := &git.CloneOptions{
40 URL: addr,
41 RemoteName: "origin",
42 ReferenceName: plumbing.ReferenceName(ref),
43 SingleBranch: true,
44 Depth: 1,
45 InsecureSkipTLS: true,
46 Progress: os.Stdout,
47 }
48 if signer != nil {
49 opts.Auth = &gitssh.PublicKeys{
gio0eaf2712024-04-14 13:08:46 +040050 User: "git",
51 Signer: signer,
52 HostKeyCallbackHelper: gitssh.HostKeyCallbackHelper{
53 HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
54 // TODO(giolekva): verify server public key
55 fmt.Printf("--- %+v\n", ssh.MarshalAuthorizedKey(key))
56 return nil
57 },
58 },
giofc441e32024-11-11 16:26:14 +040059 }
60 }
61 c, err := git.Clone(memory.NewStorage(), osfs.New(path, osfs.WithBoundOS()), opts)
giof5ffedb2024-06-19 14:14:43 +040062 if err != nil {
63 return err
64 }
65 wt, err := c.Worktree()
66 if err != nil {
67 return err
68 }
giofc441e32024-11-11 16:26:14 +040069 if wt == nil {
70 panic(wt)
giof5ffedb2024-06-19 14:14:43 +040071 }
giofc441e32024-11-11 16:26:14 +040072 // TODO(gio): This should probably be removed.
73 // sb, err := wt.Submodules()
74 // if err != nil {
75 // return err
76 // }
77 // if err := sb.Init(); err != nil {
78 // return err
79 // }
80 // if err := sb.Update(&git.SubmoduleUpdateOptions{
81 // Depth: 1,
82 // }); err != nil {
83 // return err
84 // }
gio0eaf2712024-04-14 13:08:46 +040085 return err
86}
87
88func main() {
89 flag.Parse()
90 self, ok := os.LookupEnv("SELF_IP")
91 if !ok {
92 panic("no SELF_IP")
93 }
giofc441e32024-11-11 16:26:14 +040094 var signer ssh.Signer
gioa421b062025-04-21 09:45:04 +040095 // TODO(gio): revisit this logic
96 if *sshKey != "" && !(strings.HasPrefix(*repoAddr, "http://") || strings.HasPrefix(*repoAddr, "https://")) {
giofc441e32024-11-11 16:26:14 +040097 key, err := os.ReadFile(*sshKey)
98 if err != nil {
99 panic(err)
100 }
101 signer, err = ssh.ParsePrivateKey(key)
102 if err != nil {
103 panic(err)
104 }
gio0eaf2712024-04-14 13:08:46 +0400105 }
giofc441e32024-11-11 16:26:14 +0400106 if err := CloneRepositoryBranch(*repoAddr, *branch, *rootDir, signer, *appDir); err != nil {
gio0eaf2712024-04-14 13:08:46 +0400107 panic(err)
108 }
109 r, err := os.Open(*runCfg)
110 if err != nil {
111 panic(err)
112 }
113 defer r.Close()
114 var cmds []Command
115 if err := json.NewDecoder(r).Decode(&cmds); err != nil {
116 panic(err)
117 }
giofc441e32024-11-11 16:26:14 +0400118 s := NewServer(*port, *appId, *repoAddr, *branch, *rootDir, signer, *appDir, cmds, self, *managerAddr)
gio5e4d1a72024-10-09 15:25:29 +0400119 if err := s.Start(); err != nil {
120 log.Fatal(err)
121 }
gio0eaf2712024-04-14 13:08:46 +0400122}