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.

Code

395 commit(s) on main

update readme Keenan Nemetz · 23m ago 32290114
source preview history blame raw 15.2 KiB
1# CLI reference
2
3The command line is Vole's admin interface. That is deliberate: if you can run
4Vole on the machine, you are the operator. There is no separate admin panel to
5secure or keep in sync.
6
7Run `vole help` for the built-in summary. If you make a usage mistake, Vole exits
8with code `129`, just like Git.
9
10## Common options
11
12| Option | Used by | Meaning |
13|---|---|---|
14| `--config <path>` | Local server management | Use a different `vole.toml` (default: `./vole.toml`, then `~/.vole/vole.toml`; `VOLE_CONFIG` overrides both) |
15| `--remote <name\|url>` | `admin`, issue, change, release, and pages commands | Git remote or instance SSH URL to talk to |
16| `--json` | `admin --remote` | Print the server's JSON response |
17| `--no-push` | `issue`, `change` | Commit locally without pushing |
18| `--dir <path>` | `init`, `workflow`, `runner` | Working or checkout directory |
19| `--branch <name>` | `pages` | Site branch (default `pages`) |
20| `--format <fmt>` | `issue list`, `change list` | Output fields such as `%(id)`, `%(number)` and `%(title)`, or `json` |
21| `-h`, `--help` | All | Print usage |
22
23Options follow Git's conventions: `--long value`, `--long=value`, `-o value`,
24`-ovalue`, bundled short options such as `-am`, repeated options, and `--` to
25end option parsing. Options may appear before or after arguments. `vole help
26<command>` and `vole <command> -h` print that command's usage.
27
28## Secrets
29
30A repository's secrets are the values its maintainers share, stored on the
31instance, encrypted, and never in the repository:
32
33```sh
34vole secret list <repo>
35vole secret set <repo> <NAME> # the value is read from stdin
36vole secret set <repo> <NAME> --from-file key.pem
37vole secret get <repo> <NAME> # the value, and nothing else
38vole secret rm <repo> <NAME>
39```
40
41`set` reads the value from standard input or a file and never from the command
42line: an argument is visible to every process on the host and lands in shell
43history. On a terminal it prompts without echoing; from a pipe it removes one
44trailing newline, so `echo "$TOKEN" | vole secret set demo DEPLOY_KEY` stores the
45token and not the line ending. `get` writes the value with no newline added, so it
46can be redirected to a file.
47
48`set` needs the maintainer role in that repository, and every read and change is
49recorded in `data/audit.log`. `list` shows names, versions, who last changed one,
50and when a value was last read — never a value. The same values appear on the
51repository's **Settings** tab, which is write-only: a saved value is not shown
52again.
53
54Names are upper-case letters, digits and `_`, so a name can be read as an
55environment variable. A value is limited to 128 KiB, the most one environment
56variable can carry.
57
58## Instance
59
60```sh
61vole admin init [--dir <path> | --config <path>]
62vole serve [--config <path>] [--log debug]
63vole version
64```
65
66## Server management
67
68`vole admin` is the single namespace for account, repository (`repo`), and access
69(`acl`) management.
70Without `--remote`, it changes the instance named by the local `vole.toml`. With
71`--remote`, it sends the same command over SSH and must be run by an instance
72admin.
73
74```sh
75vole admin account create alice --key ~/.ssh/id_ed25519.pub
76vole admin --config /srv/vole/vole.toml account list
77vole admin --remote origin account create bob --key bob.pub
78vole admin --remote ssh://git@forge.example.com:2222 account list
79```
80
81`--config` names a `vole.toml` other than the one discovery finds, and may sit on
82either side of the command (`vole admin --config P account list` and `vole admin
83account list --config P` are the same). It is local only: with `--remote` the
84server's own config is the one that applies.
85
86See [Accounts and access](accounts-and-access.md#remote-administration).
87
88`vole admin account` is the documented spelling. The old `vole admin user` form
89and the pre-admin aliases (`vole account`, `vole user`, `vole repo`, `vole acl`,
90`vole index`, and `vole gc`) remain for compatibility; documentation and help use
91`vole admin account`.
92
93### Accounts
94
95The `account` commands manage accounts.
96
97```sh
98vole admin account create [--key <file|->] [--role <role>] [--bot] <name>
99vole admin account invite <name>
100vole admin account credentials <name>
101vole admin account rm-credential <name> <credential-id>
102vole admin account sessions <name>
103vole admin account revoke-sessions [--all | <name>]
104vole admin account add-key --key <file|-> <name>
105vole admin account rm-key <name> <fingerprint>
106vole admin account retire <name>
107vole admin account role <name> <none|read|contribute|maintain|admin>
108vole admin account grant-admin <name>
109vole admin account revoke-admin <name>
110vole admin account show <name>
111vole admin account list
112vole admin account backup <path>
113vole whoami [--remote <name>] [--role]
114```
115
116Omitting `--key` creates a browser-only account and prints a one-time enrollment
117link. `--bot` creates an automation account instead: it has no browser sign-in and
118cannot be an instance admin, so it must be created with a key. `--role` sets the
119account's instance-wide role; it applies to public repositories, while `admin`
120applies to every repository. `account role` changes it later. `account invite`
121issues a fresh link for an existing account. `account backup` writes a file on the
122host, so it is local-only.
123
124The account name is the only identifier an account has. It cannot be changed: it
125is the folder a `contribute` account's branches live under, so it is fixed at
126creation and never reissued.
127
128`vole whoami` prints the account name. With `--role` it prints the effective role
129on the repository named by the remote: the repository's default and per-account
130rules, with the account's instance-wide role applied where the repository is
131public. A private repository the account cannot read is reported as not found,
132the same as a fetch.
133
134### Repositories
135
136```sh
137vole admin repo create --owner <account> <name> [--description <text>]
138vole admin repo list
139vole admin repo show <name>
140vole admin repo rename <old> <new>
141vole admin repo delete <name>
142```
143
144New repositories are private. The owner becomes the first admin.
145
146### Access
147
148Instance-wide roles are account standing; repository rules are set with `acl`:
149
150```sh
151vole admin account role <name> <none|read|contribute|maintain|admin>
152
153vole admin acl show <repo>
154vole admin acl set-role <repo> <account> <none|read|contribute|maintain|admin>
155vole admin acl set-default-role <repo> <none|read|contribute|maintain|admin>
156vole admin acl set-approvals <repo> <n>
157
158vole admin acl checks enable <repo>
159vole admin acl checks disable <repo>
160
161vole admin acl require-issues enable <repo>
162vole admin acl require-issues disable <repo>
163
164vole admin acl protect list <repo>
165vole admin acl protect add <repo> <ref-pattern>...
166vole admin acl protect remove <repo> <ref-pattern>...
167vole admin acl protect set <repo> <ref-pattern>...
168vole admin acl protect clear <repo>
169
170vole admin acl runners list <repo>
171vole admin acl runners add <repo> <account>...
172vole admin acl runners remove <repo> <account>...
173vole admin acl runners set <repo> <account>...
174vole admin acl runners clear <repo>
175```
176
177`set-role` and `set-default-role` accept `none` to remove access. `protect set`
178and `runners set` replace the whole list; the `add` and `remove` forms change one
179entry at a time. `require-issues enable` makes a linked issue mandatory when a
180new change request is opened.
181
182A protected ref pattern is either an exact ref (`refs/heads/main`) or a ref
183prefix ending in one `*` (`refs/heads/release/*`), the two shapes the hook
184understands. `protect add` and `protect set` refuse anything else, because a
185pattern that can never match would leave the branch open while `acl show` listed
186it as protected. A misspelled category is named in the refusal:
187
188```console
189$ vole admin acl protect add demo refs/head/main
190vole: protected pattern "refs/head/main" cannot match any ref: did you mean "refs/heads/main"?
191```
192
193See [Accounts and access](accounts-and-access.md) and
194[Runners](runner.md#who-can-run-jobs-and-report-results).
195
196### Maintenance
197
198```sh
199vole admin gc [--dry-run] [--grace <duration>]
200vole admin index rebuild
201```
202
203These are local-only. See [Operations](operations.md).
204
205## Issues
206
207```sh
208vole issue new --title <title> [-m <text> | -F <file>] [-l <label>]... [-a <account>]...
209vole issue comment <id> [-m <text> | -F <file>] [--reply-to <comment-id>]
210vole issue edit-comment <id> <comment-id> [-m <text> | -F <file>]
211vole issue rm-comment <id> <comment-id>
212vole issue edit <id> [--title <title>] [-m <text> | -F <file>] [-l <label>]... [-a <account>]... [--unassign <account>]...
213vole issue assign <id> <account>...
214vole issue unassign <id> <account>...
215vole issue close <id>
216vole issue reopen <id>
217vole issue list [--state open|closed|all] [-l <label>]... [--assignee <account>]... [--format <fmt>]
218vole issue show <id>
219```
220
221Ids and comment ids accept a unique prefix. See [Issues](issues.md).
222
223## Change requests
224
225```sh
226vole change new --title <title> --base <branch> [--head <rev>] [--closes <issue>]... [-m <text> | -F <file>]
227vole change list [--state open|closed|all] [--format <fmt>]
228vole change show <id>
229vole change comment <id> [-m <text> | -F <file>] [--path <file> --line <n> [--side new|old]] [--reply-to <comment-id>]
230vole change edit-comment <id> <comment-id> [-m <text> | -F <file>]
231vole change rm-comment <id> <comment-id>
232vole change update <id> [--base <branch>] [--head <rev>] [--closes <issue>]... [--no-closes]
233vole change approve <id> [--as <account>]
234vole change merge <id>
235vole change close <id>
236vole change reopen <id>
237```
238
239`change` also accepts `request`, `requests` and `cr` as compatibility aliases. An
240approval is only accepted from the account it names. `--closes` takes a full
241issue id (repeatable, comma lists accepted) and names the issues landing the
242request closes; it replaces the list on `update`, and `--no-closes` clears it.
243A request opened with `--head <branch>` follows that branch: a later push moves its
244head and invalidates the old approvals and checks. `--head <commit>` (or a tag)
245pins the request to that commit instead. `--base <branch>` on `update` retargets an
246open request, which is how a stacked request moves onto `main` after the branch
247below it lands; approvals named the old base and stop counting. See
248[Change requests](change-requests.md).
249
250`change merge` lands the request. When the combined result is still building it
251prints that the request will merge when the result passes, which is the same
252"merge when ready" a click on the page arms. `change show` prints the combined
253result and whether the landing is ready.
254
255## Releases
256
257```sh
258vole release create <tag> (-m <text> | -F <file|->)
259vole release attach <tag> <file>... [--remote <name>]
260```
261
262`create` writes the annotated tag in the current repository; push it with
263`git push --follow-tags`. See [Releases](releases.md).
264
265## Pages
266
267```sh
268vole pages deploy [<dir>] [--branch <name>] [-m <text> | -F <file>] [--dry-run] [--remote <name>]
269vole pages status [--branch <name>] [--remote <name>]
270vole pages unpublish [--branch <name>] [--remote <name>]
271```
272
273See [Sites](sites.md).
274
275## CI
276
277```sh
278vole runner --remote <ssh-url> [--once] [--jobs <n>] [--dir <path>] [--repos <name>]... [--label <name>]...
279 [--container-runtime <name>] [--container-network none|bridge]
280 [--container-pull missing|always|never] [--container-user <uid:gid>] [--container-userns <mode>]
281 [--container-memory <size>] [--container-cpus <n>] [--container-pids <n>]
282 [--cache-size <size>] [--git-cache-size <size>] [--no-cache]
283vole run list [--state <state>] [--branch <branch>] [--commit <sha>] [--limit <n>]
284 [--format <fmt>] [--remote <name|url>]
285vole run show <id> [--remote <name|url>]
286vole run logs <id> [--attempt <n>] [--step <n>] [--remote <name|url>]
287vole run cancel <id> [--remote <name|url>]
288vole run rerun <id> [--remote <name|url>]
289vole workflow check [--dir <path>]
290vole workflow list [--dir <path>]
291vole workflow run [--dir <path>] [<workflow>...] [--job <id>]...
292 [--container-runtime <name>]
293 [--container-network none|bridge] [--container-pull missing|always|never]
294 [--container-user <uid:gid>] [--container-userns <mode>]
295 [--cache-size <size>] [--no-cache]
296vole workflow dispatch --remote <name|url> --workflow <path> [--ref <branch>]
297 [--input name=value]...
298```
299
300`--jobs` is how many jobs one runner process runs at once (default 1). Each is a
301session of its own, so the container limits are per job and a machine running four
302jobs needs room for four containers. Under `--once` the runner still starts `--jobs`
303jobs, and exits when they all finish.
304
305`workflow run` executes steps in the working tree, in the job's image. It needs no
306runner, but it does read the secrets its jobs declare from the instance the
307checkout's `origin` names, using your key; a value it cannot read is left unset with
308a note, and the values it did read are masked in the output. It needs a container
309runtime; there is no host mode. Both it and
310`vole runner` reuse a job cache (see [Runners § Caching](runner.md#caching)). A
311runner also keeps a copy of every repository it builds and clones each job from it,
312so the history crosses the network once rather than once per run (see
313[Runners § Saved checkouts](runner.md#saved-checkouts)). See
314[Workflows § Check and run a workflow locally](workflows.md#check-and-run-a-workflow-locally).
315
316`workflow dispatch` queues a manual run on the instance instead. The workflow must
317declare `on.workflow-dispatch`; `--ref` defaults to the default branch, and each
318`--input` is checked against the input's declared type, options, and default. Only
319a maintainer or instance admin may dispatch.
320
321`run list`, `run show` and `run logs` are the CLI half of the runs page and a run's
322log. The queue lives on the instance, so they read it over the key you push with; any
323account that may read the repository may use them. `run list` defaults to the newest
32420 runs and narrows by status, branch or a commit id or prefix. `--format` understands
325`%(id)`, `%(shortid)`, `%(status)`, `%(workflow)`, `%(job)`, `%(branch)`, `%(sha)`,
326`%(trigger)`, `%(trigger_title)`, `%(exit)`, `%(attempts)`, `%(log)` and `%(created)`.
327
328`run show` prints the run's status, commit, trigger, steps with their exit codes and
329durations, each attempt's log size, the published artifacts, and whether the result
330counts as a check. The id is the 26-character one on the run page; `vole change show`
331also lists the head's runs, and the combined result's runs when there is one, so a
332reviewer can copy the failing id without opening the browser.
333
334`run logs` writes the bytes the runner wrote to stdout, with nothing added, so it can
335be redirected or piped. It opens the attempt the run is on, or the newest logged
336attempt once the run has finished; `--attempt` picks a retry and `--step` narrows the
337output to one step's range inside it. A refusal goes to stderr, so a redirect produces
338a log or an empty file.
339
340`run cancel` is the CLI counterpart of the cancel button on a run page. A queued run
341is canceled outright, and a running one is asked to stop, with its runner stopping at
342the next heartbeat. `run rerun` queues a finished run again with the same pinned job.
343Only a maintainer or instance admin may do either, and `data/audit.log` records the
344account, the repository, and the run (`run.cancel` or `run.rerun`).
345
346## Internal
347
348`vole hook pre-receive|post-receive` is installed in repositories by Vole. It is
349not intended to be run by hand.
350