Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/vole.git

Write over SSH with a registered key:

git clone ssh://git@rodent.software:2222/vole.git

A free and open-source forge that lives in your Git repo.

Read a run and its log from the CLI

92d8afc86ab7a5e8f2e56a8981e0614aa55980f1 · Keenan Nemetz · 3h ago · parent 4b8c9e1d

Read a run and its log from the CLI

The queue and its logs live on the instance, so the CLI now has read verbs
beside the cancel and rerun writes: run list, run show and run logs. They
check the repository's read capability, scope an id to its repository, and
stream a log to stdout with refusals on stderr.

change show lists the runs for the head and, when the landing needs one, the
combined result, so a red check carries the id needed to open it. The queue
search narrows by status, branch and commit prefix without a pager.

closes: 01M6YZAQZVJWTA9BA5RV2H6PQ8

server/ssh/sshserver_test.go +6−2

@@ -18,6 +18,7 @@ import (
18 18
19 19 xssh "golang.org/x/crypto/ssh"
20 20
21 "rodent.software/vole/ci/logs"
21 22 "rodent.software/vole/ci/runs"
22 23 "rodent.software/vole/core/lfs"
23 24 "rodent.software/vole/forge/access"
@@ -77,7 +78,8 @@ type harness struct {
77 78 roKey string // private key file for the read-only user
78 79 repoName string
79 80 runs *runs.Store // the CI queue the runner verb serves
80 objects *lfs.Store // where a run's log and artifacts are checked for
81 logs *logs.Store // the attempt logs the run verbs serve
82 objects *lfs.Store // where a run's artifacts are checked for
81 83 writerID string // the account id the writer's key belongs to
82 84 }
83 85
@@ -147,12 +149,14 @@ func newHarnessWith(t *testing.T, tweak func(*Config)) *harness {
147 149 }
148 150 t.Cleanup(func() { queue.Close() })
149 151 objects := lfs.New(filepath.Join(dir, "objects"), 1<<20)
152 logStore := logs.New(filepath.Join(dir, "logs"))
150 153
151 154 log := slog.New(slog.NewTextHandler(io.Discard, nil))
152 155 cfg := Config{
153 156 Identity: ident,
154 157 Repos: rs,
155 158 Runs: queue,
159 Logs: logStore,
156 160 LFS: objects,
157 161 Log: log,
158 162 HostKeyPath: filepath.Join(dir, "host_key"),
@@ -175,7 +179,7 @@ func newHarnessWith(t *testing.T, tweak func(*Config)) *harness {
175 179 return &harness{
176 180 t: t, dir: dir, addr: ln.Addr().String(), ident: ident, repos: rs,
177 181 srv: srv, keyPath: writer, roKey: reader, repoName: "demo",
178 runs: queue, objects: objects, writerID: writerID,
182 runs: queue, logs: logStore, objects: objects, writerID: writerID,
179 183 }
180 184 }
181 185