1package server
2
3import (
4 "fmt"
5 "log"
6 "net"
7 "os"
8 "path/filepath"
9 "testing"
10
11 "github.com/charmbracelet/keygen"
12 ggit "github.com/charmbracelet/soft-serve/git"
13 "github.com/charmbracelet/soft-serve/server/config"
14 "github.com/gliderlabs/ssh"
15 "github.com/go-git/go-git/v5"
16 gconfig "github.com/go-git/go-git/v5/config"
17 "github.com/go-git/go-git/v5/plumbing/object"
18 gssh "github.com/go-git/go-git/v5/plumbing/transport/ssh"
19 "github.com/matryer/is"
20 cssh "golang.org/x/crypto/ssh"
21)
22
23var (
24 cfg = &config.Config{
25 Host: "",
26 Git: config.GitConfig{Port: 9418},
27 }
28)
29
30func TestPushRepo(t *testing.T) {
31 is := is.New(t)
32 _, pkPath := createKeyPair(t)
33 s := setupServer(t)
34 err := s.Reload()
35 is.NoErr(err)
36 rp := t.TempDir()
37 r, err := git.PlainInit(rp, false)
38 is.NoErr(err)
39 wt, err := r.Worktree()
40 is.NoErr(err)
41 _, err = wt.Filesystem.Create("testfile")
42 is.NoErr(err)
43 _, err = wt.Add("testfile")
44 is.NoErr(err)
45 author := &object.Signature{
46 Name: "test",
47 Email: "",
48 }
49 _, err = wt.Commit("test commit", &git.CommitOptions{
50 All: true,
51 Author: author,
52 Committer: author,
53 })
54 is.NoErr(err)
55 _, err = r.CreateRemote(&gconfig.RemoteConfig{
56 Name: "origin",
57 URLs: []string{fmt.Sprintf("ssh://localhost:%d/%s", cfg.SSH.Port, "testrepo")},
58 })
59 auth, err := gssh.NewPublicKeysFromFile("git", pkPath, "")
60 is.NoErr(err)
61 auth.HostKeyCallbackHelper = gssh.HostKeyCallbackHelper{
62 HostKeyCallback: cssh.InsecureIgnoreHostKey(),
63 }
64 err = r.Push(&git.PushOptions{
65 RemoteName: "origin",
66 Auth: auth,
67 })
68 is.NoErr(err)
69}
70
71func TestCloneRepo(t *testing.T) {
72 is := is.New(t)
73 _, pkPath := createKeyPair(t)
74 s := setupServer(t)
75 log.Print("starting server")
76 err := s.Reload()
77 log.Print("reloaded server")
78 is.NoErr(err)
79 dst := t.TempDir()
80 url := fmt.Sprintf("ssh://localhost:%d/config", cfg.SSH.Port)
81 log.Print("cloning repo")
82 err = ggit.Clone(url, dst, ggit.CloneOptions{
83 CommandOptions: ggit.CommandOptions{
84 Envs: []string{
85 fmt.Sprintf(`GIT_SSH_COMMAND=ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i %s -F /dev/null`, pkPath),
86 },
87 },
88 })
89 is.NoErr(err)
90}
91
92func randomPort() int {
93 addr, _ := net.Listen("tcp", ":0") //nolint:gosec
94 _ = addr.Close()
95 return addr.Addr().(*net.TCPAddr).Port
96}
97
98func setupServer(t *testing.T) *Server {
99 t.Helper()
100 cfg.DataPath = t.TempDir()
101 cfg.SSH.Port = randomPort()
102 s := NewServer(cfg)
103 go func() {
104 log.Print("starting server")
105 s.Start()
106 }()
107 t.Cleanup(func() {
108 s.Close()
109 os.RemoveAll(cfg.DataPath)
110 })
111 return s
112}
113
114func createKeyPair(t *testing.T) (ssh.PublicKey, string) {
115 t.Helper()
116 is := is.New(t)
117 keyDir := t.TempDir()
118 kp, err := keygen.NewWithWrite(filepath.Join(keyDir, "id"), nil, keygen.Ed25519)
119 is.NoErr(err)
120 pubkey, _, _, _, err := ssh.ParseAuthorizedKey(kp.PublicKey())
121 is.NoErr(err)
122 return pubkey, filepath.Join(keyDir, "id_ed25519")
123}