##// END OF EJS Templates
Backport PR #9211: Release process tweaks...
Min RK -
Show More
@@ -1,185 +1,185 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 1. Set Environment variables
13 1. Set Environment variables
14 ----------------------------
14 ----------------------------
15
15
16 Set environment variables to document previous release tag, current
16 Set environment variables to document previous release tag, current
17 release milestone, current release version, and git tag::
17 release milestone, current release version, and git tag::
18
18
19 PREV_RELEASE=rel-1.0.0
19 PREV_RELEASE=rel-1.0.0
20 MILESTONE=1.1
20 MILESTONE=1.1
21 VERSION=1.1.0
21 VERSION=1.1.0
22 TAG="rel-$VERSION"
22 TAG="rel-$VERSION"
23 BRANCH=master
23 BRANCH=master
24
24
25 These variables may be used later to copy/paste as answers to the script
25 These variables may be used later to copy/paste as answers to the script
26 questions instead of typing the appropriate command when the time comes. These
26 questions instead of typing the appropriate command when the time comes. These
27 variables are not used by the scripts directly; therefore, there is no need to
27 variables are not used by the scripts directly; therefore, there is no need to
28 `export` the variables.
28 `export` the variables.
29
29
30 2. Create GitHub stats and finish release note
30 2. Create GitHub stats and finish release note
31 ----------------------------------------------
31 ----------------------------------------------
32
32
33 .. note::
33 .. note::
34
34
35 Before generating the GitHub stats, verify that all closed issues and
35 Before generating the GitHub stats, verify that all closed issues and
36 pull requests have `appropriate milestones <https://github.com/ipython/ipython/wiki/Dev%3A-GitHub-workflow#milestones>`_.
36 pull requests have `appropriate milestones <https://github.com/ipython/ipython/wiki/Dev%3A-GitHub-workflow#milestones>`_.
37 `This search <https://github.com/ipython/ipython/issues?q=is%3Aclosed+no%3Amilestone+is%3Aissue>`_
37 `This search <https://github.com/ipython/ipython/issues?q=is%3Aclosed+no%3Amilestone+is%3Aissue>`_
38 should return no results before creating the GitHub stats.
38 should return no results before creating the GitHub stats.
39
39
40 If a major release:
40 If a major release:
41
41
42 - merge any pull request notes into what's new::
42 - merge any pull request notes into what's new::
43
43
44 python tools/update_whatsnew.py
44 python tools/update_whatsnew.py
45
45
46 - update `docs/source/whatsnew/development.rst`, to ensure it covers
46 - update `docs/source/whatsnew/development.rst`, to ensure it covers
47 the major release features
47 the major release features
48 - move the contents of `development.rst` to `versionX.rst` where `X` is
48 - move the contents of `development.rst` to `versionX.rst` where `X` is
49 the numerical release version
49 the numerical release version
50 - generate summary of GitHub contributions, which can be done with::
50 - generate summary of GitHub contributions, which can be done with::
51
51
52 python tools/github_stats.py --milestone $MILESTONE > stats.rst
52 python tools/github_stats.py --milestone $MILESTONE > stats.rst
53
53
54 which may need some manual cleanup of `stats.rst`. Add the cleaned
54 which may need some manual cleanup of `stats.rst`. Add the cleaned
55 `stats.rst` results to `docs/source/whatsnew/github-stats-X.rst` where
55 `stats.rst` results to `docs/source/whatsnew/github-stats-X.rst` where
56 `X` is the numerical release version. If creating a major release, make
56 `X` is the numerical release version. If creating a major release, make
57 a new `github-stats-X.rst` file; if creating a minor release, the
57 a new `github-stats-X.rst` file; if creating a minor release, the
58 content from `stats.rst` may simply be added to the top of an existing
58 content from `stats.rst` may simply be added to the top of an existing
59 `github-stats-X.rst` file.
59 `github-stats-X.rst` file.
60
60
61 To find duplicates and update `.mailmap`, use::
61 To find duplicates and update `.mailmap`, use::
62
62
63 git log --format="%aN <%aE>" $PREV_RELEASE... | sort -u -f
63 git log --format="%aN <%aE>" $PREV_RELEASE... | sort -u -f
64
64
65 3. Make sure the repository is clean
65 3. Make sure the repository is clean
66 ------------------------------------
66 ------------------------------------
67
67
68 of any file that could be problematic.
68 of any file that could be problematic.
69 Remove all non-tracked files with:
69 Remove all non-tracked files with:
70
70
71 .. code::
71 .. code::
72
72
73 git clean -xfdi
73 git clean -xfdi
74
74
75 This will ask for confirmation before removing all untracked files. Make
75 This will ask for confirmation before removing all untracked files. Make
76 sure the ``dist/`` folder is clean to avoid any stale builds from
76 sure the ``dist/`` folder is clean to avoid any stale builds from
77 previous build attempts.
77 previous build attempts.
78
78
79
79
80
80
81 4. Run the `tools/build_release` script
81 4. Run the `tools/build_release` script
82 ---------------------------------------
82 ---------------------------------------
83
83
84 Running `tools/build_release` does all the file checking and building that
84 Running `tools/build_release` does all the file checking and building that
85 the real release script will do. This makes test installations, checks that
85 the real release script will do. This makes test installations, checks that
86 the build procedure runs OK, and tests other steps in the release process.
86 the build procedure runs OK, and tests other steps in the release process.
87
87
88 We encourage creating a test build of the docs as well.
88 We encourage creating a test build of the docs as well.
89
89
90 5. Create and push the new tag
90 5. Create and push the new tag
91 ------------------------------
91 ------------------------------
92
92
93 Edit `IPython/core/release.py` to have the current version.
93 Edit `IPython/core/release.py` to have the current version.
94
94
95 in particular, update version number and ``_version_extra`` content in
95 in particular, update version number and ``_version_extra`` content in
96 ``IPython/core/release.py``.
96 ``IPython/core/release.py``.
97
97
98 Make sure the version number matches pep440, in particular, `rc` and `beta` are
98 Make sure the version number matches pep440, in particular, `rc` and `beta` are
99 not separated by `.` or the `sdist` and `bdist` will appear as different
99 not separated by `.` or the `sdist` and `bdist` will appear as different
100 releases. For example, a valid version number for a release candidate (rc)
100 releases. For example, a valid version number for a release candidate (rc)
101 release is: ``1.3rc1``. Notice that there is no separator between the '3' and
101 release is: ``1.3rc1``. Notice that there is no separator between the '3' and
102 the 'r'.
102 the 'r'.
103
103
104
104
105 Commit the changes to release.py and jsversion::
105 Commit the changes to release.py::
106
106
107 git commit -am "release $VERSION"
107 git commit -am "release $VERSION"
108 git push origin $BRANCH
108 git push origin $BRANCH
109
109
110 Create and push the tag::
110 Create and push the tag::
111
111
112 git tag -am "release $VERSION" "$TAG"
112 git tag -am "release $VERSION" "$TAG"
113 git push origin --tags
113 git push origin --tags
114
114
115 Update release.py back to `x.y-dev` or `x.y-maint`, and push::
115 Update release.py back to `x.y-dev` or `x.y-maint`, and push::
116
116
117 git commit -am "back to development"
117 git commit -am "back to development"
118 git push origin $BRANCH
118 git push origin $BRANCH
119
119
120 6. Get a fresh clone
120 6. Get a fresh clone
121 --------------------
121 --------------------
122
122
123 Get a fresh clone of the tag for building the release::
123 Get a fresh clone of the tag for building the release::
124
124
125 cd /tmp
125 cd /tmp
126 git clone --depth 1 https://github.com/ipython/ipython.git -b "$TAG"
126 git clone --depth 1 https://github.com/ipython/ipython.git -b "$TAG"
127
127
128 7. Run the release script
128 7. Run the release script
129 -------------------------
129 -------------------------
130
130
131 Run the `release` script, this step requires having a current wheel, Python >=3.4 and Python 2.7.::
131 Run the `release` script, this step requires having a current wheel, Python >=3.4 and Python 2.7.::
132
132
133 cd tools && ./release
133 cd tools && ./release
134
134
135 This makes the tarballs, zipfiles, and wheels, and put them under the `dist/`
135 This makes the tarballs, zipfiles, and wheels, and put them under the `dist/`
136 folder. Be sure to test the ``wheel`` and the ``sdist`` locally before uploading
136 folder. Be sure to test the ``wheel`` and the ``sdist`` locally before uploading
137 them to PyPI.
137 them to PyPI.
138
138
139 Use the following to actually upload the result of the build:
139 Use the following to actually upload the result of the build:
140
140
141 ./release upload
141 ./release upload
142
142
143 It should posts them to ``archive.ipython.org`` and registers the release
143 It should posts them to ``archive.ipython.org`` and registers the release
144 with PyPI if you have the various authorisations.
144 with PyPI if you have the various authorisations.
145
145
146 You might need to use `twine <https://github.com/pypa/twine>`_ (`twine upload
146 You might need to use `twine <https://github.com/pypa/twine>`_ (`twine upload
147 dist/*`) manually to actually upload on PyPI. Unlike setuptools, twine is able
147 dist/*`) manually to actually upload on PyPI. Unlike setuptools, twine is able
148 to upload packages over SSL.
148 to upload packages over SSL.
149
149
150
150
151 8. Draft a short release announcement
151 8. Draft a short release announcement
152 -------------------------------------
152 -------------------------------------
153
153
154 The announcement should include:
154 The announcement should include:
155
155
156 - release highlights
156 - release highlights
157 - a link to the html version of the *What's new* section of the documentation
157 - a link to the html version of the *What's new* section of the documentation
158 - a link to upgrade or installation tips (if necessary)
158 - a link to upgrade or installation tips (if necessary)
159
159
160 Post the announcement to the mailing list and or blog, and link from Twitter.
160 Post the announcement to the mailing list and or blog, and link from Twitter.
161
161
162 9. Update milestones on GitHub
162 9. Update milestones on GitHub
163 ------------------------------
163 ------------------------------
164
164
165 These steps will bring milestones up to date:
165 These steps will bring milestones up to date:
166
166
167 - close the just released milestone
167 - close the just released milestone
168 - open a new milestone for the next release (x, y+1), if the milestone doesn't
168 - open a new milestone for the next release (x, y+1), if the milestone doesn't
169 exist already
169 exist already
170
170
171 10. Update the IPython website
171 10. Update the IPython website
172 ------------------------------
172 ------------------------------
173
173
174 The IPython website should document the new release:
174 The IPython website should document the new release:
175
175
176 - add release announcement (news, announcements)
176 - add release announcement (news, announcements)
177 - update current version and download links
177 - update current version and download links
178 - update links on the documentation page (especially if a major release)
178 - update links on the documentation page (especially if a major release)
179
179
180 11. Celebrate!
180 11. Celebrate!
181 --------------
181 --------------
182
182
183 Celebrate the release and please thank the contributors for their work. Great
183 Celebrate the release and please thank the contributors for their work. Great
184 job!
184 job!
185
185
@@ -1,32 +1,29 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 """IPython release build script.
2 """IPython release build script.
3 """
3 """
4 import os
4 import os
5 from shutil import rmtree
5 from shutil import rmtree
6
6
7 from toollib import sh, pjoin, get_ipdir, cd, compile_tree, execfile, sdists, buildwheels
7 from toollib import sh, pjoin, get_ipdir, cd, execfile, sdists, buildwheels
8
8
9 def build_release():
9 def build_release():
10
10
11 # Get main ipython dir, this will raise if it doesn't pass some checks
11 # Get main ipython dir, this will raise if it doesn't pass some checks
12 ipdir = get_ipdir()
12 ipdir = get_ipdir()
13 cd(ipdir)
13 cd(ipdir)
14
14
15 # Load release info
15 # Load release info
16 execfile(pjoin('IPython', 'core', 'release.py'), globals())
16 execfile(pjoin('IPython', 'core', 'release.py'), globals())
17
17
18 # Check that everything compiles
19 compile_tree('*')
20
21 # Cleanup
18 # Cleanup
22 for d in ['build', 'dist', pjoin('docs', 'build'), pjoin('docs', 'dist'),
19 for d in ['build', 'dist', pjoin('docs', 'build'), pjoin('docs', 'dist'),
23 pjoin('docs', 'source', 'api', 'generated')]:
20 pjoin('docs', 'source', 'api', 'generated')]:
24 if os.path.isdir(d):
21 if os.path.isdir(d):
25 rmtree(d)
22 rmtree(d)
26
23
27 # Build source and binary distros
24 # Build source and binary distros
28 sh(sdists)
25 sh(sdists)
29 buildwheels()
26 buildwheels()
30
27
31 if __name__ == '__main__':
28 if __name__ == '__main__':
32 build_release()
29 build_release()
@@ -1,66 +1,57 b''
1 """Various utilities common to IPython release and maintenance tools.
1 """Various utilities common to IPython release and maintenance tools.
2 """
2 """
3 from __future__ import print_function
3 from __future__ import print_function
4
4
5 # Library imports
5 # Library imports
6 import os
6 import os
7
7
8 # Useful shorthands
8 # Useful shorthands
9 pjoin = os.path.join
9 pjoin = os.path.join
10 cd = os.chdir
10 cd = os.chdir
11
11
12 # Constants
12 # Constants
13
13
14 # SSH root address of the archive site
14 # SSH root address of the archive site
15 archive_user = 'ipython@archive.ipython.org'
15 archive_user = 'ipython@archive.ipython.org'
16 archive_dir = 'archive.ipython.org'
16 archive_dir = 'archive.ipython.org'
17 archive = '%s:%s' % (archive_user, archive_dir)
17 archive = '%s:%s' % (archive_user, archive_dir)
18
18
19 # Build commands
19 # Build commands
20 # Source dists
20 # Source dists
21 sdists = './setup.py sdist --formats=gztar,zip'
21 sdists = './setup.py sdist --formats=gztar,zip'
22 # Binary dists
22 # Binary dists
23 def buildwheels():
23 def buildwheels():
24 for py in ('2', '3'):
24 for py in ('2', '3'):
25 sh('python%s setupegg.py bdist_wheel' % py)
25 sh('python%s setupegg.py bdist_wheel' % py)
26
26
27 # Utility functions
27 # Utility functions
28 def sh(cmd):
28 def sh(cmd):
29 """Run system command in shell, raise SystemExit if it returns an error."""
29 """Run system command in shell, raise SystemExit if it returns an error."""
30 print("$", cmd)
30 print("$", cmd)
31 stat = os.system(cmd)
31 stat = os.system(cmd)
32 #stat = 0 # Uncomment this and comment previous to run in debug mode
32 #stat = 0 # Uncomment this and comment previous to run in debug mode
33 if stat:
33 if stat:
34 raise SystemExit("Command %s failed with code: %s" % (cmd, stat))
34 raise SystemExit("Command %s failed with code: %s" % (cmd, stat))
35
35
36 # Backwards compatibility
36 # Backwards compatibility
37 c = sh
37 c = sh
38
38
39 def get_ipdir():
39 def get_ipdir():
40 """Get IPython directory from command line, or assume it's the one above."""
40 """Get IPython directory from command line, or assume it's the one above."""
41
41
42 # Initialize arguments and check location
42 # Initialize arguments and check location
43 ipdir = pjoin(os.path.dirname(__file__), os.pardir)
43 ipdir = pjoin(os.path.dirname(__file__), os.pardir)
44
44
45 ipdir = os.path.abspath(ipdir)
45 ipdir = os.path.abspath(ipdir)
46
46
47 cd(ipdir)
47 cd(ipdir)
48 if not os.path.isdir('IPython') and os.path.isfile('setup.py'):
48 if not os.path.isdir('IPython') and os.path.isfile('setup.py'):
49 raise SystemExit('Invalid ipython directory: %s' % ipdir)
49 raise SystemExit('Invalid ipython directory: %s' % ipdir)
50 return ipdir
50 return ipdir
51
51
52
53 def compile_tree(folder='.'):
54 """Compile all Python files below current directory."""
55 stat = os.system('python -m compileall {}'.format(folder))
56 if stat:
57 msg = '*** ERROR: Some Python files in tree do NOT compile! ***\n'
58 msg += 'See messages above for the actual file that produced it.\n'
59 raise SystemExit(msg)
60
61 try:
52 try:
62 execfile
53 execfile = execfile
63 except NameError:
54 except NameError:
64 def execfile(fname, globs, locs=None):
55 def execfile(fname, globs, locs=None):
65 locs = locs or globs
56 locs = locs or globs
66 exec(compile(open(fname).read(), fname, "exec"), globs, locs)
57 exec(compile(open(fname).read(), fname, "exec"), globs, locs)
General Comments 0
You need to be logged in to leave comments. Login now