##// END OF EJS Templates
Merge pull request #10241 from takluyver/release-integrate-twine...
Matthias Bussonnier -
r23304:a1a338f2 merge
parent child Browse files
Show More
@@ -1,259 +1,246 b''
1 .. _release_process:
1 .. _release_process:
2
2
3 =======================
3 =======================
4 IPython release process
4 IPython release process
5 =======================
5 =======================
6
6
7 This document contains the process that is used to create an IPython release.
7 This document contains the process that is used to create an IPython release.
8
8
9 Conveniently, the ``release`` script in the ``tools`` directory of the ``IPython``
9 Conveniently, the ``release`` script in the ``tools`` directory of the ``IPython``
10 repository automates most of the release process. This document serves as a
10 repository automates most of the release process. This document serves as a
11 handy reminder and checklist for the release manager.
11 handy reminder and checklist for the release manager.
12
12
13 During the release process, you might need the extra following dependencies:
13 During the release process, you might need the extra following dependencies:
14
14
15 - ``keyring`` to access your GitHub authentication tokens
15 - ``keyring`` to access your GitHub authentication tokens
16 - ``graphviz`` to generate some graphs in the documentation
16 - ``graphviz`` to generate some graphs in the documentation
17
17
18 Make sure you have all the required dependencies to run the tests as well.
18 Make sure you have all the required dependencies to run the tests as well.
19
19
20
20
21 1. Set Environment variables
21 1. Set Environment variables
22 ----------------------------
22 ----------------------------
23
23
24 Set environment variables to document previous release tag, current
24 Set environment variables to document previous release tag, current
25 release milestone, current release version, and git tag.
25 release milestone, current release version, and git tag.
26
26
27 These variables may be used later to copy/paste as answers to the script
27 These variables may be used later to copy/paste as answers to the script
28 questions instead of typing the appropriate command when the time comes. These
28 questions instead of typing the appropriate command when the time comes. These
29 variables are not used by the scripts directly; therefore, there is no need to
29 variables are not used by the scripts directly; therefore, there is no need to
30 ``export`` them. The format for bash is as follows, but note that these values
30 ``export`` them. The format for bash is as follows, but note that these values
31 are just an example valid only for the 5.0 release; you'll need to update them
31 are just an example valid only for the 5.0 release; you'll need to update them
32 for the release you are actually making::
32 for the release you are actually making::
33
33
34 PREV_RELEASE=4.2.1
34 PREV_RELEASE=4.2.1
35 MILESTONE=5.0
35 MILESTONE=5.0
36 VERSION=5.0.0
36 VERSION=5.0.0
37 BRANCH=master
37 BRANCH=master
38
38
39
39
40 2. Create GitHub stats and finish release note
40 2. Create GitHub stats and finish release note
41 ----------------------------------------------
41 ----------------------------------------------
42
42
43 .. note::
43 .. note::
44
44
45 This step is optional if making a Beta or RC release.
45 This step is optional if making a Beta or RC release.
46
46
47 .. note::
47 .. note::
48
48
49 Before generating the GitHub stats, verify that all closed issues and pull
49 Before generating the GitHub stats, verify that all closed issues and pull
50 requests have `appropriate milestones
50 requests have `appropriate milestones
51 <https://github.com/ipython/ipython/wiki/Dev:-GitHub-workflow#milestones>`_.
51 <https://github.com/ipython/ipython/wiki/Dev:-GitHub-workflow#milestones>`_.
52 `This search
52 `This search
53 <https://github.com/ipython/ipython/issues?q=is%3Aclosed+no%3Amilestone+is%3Aissue>`_
53 <https://github.com/ipython/ipython/issues?q=is%3Aclosed+no%3Amilestone+is%3Aissue>`_
54 should return no results before creating the GitHub stats.
54 should return no results before creating the GitHub stats.
55
55
56 If a major release:
56 If a major release:
57
57
58 - merge any pull request notes into what's new::
58 - merge any pull request notes into what's new::
59
59
60 python tools/update_whatsnew.py
60 python tools/update_whatsnew.py
61
61
62 - update ``docs/source/whatsnew/development.rst``, to ensure it covers
62 - update ``docs/source/whatsnew/development.rst``, to ensure it covers
63 the major release features
63 the major release features
64
64
65 - move the contents of ``development.rst`` to ``versionX.rst`` where ``X`` is
65 - move the contents of ``development.rst`` to ``versionX.rst`` where ``X`` is
66 the numerical release version
66 the numerical release version
67
67
68 - generate summary of GitHub contributions, which can be done with::
68 - generate summary of GitHub contributions, which can be done with::
69
69
70 python tools/github_stats.py --milestone $MILESTONE > stats.rst
70 python tools/github_stats.py --milestone $MILESTONE > stats.rst
71
71
72 which may need some manual cleanup of ``stats.rst``. Add the cleaned
72 which may need some manual cleanup of ``stats.rst``. Add the cleaned
73 ``stats.rst`` results to ``docs/source/whatsnew/github-stats-X.rst``
73 ``stats.rst`` results to ``docs/source/whatsnew/github-stats-X.rst``
74 where ``X`` is the numerical release version (don't forget to add it to
74 where ``X`` is the numerical release version (don't forget to add it to
75 the git repo as well). If creating a major release, make a new
75 the git repo as well). If creating a major release, make a new
76 ``github-stats-X.rst`` file; if creating a minor release, the content
76 ``github-stats-X.rst`` file; if creating a minor release, the content
77 from ``stats.rst`` may simply be added to the top of an existing
77 from ``stats.rst`` may simply be added to the top of an existing
78 ``github-stats-X.rst`` file. Finally, edit
78 ``github-stats-X.rst`` file. Finally, edit
79 ``docs/source/whatsnew/index.rst`` to list the new ``github-stats-X``
79 ``docs/source/whatsnew/index.rst`` to list the new ``github-stats-X``
80 file you just created and remove temporarily the first entry called
80 file you just created and remove temporarily the first entry called
81 ``development`` (you'll need to add it back after release).
81 ``development`` (you'll need to add it back after release).
82
82
83 Make sure that the stats file has a header or it won't be rendered in
83 Make sure that the stats file has a header or it won't be rendered in
84 the final documentation.
84 the final documentation.
85
85
86 To find duplicates and update `.mailmap`, use::
86 To find duplicates and update `.mailmap`, use::
87
87
88 git log --format="%aN <%aE>" $PREV_RELEASE... | sort -u -f
88 git log --format="%aN <%aE>" $PREV_RELEASE... | sort -u -f
89
89
90 If a minor release you might need to do some of the above points manually, and
90 If a minor release you might need to do some of the above points manually, and
91 forward port the changes.
91 forward port the changes.
92
92
93 3. Make sure the repository is clean
93 3. Make sure the repository is clean
94 ------------------------------------
94 ------------------------------------
95
95
96 of any file that could be problematic.
96 of any file that could be problematic.
97 Remove all non-tracked files with:
97 Remove all non-tracked files with:
98
98
99 .. code::
99 .. code::
100
100
101 git clean -xfdi
101 git clean -xfdi
102
102
103 This will ask for confirmation before removing all untracked files. Make
103 This will ask for confirmation before removing all untracked files. Make
104 sure the ``dist/`` folder is clean to avoid any stale builds from
104 sure the ``dist/`` folder is clean to avoid any stale builds from
105 previous build attempts.
105 previous build attempts.
106
106
107
107
108 4. Update the release version number
108 4. Update the release version number
109 ------------------------------------
109 ------------------------------------
110
110
111 Edit ``IPython/core/release.py`` to have the current version.
111 Edit ``IPython/core/release.py`` to have the current version.
112
112
113 in particular, update version number and ``_version_extra`` content in
113 in particular, update version number and ``_version_extra`` content in
114 ``IPython/core/release.py``.
114 ``IPython/core/release.py``.
115
115
116 Step 5 will validate your changes automatically, but you might still want to
116 Step 5 will validate your changes automatically, but you might still want to
117 make sure the version number matches pep440.
117 make sure the version number matches pep440.
118
118
119 In particular, ``rc`` and ``beta`` are not separated by ``.`` or the ``sdist``
119 In particular, ``rc`` and ``beta`` are not separated by ``.`` or the ``sdist``
120 and ``bdist`` will appear as different releases. For example, a valid version
120 and ``bdist`` will appear as different releases. For example, a valid version
121 number for a release candidate (rc) release is: ``1.3rc1``. Notice that there
121 number for a release candidate (rc) release is: ``1.3rc1``. Notice that there
122 is no separator between the '3' and the 'r'. Check the environment variable
122 is no separator between the '3' and the 'r'. Check the environment variable
123 ``$VERSION`` as well.
123 ``$VERSION`` as well.
124
124
125 You will likely just have to modify/comment/uncomment one of the lines setting
125 You will likely just have to modify/comment/uncomment one of the lines setting
126 ``_version_extra``
126 ``_version_extra``
127
127
128
128
129 5. Run the `tools/build_release` script
129 5. Run the `tools/build_release` script
130 ---------------------------------------
130 ---------------------------------------
131
131
132 Running ``tools/build_release`` does all the file checking and building that
132 Running ``tools/build_release`` does all the file checking and building that
133 the real release script will do. This makes test installations, checks that
133 the real release script will do. This makes test installations, checks that
134 the build procedure runs OK, and tests other steps in the release process.
134 the build procedure runs OK, and tests other steps in the release process.
135
135
136 The ``build_release`` script will in particular verify that the version number
136 The ``build_release`` script will in particular verify that the version number
137 match PEP 440, in order to avoid surprise at the time of build upload.
137 match PEP 440, in order to avoid surprise at the time of build upload.
138
138
139 We encourage creating a test build of the docs as well.
139 We encourage creating a test build of the docs as well.
140
140
141 6. Create and push the new tag
141 6. Create and push the new tag
142 ------------------------------
142 ------------------------------
143
143
144 Commit the changes to release.py::
144 Commit the changes to release.py::
145
145
146 git commit -am "release $VERSION"
146 git commit -am "release $VERSION"
147 git push origin $BRANCH
147 git push origin $BRANCH
148
148
149 Create and push the tag::
149 Create and push the tag::
150
150
151 git tag -am "release $VERSION" "$VERSION"
151 git tag -am "release $VERSION" "$VERSION"
152 git push origin --tags
152 git push origin --tags
153
153
154 Update release.py back to ``x.y-dev`` or ``x.y-maint``, and re-add the
154 Update release.py back to ``x.y-dev`` or ``x.y-maint``, and re-add the
155 ``development`` entry in ``docs/source/whatsnew/index.rst`` and push::
155 ``development`` entry in ``docs/source/whatsnew/index.rst`` and push::
156
156
157 git commit -am "back to development"
157 git commit -am "back to development"
158 git push origin $BRANCH
158 git push origin $BRANCH
159
159
160 7. Get a fresh clone
160 7. Get a fresh clone
161 --------------------
161 --------------------
162
162
163 Get a fresh clone of the tag for building the release::
163 Get a fresh clone of the tag for building the release::
164
164
165 cd /tmp
165 cd /tmp
166 git clone --depth 1 https://github.com/ipython/ipython.git -b "$VERSION"
166 git clone --depth 1 https://github.com/ipython/ipython.git -b "$VERSION"
167 cd ipython
167 cd ipython
168
168
169 .. note::
169 .. note::
170
170
171 You can aslo cleanup the current working repository with ``git clean -xfdi``
171 You can also cleanup the current working repository with ``git clean -xfdi``
172
172
173 8. Run the release script
173 8. Run the release script
174 -------------------------
174 -------------------------
175
175
176 .. important::
177
178 These steps cover instructions for creating releases of IPython 5.x LTS and
179 IPython 6.x. Ignore release steps for Python 2 when releasing IPython 6.x
180 which no longer supports Python 2.
181
182 Run the ``release`` script, this step requires having a current wheel, Python
176 Run the ``release`` script, this step requires having a current wheel, Python
183 >=3.4 and Python 2.7.::
177 >=3.4 and Python 2.7.::
184
178
185 ./tools/release
179 ./tools/release
186
180
187 This makes the tarballs and wheels, and puts them under the ``dist/``
181 This makes the tarballs and wheels, and puts them under the ``dist/``
188 folder. Be sure to test the ``wheels`` and the ``sdist`` locally before
182 folder. Be sure to test the ``wheels`` and the ``sdist`` locally before
189 uploading them to PyPI. We do not use an universal wheel as each wheel
183 uploading them to PyPI. We do not use an universal wheel as each wheel
190 installs an ``ipython2`` or ``ipython3`` script, depending on the version of
184 installs an ``ipython2`` or ``ipython3`` script, depending on the version of
191 Python it is built for. Using an universal wheel would prevent this.
185 Python it is built for. Using an universal wheel would prevent this.
192
186
193 Use the following to actually upload the result of the build::
187 Use the following to actually upload the result of the build::
194
188
195 ./tools/release upload
189 ./tools/release upload
196
190
197 It should posts them to ``archive.ipython.org``.
191 It should posts them to ``archive.ipython.org`` and to PyPI.
198
199 You will need to use `twine <https://github.com/pypa/twine>`_ ) manually to
200 actually upload on PyPI. Unlike setuptools, twine is able to upload packages
201 over SSL::
202
203 twine upload dist/*
204
205
192
206 PyPI/Warehouse will automatically hide previous releases. If you are uploading
193 PyPI/Warehouse will automatically hide previous releases. If you are uploading
207 a non-stable version, make sure to log-in to PyPI and un-hide previous version.
194 a non-stable version, make sure to log-in to PyPI and un-hide previous version.
208
195
209
196
210 9. Draft a short release announcement
197 9. Draft a short release announcement
211 -------------------------------------
198 -------------------------------------
212
199
213 The announcement should include:
200 The announcement should include:
214
201
215 - release highlights
202 - release highlights
216 - a link to the html version of the *What's new* section of the documentation
203 - a link to the html version of the *What's new* section of the documentation
217 - a link to upgrade or installation tips (if necessary)
204 - a link to upgrade or installation tips (if necessary)
218
205
219 Post the announcement to the mailing list and or blog, and link from Twitter.
206 Post the announcement to the mailing list and or blog, and link from Twitter.
220
207
221 .. note::
208 .. note::
222
209
223 If you are doing a RC or Beta, you can likely skip the next steps.
210 If you are doing a RC or Beta, you can likely skip the next steps.
224
211
225 10. Update milestones on GitHub
212 10. Update milestones on GitHub
226 -------------------------------
213 -------------------------------
227
214
228 These steps will bring milestones up to date:
215 These steps will bring milestones up to date:
229
216
230 - close the just released milestone
217 - close the just released milestone
231 - open a new milestone for the next release (x, y+1), if the milestone doesn't
218 - open a new milestone for the next release (x, y+1), if the milestone doesn't
232 exist already
219 exist already
233
220
234 11. Update the IPython website
221 11. Update the IPython website
235 ------------------------------
222 ------------------------------
236
223
237 The IPython website should document the new release:
224 The IPython website should document the new release:
238
225
239 - add release announcement (news, announcements)
226 - add release announcement (news, announcements)
240 - update current version and download links
227 - update current version and download links
241 - update links on the documentation page (especially if a major release)
228 - update links on the documentation page (especially if a major release)
242
229
243 12. Update readthedocs
230 12. Update readthedocs
244 ----------------------
231 ----------------------
245
232
246 Make sure to update readthedocs and set the latest tag as stable, as well as
233 Make sure to update readthedocs and set the latest tag as stable, as well as
247 checking that previous release is still building under its own tag.
234 checking that previous release is still building under its own tag.
248
235
249 13. Update the Conda-Forge feedstock
236 13. Update the Conda-Forge feedstock
250 ------------------------------------
237 ------------------------------------
251
238
252 Follow the instructions on `the repository <https://github.com/conda-forge/ipython-feedstock>`_
239 Follow the instructions on `the repository <https://github.com/conda-forge/ipython-feedstock>`_
253
240
254 14. Celebrate!
241 14. Celebrate!
255 --------------
242 --------------
256
243
257 Celebrate the release and please thank the contributors for their work. Great
244 Celebrate the release and please thank the contributors for their work. Great
258 job!
245 job!
259
246
@@ -1,89 +1,94 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 """IPython release script.
2 """IPython release script.
3
3
4 This should ONLY be run at real release time.
4 This should ONLY be run at real release time.
5 """
5 """
6 from __future__ import print_function
6 from __future__ import print_function
7
7
8 import os
8 import os
9 from subprocess import call
9 import sys
10 import sys
10
11
11 from toollib import (get_ipdir, pjoin, cd, execfile, sh, archive,
12 from toollib import (get_ipdir, pjoin, cd, execfile, sh, archive,
12 sdists, archive_user, archive_dir, buildwheels)
13 sdists, archive_user, archive_dir, buildwheels)
13 from gh_api import post_download
14 from gh_api import post_download
14
15
15 # Get main ipython dir, this will raise if it doesn't pass some checks
16 # Get main ipython dir, this will raise if it doesn't pass some checks
16 ipdir = get_ipdir()
17 ipdir = get_ipdir()
17 tooldir = pjoin(ipdir, 'tools')
18 tooldir = pjoin(ipdir, 'tools')
18 distdir = pjoin(ipdir, 'dist')
19 distdir = pjoin(ipdir, 'dist')
19
20
20 # Where I keep static backups of each release
21 # Where I keep static backups of each release
21 ipbackupdir = os.path.expanduser('~/ipython/backup')
22 ipbackupdir = os.path.expanduser('~/ipython/backup')
22 if not os.path.exists(ipbackupdir):
23 if not os.path.exists(ipbackupdir):
23 os.makedirs(ipbackupdir)
24 os.makedirs(ipbackupdir)
24
25
25 # Start in main IPython dir
26 # Start in main IPython dir
26 cd(ipdir)
27 cd(ipdir)
27
28
28 # Load release info
29 # Load release info
29 version = None
30 version = None
30 execfile(pjoin('IPython','core','release.py'), globals())
31 execfile(pjoin('IPython','core','release.py'), globals())
31
32
32 # Build site addresses for file uploads
33 # Build site addresses for file uploads
33 release_site = '%s/release/%s' % (archive, version)
34 release_site = '%s/release/%s' % (archive, version)
34 backup_site = '%s/backup/' % archive
35 backup_site = '%s/backup/' % archive
35
36
36 # Start actual release process
37 # Start actual release process
37 print()
38 print()
38 print('Releasing IPython')
39 print('Releasing IPython')
39 print('=================')
40 print('=================')
40 print()
41 print()
41 print('Version:', version)
42 print('Version:', version)
42 print()
43 print()
43 print('Source IPython directory:', ipdir)
44 print('Source IPython directory:', ipdir)
44 print()
45 print()
45
46
46 # Perform local backup, go to tools dir to run it.
47 # Perform local backup, go to tools dir to run it.
47 cd(tooldir)
48 cd(tooldir)
48
49
49 if 'upload' in sys.argv:
50 if 'upload' in sys.argv:
50 cd(distdir)
51 cd(distdir)
51 print( 'Uploading distribution files to GitHub...')
52 #print( 'Uploading distribution files to GitHub...')
52
53
53 for fname in os.listdir('.'):
54 for fname in os.listdir('.'):
54 # TODO: update to GitHub releases API
55 # TODO: update to GitHub releases API
55 continue
56 continue
56 print('uploading %s to GitHub' % fname)
57 print('uploading %s to GitHub' % fname)
57 desc = "IPython %s source distribution" % version
58 desc = "IPython %s source distribution" % version
58 post_download("ipython/ipython", fname, description=desc)
59 post_download("ipython/ipython", fname, description=desc)
59
60
60 # Make target dir if it doesn't exist
61 # Make target dir if it doesn't exist
61 print('Uploading IPython to backup site.')
62 print('1. Uploading IPython to archive.ipython.org')
62 sh('ssh %s "mkdir -p %s/release/%s" ' % (archive_user, archive_dir, version))
63 sh('ssh %s "mkdir -p %s/release/%s" ' % (archive_user, archive_dir, version))
63 sh('scp * %s' % release_site)
64 sh('scp * %s' % release_site)
64
65
65 print( 'Uploading backup files...')
66 print('2. Uploading backup files...')
66 cd(ipbackupdir)
67 cd(ipbackupdir)
67 sh('scp `ls -1tr *tgz | tail -1` %s' % backup_site)
68 sh('scp `ls -1tr *tgz | tail -1` %s' % backup_site)
68
69
69 print('Done!')
70 print('3. Uploading to PyPI using twine')
70 print('Use `twine upload dist/*` to upload the files to PyPI')
71 cd(distdir)
72 call(['twine', 'upload'] + os.listdir('.'))
73
71 else:
74 else:
75 # Build, but don't upload
76
77 # Make backup tarball
72 sh('./make_tarball.py')
78 sh('./make_tarball.py')
73 sh('mv ipython-*.tgz %s' % ipbackupdir)
79 sh('mv ipython-*.tgz %s' % ipbackupdir)
74
80
75 # Build release files
81 # Build release files
76 sh('./build_release %s' % ipdir)
82 sh('./build_release %s' % ipdir)
77
83
78 # Not Registering with PyPI, registering with setup.py is insecure as communication is not encrypted
79 cd(ipdir)
84 cd(ipdir)
80
85
81 # Upload all files
86 # Upload all files
82 sh(sdists)
87 sh(sdists)
83
88
84 buildwheels()
89 buildwheels()
85 print("`./release upload` to upload source distribution on github and ipython archive")
90 print("`./release upload` to upload source distribution on PyPI and ipython archive")
86 sys.exit(0)
91 sys.exit(0)
87
92
88
93
89
94
General Comments 0
You need to be logged in to leave comments. Login now