##// END OF EJS Templates
Backport PR #12347: What's new in 7.15+ Reproducible build working
Matthias Bussonnier -
Show More
@@ -0,0 +1,60 b''
1 """
2 Un-targz and retargz a targz file to ensure reproducible build.
3
4 usage:
5
6 $ export SOURCE_DATE_EPOCH=$(date +%s)
7 ...
8 $ python retar.py <tarfile.gz>
9
10 The process of creating an sdist can be non-reproducible:
11 - directory created during the process get a mtime of the creation date;
12 - gziping files embed the timestamp of fo zip creation.
13
14 This will untar-retar; ensuring that all mtime > SOURCE_DATE_EPOCH will be set
15 equal to SOURCE_DATE_EPOCH.
16
17 """
18
19 import tarfile
20 import sys
21 import os
22 import gzip
23 import io
24
25 if len(sys.argv) > 2:
26 raise ValueError("Too many arguments")
27
28
29 timestamp = int(os.environ["SOURCE_DATE_EPOCH"])
30
31 old_buf = io.BytesIO()
32 with open(sys.argv[1], "rb") as f:
33 old_buf.write(f.read())
34 old_buf.seek(0)
35 old = tarfile.open(fileobj=old_buf, mode="r:gz")
36
37 buf = io.BytesIO()
38 new = tarfile.open(fileobj=buf, mode="w", format=tarfile.GNU_FORMAT)
39 for i, m in enumerate(old):
40 data = None
41 # mutation does not work, copy
42 if m.name.endswith('.DS_Store'):
43 continue
44 m2 = tarfile.TarInfo(m.name)
45 m2.mtime = min(timestamp, m.mtime)
46 m2.size = m.size
47 m2.type = m.type
48 m2.linkname = m.linkname
49 if m.isdir():
50 data = old.extractfile(m)
51 new.addfile(m2, data)
52 else:
53 new.addfile(m2)
54 new.close()
55 old.close()
56
57 buf.seek(0)
58 with open(sys.argv[1], "wb") as f:
59 with gzip.GzipFile('', "wb", fileobj=f, mtime=timestamp) as gzf:
60 gzf.write(buf.read())
@@ -80,6 +80,13 b' for the release you are actually making::'
80 80 VERSION=5.0.0
81 81 BRANCH=master
82 82
83 For `reproducibility of builds <https://reproducible-builds.org/specs/source-date-epoch/>`_,
84 we recommend setting ``SOURCE_DATE_EPOCH`` prior to running the build; record the used value
85 of ``SOURCE_DATE_EPOCH`` as it may not be available from build artifact. You
86 should be able to use ``date +%s`` to get a formatted timestamp::
87
88 SOURCE_DATE_EPOCH=$(date +%s)
89
83 90
84 91 2. Create GitHub stats and finish release note
85 92 ----------------------------------------------
@@ -229,6 +236,16 b' uploading them to PyPI. We do not use an universal wheel as each wheel'
229 236 installs an ``ipython2`` or ``ipython3`` script, depending on the version of
230 237 Python it is built for. Using an universal wheel would prevent this.
231 238
239 Check the shasum of files with::
240
241 shasum -a 256 dist/*
242
243 and takes notes of them you might need them to update the conda-forge recipes.
244 Rerun the command and check the hash have not changed::
245
246 ./tools/release
247 shasum -a 256 dist/*
248
232 249 Use the following to actually upload the result of the build::
233 250
234 251 ./tools/release upload
@@ -2,6 +2,90 b''
2 2 7.x Series
3 3 ============
4 4
5 .. _version 715:
6
7 IPython 7.15
8 ============
9
10 IPython 7.15 brings a number of bug fixes and user facing improvements.
11
12 Misc Noticeable changes:
13 ------------------------
14
15 - Long completion name have better elision in terminal :ghpull:`12284`
16 - I've started to test on Python 3.9 :ghpull:`12307` and fix some errors.
17 - Hi DPI scaling of figures when using qt eventloop :ghpull:`12314`
18 - Document the ability to have systemwide configuration for IPython.
19 :ghpull:`12328`
20 - Fix issues with input autoformatting :ghpull:`12336`
21
22 Reproducible Build
23 ------------------
24
25 Starting with IPython 7.15, I am attempting to provide reproducible builds,
26 that is to say you should be able from the source tree to generate an sdist
27 and wheel that are identical byte for byte with the publish version on PyPI.
28
29 I've only tested on a couple of machines so far and the process is relatively
30 straightforward, so this mean that IPython not only have a deterministic build
31 process, but also I have either removed, or put under control all effects of
32 the build environments on the final artifact. I encourage you to attempt the
33 build process on your machine as documented in :ref:`core_developer_guide`
34 and let me know if you do not obtain an identical artifact.
35
36 While reproducible builds is critical to check that the supply chain of (open
37 source) software has not been compromised, it can also help to speedup many
38 of the build processes in large environment (conda, apt...) by allowing
39 better caching of intermediate build steps.
40
41 Learn more on `<https://reproducible-builds.org/>`_. `Reflections on trusting
42 trust <https://dl.acm.org/doi/10.1145/358198.358210>`_ is also one of the
43 cornerstone and recommended reads on this subject.
44
45 .. note::
46
47 The build commit from which the sdist is generated is also `signed
48 <https://en.wikipedia.org/wiki/Digital_signature>`_, so you should be able to
49 check it has not been compromised, and the git repository is a `merkle-tree
50 <https://en.wikipedia.org/wiki/Merkle_tree>`_, you can check the consistency
51 with `git-fsck <https://git-scm.com/docs/git-fsck>`_ which you likely `want
52 to enable by default
53 <https://gist.github.com/mbbx6spp/14b86437e794bffb4120>`_.
54
55 NEP29: Last version to support Python 3.6
56 -----------------------------------------
57
58 IPython 7.15 will be the Last IPython version to officially support Python
59 3.6, as stated by `NumPy Enhancement Proposal 29
60 <https://numpy.org/neps/nep-0029-deprecation_policy.html>`_. Starting with
61 next minor version of IPython I may stop testing on Python 3.6 and may stop
62 publishing release artifacts that install on Python 3.6
63
64 Highlighted features
65 --------------------
66
67 Highlighted features are not new, but seem to not be widely known, this
68 section will help you discover in more narrative form what you can do with
69 IPython.
70
71 Increase Tab Completion Menu Height
72 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
73
74 In terminal IPython it is possible to increase the hight of the tab-completion
75 menu. To do so set the value of
76 :configtrait:`TerminalInteractiveShell.space_for_menu`, this will reserve more
77 space at the bottom of the screen for various kind of menus in IPython including
78 tab completion and searching in history.
79
80 Autoformat Code in the terminal
81 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
82
83 If you have a preferred code formatter, you can configure IPython to
84 reformat your code. Set the value of
85 :configtrait:`TerminalInteractiveShell.autoformatter` to for example ``'black'``
86 and IPython will auto format your code when possible.
87
88
5 89 .. _version 714:
6 90
7 91 IPython 7.14
@@ -225,7 +225,7 b' everything = set()'
225 225 for key, deps in extras_require.items():
226 226 if ':' not in key:
227 227 everything.update(deps)
228 extras_require['all'] = everything
228 extras_require['all'] = list(sorted(everything))
229 229
230 230 if 'setuptools' in sys.modules:
231 231 setuptools_extra_args['python_requires'] = '>=3.6'
@@ -2,6 +2,7 b''
2 2 """IPython release build script.
3 3 """
4 4 import os
5 import sys
5 6 from shutil import rmtree
6 7
7 8 from toollib import sh, pjoin, get_ipdir, cd, sdists, buildwheels
@@ -12,15 +13,10 b' def build_release():'
12 13 ipdir = get_ipdir()
13 14 cd(ipdir)
14 15
15 # Cleanup
16 for d in ['build', 'dist', pjoin('docs', 'build'), pjoin('docs', 'dist'),
17 pjoin('docs', 'source', 'api', 'generated')]:
18 if os.path.isdir(d):
19 rmtree(d)
20
21 16 # Build source and binary distros
22 17 sh(sdists)
23 18 buildwheels()
19 sh(' '.join([sys.executable, 'tools/retar.py', 'dist/*.gz']))
24 20
25 21 if __name__ == '__main__':
26 22 build_release()
@@ -3,7 +3,6 b''
3 3 """
4 4
5 5 import subprocess
6 import os
7 6
8 7 from toollib import cd, sh
9 8
@@ -81,13 +81,10 b' else:'
81 81 sh('mv ipython-*.tgz %s' % ipbackupdir)
82 82
83 83 # Build release files
84 sh('./build_release %s' % ipdir)
84 sh('./build_release')
85 85
86 86 cd(ipdir)
87 87
88 # Upload all files
89 sh(sdists)
90
91 88 buildwheels()
92 89 print("`./release upload` to upload source distribution on PyPI and ipython archive")
93 90 sys.exit(0)
@@ -98,12 +98,6 b' then'
98 98
99 99 fi
100 100
101 echo
102 echo $BLUE"Attempting to build package..."$NOR
103
104 tools/build_release
105 rm dist/*
106
107 101 if ask_section "Should we commit, tag, push... etc ? "
108 102 then
109 103 echo
@@ -161,13 +155,40 b' fi'
161 155 if ask_section "Should we build and release ?"
162 156 then
163 157
158 echo $BLUE"going to set SOURCE_DATE_EPOCH"$NOR
159 echo $BLUE'export SOURCE_DATE_EPOCH=$(git show -s --format=%ct HEAD)'$NOR
160 echo $GREEN"Press enter to continue"$NOR
161 read
162
163 export SOURCE_DATE_EPOCH=$(git show -s --format=%ct HEAD)
164
165 echo $BLUE"SOURCE_DATE_EPOCH set to $SOURCE_DATE_EPOCH"$NOR
166 echo $GREEN"Press enter to continue"$NOR
167 read
168
169
170
171 echo
172 echo $BLUE"Attempting to build package..."$NOR
173
174 tools/release
175
176
177 echo $RED'$ shasum -a 256 dist/*'
178 shasum -a 256 dist/*
179 echo $NOR
180
181 echo $BLUE"We are going to rebuild, node the hash above, and compare them to the rebuild"$NOR
182 echo $GREEN"Press enter to continue"$NOR
183 read
184
164 185 echo
165 186 echo $BLUE"Attempting to build package..."$NOR
166 187
167 188 tools/release
168 189
169 echo $RED
170 echo '$ shasum -a 256 dist/*'
190 echo $RED"Check the shasum for SOURCE_DATE_EPOCH=$SOURCE_DATE_EPOCH"
191 echo $RED'$ shasum -a 256 dist/*'
171 192 shasum -a 256 dist/*
172 193 echo $NOR
173 194
General Comments 0
You need to be logged in to leave comments. Login now