pupdates

Reproducible Builds for Ruby Gems

Last updated: 2024-01-30

What are they and why do I care?

A reproducible build is one where you can run the build process again and get artifacts that are identical.

Reproducible builds allow people to identify problems such as compromised build environments or releases not using the official source.

What’s it look like in practice?

When gem reproduce succeeds, it looks like this:

~/test$ git clone --quiet https://github.com/duckinator/okay.git
~/test$ cd okay
~/test/okay$ git checkout v12.0.3
HEAD is now at 40fe265 Merge pull request #16 from duckinator/bump-deps
puppy@orthrus:~/test/okay$ gem rebuild okay 12.0.3
Fetching okay-12.0.3.gem
Downloaded okay version 12.0.3 as /tmp/gem_rebuild20240130-73307-ai5jxs/old/okay-12.0.3.gem.
  Successfully built RubyGem
  Name: okay
  Version: 12.0.3
  File: okay-12.0.3.gem

Built at: 2024-01-01 08:05:03 EST (1704114303)
Original build saved to:   /tmp/gem_rebuild20240130-73307-ai5jxs/old/okay-12.0.3.gem
Reproduced build saved to: /tmp/gem_rebuild20240130-73307-ai5jxs/new/okay-12.0.3.gem
Working directory: /usr/home/puppy/test/okay

Hash comparison:
  c6017966f3498623910f9a4a7bfcbd98ebab881f0e1315491b3340afa2e20b1c      /tmp/gem_rebuild20240130-73307-ai5jxs/old/okay-12.0.3.gem
  c6017966f3498623910f9a4a7bfcbd98ebab881f0e1315491b3340afa2e20b1c      /tmp/gem_rebuild20240130-73307-ai5jxs/new/okay-12.0.3.gem

SUCCESS - original and rebuild hashes matched
~/test/okay$

When it fails, it looks like this:

~/test/okay$ echo "# some change" >> lib/okay.rb
~/test/okay$ gem rebuild okay 12.0.3
Fetching okay-12.0.3.gem
Downloaded okay version 12.0.3 as /tmp/gem_rebuild20240130-73881-x2dknj/old/okay-12.0.3.gem.
WARNING:  open-ended dependency on cacert (>= 0) is not recommended
  use a bounded requirement, such as "~> x.y"
WARNING:  See https://guides.rubygems.org/specification-reference/ for help
  Successfully built RubyGem
  Name: okay
  Version: 12.0.3
  File: okay-12.0.3.gem

Built at: 2024-01-01 08:05:03 EST (1704114303)
Original build saved to:   /tmp/gem_rebuild20240130-73881-x2dknj/old/okay-12.0.3.gem
Reproduced build saved to: /tmp/gem_rebuild20240130-73881-x2dknj/new/okay-12.0.3.gem
Working directory: /usr/home/puppy/test/okay

Hash comparison:
  c6017966f3498623910f9a4a7bfcbd98ebab881f0e1315491b3340afa2e20b1c      /tmp/gem_rebuild20240130-73881-x2dknj/old/okay-12.0.3.gem
  8910ae67d46e9cccc59c2a2dd08b29ddf03ac703bc95bcc7f69e1722926def94      /tmp/gem_rebuild20240130-73881-x2dknj/new/okay-12.0.3.gem

FAILURE - original and rebuild hashes did not match
~/test/okay$

When --diff is specified, it’ll run the resulting files through diffoscope if they don’t match.

How do I make this work for my project?

Check back soon; still working on the details of this part. ♥