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.

Add packaging, a CI workflow, and containerised local runs

3b39a84c913cabe15bfa6a60dd176ff2dd28d241 · Keenan Nemetz · 14d ago · parent 30a72490

Add packaging, a CI workflow, and containerised local runs

A v* tag now builds a .deb and a .rpm for amd64 and arm64 with nfpm and attaches them, with checksums, to the release. The package ships the systemd unit, a config at /etc/vole/vole.toml, and a postinstall that creates the service account and prepares the instance that config names; `vole admin init --config` is what makes that possible, and the binary's version is stamped from the tag instead of the source tree.

scripts/ci.sh becomes .vole/workflows/ci.yaml, so `vole workflow run ci` executes exactly what a push runs, and the Markdown link check moves to scripts/check-links.py. Local runs now always execute in the job image and share ci/container with the runner; --no-container is gone, because a run in a different environment proves nothing about CI.

The runner mounts a per-repository namespace at /cache and sets no variable for it: a job opts in through its image's env or the new job-level env, which is pinned with the queue and delivered with the lease. Whole namespaces are evicted least-recently-written first so a module cache is never half-deleted, and contributor branches get their own namespace so an untrusted tip cannot seed the cache a protected branch builds into.

Running the suite in that container found four bugs worth naming: /tmp was mounted noexec, which broke `go test` and `go run`; the read-only root is gone, because images make toolchain directories world-writable deliberately and the mount set is what protects the host; OpenSSH needs a passwd entry for the job's uid; and a lost metadata push reported as "cannot lock ref" was not classified as a race, so concurrent CLI writes gave up on the first collision. That retry now backs off exponentially with jitter.

packaging/scripts/postinstall.sh +26

@@ -0,0 +1,26 @@
1 #!/bin/sh
2 # Runs after install and after every upgrade, as root, for both .deb and .rpm.
3 #
4 # It creates the service account and prepares the instance the shipped config
5 # names. It does not create an administrator or start the service: on Debian the
6 # package manager starts enabled units itself, and on RHEL the unit is not enabled
7 # until an operator does it. Either way, who may administer the instance is the
8 # operator's decision, not the package's.
9 set -e
10
11 if ! getent group vole >/dev/null 2>&1; then
12 groupadd --system vole
13 fi
14 if ! getent passwd vole >/dev/null 2>&1; then
15 useradd --system --gid vole --home-dir /var/lib/vole --no-create-home \
16 --shell /usr/sbin/nologin --comment "Vole software forge" vole
17 fi
18
19 install -d -o vole -g vole -m 0750 /var/lib/vole
20
21 # Init is idempotent: it leaves an existing config, repository tree, and database
22 # alone. Running it as the service account keeps the data it creates writable by
23 # the service, and a failed upgrade never leaves root-owned state behind.
24 su -s /bin/sh vole -c 'umask 0027; /usr/bin/vole admin init --config /etc/vole/vole.toml' </dev/null
25
26 exit 0