Source: tox Version: 4.4.6-2 Severity: wishlist Tags: patch User: reproducible-bui...@lists.alioth.debian.org Usertags: timestamps, randomness X-Debbugs-Cc: reproducible-b...@lists.alioth.debian.org
Hi, Whilst working on the Reproducible Builds effort [0], we noticed that tox could not be built reproducibly. This is because: a) The documentation embeded the current build date via the copyright year and a "last updated" timestamp. The attached patch changes this to use SOURCE_DATE_EPOCH if available. b) The default value for the --hashset argument (a random integer) was encoded into the documentation. As this value was nondeterminstic, a fresh value is inserted into the documentation on each build. This in turn makes the package unreproducible. The attached patch changes this to use the Pythonic "default=None … if default is None" pattern (NB. this is distinct from the "notset" value, which, incidentally, is typod in the --help text.) [0] https://reproducible-builds.org/ Regards, -- ,''`. : :' : Chris Lamb `. `'` la...@debian.org / chris-lamb.co.uk `-
--- a/debian/patches/reproducible-build.patch 1970-01-01 01:00:00.000000000 +0100 --- b/debian/patches/reproducible-build.patch 2023-08-09 09:12:22.249949353 +0100 @@ -0,0 +1,67 @@ +Description: Make the build reproducible +Author: Chris Lamb <la...@debian.org> +Last-Update: 2023-08-09 + +--- tox-4.4.6.orig/docs/conf.py ++++ tox-4.4.6/docs/conf.py +@@ -1,9 +1,11 @@ + from __future__ import annotations + ++import os + import re + import subprocess + import sys +-from datetime import date, datetime ++import time ++from datetime import datetime + from importlib.machinery import SourceFileLoader + from pathlib import Path + from subprocess import check_output +@@ -20,9 +22,13 @@ from sphinx.ext.extlinks import External + + from tox import __version__ + ++build_date = datetime.utcfromtimestamp( ++ int(os.environ.get('SOURCE_DATE_EPOCH', time.time())) ++) ++ + company, name = "tox-dev", "tox" + release, version = __version__, ".".join(__version__.split(".")[:2]) +-copyright = f"2010-{date.today().year}, {company}" ++copyright = f"2010-{build_date.year}, {company}" + master_doc, source_suffix = "index", ".rst" + + sphinx_argparse_cli_prefix_document = True +@@ -31,7 +37,7 @@ man_pages = [ + ] + + html_theme = "furo" +-html_title, html_last_updated_fmt = "tox", datetime.now().isoformat() ++html_title, html_last_updated_fmt = "tox", build_date.isoformat() + pygments_style, pygments_dark_style = "sphinx", "monokai" + html_static_path, html_css_files = ["_static"], ["custom.css"] + html_logo, html_favicon = "_static/img/tox.svg", "_static/img/toxfavi.ico" +--- tox-4.4.6.orig/src/tox/session/cmd/run/common.py ++++ tox-4.4.6/src/tox/session/cmd/run/common.py +@@ -122,6 +122,8 @@ def env_run_create_flags(parser: Argumen + ) -> None: + if values == "notset": + result = None ++ elif values is None: ++ result = random.randint(1, 1024 if sys.platform == "win32" else 4294967295) + else: + try: + result = int(cast(str, values)) +@@ -135,10 +137,10 @@ def env_run_create_flags(parser: Argumen + "--hashseed", + metavar="SEED", + help="set PYTHONHASHSEED to SEED before running commands. Defaults to a random integer in the range " +- "[1, 4294967295] ([1, 1024] on Windows). Passing 'noset' suppresses this behavior.", ++ "[1, 4294967295] ([1, 1024] on Windows). Passing 'notset' suppresses this behavior.", + action=SeedAction, + of_type=Optional[int], +- default=random.randint(1, 1024 if sys.platform == "win32" else 4294967295), ++ default=None, + dest="hash_seed", + ) + parser.add_argument( --- a/debian/patches/series 2023-08-09 09:02:18.061945063 +0100 --- b/debian/patches/series 2023-08-09 09:06:31.910569337 +0100 @@ -2,3 +2,4 @@ docs-remove-shields-io-badges.patch sphinx-manpage-conf.patch intersphinx-mapping-local.patch +reproducible-build.patch