rmqa 0.1 Checks a Software Release Before You Publish It
A release is a handful of files. An archive for Linux on Intel, one for Linux on ARM, two for macOS, a zip for Windows, a checksums file. Every one of them was produced by a pipeline that went green, and yet the set can still be wrong in ways nobody looks for: the ARM archive holds the Intel build, the Intel Mac archive still has last week’s program inside, the license is missing from the zip.
rmqa 0.1 looks for exactly that. You describe once what every release must contain, and before you publish, rmqa opens the real archives and the real programs and checks them against the description, file by file.

What It Checks
For each download the manifest expects, rmqa checks that it’s there, that it isn’t empty, and that it opens. Inside each archive it checks:
- The right program for the platform. rmqa reads the program’s header, ELF, Mach-O or PE, and compares the operating system and processor with the download it sits in. An amd64 build in the arm64 archive is an error, and so is a Linux build in the macOS download.
- The right version. The program must contain the version string. With
run = ["--version"], rmqa also runs the build for its own machine and reads the version back. - The executable permission. A program that lost its executable bit in a tar archive gets an error, because every user will hit “permission denied”.
- The files that must ship with it. LICENSE, NOTICE, a README, whatever the manifest lists. Present and not empty.
- The files that must never ship.
.env, private keys,.gitfolders. And clutter such as.DS_Store, as a warning. - Safe paths. An entry that would unpack outside the target folder, through
../or an absolute path or a link, is an error.
Across the release, it checks that no two platforms ship the same program byte for byte, that the checksums file matches every file and lists every file, and that nothing is in the release that the manifest doesn’t mention.
Two Commands
rmqa init writes the manifest from a release you know is good. It finds the programs, works out their platforms, and turns the file names into a template, so tidy_linux_arm64.tar.gz and its four siblings become one line: name = "tidy_{os}_{arch}.{archive}".
rmqa check checks a release against it, from a folder or straight from GitHub, drafts included. It exits with status 0 when the release is ready and 1 when it isn’t, which makes it a gate in any CI system. With --format github, each problem appears as an annotation on the GitHub Actions run, and there’s a ready-made GitHub Action as well.
Small on Purpose
rmqa is one program written in Go with the standard library only. It reads .tar.gz, .tgz, .tar.bz2, .tar, .zip and .gz archives, and Linux, macOS and Windows programs, including macOS universal binaries. It doesn’t build anything, sign anything or upload anything. It sits after your build tool, whichever one that is, and before the publish button.
It also checks its own releases. The release workflow builds rmqa for five platforms, then runs rmqa on the result, and only publishes if it passes. How rmqa was tested covers that, and the bug that first self-check turned up.
The code is open source under the Apache License 2.0. The binaries are on the download page, and the quick start goes from nothing to a checked release in a few minutes.