Skip to content

Contributing

Mason Rowe edited this page Oct 31, 2026 · 1 revision

Contributing

In short

YABS is a single bash file maintained conservatively: minimal diffs, extreme portability, and edge cases tested in containers before anything lands. Contributions are welcome via issues and pull requests — but read the conventions below first, because the maintainer's bar for merging is "does it help the majority of VPS users without breaking the weird ones".

Repo layout

yet-another-bench-script/
├── yabs.sh                      # the entire product — ~1200 lines of bash
├── README.md                    # user docs (has a few known stale bits)
├── LICENSE                      # WTFPL
├── AGENTS.md                    # maintainer/agent notes — worth reading before editing
├── bin/
│   ├── README.md                # binary build docs
│   ├── compile.sh               # native (x86_64) build in Holy Build Box
│   ├── cross-compile.sh         # musl cross build, driven by ARCH/CROSS/HOST
│   └── example.json             # JSON schema example (stale: v2023-04-23)
└── .github/workflows/
    ├── ci.yml                   # ShellCheck gate on push to master
    ├── build-fio.yml            # fio release pipeline
    └── build-iperf3.yml         # iperf3 release pipeline

The fio/iperf3 binaries are not in the repo — they're release assets built by the workflows. See Precompiled Binaries.

A typical fix goes: reproduce (ideally in a named container) → edit yabs.sh → bash -n → ShellCheck → regression-diff old vs new (-f -i -g -n and -h) → describe the evidence in the issue/PR.

The maintainer's rules of the road

  • No dependency additions. The whole point is zero deps and no root. Solutions must use POSIX-ish tools already in play (awk, sed, grep, df, stat…) or degrade gracefully.
  • JSON is a public schema. Third-party sites consume it — additive changes only, never rename keys or change value formats/units. See JSON Output.
  • Minimal, surgical diffs. Match the file's conventions: tab indentation, lowercase comments that explain why (not what), no gratuitous reformatting or comment churn.
  • No noise features for the majority audience. E.g. printing disk model names was declined (#106) as noise for most VPS users.
  • iperf server changes are 1:1 swaps. The list is donated bandwidth; additions must improve diversity/capacity as a swap, not grow the list. See Tests: Network.
  • YABS_VERSION bumps are the maintainer's job — done inside the same commit as the change; don't bump it in a PR.
  • Commit messages: short, lowercase, imperative, issue number in parens — e.g. fix for disk size over-counting with btrfs subvolumes/bind mounts (#130), add tar check and clearer error message for geekbench (#99).
  • The maintainer commits/pushes/tags/releases manually — don't expect contributors to do any of that.

Testing your change

The standard verification battery:

# syntax
bash -n yabs.sh

# ShellCheck — exactly what ci.yml runs (shellcheck isn't assumed installed)
docker run --rm -v "$PWD/yabs.sh:/y.sh:ro" koalaman/shellcheck:stable -S warning /y.sh

# smoke test: system info only, no tests, exits in seconds
bash yabs.sh -f -i -g -n

# dry-run: flag/binary/connectivity detection output
bash yabs.sh -h

# workflows changed? lint them too
docker run --rm -v "$PWD:/repo:ro" rhysd/actionlint:latest /repo/.github/workflows/*.yml

Regression check: run the unmodified and modified scripts side by side with -f -i -g -n and -h, and diff the output — only the uptime/date/runtime lines should differ.

Portability testing in containers

The project's historical bugs are portability bugs. Docker images used for testing (no sudo needed):

Image What it exercises
alpine:3.20 BusyBox userland — df without -t/--total, no grep -P, musl
busybox:1.36-musl bare-minimum BusyBox
almalinux:9-minimal minimal RHEL-ish — no tar (the #99 case)
debian:12-slim typical Debian minimal
ubuntu:25.10 uutils Rust coreutils — Ubuntu's new default
opensuse/tumbleweed container has no awk (real installs do)
docker run --rm -v "$PWD/yabs.sh:/y.sh:ro" alpine:3.20 sh -c 'apk add bash >/dev/null && bash /y.sh -f -i -g -n'

--privileged containers can mount loop devices — how the btrfs-subvolume disk-counting bug (#130) was reproduced.

Style quick reference

Convention Rule
Indentation tabs
Comments lowercase, explain why; don't narrate the code
Version string maintainer bumps YABS_VERSION in the release commit — leave it alone
Commit messages short, lowercase, imperative, (#NNN) issue ref
JSON additive only; never rename keys or change units
Messages to users quoted literally, terse, actionable where possible

Hard-won portability rules (don't relearn these)

  • Never stat -f an unfiltered mount — stale NFS/CIFS mounts can hang the run. Filter by fstype first.
  • Redirection order silences correctly one way: done 2>/dev/null < file, not done < file 2>/dev/null (leaks "No such file").
  • Keep arithmetic in awk — bc is not universal (#79).
  • LC_ALL=C is exported early — parsing must stay locale-stable.

What to work on

Open an issue before a large change so the approach can be agreed first — several past PRs were declined on the principles above rather than on code quality. Good first contributions historically look like: concrete bug with repro (ideally a container recipe), portability fix with evidence on the affected userland, or a docs fix. For binary/toolchain work, see GitHub Actions Automation — and run bin/cross-compile.sh on a copy in a scratch dir, not in the repo.

Proposing an iperf server change

The server list is donated bandwidth, so the rule is 1:1 swap only: identify which existing entry your proposal replaces, and argue it on geographic/provider diversity, port-range depth, or link capacity. Pure additions get declined regardless of how good the server is — see the two parked PRs (#125, #115) held for a future assessment.

Filing a good bug report

Include: the YABS_VERSION from the banner, uname -a, distro, the exact flags, and the exact output. For portability bugs, a Dockerfile or image name that reproduces the failure is worth more than paragraphs of description — most historical fixes trace back to a reproducible minimal environment (a container, a VM image, a specific fstype).

See also

Clone this wiki locally