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/git/vole.git

Write over SSH with a registered key:

git clone ssh://git@0.0.0.0:2222/vole.git

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

Store CI run records in the database, not the repository

b312e1660ac3d570fc35350a22b3514c56ab466f · Keenan Nemetz · 11d ago · parent db5e4382

Store CI run records in the database, not the repository

A finished attempt was a set of files on the vole branch: a record, step
ranges, and artifact pointers, pushed as a commit. At 959 files, CI records
were 849 of them, and every human metadata write had to carry them.

The runner now sends the record with its finish message over the SSH channel
that holds the lease. The server checks the account, the job, and the log and
artifact pointers, then writes the attempt, steps, artifacts, attestation, and
run result in one transaction in data/runs.db. A tagged build still pushes its
release pointers to the branch after the record is stored.

Pre-receive refuses a new runs/ file. vole admin index rebuild imports records
still on an old branch; records written since are never deleted by a rebuild.
The run page reads the stored attempt, and runs.db is now a source that must be
backed up.

This stops new CI history from entering Git. Existing commits keep the records
they already have; removing those would require rewriting the protected vole
branch, which this change does not do.

docs/operations.md +26−11

@@ -51,6 +51,7 @@ Back up the instance state:
51 51
52 52 ```sh
53 53 vole admin account backup backup/users.db # accounts, keys, sessions, rules, locks, views
54 sqlite3 data/runs.db ".backup 'backup/runs.db'" # CI history, queue, and approvals
54 55 cp data/ssh_host_ed25519_key backup/ # the SSH host key
55 56 cp -a data/acme backup/ 2>/dev/null # TLS account key and certificates, if ACME is on
56 57 cp data/audit.log backup/ 2>/dev/null # history of admin actions
@@ -58,7 +59,8 @@ cp data/audit.log backup/ 2>/dev/null # history of admin actions
58 59
59 60 `vole admin account backup` takes a consistent copy, even while Vole is running. Copying
60 61 `users.db` by hand can miss recent changes that have not been written to the main
61 database file yet.
62 database file yet. Do the same for `runs.db` with SQLite's backup command; copying it
63 by hand while the server is writing can miss WAL pages.
62 64
63 65 If you lose the account database, you need to recreate accounts and re-enroll
64 66 their passkeys. You do not lose repositories. The backup contains account metadata,
@@ -66,14 +68,17 @@ public keys, and hashes of session and enrollment tokens; it does not contain a
66 68 usable password or a plaintext session token. Treat it as private anyway.
67 69
68 70 Repositories are ordinary Git repositories under `data/repos/`. You can back them
69 up by copying or cloning. Issues, change requests, releases, and CI records travel
70 with them because they are stored in Git.
71 up by copying or cloning. Issues, change requests, and releases travel with them
72 because they are stored in Git. CI history does not: it lives in `data/runs.db` and
73 must be backed up with it.
71 74
72 75 ## Restore an instance
73 76
74 1. Restore `data/users.db`, `data/ssh_host_ed25519_key`, `data/audit.log`, and
75 `data/acme/` if the instance obtains its own TLS certificates.
76 2. Restore the repositories under `data/repos/`.
77 1. Restore `data/users.db`, `data/runs.db`, `data/ssh_host_ed25519_key`,
78 `data/audit.log`, and `data/acme/` if the instance obtains its own TLS
79 certificates.
80 2. Restore the repositories under `data/repos/` and the object store under
81 `data/lfs/` if you keep CI logs and artifacts.
77 82 3. Run `vole admin index rebuild`.
78 83 4. Run `vole admin account revoke-sessions --all` so sessions from the restored copy
79 84 cannot outlive their cookies.
@@ -94,6 +99,12 @@ fetched, but only a maintainer can push them; existing change requests still nam
94 99 the same head commit. A contributor who wants to keep working pushes the same
95 100 commit under their new folder and opens a request from it.
96 101
102 CI records moved from the `vole` branch to `data/runs.db`. Upgrade the server and
103 its runners together: an older runner's finish message carries no record and is
104 refused. Run `vole admin index rebuild` once after upgrading to import any records
105 still on a repository's branch, and start backing up `runs.db`. A job that was
106 running during the upgrade may need to be rerun.
107
97 108 Large files, CI logs, and build artifacts live in `data/lfs/`. Back that directory
98 109 up too if you need those files. `vole admin gc` treats files reachable from a
99 110 repository, an archived CI log, or a published artifact as things to keep.
@@ -124,10 +135,14 @@ storage only grows when someone pushes files.
124 135 vole admin index rebuild
125 136 ```
126 137
127 `data/runs.db` holds the CI queue, run index, and contributor-branch CI approvals. Deleting it loses attempts that
128 were in progress. Vole queues current branch and tag tips again from Git, and
129 `vole admin index rebuild` restores finished history from the run records on each
130 repository's `vole` branch.
138 `data/runs.db` holds the CI queue, finished-run records, and contributor-branch CI
139 approvals. It is a source of truth, not a rebuildable index: deleting it loses CI
140 history as well as attempts that were in progress. Back it up with the rest of the
141 instance.
142
143 `vole admin index rebuild` imports run records that are still on an older
144 repository's `vole` branch. It cannot restore records written after CI history moved
145 into the database; only a `runs.db` backup can do that.
131 146
132 147 ## Security notes
133 148
@@ -197,7 +212,7 @@ the linked sections explain each in full.
197 212 - **Quotas.** Every repository is bounded, so one contributor or maintainer cannot
198 213 make every page slow or fill the disk: `repo_max_refs` (500), `repo_max_metadata_entries`
199 214 (2000) and `repo_max_metadata_bytes` (32 MiB) of documents on the metadata branch
200 (issues, requests, comments, approvals, run and release records),
215 (issues, requests, comments, approvals, and release records),
201 216 `repo_max_bytes` (5 GiB) of Git objects, and `repo_max_lfs_bytes` (10 GiB) of
202 217 LFS objects, logs and artifacts. The checks run in pre-receive, so a refused push
203 218 moves no refs, and the object bound is enforced on upload. When one bites, the