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.
README.md +9−1
| @@ -82,6 +82,7 @@ never confirms that it is there. | |||
| 82 | 82 | | Publish a release | [Releases](docs/releases.md) | | |
| 83 | 83 | | Host a website from a repository | [Sites](docs/sites.md) | | |
| 84 | 84 | | Back up or recover an instance | [Operations](docs/operations.md) | | |
| 85 | | Install a `.deb` or `.rpm` | [Packages](docs/packaging.md) | | ||
| 85 | 86 | ||
| 86 | 87 | Reference: [CLI commands](docs/cli.md) · [Architecture](docs/architecture.md) | |
| 87 | 88 | ||
| @@ -91,9 +92,16 @@ Full index: [docs/README.md](docs/README.md). | |||
| 91 | 92 | ||
| 92 | 93 | ```sh | |
| 93 | 94 | go test ./... | |
| 94 | ./scripts/ci.sh # everything CI runs, before you push | ||
| 95 | vole workflow run ci # everything CI runs, before you push | ||
| 95 | 96 | ``` | |
| 96 | 97 | ||
| 98 | The checks live in [`.vole/workflows/ci.yaml`](.vole/workflows/ci.yaml), so the | ||
| 99 | workflow and `vole workflow run ci` cannot drift apart: a local run executes the | ||
| 100 | steps in the same image, so it needs a container runtime (Docker, Podman, or | ||
| 101 | nerdctl) rather than the tools installed on your `PATH`. The workflow needs network | ||
| 102 | for module downloads, which is why the runner that takes it is started with | ||
| 103 | `--container-network bridge`; the local run defaults to the same network. | ||
| 104 | |||
| 97 | 105 | Vole is also usable as a Go library. See | |
| 98 | 106 | [Architecture § Using Vole as a library](docs/architecture.md#using-vole-as-a-library). | |
| 99 | 107 | ||