RigForge follows Semantic Versioning. The current version is
tracked in VERSION and the history in CHANGELOG.md.
- MAJOR: incompatible
config.json/ CLI / behavior changes. - MINOR: new, backwards-compatible functionality.
- PATCH: backwards-compatible fixes.
From 1.0.0 on, the config.json and CLI surface is stable, so a breaking change bumps MAJOR. (Pre-1.0
0.x releases could break the interface between minor versions while it settled.)
Work lands on develop (the integration branch); a release is the point where develop is
promoted to main and tagged. The steps below build the release commit on develop, merge it to
main, and tag from main.
-
Ensure
developis green:make test(andmake test-e2eif Docker is available). -
Full real-hardware e2e (the release gate). CI exercises everything it can (lint, the dependency-free suite, the Docker
/etce2e, the coverage gate), but it can't compile XMRig, reserve HugePages, write MSRs, set the governor, or actually hash. So on a real Linux rig, run the genuine deploy end to end and assert each step:sudo bash tests/e2e-real.sh provision # real deps + XMRig build + tuning + kernel tuning + service sudo reboot # HugePages (1G + GRUB cmdline) take effect on boot; reconnect sudo bash tests/e2e-real.sh verify # doctor (HugePages/MSR/governor/service) + bench (real H/s) + a short tune + a live auto-tune pass sudo bash tests/e2e-real.sh control # the writable control path (#236) against real systemd: enable, POST a change, poll to applied, revert sudo bash tests/e2e-real.sh upgrade # the remote-upgrade chain (#308/#322) with REAL git: noop + refused-tag rollback legs, revert (opt-in forward leg: E2E_UPGRADE_TARGET=vX.Y.Z) sudo bash tests/e2e-real.sh perf # offline bench vs the committed per-host baseline + best-ever history (the release perf gate) sudo bash tests/e2e-real.sh teardown # uninstall + assert a clean revert
When a live Pithead stack is reachable, also run the worker↔stack contract gate (stack on its latest release tag — record
pithead versionin the run log). It asserts the mining round-trip, the:8080API contract, stratum auth (passE2E_STRATUM_PASSif the stack uses one), dashboard visibility (E2E_DASH_URL), and that the sister API does not shave hashrate under polling load:PITHEAD_URL=gouda.lan:3333 sudo -E make e2e-pithead
Both gates carry the standardized performance checks (see
tests/README.md› Performance testing):e2e-real'sperfphase compares the offline bench against the committed per-host baseline intests/perf-baselines/, ande2e-pithead'sapi-impactphase proves the sister API doesn't shave live hashrate. A perf regression fails the gate — investigate or consciously re-record the baseline before tagging.Each phase must report
E2E-REAL (<phase>): PASS. This proves a release bundle actually builds, tunes, and hashes on real hardware, which the suites can't since they all stub XMRig.- Put a real, reachable pool in
config.jsonfirst. Without one,setupwrites an unroutable placeholder andverifyfails the connect + share-submission round-trip. That round-trip is mandatory, since proving the rig really mines is the whole point of the gate. Pointpools[0].urlat a real low-difficulty pool you control (e.g. the stack's test pool). For a deliberate offline smoke run with no pool on hand, setE2E_ALLOW_OFFLINE_POOL=1to downgrade it to an explicit skip. - Quick subset:
make smoke(bench-only) is the fast version when you just need to confirm a built worker still hashes; the fulle2e-realflow above supersedes it for a real release. - Kept out of CI on purpose (a real build + HugePages + mining are flaky by nature and against Actions' ToS); it's a manual pre-tag gate the releaser runs.
- Put a real, reachable pool in
-
In
CHANGELOG.md, move the## [Unreleased]entries under a new## [X.Y.Z] - YYYY-MM-DDheading, then leave a fresh empty## [Unreleased]above it. -
Bump
VERSIONtoX.Y.Z. -
Commit the two together on
develop:git commit -am "release: vX.Y.Z" git push origin develop -
Promote
developtomainthrough a pull request —mainis a protected release branch, so the promotion goes through a reviewable PR (its own gate + audit trail), not a direct push:gh pr create --base main --head develop --title "release: vX.Y.Z" \ --body "Promote develop to main for the vX.Y.Z release."
Review and merge it. Keep
mainlinear with a fast-forward (rebase) merge so the tag sits on the same commit asdevelop's release commit:gh pr merge --rebase --admin # fast-forward main to develop; --admin lets the releaser merge -
Tag and push from
main(annotated tag, matchingVERSION) once the PR is merged:git checkout main && git pull --ff-only origin main git tag -a vX.Y.Z -m "RigForge vX.Y.Z" git push origin main --follow-tags
Pushing the tag triggers the release pipeline
(.github/workflows/release.yml), which:
- verifies the tag matches
VERSION(the build fails otherwise), - packages the deploy bundle (
rigforge.sh,util/,systemd/,config.minimal.json,config.reference.json,README.md,docs/,images/,LICENSE,VERSION) asrigforge-vX.Y.Z.zipand.tar.gz(tests/,.github/, and other dev files are excluded), - generates
SHA256SUMSfor the artifacts, - pulls that version's section from
CHANGELOG.mdas the release notes, - creates the GitHub Release as a draft. Review the generated notes and bundles, then click
Publish (pre-1.0
0.xtags are marked pre-release;1.0.0+ are full releases).
After the fleet is re-tagged, record each rig's benchmark for the release
(E2E_PERF_TAG=vX.Y.Z E2E_PERF_RECORD=1 sudo bash tests/e2e-real.sh perf on the rig) and commit
the updated tests/perf-baselines/ files — the per-release history is what lets the perf gate
catch slow drift across releases (see tests/perf-baselines/README.md). The recording is also
the per-rig perf gate (#214): it judges against the committed baseline and best-ever history
before writing, refuses to record a regressed number (fix it, or consciously override with
E2E_PERF_FORCE=1), so a failed rig means investigate before calling the fleet healthy. Once the collected
baselines are merged, reset each rig's copy (sudo git checkout -- tests/perf-baselines/ in
/opt/rigforge): the recording dirties the rig's checkout, and the next release's
git checkout <tag> aborts on exactly those files (this bit both the v1.4.0 and v1.5.0 deploys).
To verify a downloaded bundle: sha256sum -c SHA256SUMS (see
SECURITY.md › Release integrity).
The release is created as a draft so a human reviews it before it goes public, a deliberate gate for a tool that installs a root miner. Drop
--draftfromrelease.ymlto auto-publish on tag instead.
- Keep
VERSIONand the latestCHANGELOG.mdheading in lock-step; the test suite checksVERSIONis valid SemVer. VERSIONis also surfaced at runtime:rigforge.sh version(or--version/-v) reads it, so a release tag, the changelog heading, and what the script reports all stay in agreement.