pico

created pr with 13.1 on 2024-07-22T18:12:32Z · by 964fa508
added 13.2 on 2024-07-22T18:36:17Z · by c8ef7d19
-: ------- > 1: 605c47b nice!
1: be8edcf = 2: 605c47b contrib: add dev script
changed status to accepted on 2024-07-22T18:36:17Z · by c8ef7d19
cmds
checkout latest patchset:
ssh pr.pico.sh print 13 | git am -3
checkout any patchset in a patch request:
ssh pr.pico.sh print 13.[rev] | git am -3
add changes to patch request:
git format-patch main --stdout | ssh pr.pico.sh pr add 13
set PR to open (enables RSS notifications):
ssh pr.pico.sh pr open 13
set PR to draft (stops RSS notifications):
ssh pr.pico.sh pr draft 13

Patchset 13.1 on 2024-07-22T18:12:32Z · commit be8edcf

contrib: add dev script
jolheiser 2024-07-22T18:05:39Z
This 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"`
+6 -0 fixtures/fixtures.go #
......@@ -0,0 +1,6 @@
1+package fixtures
2+
3+import "embed"
4+
5+//go:embed *
6+var Fixtures embed.FS
Back to top