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.

Add packaging, a CI workflow, and containerised local runs

3b39a84c913cabe15bfa6a60dd176ff2dd28d241 · Keenan Nemetz · 15d 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/nfpm.yaml +52

@@ -0,0 +1,52 @@
1 # nfpm builds both the .deb and the .rpm from this file. The release workflow
2 # renders it once per architecture, with VERSION and ARCH supplied:
3 #
4 # ARCH=amd64 VERSION=0.2.0 nfpm package -f packaging/nfpm.yaml -p deb -p rpm -t dist
5 #
6 # See docs/packaging.md.
7 name: vole
8 arch: ${ARCH}
9 platform: linux
10 version: ${VERSION}
11 release: "1"
12 section: devel
13 priority: optional
14 maintainer: Keenan Nemetz <keenan.nemetz@gmail.com>
15 vendor: Rodent Software
16 homepage: https://github.com/rodent-software/vole
17 license: Apache-2.0
18 description: |
19 A small software forge that lives in your Git repository.
20
21 Code, issues, change requests, approvals, releases, and CI records live in Git.
22 One binary, one config file, no extra services to operate.
23 depends:
24 # The server shells out to git for every push, clone, and metadata write.
25 - git
26 contents:
27 - src: dist/vole-linux-${ARCH}
28 dst: /usr/bin/vole
29 # nfpm only expands ${...} in a source path when asked to.
30 expand: true
31 file_info:
32 mode: 0755
33 - src: packaging/systemd/vole.service
34 dst: /usr/lib/systemd/system/vole.service
35 file_info:
36 mode: 0644
37 # An operator's edits survive upgrades: rpm gets %config(noreplace), deb gets a
38 # conffile. Changing this file is how you set public_url, pages_domain, or a
39 # different listen address.
40 - src: packaging/vole.toml
41 dst: /etc/vole/vole.toml
42 type: config|noreplace
43 - src: LICENSE
44 dst: /usr/share/doc/vole/LICENSE
45 file_info:
46 mode: 0644
47 - src: NOTICE
48 dst: /usr/share/doc/vole/NOTICE
49 file_info:
50 mode: 0644
51 scripts:
52 postinstall: packaging/scripts/postinstall.sh