1package server
2
3import (
4 "fmt"
5 "path/filepath"
6 "testing"
7
8 "github.com/charmbracelet/keygen"
9 ggit "github.com/charmbracelet/soft-serve/git"
10 "github.com/charmbracelet/soft-serve/server/config"
11 "github.com/gliderlabs/ssh"
12 "github.com/go-git/go-git/v5"
13 gconfig "github.com/go-git/go-git/v5/config"
14 "github.com/go-git/go-git/v5/plumbing/object"
15 gssh "github.com/go-git/go-git/v5/plumbing/transport/ssh"
16 "github.com/matryer/is"
17 cssh "golang.org/x/crypto/ssh"
18)
19
20var (
21 cfg = &config.Config{
22 BindAddr: "",
23 Host: "localhost",
24 Port: 22222,
25 }
26)
27
28func TestPushRepo(t *testing.T) {
29 is := is.New(t)
30 _, pkPath := createKeyPair(t)
31 s := setupServer(t)
32 defer s.Close()
33 err := s.Reload()
34 is.NoErr(err)
35
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://%s:%d/%s", cfg.Host, cfg.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 defer s.Close()
76 err := s.Reload()
77 is.NoErr(err)
78
79 dst := t.TempDir()
80 url := fmt.Sprintf("ssh://%s:%d/config", cfg.Host, cfg.Port)
81 err = ggit.Clone(url, dst, ggit.CloneOptions{
82 CommandOptions: ggit.CommandOptions{
83 Envs: []string{
84 fmt.Sprintf(`GIT_SSH_COMMAND=ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i %s -F /dev/null`, pkPath),
85 },
86 },
87 })
88 is.NoErr(err)
89}
90
91func setupServer(t *testing.T) *Server {
92 t.Helper()
93 tmpdir := t.TempDir()
94 cfg.RepoPath = filepath.Join(tmpdir, "repos")
95 cfg.KeyPath = filepath.Join(tmpdir, "key")
96 s := NewServer(cfg)
97 go func() {
98 s.Start()
99 }()
100 t.Cleanup(func() {
101 s.Close()
102 })
103 return s
104}
105
106func createKeyPair(t *testing.T) (ssh.PublicKey, string) {
107 t.Helper()
108 is := is.New(t)
109 keyDir := t.TempDir()
110 kp, err := keygen.NewWithWrite(filepath.Join(keyDir, "id"), nil, keygen.Ed25519)
111 is.NoErr(err)
112 pubkey, _, _, _, err := ssh.ParseAuthorizedKey(kp.PublicKey())
113 is.NoErr(err)
114 return pubkey, filepath.Join(keyDir, "id_ed25519")
115}