Files
stalwart-migrator/CONTRIBUTING.md
T
jcoffey-dev da31f415f8
github/ci (branch) GitHub Actions
ci / test (pull_request) Skipped
ci / release (pull_request) Skipped
ci / github (pull_request) Successful in 28s
ci / announce (pull_request) Skipped
CONTRIBUTING: how to send a change without repository access
New accounts on git.coffeylabs.org can file issues but can't push or fork.
Until a volunteer is given access, a change arrives as a patch on an issue.
2026-10-11 01:02:33 -07:00

3.4 KiB

Contributing to stalwart-migrator

How to build and test the tool, and where its design is written down. For what the tool does and how to use it, see the README.

Sending a change

New accounts on git.coffeylabs.org can file issues but can't push or fork. Until you have repository access, open an issue for the change, or say hello on community.coffeylabs.org, and attach the change to the issue as a patch:

git format-patch origin/main --stdout > my-change.patch

Repository access goes to volunteers we have worked with; a few good issues or patches is the usual way in. After that you push a branch here and open a pull request. The GitHub copy is a read-only mirror, so pull requests opened there are not merged.

Build and test

go build ./...
go test ./...

Requires Go 1.26.8 or newer. The tool is Go standard library only — no external dependencies — and nothing third-party is vendored.

To try a command from a checkout without installing it:

sudo go run ./cmd/stalwart-migrate preflight

docs/rehearsal.md explains why even read-only commands need write access to the checkpoint directory.

Releases

Releases are tagged by date, like ihasmail's: v2026.9.15, with .1, .2 added for another release the same day. Binaries for linux/amd64 and linux/arm64 and a SHA256SUMS file are attached to every release.

Every release is built by the release workflow from a tagged commit on main, after the tests and a known-vulnerabilities check pass. The archives are reproducible: scripts/build-release.sh builds the same bytes from the same commit, so a release can be checked before tagging:

scripts/build-release.sh v2026.9.15 dist

If a pushed tag's run never starts, run the workflow by hand from the Actions tab and give it the tag.

Why not a shell script

Stalwart's 0.15 → 0.16 boundary is not a drop-in binary swap: settings move, and the data directory has to be migrated rather than merely copied. The failure mode that matters is a half-migrated mail store with no way back — which is why backup verification and checkpointing are the design center rather than conveniences bolted on afterwards — and why the tool refuses to cut over until you confirm you have a way back.

Where the design is written down

ARCHITECTURE.md covers the design in full: §1 on why a thin wrapper is insufficient, §4 on the migration phases, §5 on the checkpoint state machine, §6 on the CLI surface, and §8 on what is still open. It was written before the implementation and records the reasoning; where it and the code disagree about current behavior — the flags shown in §6, for example — the code and stalwart-migrate <command> -h are right.

docs/status.md has the state of each command and package, and what has been tested against real servers.

Testing against something real

Where a phase runs an external program, its tests drive a fake one. That is sound for logic and ordering, and it is not evidence about production. Before trusting a change to a migration path, run it on a clone of a real server — see Rehearse on a clone first.