Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deterministic Builds #3

Open
maltfield opened this issue Jul 3, 2020 · 12 comments
Open

Deterministic Builds #3

maltfield opened this issue Jul 3, 2020 · 12 comments
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@maltfield
Copy link
Member

maltfield commented Jul 3, 2020

This task is for me to confirm that all three of our build scripts produce deterministic artifacts.

Files produced by our build script run via GitHub's CI workflows should have identical checksums to files produced by our build script run on our developer's local machines.

See also:

maltfield added a commit that referenced this issue Jul 3, 2020
 * #3

I confirmed that our linux build is *not* deterministc because:

1. Our AppImage is shipping with a ton of __pycache__/.../*.pyc files that differ from the GitHub build and our local build

2. The contents of buskill_version.py breaks determinism. I can manually set GITUB_SHA and GITHUB_REF on local builds (attempted in this commit), but GITHUB_RUN breaks determinism, so it's been removed
@maltfield
Copy link
Member Author

maltfield commented Jul 3, 2020

I'm starting with this task starting with Linux. I had two issues with my linux build script that was preventing it from being deterministic:

  1. Our AppImage is shipping with a ton of __pycache__/.../*.pyc files that differ from the GitHub build and our local build

  2. The contents of buskill_version.py breaks determinism. I can manually set GITHUB_SHA and GITHUB_REF on local builds (attempted in this commit), but GITHUB_RUN breaks determinism, so it's been removed.

I fixed those in this commit 0a98242

Unfortunately, I found the build from GitHub and my local build on a Debian 10 DispVM produced distinct checksums. I extracted the AppImage and found the dirs identical. I built a new AppImage from one of the build's extracted squashfs-root dir, then I immediately built another thereafter. Indeed, the checkums still differed, and it's extremely unlikely that the contents or its metadata changed in any way between the two runs.

user@disp6736:~/Downloads$ ls
buskill-linux-x86_64.156764000.tar.bz2
user@disp6736:~/Downloads$ tar -xjf buskill-linux-x86_64.156764000.tar.bz2
user@disp6736:~/Downloads$ cd dist/
user@disp6736:~/Downloads/dist$ sha384sum buskill.AppImage
fdd2ede3895567ae709febeef78b28c036eccb6a1e5b3501d8880b9628e5f5acd0416f7eff80f28be73897c82db95f63  buskill.AppImage
user@disp6736:~/Downloads/dist$ ./buskill.AppImage --appimage-extract > /dev/null
user@disp6736:~/Downloads/dist$ wget --quiet --continue --output-document="appimagetool.AppImage" https://github.com/AppImage/AppImageKit/releases/download/12/appimagetool-x86_64.AppImage
user@disp6736:~/Downloads/dist$ chmod +x appimagetool.AppImage
user@disp6736:~/Downloads/dist$ ./appimagetool.AppImage --no-appstream squashfs-root buskill_1.AppImage
appimagetool, continuous build (commit effcebc), build 2084 built on 2019-05-01 21:02:41 UTC
Using architecture x86_64
/home/user/Downloads/dist/squashfs-root should be packaged as buskill_1.AppImage
Generating squashfs...
Parallel mksquashfs: Using 2 processors
Creating 4.0 filesystem on buskill_1.AppImage, block size 131072.
[=============================================================\] 2524/2524 100%

Exportable Squashfs 4.0 filesystem, gzip compressed, data block size 131072
	compressed data, compressed metadata, compressed fragments, compressed xattrs
	duplicates are removed
Filesystem size 31138.46 Kbytes (30.41 Mbytes)
	33.09% of uncompressed filesystem size (94107.66 Kbytes)
Inode table size 21871 bytes (21.36 Kbytes)
	30.34% of uncompressed inode table size (72097 bytes)
Directory table size 21938 bytes (21.42 Kbytes)
	46.19% of uncompressed directory table size (47490 bytes)
Number of duplicate files found 18
Number of inodes 2161
Number of files 2007
Number of fragments 205
Number of symbolic links  19
Number of device nodes 0
Number of fifo nodes 0
Number of socket nodes 0
Number of directories 135
Number of ids (unique uids + gids) 1
Number of uids 1
	root (0)
Number of gids 1
	root (0)
Embedding ELF...
Marking the AppImage as executable...
Embedding MD5 digest
Success

Please consider submitting your AppImage to AppImageHub, the crowd-sourced
central directory of available AppImages, by opening a pull request
at https://github.com/AppImage/appimage.github.io
user@disp6736:~/Downloads/dist$ ./appimagetool.AppImage --no-appstream squashfs-root buskill_2.AppImage > /dev/null
appimagetool, continuous build (commit effcebc), build 2084 built on 2019-05-01 21:02:41 UTC
Using architecture x86_64
Generating squashfs...
Embedding ELF...
Marking the AppImage as executable...
Embedding MD5 digest
Success

Please consider submitting your AppImage to AppImageHub, the crowd-sourced
central directory of available AppImages, by opening a pull request
at https://github.com/AppImage/appimage.github.io
user@disp6736:~/Downloads/dist$ sha384sum buskill_1.AppImage 
6156521f583871f485bdc48bb098fbd683a3cf178bc78e4b76bb8f90188b67fd8a8e0b0c9ff5220a1136b3038c42e593  buskill_1.AppImage
user@disp6736:~/Downloads/dist$ sha384sum buskill_2.AppImage 
32c62b6cb6bb91841838af60cf8e2e215ffb9e88a4ab086fe06d1d04885ff9ea76bdf561e72c6da6e9d057e73b4f6908  buskill_2.AppImage
user@disp6736:~/Downloads/dist$ 

It looks like the issue is related to appimagetools using mksquashfs v4.3 (from 2017). Almost a year ago, v4.4 fixed this issue, but it appears that appimagetool never added-in the updated version of mksquashfs. I asked for an ETA on when appimagetool would expect to release their next stable release including mksquashfs v4.4 here:

In the meantime, it looks like some other projects such as the electrum crypto wallet have hacked appimagetool to use squashfskit to make reproducible builds:

maltfield added a commit that referenced this issue Jul 4, 2020
 * #3

Unfortunately the latest stable version of appimagetool (v12 from 2019-05) uses a very old version of mksquashfs (v4.3 from 2014-05) which does not support building reproducable builds due to some parallelization optimizations

 * https://github.com/AppImage/AppImageKit/releases
 * https://sourceforge.net/p/squashfs/code/ci/master/tree/CHANGES
 * AppImage/AppImageKit#929 (comment)

Other projects like the electurm crypto wallet got around this issue by hacking the latest stable appimagetool to use a fork of squashfs-tools = squashfskit

 * https://github.com/squashfskit/squashfskit
 * https://github.com/SomberNight/electrum/blob/ae714772c38410a0169f2c76a14a64a62c0daff0/contrib/build-linux/appimage/build.sh#L212-L225

But in 2019-08, squashfs-tools released an updated version (v4.4) which added support for reproducable builds, as well as fixed a couple CVEs and other changes

 * https://lore.kernel.org/lkml/CAB3wodcL=gnQOmHGGNukWK3OUbU2p=OHzLmzPi7ns_WNTGBEwg@mail.gmail.com/

Therefore, in this commit, I've added the code to make changes to appimagetool's latest release to use the updated version of squashfs-tools.

The asked the maintainer of AppImageKit about this, and they said there's no future releases expected for the existing appimagetools repo, as development has been moved to a Go version, which is currently still a work-in-progress with no eta on it becoming stableo

 * https://github.com/SomberNight/electrum/blob/ae714772c38410a0169f2c76a14a64a62c0daff0/contrib/build-linux/appimage/build.sh#L212-L225

So, for now, this hack is as good as it gets.
@maltfield
Copy link
Member Author

maltfield commented Jul 4, 2020

Linux deterministic builds are complete. For a diff of the changes (and associated commit messages) needed to achieve this, see:

After the changes listed in the comment above, this is what was required:

  1. Downloading & compiling the latest version of mksquashfs (v4.4)
  2. Replacing appimagetool's mksquashfs binary with a dumb script that strips an argument and passes the call on to the new mksquashfs binary
  3. setting the SOURCE_DATE_EPOCH environment variable (for mksquashfs)
  4. changing the atime & mtime of all the files in the AppDir to SOURCE_DATE_EPOCH before creating the AppImage with find and touch

@maltfield
Copy link
Member Author

maltfield commented Jul 5, 2020

I hit a wall trying to get pyinstaller to build deterministic binaries with this app in MacOS, so I walked-back to trying to build a simple one-line "hello world" app with pyinstaller that would build deterministically, and I couldn't get it to do so.

I created a repo specific to this task here:

And I filed a bug report with pyinstaller here:

Per my last comment, it might be that the order of the dependencies written to the binary are out-of-order and pyinstaller just needs to somehow sort them alphabetically to make their builds deterministic.

@maltfield
Copy link
Member Author

I added a windows build CI process to the workflow in my pyinstaller-deterministic-test repo above to see if PyInstaller could successfully produce reproducible builds in Windows of a simple 1-line hello world app. Sadly, it couldn't.

I added this info to a new comment in the bug report I created yesterday with the PyInstaller team, but this actually might require a distinct patch from the MacOS issues found above.

Sadly, I'm not sure there's much I can do to make BusKill's builds deterministic in MacOS/Windows (other than abandoning PyInstaller?) until this is fixed upstream.

@maltfield maltfield added enhancement New feature or request help wanted Extra attention is needed labels Jul 12, 2020
maltfield added a commit that referenced this issue Jul 12, 2020
This is the first commit where I can say that this app is finally functional on all 3 platforms: Linux, Windows, and MacOS. Further testing will be done, but I won't be implmeneting new features until our first release of v0.1.0 is out

Before I can make a release, we need to address some prerequisite tasks around documentation and security:

 1. I need a proper documentation solution. I'll probably use Sphinx / Read The Docs for this

 2. I need to sign all my commits on github with gpg

 3. I need to update the build scripts to verify the integrity of any depends being downloaded

 4. I need to make sure that the builds are deterministic. Any files produced by the build from the GitHub's CI process should match exactly the files produced by the bulild from my local machine.

 5. I need to find out if it's possible for me to upload a (distinct, purpose-created) pgp private key to GitHub somehow such that it's secure/not-public and can be used by the CI process to cryptographically sign build artifacts

 6. I need to setup TUF to sign releases. This will also be leveraged in a later release when I implement a self-updater feature into this app.

I hope that this commit solves #2 above, as I've added a signing subkey to my primary, master gpg key and copied it to my development environment, uploaded my updated public key to my GitHub account, and enabled commit signing by default in this repo's remote sandbox on my machine. Hopefully this commit will be signed and GitHub will give it a green checkbox.

As part of addressing #3, my build process currently requires downloading two dependencies from pip. Pip does not provide cryptographic authentication or integrity checks, but it does have a system for project maintainers to sign their releases with gpg and upload that to PyPI using twine. I've opened tickets requesting that the developers for the projects that we depend on begin to sign their releases to PyPI so that our build process can be more secure. In the meantime, I should 3TOFU a set of checksums and update the build scripts to fail if the integrity doesn't match the hard-coded checkums.

 * vpelletier/python-libusb1#54
 * kivy/kivy#6973
@maltfield
Copy link
Member Author

maltfield commented Jul 31, 2020

I made a few final changes to the linux build script so our linux builds are reproducible across the github shared runners and my laptop

Note that, as of now, our first (alpha) release is out!

maltfield added a commit that referenced this issue Sep 8, 2020
For some reason the .app built from GitHub spits this out and exits immediately where it *should* give me a pdb shell.

10:44:35,169 root DEBUG ========================================================
=======================
10:44:35,169 root DEBUG BUSKILL_VERSION|{'VERSION': '1599550992', 'GITHUB_REF':
'refs/heads/dev', 'GITHUB_SHA': 'ba2300aee40f587dbc652b284088f6f561cc7908', 'SOU
RCE_DATE_EPOCH': '1599550992'}|
10:44:35,169 root DEBUG os.environ|environ({'PWD': '/Users/maltfield/Downloads',
 'TERMCAP': 'SC|screen|VT 100/ANSI X3.64 virtual terminal:\\\n\t:DO=\\E[%dB:LE=\\E[%dD:RI=\\E[%dC:UP=\\E[%dA:bs:bt=\\E[Z:\\\n\t:cd=\\E[J:ce=\\E[K:cl=\\E[H\\E[J:cm=\\E[%i%d;%dH:ct=\\E[3g:\\\n\t:do=^J:nd=\\E[C:pt:rc=\\E8:rs=\\Ec:sc=\\E7:st=\\EH:up=\\EM:\\\n\t:le=^H:bl=^G:cr=^M:it#8:ho=\\E[H:nw=\\EE:ta=^I:is=\\E)0:\\\n\t:li#47:co#80:am:xn:xv:LP:sr=\\EM:al=\\E[L:AL=\\E[%dL:\\\n\t:cs=\\E[%i%d;%dr:dl=\\E[M:DL=\\E[%dM:dc=\\E[P:DC=\\E[%dP:\\\n\t:im=\\E[4h:ei=\\E[4l:mi:IC=\\E[%d@:ks=\\E[?1h\\E=:\\\n\t:ke=\\E[?1l\\E>:vi=\\E[?25l:ve=\\E[34h\\E[?25h:vs=\\E[34l:\\\n\t:ti=\\E[?1049h:te=\\E[?1049l:us=\\E[4m:ue=\\E[24m:so=\\E[3m:\\\n\t:se=\\E[23m:mb=\\E[5m:md=\\E[1m:mr=\\E[7m:me=\\E[m:ms:\\\n\t:Co#8:pa#64:AF=\\E[3%dm:AB=\\E[4%dm:op=\\E[39;49m:AX:\\\n\t:vb=\\Eg:G0:as=\\E(0:ae=\\E(B:\\\n\t:ac=\\140\\140aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~..--++,,hhII00:\\\n\t:po=\\E[5i:pf=\\E[4i:k0=\\E[10~:k1=\\EOP:k2=\\EOQ:k3=\\EOR:\\\n\t:k4=\\EOS:k5=\\E[15~:k6=\\E[17~:k7=\\E[18~:k8=\\E[19~:\\\n\t:k9=\\E[20~:k;=\\E[21~:F1=\\E[23~:F2=\\E[24~:F3=\\E[1;2P:\\\n\t:F4=\\E[1;2Q:F5=\\E[1;2R:F6=\\E[1;2S:F7=\\E[15;2~:\\\n\t:F8=\\E[17;2~:F9=\\E[18;2~:FA=\\E[19;2~:kb=^H:K2=\\EOE:\\\n\t:kB=\\E[Z:kF=\\E[1;2B:kR=\\E[1;2A:*4=\\E[3;2~:*7=\\E[1;2F:\\\n\t:#2=\\E[1;2H:#3=\\E[2;2~:#4=\\E[1;2D:%c=\\E[6;2~:%e=\\E[5;2~:\\\n\t:%i=\\E[1;2C:kh=\\E[1~:@1=\\E[1~:kH=\\E[4~:@7=\\E[4~:\\\n\t:kN=\\E[6~:kP=\\E[5~:kI=\\E[2~:kD=\\E[3~:ku=\\EOA:kd=\\EOB:\\\n\t:kr=\\EOC:kl=\\EOD:km:', 'USER': 'maltfield', 'SSH_TTY': '/dev/ttys001', 'LANG': 'en_US.UTF-8', 'WINDOW': '3', 'TERM': 'screen', 'LOGNAME': 'maltfield', 'STY': '1277.buskill', 'PATH': '/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin', 'SHLVL': '3', 'OLDPWD': '/Users/maltfield/Downloads/buskill-1599545602.app', 'SSH_CLIENT': '110.44.115.190 17388 4518', 'SHELL': '/bin/zsh', '_': '/usr/bin/open', 'HOME': '/Users/maltfield', '__CF_USER_TEXT_ENCODING': '0x1F6:0:2', 'TMPDIR': '/var/folders/kx/2fp3kfgj4dj7rx9s5mlb52640000gp/T/', 'SSH_CONNECTION': '110.44.115.190 17388 207.254.29.173 4518', 'XPC_SERVICE_NAME': 'buskill.9148', 'SSH_AUTH_SOCK': '/private/tmp/com.apple.launchd.Bx0RjQIl42/Listeners', 'XPC_FLAGS': '0x0', 'KIVY_DATA_DIR': '/Users/maltfield/Downloads/buskill-1599550992.app/Contents/MacOS/kivy_install/data', 'KIVY_MODULES_DIR': '/Users/maltfield/Downloads/buskill-1599550992.app/Contents/MacOS/kivy_install/modules', 'GST_REGISTRY_FORK': 'no', 'GST_PLUGIN_PATH': '/Users/maltfield/Downloads/buskill-1599550992.app/Contents/MacOS:/Users/maltfield/Downloads/buskill-1599550992.app/Contents/MacOS/gst-plugins', 'GST_REGISTRY': '/Users/maltfield/Downloads/buskill-1599550992.app/Contents/MacOS/registry.bin', 'GST_PLUGIN_SYSTEM_PATH': ''})|
10:44:35,169 root DEBUG sys.argv|['/Users/maltfield/Downloads/buskill-1599550992.app/Contents/MacOS/buskill']|
10:44:35,169 root DEBUG sys.builtin_modules_names|('_abc', '_ast', '_codecs', '_collections', '_functools', '_imp', '_io', '_locale', '_operator', '_signal', '_sre', '_stat', '_string', '_symtable', '_thread', '_tracemalloc', '_warnings', '_weakref', 'atexit', 'builtins', 'errno', 'faulthandler', 'gc', 'itertools', 'marshal', 'posix', 'pwd', 'sys', 'time', 'xxsubtype', 'zipimport')|
10:44:35,169 root DEBUG sys.executable|/Users/maltfield/Downloads/buskill-1599550992.app/Contents/MacOS/buskill|
10:44:35,170 root DEBUG sys.path|['/Users/maltfield/Downloads/buskill-1599550992.app/Contents/MacOS/base_library.zip', '/Users/maltfield/Downloads/buskill-1599550992.app/Contents/MacOS']|
10:44:35,170 root DEBUG sys.platform|darwin|
10:44:35,170 root DEBUG sys.prefix|/Users/maltfield/Downloads/buskill-1599550992.app/Contents/MacOS|
10:44:35,170 root DEBUG sys.version|3.7.8 (default, Jul  4 2020, 10:17:17)
[Clang 11.0.3 (clang-1103.0.32.62)]|
10:44:35,170 root DEBUG sys.api_version|1013|
10:44:35,170 root DEBUG sys.version_info|sys.version_info(major=3, minor=7, micro=8, releaselevel='final', serial=0)|
10:44:35,170 root INFO buskill version {'VERSION': '1599550992', 'GITHUB_REF': 'refs/heads/dev', 'GITHUB_SHA': 'ba2300aee40f587dbc652b284088f6f561cc7908', 'SOURCE_DATE_EPOCH': '1599550992'}
10:44:35,225 kivy INFO [Logger      ] Record log in /Users/maltfield/.kivy/logs/kivy_20-09-08_11.txt
10:44:35,225 kivy INFO [Kivy        ] v1.11.1
10:44:35,226 kivy INFO [Kivy        ] Installed at "/Users/maltfield/Downloads/buskill-1599550992.app/Contents/MacOS/kivy/__init__.pyc"
10:44:35,226 kivy INFO [Python      ] v3.7.8 (default, Jul  4 2020, 10:17:17)
[Clang 11.0.3 (clang-1103.0.32.62)]
10:44:35,226 kivy INFO [Python      ] Interpreter at "/Users/maltfield/Downloads/buskill-1599550992.app/Contents/MacOS/buskill"
10:44:35,260 kivy INFO [Factory     ] 184 symbols loaded
10:44:35,345 kivy INFO [Image       ] Providers: img_tex, img_imageio, img_dds, img_sdl2, img_gif (img_pil, img_ffpyplayer ignored)
10:44:35,560 kivy INFO [Window      ] Provider: sdl2
10:44:35,761 kivy INFO [GL          ] Using the "OpenGL ES 2" graphics system
10:44:35,761 kivy INFO [GL          ] Backend used <sdl2>
10:44:35,762 kivy INFO [GL          ] OpenGL version <b'2.1 INTEL-14.7.8'>
10:44:35,762 kivy INFO [GL          ] OpenGL vendor <b'Intel Inc.'>
10:44:35,762 kivy INFO [GL          ] OpenGL renderer <b'Intel HD Graphics 4000 OpenGL Engine'>
10:44:35,762 kivy INFO [GL          ] OpenGL parsed version: 2, 1
10:44:35,762 kivy INFO [GL          ] Shading version <b'1.20'>
10:44:35,762 kivy INFO [GL          ] Texture max size <16384>
10:44:35,763 kivy INFO [GL          ] Texture max units <16>
10:44:35,781 kivy INFO [Window      ] auto add sdl2 input provider
10:44:35,806 kivy INFO [Window      ] virtual keyboard not allowed, single mode, not docked
10:44:35,828 kivy INFO [Text        ] Provider: sdl2
10:44:35,834 kivy INFO [INFO        ] using DATA_DIR:|/Users/maltfield/Downloads/buskill-1599550992.app/Contents/MacOS/.buskill|
10:44:35,889 kivy INFO [GL          ] NPOT texture support is available
10:44:35,905 kivy INFO [Base        ] Start application main loop
10:46:11,686 kivy INFO [Base        ] Leaving application in progress...
10:46:11,687 kivy WARNING stderr: Traceback (most recent call last):
10:46:11,687 kivy WARNING stderr:   File "main.py", line 97, in <module>
10:46:11,687 kivy WARNING stderr:     BusKillApp().run()
10:46:11,687 kivy WARNING stderr:   File "kivy/app.py", line 855, in run
10:46:11,688 kivy WARNING stderr:   File "kivy/base.py", line 504, in runTouchApp
10:46:11,688 kivy WARNING stderr:   File "kivy/core/window/window_sdl2.py", line 747, in mainloop
10:46:11,688 kivy WARNING stderr:   File "kivy/core/window/window_sdl2.py", line 479, in _mainloop
10:46:11,688 kivy WARNING stderr:   File "kivy/base.py", line 342, in idle
10:46:11,688 kivy WARNING stderr:   File "kivy/base.py", line 327, in dispatch_input
10:46:11,689 kivy WARNING stderr:   File "kivy/base.py", line 293, in post_dispatch_input
10:46:11,689 kivy WARNING stderr:   File "kivy/_event.pyx", line 707, in kivy._event.EventDispatcher.dispatch
10:46:11,689 kivy WARNING stderr:   File "kivy/uix/behaviors/button.py", line 179, in on_touch_up
10:46:11,689 kivy WARNING stderr:   File "kivy/_event.pyx", line 703, in kivy._event.EventDispatcher.dispatch
10:46:11,689 kivy WARNING stderr:   File "kivy/_event.pyx", line 1214, in kivy._event.EventObservers.dispatch
10:46:11,689 kivy WARNING stderr:   File "kivy/_event.pyx", line 1098, in kivy._event.EventObservers._dispatch
10:46:11,690 kivy WARNING stderr:   File "kivy/lang/builder.py", line 64, in custom_callback
10:46:11,690 kivy WARNING stderr:   File "/Users/maltfield/Downloads/buskill-1599550992.app/Contents/MacOS/buskill.kv", line 190, in <module>
10:46:11,690 kivy WARNING stderr:     on_release: root.continue_function()
10:46:11,690 kivy WARNING stderr:   File "buskill_gui.py", line 154, in update2
10:46:11,691 kivy WARNING stderr:     self.bk.upgrade_bg()
10:46:11,691 kivy WARNING stderr:   File "packages/buskill/__init__.py", line 639, in upgrade_bg
10:46:11,691 kivy WARNING stderr:   File "packages/buskill/__init__.py", line 639, in upgrade_bg
10:46:11,692 kivy WARNING stderr:   File "bdb.py", line 88, in trace_dispatch
10:46:11,692 kivy WARNING stderr:   File "bdb.py", line 113, in dispatch_line
10:46:11,692 kivy WARNING stderr: bdb.BdbQuit
10:46:11,692 kivy WARNING stderr: [INFO/MainProcess] process shutting down
10:46:11,692 kivy WARNING stderr: [DEBUG/MainProcess] running all "atexit" finalizers with priority >= 0
10:46:11,693 kivy WARNING stderr: [DEBUG/MainProcess] running the remaining "atexit" finalizers
@maltfield
Copy link
Member Author

maltfield commented Sep 21, 2021

update: newer versions of PyInstaller appear to have fixed reproducibility or MacOS

TODO: see if it works for our buskill MacOS builds, too.

@maltfield
Copy link
Member Author

TOFU 1/3 via VPN in Netherlands

user@disp5319:/tmp/tmp.p7j2Zbimtj$ # first get some info about our internet connection
user@disp5319:/tmp/tmp.p7j2Zbimtj$ ${CURL} -s https://ifconfig.co/country | head -n1
Netherlands
user@disp5319:/tmp/tmp.p7j2Zbimtj$ ${CURL} -s https://check.torproject.org | grep Congratulations | head -n1
user@disp5319:/tmp/tmp.p7j2Zbimtj$ 
user@disp5319:/tmp/tmp.p7j2Zbimtj$ # and today's date
user@disp5319:/tmp/tmp.p7j2Zbimtj$ date -u +"%Y-%m-%d"
2021-12-01
user@disp5319:/tmp/tmp.p7j2Zbimtj$ 
user@disp5319:/tmp/tmp.p7j2Zbimtj$ # get the file
user@disp5319:/tmp/tmp.p7j2Zbimtj$ pip3 download ${PIP_PKGS}
Collecting pyinstaller
  Using cached https://files.pythonhosted.org/packages/00/ca/58dd68fee42490be1c86c9e912fc9ad0bf44c72edd882397ad11c21fbecb/pyinstaller-4.7.tar.gz
  Saved ./pyinstaller-4.7.tar.gz
  Installing build dependencies ... done
Collecting setuptools (from pyinstaller)
  Using cached https://files.pythonhosted.org/packages/6f/ea/e12311dabc63a6a434be25e6011c1513cc95d0cf22e5f13036f75b3ec508/setuptools-59.4.0-py3-none-any.whl
  Saved ./setuptools-59.4.0-py3-none-any.whl
Collecting altgraph (from pyinstaller)
  Downloading https://files.pythonhosted.org/packages/84/3f/1a5c9bef54cac9bf41edd6f4aaf61cd52ed578e10ccc607e0278012cb4a5/altgraph-0.17.2-py2.py3-none-any.whl
  Saved ./altgraph-0.17.2-py2.py3-none-any.whl
Collecting pyinstaller-hooks-contrib>=2020.6 (from pyinstaller)
  Downloading https://files.pythonhosted.org/packages/80/74/4c885df43604c4ae570610e187052f29d806d582e398c2e48b83dad74610/pyinstaller_hooks_contrib-2021.4-py2.py3-none-any.whl (215kB)
    100% |████████████████████████████████| 225kB 2.4MB/s 
  Saved ./pyinstaller_hooks_contrib-2021.4-py2.py3-none-any.whl
Collecting importlib-metadata (from pyinstaller)
  Downloading https://files.pythonhosted.org/packages/c4/1f/e2238896149df09953efcc53bdcc7d23597d6c53e428c30e572eda5ec6eb/importlib_metadata-4.8.2-py3-none-any.whl
  Saved ./importlib_metadata-4.8.2-py3-none-any.whl
Collecting typing-extensions>=3.6.4; python_version < "3.8" (from importlib-metadata->pyinstaller)
  Downloading https://files.pythonhosted.org/packages/05/e4/baf0031e39cf545f0c9edd5b1a2ea12609b7fcba2d58e118b11753d68cf0/typing_extensions-4.0.1-py3-none-any.whl
  Saved ./typing_extensions-4.0.1-py3-none-any.whl
Collecting zipp>=0.5 (from importlib-metadata->pyinstaller)
  Downloading https://files.pythonhosted.org/packages/bd/df/d4a4974a3e3957fd1c1fa3082366d7fff6e428ddb55f074bf64876f8e8ad/zipp-3.6.0-py3-none-any.whl
  Saved ./zipp-3.6.0-py3-none-any.whl
Successfully downloaded pyinstaller setuptools altgraph pyinstaller-hooks-contrib importlib-metadata typing-extensions zipp
user@disp5319:/tmp/tmp.p7j2Zbimtj$ 
user@disp5319:/tmp/tmp.p7j2Zbimtj$ # checksum
user@disp5319:/tmp/tmp.p7j2Zbimtj$ sha256sum *
743628f2ac6a7c26f5d9223c91ed8ecbba535f506f4b6f558885a8a56a105857  altgraph-0.17.2-py2.py3-none-any.whl
53ccfd5c134223e497627b9815d5030edf77d2ed573922f7a0b8f8bb81a1c100  importlib_metadata-4.8.2-py3-none-any.whl
2c7f4810dc5272ec1b388a7f1ff6b56d38653c1b0c9ac2d9dd54fa06b590e372  pyinstaller-4.7.tar.gz
60a57e4057fa2183bbaa81f10401a27eb7dd701ef8a11b287bb6345b571f94e7  pyinstaller_hooks_contrib-2021.4-py2.py3-none-any.whl
feb5ff19b354cde9efd2344ef6d5e79880ce4be643037641b49508bbb850d060  setuptools-59.4.0-py3-none-any.whl
7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b  typing_extensions-4.0.1-py3-none-any.whl
9fe5ea21568a0a70e50f273397638d39b03353731e6cbbb3fd8502a33fec40bc  zipp-3.6.0-py3-none-any.whl
user@disp5319:/tmp/tmp.p7j2Zbimtj$ 

@maltfield
Copy link
Member Author

maltfield commented Dec 1, 2021

Hmm..I ran this on my actual buskill dev VM, and I got a diff. It's actually a totally distinct file.

In the TOFU above, I get a file named:

2c7f4810dc5272ec1b388a7f1ff6b56d38653c1b0c9ac2d9dd54fa06b590e372  pyinstaller-4.7.tar.gz

But on my buskill VM, I get:

03636feec822de1d23d9753054f0b1229fb23d58723ae796f41b1127fc54f572  pyinstaller-4.7-py3-none-manylinux2014_x86_64.whl

Not that both are running Debian 10 with the same kernel version, but the former is using pip v18.1 and the latter pip v20.1.1.

EDIT: Ah, it looks like I pinned pip to v20.1.1 in 2020-07 as it was a dependency for kivy:

So in order for this 3TOFU to work, I should first make sure I'm using pip v20.1.1. I'll update the TOFU commands to be:

# SETTINGS
PIP_PKGS="pyinstaller"

CURL="/usr/bin/curl"
WGET="/usr/bin/wget --retry-on-host-error --retry-connrefused"
PYTHON="/usr/bin/python3"
PIP="${PYTHON} -m pip"

# prereqs
sudo apt-get -y install python3-pip
python3 -m pip install pip==20.1.1

tmpDir=`mktemp -d`
pushd "${tmpDir}"

# first get some info about our internet connection
${CURL} -s https://ifconfig.co/country | head -n1
${CURL} -s https://check.torproject.org | grep Congratulations | head -n1

# and today's date
date -u +"%Y-%m-%d"

# get the file
pip3 download ${PIP_PKGS}

# checksum
sha256sum *

@maltfield
Copy link
Member Author

Re-doing TOFU (via Netherlands VPN) 1/3 w/ pip v20.1.1

user@disp8698:/tmp/tmp.dSXPTNl8s8$ # first get some info about our internet connection
user@disp8698:/tmp/tmp.dSXPTNl8s8$ ${CURL} -s https://ifconfig.co/country | head -n1
Netherlands
user@disp8698:/tmp/tmp.dSXPTNl8s8$ ${CURL} -s https://check.torproject.org | grep Congratulations | head -n1
user@disp8698:/tmp/tmp.dSXPTNl8s8$ 
user@disp8698:/tmp/tmp.dSXPTNl8s8$ # and today's date
user@disp8698:/tmp/tmp.dSXPTNl8s8$ date -u +"%Y-%m-%d"
2021-12-01
user@disp8698:/tmp/tmp.dSXPTNl8s8$ 
user@disp8698:/tmp/tmp.dSXPTNl8s8$ # get the file
user@disp8698:/tmp/tmp.dSXPTNl8s8$ pip3 download ${PIP_PKGS}
WARNING: pip is being invoked by an old script wrapper. This will fail in a future version of pip.
Please see https://github.com/pypa/pip/issues/5599 for advice on fixing the underlying issue.
To avoid this problem you can invoke Python with '-m pip' instead of running pip directly.
Collecting pyinstaller
  Downloading pyinstaller-4.7-py3-none-manylinux2014_x86_64.whl (1.5 MB)
     |████████████████████████████████| 1.5 MB 1.9 MB/s 
  Saved ./pyinstaller-4.7-py3-none-manylinux2014_x86_64.whl
Collecting importlib-metadata; python_version < "3.8"
  Downloading importlib_metadata-4.8.2-py3-none-any.whl (17 kB)
  Saved ./importlib_metadata-4.8.2-py3-none-any.whl
Collecting setuptools
  Downloading setuptools-59.4.0-py3-none-any.whl (952 kB)
     |████████████████████████████████| 952 kB 3.8 MB/s 
  Saved ./setuptools-59.4.0-py3-none-any.whl
Collecting pyinstaller-hooks-contrib>=2020.6
  Downloading pyinstaller_hooks_contrib-2021.4-py2.py3-none-any.whl (215 kB)
     |████████████████████████████████| 215 kB 3.8 MB/s 
  Saved ./pyinstaller_hooks_contrib-2021.4-py2.py3-none-any.whl
Collecting altgraph
  Downloading altgraph-0.17.2-py2.py3-none-any.whl (21 kB)
  Saved ./altgraph-0.17.2-py2.py3-none-any.whl
Collecting typing-extensions>=3.6.4; python_version < "3.8"
  Downloading typing_extensions-4.0.1-py3-none-any.whl (22 kB)
  Saved ./typing_extensions-4.0.1-py3-none-any.whl
Collecting zipp>=0.5
  Downloading zipp-3.6.0-py3-none-any.whl (5.3 kB)
  Saved ./zipp-3.6.0-py3-none-any.whl
Successfully downloaded pyinstaller importlib-metadata setuptools pyinstaller-hooks-contrib altgraph typing-extensions zipp
WARNING: You are using pip version 20.1.1; however, version 21.3.1 is available.
You should consider upgrading via the '/usr/bin/python3 -m pip install --upgrade pip' command.
user@disp8698:/tmp/tmp.dSXPTNl8s8$ 
user@disp8698:/tmp/tmp.dSXPTNl8s8$ # checksum
user@disp8698:/tmp/tmp.dSXPTNl8s8$ sha256sum *
743628f2ac6a7c26f5d9223c91ed8ecbba535f506f4b6f558885a8a56a105857  altgraph-0.17.2-py2.py3-none-any.whl
53ccfd5c134223e497627b9815d5030edf77d2ed573922f7a0b8f8bb81a1c100  importlib_metadata-4.8.2-py3-none-any.whl
03636feec822de1d23d9753054f0b1229fb23d58723ae796f41b1127fc54f572  pyinstaller-4.7-py3-none-manylinux2014_x86_64.whl
60a57e4057fa2183bbaa81f10401a27eb7dd701ef8a11b287bb6345b571f94e7  pyinstaller_hooks_contrib-2021.4-py2.py3-none-any.whl
feb5ff19b354cde9efd2344ef6d5e79880ce4be643037641b49508bbb850d060  setuptools-59.4.0-py3-none-any.whl
7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b  typing_extensions-4.0.1-py3-none-any.whl
9fe5ea21568a0a70e50f273397638d39b03353731e6cbbb3fd8502a33fec40bc  zipp-3.6.0-py3-none-any.whl
user@disp8698:/tmp/tmp.dSXPTNl8s8$ 

maltfield added a commit that referenced this issue Dec 1, 2021
The current version v3.6 has some bugs preventing reproducable builds in MacOS.

 * #3
 * pyinstaller/pyinstaller#4972

The changelog says these were fixed in PyInstaller v4.2. I'm going ahead and upgrading past that to the latest at the time of writing, which is v4.7.
@maltfield
Copy link
Member Author

maltfield commented Dec 1, 2021

Maybe I have to go back to the tarball somehow because the pyinstaller...manylinux.whl file doesn't work for MacOS builds

2021-12-01T21:28:29.4679930Z + /usr/local/Cellar/python/3.7.8/bin/pip3 install --ignore-installed --upgrade --cache-dir build/deps/ --no-index --find-links file:///Users/runner/work/buskill-app/buskill-app/build/deps/ build/deps/pyinstaller-4.7-py3-none-manylinux2014_x86_64.whl
2021-12-01T21:28:30.0097130Z ERROR: pyinstaller-4.7-py3-none-manylinux2014_x86_64.whl is not a supported wheel on this platform.

I ran this from our MacMini, and confirmed it got the tarball

maltfield@5129 ~ % python3 -m pip --version          
pip 20.1.1 from /usr/local/lib/python3.9/site-packages/pip (python 3.9)
maltfield@5129 ~ % tmpDir=`mktemp -d`
pushd "${tmpDir}"

/var/folders/kx/2fp3kfgj4dj7rx9s5mlb52640000gp/T/tmp.iabUvGw4 ~
maltfield@5129 tmp.iabUvGw4 % python3 -m pip download pyinstaller
Collecting pyinstaller
  Downloading pyinstaller-4.7.tar.gz (2.8 MB)
     |████████████████████████████████| 2.8 MB 13.3 MB/s 
  Installing build dependencies ... done
  Getting requirements to build wheel ... done
    Preparing wheel metadata ... done
  Saved ./pyinstaller-4.7.tar.gz
Collecting pyinstaller-hooks-contrib>=2020.6
  Downloading pyinstaller_hooks_contrib-2021.4-py2.py3-none-any.whl (215 kB)
     |████████████████████████████████| 215 kB 12.5 MB/s 
  Saved ./pyinstaller_hooks_contrib-2021.4-py2.py3-none-any.whl
Collecting setuptools
  Using cached setuptools-59.4.0-py3-none-any.whl (952 kB)
  Saved ./setuptools-59.4.0-py3-none-any.whl
Collecting macholib>=1.8; sys_platform == "darwin"
  Using cached macholib-1.15.2-py2.py3-none-any.whl (37 kB)
  Saved ./macholib-1.15.2-py2.py3-none-any.whl
Collecting altgraph
  Using cached altgraph-0.17.2-py2.py3-none-any.whl (21 kB)
  Saved ./altgraph-0.17.2-py2.py3-none-any.whl
Successfully downloaded pyinstaller pyinstaller-hooks-contrib setuptools macholib altgraph
maltfield@5129 tmp.iabUvGw4 %
...
maltfield@5129 tmp.iabUvGw4 % shasum -a 256 *
743628f2ac6a7c26f5d9223c91ed8ecbba535f506f4b6f558885a8a56a105857  altgraph-0.17.2-py2.py3-none-any.whl
885613dd02d3e26dbd2b541eb4cc4ce611b841f827c0958ab98656e478b9e6f6  macholib-1.15.2-py2.py3-none-any.whl
2c7f4810dc5272ec1b388a7f1ff6b56d38653c1b0c9ac2d9dd54fa06b590e372  pyinstaller-4.7.tar.gz
60a57e4057fa2183bbaa81f10401a27eb7dd701ef8a11b287bb6345b571f94e7  pyinstaller_hooks_contrib-2021.4-py2.py3-none-any.whl
feb5ff19b354cde9efd2344ef6d5e79880ce4be643037641b49508bbb850d060  setuptools-59.4.0-py3-none-any.whl
maltfield@5129 tmp.iabUvGw4 % 

The hashes of the files here match the first TOFU above -- except there's an additional file for macholib

@maltfield
Copy link
Member Author

It's going to be a PIA to do 3TOFU from my one mac mini server, so I hacked-up a better set of commands. Note the grepping hackery of the PyPI simple API because PIP has no way to say pip download for a given platform.

CURL="/usr/bin/curl"
WGET="/usr/bin/wget --retry-on-host-error --retry-connrefused"

tmpDir=`mktemp -d`
pushd "${tmpDir}"

# first get some info about our internet connection
${CURL} -s https://ifconfig.co/country | head -n1
${CURL} -s https://check.torproject.org | grep Congratulations | head -n1

# and today's date
date -u +"%Y-%m-%d"

# GET THE FILES

# altgraph
download_url=`${CURL} -s https://pypi.org/simple/altgraph/ | grep -oE "https://.*altgraph-0.17.2-py2.py3-none-any.whl#"`
${WGET} ${download_url}

# macholib
download_url=`${CURL} -s https://pypi.org/simple/macholib/ | grep -oE "https://.*macholib-1.15.2-py2.py3-none-any.whl#"`
${WGET} ${download_url}

# pyinstaller
download_url=`${CURL} -s https://pypi.org/simple/pyinstaller/ | grep -oE "https://.*pyinstaller-4.7.tar.gz#"`
${WGET} ${download_url}

# pyinstaller-hooks-contrib
download_url=`${CURL} -s https://pypi.org/simple/pyinstaller-hooks-contrib/ | grep -oE "https://.*pyinstaller_hooks_contrib-2021.4-py2.py3-none-any.whl#"`
${WGET} ${download_url}

# setuptools
download_url=`${CURL} -s https://pypi.org/simple/setuptools/ | grep -oE "https://.*setuptools-59.4.0-py3-none-any.whl#"`
${WGET} ${download_url}

# checksum
sha256sum *

@maltfield
Copy link
Member Author

So here's the third attempt of TOFU 1/3 (also VPN via Netherlands)

user@disp2324:/tmp/tmp.bzHGsqimss$ # first get some info about our internet connection
user@disp2324:/tmp/tmp.bzHGsqimss$ ${CURL} -s https://ifconfig.co/country | head -n1
Netherlands
user@disp2324:/tmp/tmp.bzHGsqimss$ ${CURL} -s https://check.torproject.org | grep Congratulations | head -n1
user@disp2324:/tmp/tmp.bzHGsqimss$ 
user@disp2324:/tmp/tmp.bzHGsqimss$ # and today's date
user@disp2324:/tmp/tmp.bzHGsqimss$ date -u +"%Y-%m-%d"
2021-12-01
user@disp2324:/tmp/tmp.bzHGsqimss$ # GET THE FILES
user@disp2324:/tmp/tmp.bzHGsqimss$ 
user@disp2324:/tmp/tmp.bzHGsqimss$ # altgraph
user@disp2324:/tmp/tmp.bzHGsqimss$ download_url=`${CURL} -s https://pypi.org/simple/altgraph/ | grep -oE "https://.*altgraph-0.17.2-py2.py3-none-any.whl#"`
user@disp2324:/tmp/tmp.bzHGsqimss$ ${WGET} ${download_url}
--2021-12-01 23:09:40--  https://files.pythonhosted.org/packages/84/3f/1a5c9bef54cac9bf41edd6f4aaf61cd52ed578e10ccc607e0278012cb4a5/altgraph-0.17.2-py2.py3-none-any.whl
Resolving files.pythonhosted.org (files.pythonhosted.org)... 151.101.37.63, 2a04:4e42:9::319
Connecting to files.pythonhosted.org (files.pythonhosted.org)|151.101.37.63|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 21200 (21K) [application/octet-stream]
Saving to: ‘altgraph-0.17.2-py2.py3-none-any.whl’

altgraph-0.17.2-py2. 100%[=====================>]  20.70K  --.-KB/s    in 0.001s  

2021-12-01 23:09:40 (29.9 MB/s) - ‘altgraph-0.17.2-py2.py3-none-any.whl’ saved [21200/21200]

user@disp2324:/tmp/tmp.bzHGsqimss$ 
user@disp2324:/tmp/tmp.bzHGsqimss$ # macholib
user@disp2324:/tmp/tmp.bzHGsqimss$ download_url=`${CURL} -s https://pypi.org/simple/macholib/ | grep -oE "https://.*macholib-1.15.2-py2.py3-none-any.whl#"`
user@disp2324:/tmp/tmp.bzHGsqimss$ ${WGET} ${download_url}
--2021-12-01 23:09:41--  https://files.pythonhosted.org/packages/59/87/d92bad3903ad3b6e10e949ac1bfbfc660433c2a8ae26849947f23299cb41/macholib-1.15.2-py2.py3-none-any.whl
Resolving files.pythonhosted.org (files.pythonhosted.org)... 151.101.37.63, 2a04:4e42:9::319
Connecting to files.pythonhosted.org (files.pythonhosted.org)|151.101.37.63|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 37678 (37K) [application/octet-stream]
Saving to: ‘macholib-1.15.2-py2.py3-none-any.whl’

macholib-1.15.2-py2. 100%[=====================>]  36.79K  --.-KB/s    in 0.01s   

2021-12-01 23:09:41 (3.26 MB/s) - ‘macholib-1.15.2-py2.py3-none-any.whl’ saved [37678/37678]

user@disp2324:/tmp/tmp.bzHGsqimss$ 
user@disp2324:/tmp/tmp.bzHGsqimss$ # pyinstaller
user@disp2324:/tmp/tmp.bzHGsqimss$ download_url=`${CURL} -s https://pypi.org/simple/pyinstaller/ | grep -oE "https://.*pyinstaller-4.7.tar.gz#"`
user@disp2324:/tmp/tmp.bzHGsqimss$ ${WGET} ${download_url}
--2021-12-01 23:09:41--  https://files.pythonhosted.org/packages/00/ca/58dd68fee42490be1c86c9e912fc9ad0bf44c72edd882397ad11c21fbecb/pyinstaller-4.7.tar.gz
Resolving files.pythonhosted.org (files.pythonhosted.org)... 151.101.37.63, 2a04:4e42:9::319
Connecting to files.pythonhosted.org (files.pythonhosted.org)|151.101.37.63|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2783049 (2.7M) [application/x-tar]
Saving to: ‘pyinstaller-4.7.tar.gz’

pyinstaller-4.7.tar. 100%[=====================>]   2.65M  3.00MB/s    in 0.9s    

2021-12-01 23:09:42 (3.00 MB/s) - ‘pyinstaller-4.7.tar.gz’ saved [2783049/2783049]

user@disp2324:/tmp/tmp.bzHGsqimss$ 
user@disp2324:/tmp/tmp.bzHGsqimss$ # pyinstaller-hooks-contrib
user@disp2324:/tmp/tmp.bzHGsqimss$ download_url=`${CURL} -s https://pypi.org/simple/pyinstaller-hooks-contrib/ | grep -oE "https://.*pyinstaller_hooks_contrib-2021.4-py2.py3-none-any.whl#"`
user@disp2324:/tmp/tmp.bzHGsqimss$ ${WGET} ${download_url}
--2021-12-01 23:09:42--  https://files.pythonhosted.org/packages/80/74/4c885df43604c4ae570610e187052f29d806d582e398c2e48b83dad74610/pyinstaller_hooks_contrib-2021.4-py2.py3-none-any.whl
Resolving files.pythonhosted.org (files.pythonhosted.org)... 151.101.37.63, 2a04:4e42:9::319
Connecting to files.pythonhosted.org (files.pythonhosted.org)|151.101.37.63|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 215202 (210K) [application/octet-stream]
Saving to: ‘pyinstaller_hooks_contrib-2021.4-py2.py3-none-any.whl’

pyinstaller_hooks_co 100%[=====================>] 210.16K  --.-KB/s    in 0.09s   

2021-12-01 23:09:42 (2.39 MB/s) - ‘pyinstaller_hooks_contrib-2021.4-py2.py3-none-any.whl’ saved [215202/215202]

user@disp2324:/tmp/tmp.bzHGsqimss$ 
user@disp2324:/tmp/tmp.bzHGsqimss$ # setuptools
user@disp2324:/tmp/tmp.bzHGsqimss$ download_url=`${CURL} -s https://pypi.org/simple/setuptools/ | grep -oE "https://.*setuptools-59.4.0-py3-none-any.whl#"`
user@disp2324:/tmp/tmp.bzHGsqimss$ ${WGET} ${download_url}
--2021-12-01 23:09:43--  https://files.pythonhosted.org/packages/6f/ea/e12311dabc63a6a434be25e6011c1513cc95d0cf22e5f13036f75b3ec508/setuptools-59.4.0-py3-none-any.whl
Resolving files.pythonhosted.org (files.pythonhosted.org)... 151.101.37.63, 2a04:4e42:9::319
Connecting to files.pythonhosted.org (files.pythonhosted.org)|151.101.37.63|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 952264 (930K) [application/octet-stream]
Saving to: ‘setuptools-59.4.0-py3-none-any.whl’

setuptools-59.4.0-py 100%[=====================>] 929.95K  2.91MB/s    in 0.3s    

2021-12-01 23:09:43 (2.91 MB/s) - ‘setuptools-59.4.0-py3-none-any.whl’ saved [952264/952264]

user@disp2324:/tmp/tmp.bzHGsqimss$ 
user@disp2324:/tmp/tmp.bzHGsqimss$ # checksum
user@disp2324:/tmp/tmp.bzHGsqimss$ sha256sum *
743628f2ac6a7c26f5d9223c91ed8ecbba535f506f4b6f558885a8a56a105857  altgraph-0.17.2-py2.py3-none-any.whl
885613dd02d3e26dbd2b541eb4cc4ce611b841f827c0958ab98656e478b9e6f6  macholib-1.15.2-py2.py3-none-any.whl
2c7f4810dc5272ec1b388a7f1ff6b56d38653c1b0c9ac2d9dd54fa06b590e372  pyinstaller-4.7.tar.gz
60a57e4057fa2183bbaa81f10401a27eb7dd701ef8a11b287bb6345b571f94e7  pyinstaller_hooks_contrib-2021.4-py2.py3-none-any.whl
feb5ff19b354cde9efd2344ef6d5e79880ce4be643037641b49508bbb850d060  setuptools-59.4.0-py3-none-any.whl
user@disp2324:/tmp/tmp.bzHGsqimss$ 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

1 participant