Design an ideal reproducibility testing tool
60-minute session on day 3
Exercise in README driven development: think what the user documentation could be for the perfect tool to answer the question “How can I know if a piece of software is reproducible?”
This tool is intended for developers who want to test whether their software is reproducible.
Let’s call it “reprotest”.
Typical usage
$ git clone https://github.com/foo/bar.git
$ cd bar
$ reprotest ./build.sh
Exit status :
0
if reproducible1
if not2
in case of problems
Provide useful information in both cases, links to reproducible documentation.
Variations
The default is to do all possible variations. The first thing tested will be the software in its current environment—with whichever tools the developer has in their normal environment. If it is shown to be reproducible there, it will attempt to try other environments similar to the systems which reported it unreproducible (e.g. reproducible.debian.net).
To control which variations are being tested:
$ reprotest --keep-same=buildpath build.sh
$ reprotest --variations=date build.sh
# fail with something like:
# Sorry, date is not supported in direct mode
# (or do we want to use libfaketime?)
$ reprotest --variations=date --runner=virtualbox build.sh
$ reprotest --variations=date --runner=qemu --qemu-image=debian-sid.img build.sh
$ reprotest --variations=cpu,kernel,user,domain,date,filesystem make
(filesystem will use disorderfs)
Artifacts
To control which artifacts will be compared at the end of the build:
# do not consider *.o file as files that need to match
$ reprotest --ignore=*.o build.sh
# only do a diff of *.deb files to determine if the thing is reproducible or not
$ reprotest --accept=*.deb dpkg-buildpackage
Commands
To compare different commands:
$ reprotest --command='make' --command='make CFLAGS=-g' --command='make CFLAGS=-O3'
Project configuration file
If you have a .reprotest
file in the current directory, you can run reprotest without
any arguments to use the command and variations specified there:
$ reprotest
By default, it will re-use the current system to run the build. To test with another toolchain:
$ reprotest --use-system-root=/path/to/chroot make
To recreate another build:
$ reprotest --buildinfo=file.buildinfo --os=debian make
# try to guess which kind of buildinfo if --os is not specified
$ reprotest --buildinfo=file.buildinfo make
If Debian allows all variations except build path then you can assess software is good for Debian by:
$ reprotest --profile=debian build.sh
User configuration file
~/.reprotestrc
:
default-runner = qemu
[qemu-runner]
default-image = ~/.reprotest/debian-sid.img
Output
$ reprotest --text=reprotest.txt => run diffoscope on all created files?
$ reprotest --html=reprotest.html
$ reprotest --junit=reprotest.junit (for jenkins) <- parsable output
# create reprotest-differences/build1/ and create reprotest-differences/build2/
$ reprotest --save-differences=reprotest-differences/
# create reprotest-differences.build1.tar.gz reprotest-differences.build2.tar.gz
$ reprotest --save-difference-archives=reprotest-differences
# create a json file with index and details about the test
$ reprotest --json=reprotest.json --save-differences=reprotest-differences/
# pass options to diffoscope
$ reprotest --diffoscope-options="--ignore=coverage/ --ignore=*.log"
Options can be combined:
$ reprotest --html=reprotest.html --save-differences=reprotest-differences/
If no output option is specified, plain text will be printed to the standard output.
Other possibilities:
Run build twice, reproducing $DEFAULT
set of information from build environment:
$ reprotest make
Run build once, reproducing $DEFAULT
set of information from xxx.buildinfo
:
$ reprotest --buildinfo=bash_amd64.buildinfo make
Run build once, reproducing fields buildpath
, username
from bash_amd64.buildinfo
:
$ reprotest --reproduce=buildpath,username --buildinfo=bash_amd64.buildinfo make
Check that *.buildinfo
have the same result hash, find all the fields that
have the same value across all files, reproduce those common fields, then run
build once, and check if output has same hash:
$ reprotest –buildinfo=1.buildinfo –buildinfo=2.buildinfo –buildinfo=3.buildinfo make