Skip to content

Commit 2ce3fc6

Browse files
committed
Take rellu tool into use for creating releases
1 parent 9c63b08 commit 2ce3fc6

File tree

3 files changed

+371
-0
lines changed

3 files changed

+371
-0
lines changed

BUILD.rst

Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
Creating PythonLibCore releases
2+
===============================
3+
4+
These instructions cover steps needed to create new releases of PythonLibCore.
5+
Many individual steps are automated, but we don't want to automate
6+
the whole procedure because it would be hard to react if something goes
7+
terribly wrong. When applicable, the steps are listed as commands that can
8+
be copied and executed on the command line.
9+
10+
.. contents::
11+
:depth: 1
12+
13+
Preconditions
14+
-------------
15+
16+
Operating system and Python requirements
17+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
18+
19+
Generating releases has only been tested on Linux, but it ought to work the
20+
same way also on OSX and other unixes. Generating releases on Windows may
21+
work but is not tested, supported, or recommended.
22+
23+
Creating releases is only supported with Python 3.6 or newer. If you are
24+
using Ubuntu or one of its derivatives and don't have Python 3.6 in the
25+
official package repository, you may consider using the
26+
`Dead Snakes PPA <https://launchpad.net/~deadsnakes/+archive/ubuntu/ppa>`_.
27+
28+
The ``pip`` and ``invoke`` commands below are also expected to run on Python
29+
3.6+. Alternatively, it's possible to use the ``python3.6 -m pip`` approach
30+
to run these commands.
31+
32+
Python dependencies
33+
~~~~~~~~~~~~~~~~~~~
34+
35+
Many steps are automated using the generic `Invoke <http://pyinvoke.org>`_
36+
tool with a help by our `rellu <https://github.com/robotframework/rellu>`_
37+
utilities, but also other tools and modules are needed. A pre-condition is
38+
installing all these, and that's easiest done using `pip
39+
<http://pip-installer.org>`_ and the provided `<requirements-build.txt>`_
40+
file::
41+
42+
pip install -r requirements-build.txt
43+
44+
Using Invoke
45+
~~~~~~~~~~~~
46+
47+
Invoke tasks are defined in the `<tasks.py>`_ file and they are executed from
48+
the command line like::
49+
50+
inv[oke] task [options]
51+
52+
Run ``invoke`` without arguments for help. All tasks can be listed using
53+
``invoke --list`` and each task's usage with ``invoke --help task``.
54+
55+
Different Git workflows
56+
~~~~~~~~~~~~~~~~~~~~~~~
57+
58+
Git commands used below always expect that ``origin`` is the project main
59+
repository. If that's not the case, and instead ``origin`` is your personal
60+
fork, you probably still want to push to the main repository. In that case
61+
you need to add ``upstream`` or similar to ``git push`` commands before
62+
running them.
63+
64+
Testing
65+
-------
66+
67+
Make sure that adequate unit and acceptance tests are executed using
68+
supported interpreters and operating systems before releases are created.
69+
Unit and acceptance tests can be executed by running `<utest/run.py>`_ and
70+
`<atest/run.py>`_ scripts, respectively.
71+
72+
Preparation
73+
-----------
74+
75+
1. Check that you are on the master branch and have nothing left to commit,
76+
pull, or push::
77+
78+
git branch
79+
git status
80+
git pull --rebase
81+
git push
82+
83+
2. Clean up::
84+
85+
invoke clean
86+
87+
3. Set version information to a shell variable to ease copy-pasting further
88+
commands. Add ``aN``, ``bN`` or ``rcN`` postfix if creating a pre-release::
89+
90+
VERSION=<version>
91+
92+
For example, ``VERSION=3.0.1`` or ``VERSION=3.1a2``.
93+
94+
Release notes
95+
-------------
96+
97+
1. Set GitHub user information into shell variables to ease copy-pasting the
98+
following command::
99+
100+
GITHUB_USERNAME=<username>
101+
GITHUB_PASSWORD=<password>
102+
103+
Alternatively, supply the credentials when running that command.
104+
105+
2. Generate a template for the release notes::
106+
107+
invoke release-notes -w -v $VERSION -u $GITHUB_USERNAME -p $GITHUB_PASSWORD
108+
109+
The ``-v $VERSION`` option can be omitted if `version is already set
110+
<Set version_>`__. Omit the ``-w`` option if you just want to get release
111+
notes printed to the console, not written to a file.
112+
113+
When generating release notes for a preview release like ``3.0.2rc1``,
114+
the list of issues is only going to contain issues with that label
115+
(e.g. ``rc1``) or with a label of an earlier preview release (e.g.
116+
``alpha1``, ``beta2``).
117+
118+
2. Fill the missing details in the generated release notes template.
119+
120+
3. Make sure that issues have correct information:
121+
122+
- All issues should have type (bug, enhancement or task) and priority set.
123+
Notice that issues with the task type are automatically excluded from
124+
the release notes.
125+
- Issue priorities should be consistent.
126+
- Issue titles should be informative. Consistency is good here too, but
127+
no need to overdo it.
128+
129+
If information needs to be added or edited, its better to edit it in the
130+
issue tracker than in the generated release notes. This allows re-generating
131+
the list of issues later if more issues are added.
132+
133+
4. Add, commit and push::
134+
135+
git add doc/PythonLibCore-$VERSION.rst
136+
git commit -m "Release notes for $VERSION" doc/PythonLibCore-$VERSION.rst
137+
git push
138+
139+
5. Update later if necessary. Writing release notes is typically the biggest
140+
task when generating releases, and getting everything done in one go is
141+
often impossible.
142+
143+
Set version
144+
-----------
145+
146+
1. Set version information in `<src/robotlibcore.py>`_::
147+
148+
invoke set-version $VERSION
149+
150+
2. Commit and push changes::
151+
152+
git commit -m "Updated version to $VERSION" src/robotlibcore.py
153+
git push
154+
155+
Tagging
156+
-------
157+
158+
1. Create an annotated tag and push it::
159+
160+
git tag -a v$VERSION -m "Release $VERSION"
161+
git push --tags
162+
163+
2. Add short release notes to GitHub's `releases page
164+
<https://github.com/robotframework/PythonLibCore/releases>`_
165+
with a link to the full release notes.
166+
167+
Creating distributions
168+
----------------------
169+
170+
1. Checkout the earlier created tag if necessary::
171+
172+
git checkout v$VERSION
173+
174+
This isn't necessary if continuing right after tagging_.
175+
176+
2. Cleanup (again). This removes temporary files as well as ``build`` and
177+
``dist`` directories::
178+
179+
invoke clean
180+
181+
3. Create source distribution and universal (i.e. Python 2 and 3 compatible)
182+
`wheel <http://pythonwheels.com>`_::
183+
184+
python setup.py sdist bdist_wheel --universal
185+
ls -l dist
186+
187+
Distributions can be tested locally if needed.
188+
189+
4. Upload distributions to PyPI::
190+
191+
twine upload dist/*
192+
193+
5. Verify that project the page at `PyPI
194+
<https://pypi.python.org/pypi/robotframework-pythonlibcore>`_
195+
looks good.
196+
197+
6. Test installation (add ``--pre`` with pre-releases)::
198+
199+
pip install --upgrade robotframework-pythonlibcore
200+
201+
Post actions
202+
------------
203+
204+
1. Back to master if needed::
205+
206+
git checkout master
207+
208+
2. Set dev version based on the previous version::
209+
210+
invoke set-version dev
211+
git commit -m "Back to dev version" src/robotlibcore.py
212+
git push
213+
214+
For example, ``1.2.3`` is changed to ``1.2.4.dev1`` and ``2.0.1a1``
215+
to ``2.0.1a2.dev1``.
216+
217+
3. Close the `issue tracker milestone
218+
<https://github.com/robotframework/PythonLibCore/milestones>`_.
219+
Create also new milestone for the next release unless one exists already.
220+
221+
Announcements
222+
-------------
223+
224+
1. `robotframework-users <https://groups.google.com/group/robotframework-users>`_
225+
and
226+
`robotframework-announce <https://groups.google.com/group/robotframework-announce>`_
227+
lists. The latter is not needed with preview releases but should be used
228+
at least with major updates. Notice that sending to it requires admin rights.
229+
230+
2. Twitter. Either Tweet something yourself and make sure it's re-tweeted
231+
by `@robotframework <http://twitter.com/robotframework>`_, or send the
232+
message directly as `@robotframework`. This makes the note appear also
233+
at http://robotframework.org.
234+
235+
Should include a link to more information. Possibly a link to the full
236+
release notes or an email to the aforementioned mailing lists.
237+
238+
3. Slack community. The ``#general`` channel is probably best.
239+
240+
4. Possibly also `Robot Framework LinkedIn
241+
<https://www.linkedin.com/groups/Robot-Framework-3710899>`_ group.

requirements-build.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Requirements needed when generating releases. See BUILD.rst for details.
2+
invoke >= 0.20
3+
rellu >= 0.6
4+
twine
5+
wheel
6+
7+
# Include other dev dependencies from requirements-dev.txt.
8+
-r requirements-dev.txt

tasks.py

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import sys
2+
from pathlib import Path
3+
4+
from invoke import task
5+
from rellu import initialize_labels, ReleaseNotesGenerator, Version
6+
from rellu.tasks import clean
7+
8+
9+
assert Path.cwd() == Path(__file__).parent
10+
11+
12+
REPOSITORY = 'robotframework/PythonLibCore'
13+
VERSION_PATH = Path('src/robotlibcore.py')
14+
RELEASE_NOTES_PATH = Path('docs/PythonLibCore-{version}.rst')
15+
RELEASE_NOTES_TITLE = 'Python Library Core {version}'
16+
RELEASE_NOTES_INTRO = '''
17+
RELEASE NOTES TEMPLATE TODO
18+
19+
`Python Library Core`_ is a generic component making it easier to create
20+
bigger `Robot Framework`_ test libraries. Python Library Core {version} is
21+
a new release with **UPDATE** enhancements and bug fixes. **MORE intro stuff**
22+
23+
**REMOVE this section with final releases or otherwise if release notes contain
24+
all issues.**
25+
All issues targeted for Python Library Core {version.milestone} can be found
26+
from the `issue tracker`_.
27+
28+
**REMOVE ``--pre`` from the next command with final releases.**
29+
If you have pip_ installed, just run
30+
31+
::
32+
33+
pip install --pre --upgrade robotframework-robotlibcore
34+
35+
to install the latest available release or use
36+
37+
::
38+
39+
pip install robotframework-robotlibcore=={version}
40+
41+
to install exactly this version. Alternatively you can download the source
42+
distribution from PyPI_ and install it manually.
43+
44+
SeleniumLibrary {version} was released on {date}.
45+
46+
.. _PythonLibCore: https://github.com/robotframework/PythonLibCore
47+
.. _Robot Framework: http://robotframework.org
48+
.. _pip: http://pip-installer.org
49+
.. _PyPI: https://pypi.python.org/pypi/robotframework-robotlibcore
50+
.. _issue tracker: https://github.com/robotframework/PythonLibCore/issues?q=milestone%3A{version.milestone}
51+
'''
52+
53+
54+
@task
55+
def set_version(ctx, version):
56+
"""Set project version in ``src/robotlibcore.py`` file.
57+
58+
Args:
59+
version: Project version to set or ``dev`` to set development version.
60+
61+
Following PEP-440 compatible version numbers are supported:
62+
- Final version like 3.0 or 3.1.2.
63+
- Alpha, beta or release candidate with ``a``, ``b`` or ``rc`` postfix,
64+
respectively, and an incremented number like 3.0a1 or 3.0.1rc1.
65+
- Development version with ``.dev`` postix and an incremented number like
66+
3.0.dev1 or 3.1a1.dev2.
67+
68+
When the given version is ``dev``, the existing version number is updated
69+
to the next suitable development version. For example, 3.0 -> 3.0.1.dev1,
70+
3.1.1 -> 3.1.2.dev1, 3.2a1 -> 3.2a2.dev1, 3.2.dev1 -> 3.2.dev2.
71+
"""
72+
version = Version(version, VERSION_PATH)
73+
version.write()
74+
print(version)
75+
76+
77+
@task
78+
def print_version(ctx):
79+
"""Print the current project version."""
80+
print(Version(path=VERSION_PATH))
81+
82+
83+
@task
84+
def release_notes(ctx, version=None, username=None, password=None, write=False):
85+
"""Generates release notes based on issues in the issue tracker.
86+
87+
Args:
88+
version: Generate release notes for this version. If not given,
89+
generated them for the current version.
90+
username: GitHub username.
91+
password: GitHub password.
92+
write: When set to True, write release notes to a file overwriting
93+
possible existing file. Otherwise just print them to the
94+
terminal.
95+
96+
Username and password can also be specified using ``GITHUB_USERNAME`` and
97+
``GITHUB_PASSWORD`` environment variable, respectively. If they aren't
98+
specified at all, communication with GitHub is anonymous and typically
99+
pretty slow.
100+
"""
101+
version = Version(version, VERSION_PATH)
102+
file = RELEASE_NOTES_PATH if write else sys.stdout
103+
generator = ReleaseNotesGenerator(REPOSITORY, RELEASE_NOTES_TITLE,
104+
RELEASE_NOTES_INTRO)
105+
generator.generate(version, username, password, file)
106+
107+
108+
@task
109+
def init_labels(ctx, username=None, password=None):
110+
"""Initialize project by setting labels in the issue tracker.
111+
112+
Args:
113+
username: GitHub username.
114+
password: GitHub password.
115+
116+
Username and password can also be specified using ``GITHUB_USERNAME`` and
117+
``GITHUB_PASSWORD`` environment variable, respectively.
118+
119+
Should only be executed once when taking ``rellu`` tooling to use or
120+
when labels it uses have changed.
121+
"""
122+
initialize_labels(REPOSITORY, username, password)

0 commit comments

Comments
 (0)