pico
created pr with
13.1
added 13.2
-: ------- > 1: 605c47b nice!
1: be8edcf = 2: 605c47b contrib: add dev script
changed status to
accepted
cmds
checkout latest patchset:
ssh pr.pico.sh print 13 | git am -3checkout any patchset in a patch request:
ssh pr.pico.sh print 13.[rev] | git am -3add changes to patch request:
git format-patch main --stdout | ssh pr.pico.sh pr add 13set PR to open (enables RSS notifications):
ssh pr.pico.sh pr open 13set PR to draft (stops RSS notifications):
ssh pr.pico.sh pr draft 13
Patchset
13.1
contrib: add dev script
jolheiser
2024-07-22T18:05:39ZThis patch adds a fairly contained dev script that almost doubles as an integration test if you squint hard enough. It runs an isolated instance that we can add more things to, it at least seems handy to me for quickly testing how changes affect e.g. the web UI, RSS feed, etc. Signed-off-by: jolheiser <git@jolheiser.com>
Semantic diff summary
5 added,
1 modified,
0 signature changed,
0 removed
across 2 analyzed files
(1 file skipped: unsupported file type)
+12
-0
contrib/dev/README.md
#
| ... | ... | @@ -0,0 +1,12 @@ | |
| 1 | + | # dev script | |
| 2 | + | ||
| 3 | + | `go run ./contrib/dev/` | |
| 4 | + | ||
| 5 | + | If you want to instead use this to bootstrap: | |
| 6 | + | ||
| 7 | + | 1. `go run ./contrib/dev/ --cleanup=false` | |
| 8 | + | 2. Note the tmp dir printed out | |
| 9 | + | 3. Stop the program `Ctrl+C` | |
| 10 | + | 4. Modify as needed within the tmp dir | |
| 11 | + | 5. Run `git-dir` and point at the config contained within the tmp dir | |
| 12 | + | 6. Remember to clean up the tmp dir yourself when finished |
+203
-0
contrib/dev/main.go
#
| ... | ... | @@ -0,0 +1,203 @@ | |
| 1 | + | package main | |
| 2 | + | ||
| 3 | + | import ( | |
| 4 | + | "crypto/ed25519" | |
| 5 | + | "crypto/rand" | |
| 6 | + | "flag" | |
| 7 | + | "fmt" | |
| 8 | + | "log/slog" | |
| 9 | + | "os" | |
| 10 | + | "os/signal" | |
| 11 | + | "path/filepath" | |
| 12 | + | "time" | |
| 13 | + | ||
| 14 | + | "github.com/picosh/git-pr" | |
| 15 | + | "github.com/picosh/git-pr/fixtures" | |
| 16 | + | "golang.org/x/crypto/ssh" | |
| 17 | + | ) | |
| 18 | + | ||
| 19 | + | func main() { | |
| 20 | + | cleanupFlag := flag.Bool("cleanup", true, "Clean up tmp dir after quitting (default: true)") | |
| 21 | + | flag.Parse() | |
| 22 | + | ||
| 23 | + | tmp, err := os.MkdirTemp(os.TempDir(), "git-pr*") | |
| 24 | + | if err != nil { | |
| 25 | + | panic(err) | |
| 26 | + | } | |
| 27 | + | defer func() { | |
| 28 | + | if *cleanupFlag { | |
| 29 | + | os.RemoveAll(tmp) | |
| 30 | + | } | |
| 31 | + | }() | |
| 32 | + | fmt.Println(tmp) | |
| 33 | + | ||
| 34 | + | adminKey, userKey := generateKeys() | |
| 35 | + | ||
| 36 | + | cfgPath := filepath.Join(tmp, "git-pr.toml") | |
| 37 | + | cfgFi, err := os.Create(cfgPath) | |
| 38 | + | if err != nil { | |
| 39 | + | panic(err) | |
| 40 | + | } | |
| 41 | + | cfgFi.WriteString(fmt.Sprintf(cfgTmpl, tmp, adminKey.public())) | |
| 42 | + | cfgFi.Close() | |
| 43 | + | ||
| 44 | + | opts := &slog.HandlerOptions{ | |
| 45 | + | AddSource: true, | |
| 46 | + | } | |
| 47 | + | logger := slog.New( | |
| 48 | + | slog.NewTextHandler(os.Stdout, opts), | |
| 49 | + | ) | |
| 50 | + | cfg := git.NewGitCfg(cfgPath, logger) | |
| 51 | + | go git.GitSshServer(cfg) | |
| 52 | + | time.Sleep(time.Second) | |
| 53 | + | go git.StartWebServer(cfg) | |
| 54 | + | ||
| 55 | + | // Hack to wait for startup | |
| 56 | + | time.Sleep(time.Second) | |
| 57 | + | ||
| 58 | + | patch, err := fixtures.Fixtures.ReadFile("single.patch") | |
| 59 | + | if err != nil { | |
| 60 | + | panic(err) | |
| 61 | + | } | |
| 62 | + | otherPatch, err := fixtures.Fixtures.ReadFile("with-cover.patch") | |
| 63 | + | if err != nil { | |
| 64 | + | panic(err) | |
| 65 | + | } | |
| 66 | + | ||
| 67 | + | // Accepted patch | |
| 68 | + | userKey.cmd(patch, "pr create test") | |
| 69 | + | userKey.cmd(nil, "pr edit 1 Accepted patch") | |
| 70 | + | adminKey.cmd(nil, "pr accept 1") | |
| 71 | + | ||
| 72 | + | // Closed patch (admin) | |
| 73 | + | userKey.cmd(patch, "pr create test") | |
| 74 | + | userKey.cmd(nil, "pr edit 2 Closed patch (admin)") | |
| 75 | + | adminKey.cmd(nil, "pr close 2") | |
| 76 | + | ||
| 77 | + | // Closed patch (contributor) | |
| 78 | + | userKey.cmd(patch, "pr create test") | |
| 79 | + | userKey.cmd(nil, "pr edit 3 Closed patch (contributor)") | |
| 80 | + | userKey.cmd(nil, "pr close 3") | |
| 81 | + | ||
| 82 | + | // Reviewed patch | |
| 83 | + | userKey.cmd(patch, "pr create test") | |
| 84 | + | userKey.cmd(nil, "pr edit 4 Reviewed patch") | |
| 85 | + | adminKey.cmd(otherPatch, "pr add --review 4") | |
| 86 | + | ||
| 87 | + | // Accepted patch with review | |
| 88 | + | userKey.cmd(patch, "pr create test") | |
| 89 | + | userKey.cmd(nil, "pr edit 5 Accepted patch with review") | |
| 90 | + | adminKey.cmd(otherPatch, "pr add --accept 5") | |
| 91 | + | ||
| 92 | + | // Closed patch with review | |
| 93 | + | userKey.cmd(patch, "pr create test") | |
| 94 | + | userKey.cmd(nil, "pr edit 6 Closed patch with review") | |
| 95 | + | adminKey.cmd(otherPatch, "pr add --close 6") | |
| 96 | + | ||
| 97 | + | fmt.Println("time to do some testing...") | |
| 98 | + | ch := make(chan os.Signal, 1) | |
| 99 | + | signal.Notify(ch, os.Interrupt, os.Kill) | |
| 100 | + | <-ch | |
| 101 | + | } | |
| 102 | + | ||
| 103 | + | type sshKey struct { | |
| 104 | + | username string | |
| 105 | + | signer ssh.Signer | |
| 106 | + | } | |
| 107 | + | ||
| 108 | + | func (s sshKey) public() string { | |
| 109 | + | pubkey := s.signer.PublicKey() | |
| 110 | + | return string(ssh.MarshalAuthorizedKey(pubkey)) | |
| 111 | + | } | |
| 112 | + | ||
| 113 | + | func (s sshKey) cmd(patch []byte, cmd string) { | |
| 114 | + | host := "localhost:2222" | |
| 115 | + | ||
| 116 | + | config := &ssh.ClientConfig{ | |
| 117 | + | User: s.username, | |
| 118 | + | Auth: []ssh.AuthMethod{ | |
| 119 | + | ssh.PublicKeys(s.signer), | |
| 120 | + | }, | |
| 121 | + | HostKeyCallback: ssh.InsecureIgnoreHostKey(), | |
| 122 | + | } | |
| 123 | + | ||
| 124 | + | client, err := ssh.Dial("tcp", host, config) | |
| 125 | + | if err != nil { | |
| 126 | + | panic(err) | |
| 127 | + | } | |
| 128 | + | defer client.Close() | |
| 129 | + | ||
| 130 | + | session, err := client.NewSession() | |
| 131 | + | if err != nil { | |
| 132 | + | panic(err) | |
| 133 | + | } | |
| 134 | + | defer session.Close() | |
| 135 | + | ||
| 136 | + | stdinPipe, err := session.StdinPipe() | |
| 137 | + | if err != nil { | |
| 138 | + | panic(err) | |
| 139 | + | } | |
| 140 | + | ||
| 141 | + | if err := session.Start(cmd); err != nil { | |
| 142 | + | panic(err) | |
| 143 | + | } | |
| 144 | + | ||
| 145 | + | if patch != nil { | |
| 146 | + | _, err = stdinPipe.Write(patch) | |
| 147 | + | if err != nil { | |
| 148 | + | panic(err) | |
| 149 | + | } | |
| 150 | + | } | |
| 151 | + | ||
| 152 | + | stdinPipe.Close() | |
| 153 | + | ||
| 154 | + | if err := session.Wait(); err != nil { | |
| 155 | + | panic(err) | |
| 156 | + | } | |
| 157 | + | } | |
| 158 | + | ||
| 159 | + | func generateKeys() (sshKey, sshKey) { | |
| 160 | + | _, adminKey, err := ed25519.GenerateKey(rand.Reader) | |
| 161 | + | if err != nil { | |
| 162 | + | panic(err) | |
| 163 | + | } | |
| 164 | + | ||
| 165 | + | adminSigner, err := ssh.NewSignerFromKey(adminKey) | |
| 166 | + | if err != nil { | |
| 167 | + | panic(err) | |
| 168 | + | } | |
| 169 | + | ||
| 170 | + | _, userKey, err := ed25519.GenerateKey(rand.Reader) | |
| 171 | + | if err != nil { | |
| 172 | + | panic(err) | |
| 173 | + | } | |
| 174 | + | ||
| 175 | + | userSigner, err := ssh.NewSignerFromKey(userKey) | |
| 176 | + | if err != nil { | |
| 177 | + | panic(err) | |
| 178 | + | } | |
| 179 | + | ||
| 180 | + | return sshKey{ | |
| 181 | + | username: "admin", | |
| 182 | + | signer: adminSigner, | |
| 183 | + | }, sshKey{ | |
| 184 | + | username: "contributor", | |
| 185 | + | signer: userSigner, | |
| 186 | + | } | |
| 187 | + | } | |
| 188 | + | ||
| 189 | + | // args: tmpdir, adminKey | |
| 190 | + | var cfgTmpl = `# url is used for help commands, exclude protocol | |
| 191 | + | url = "localhost" | |
| 192 | + | # where we store the sqlite db, this toml file, git repos, and ssh host keys | |
| 193 | + | data_dir = %q | |
| 194 | + | # this gives users the ability to submit reviews and other admin permissions | |
| 195 | + | admins = [%q] | |
| 196 | + | # set datetime format for our clients | |
| 197 | + | time_format = "01/02/2006 15:04:05 07:00" | |
| 198 | + | ||
| 199 | + | # add as many repos as you want | |
| 200 | + | [[repo]] | |
| 201 | + | id = "test" | |
| 202 | + | clone_addr = "https://github.com/picosh/test.git" | |
| 203 | + | desc = "Test repo"` |