=======================
Distribution Procedure
=======================
The release procedure was created using information from these core sources:
* `PEP 503 - Simple Repository API `_
* `Python Packaging User Guide `_
* `Twine `_
Test Release
=============
Verify that version and release numbers in ``doc/source/conf.py`` match
``setup.py``.
.. code-block:: bash
$ grep -e version -e release doc/source/conf.py
# The short X.Y version
version = u'1.0.0'
# The full version, including alpha/beta/rc tags
release = u'1.0.0'
$
Ensure there are no old build artifacts.
.. code-block:: bash
$ rm -rf dist build mqtt_codec.egg-info htmlcov
$ ls dist
$
It's a common problem to accidentally forget to commit important
changes. To combat this the ``pyvertest.py`` procedure clones the
``mqtt-codec`` repository, passes it to a docker container, and runs a
test battery in a set of environments.
.. code-block:: none
$ ./pyvertest.py
[... removed for brevity ...]
pip install python:3.7-alpine3.8
docker run --rm -v /home/kcallin/src/mqtt-codec:/mqtt-codec python:3.7-alpine3.8 pip install /mqtt-codec
Processing /mqtt-codec
Building wheels for collected packages: mqtt-codec
Running setup.py bdist_wheel for mqtt-codec: started
Running setup.py bdist_wheel for mqtt-codec: finished with status 'done'
Stored in directory: /root/.cache/pip/wheels/c1/64/0f/d02b6f3717526372cf5d4a5beb9b63181eb54bd4ed964fa7e1
Successfully built mqtt-codec
Installing collected packages: mqtt-codec
Successfully installed mqtt-codec-1.0.0-uncontrolled-20181125
Return code 0
> All okay.
Ensure that CHANGELOG.rst has release version and release date correct
as well as release content listed.
.. code-block:: bash
$ vi CHANGELOG.rst
$ git commit -S CHANGELOG.rst
Create test release artifacts.
.. code-block:: none
$ python setup.py egg_info -D -b 'a' sdist
running sdist
running egg_info
writing requirements to mqtt_codec.egg-info/requires.txt
writing mqtt_codec.egg-info/PKG-INFO
writing top-level names to mqtt_codec.egg-info/top_level.txt
writing dependency_links to mqtt_codec.egg-info/dependency_links.txt
reading manifest file 'mqtt_codec.egg-info/SOURCES.txt'
writing manifest file 'mqtt_codec.egg-info/SOURCES.txt'
running check
creating mqtt-codec-0.1.2
creating mqtt-codec-0.1.2/mqtt_codec
[... removed for brevity ...]
copying tests/test_reactor.py -> mqtt-codec-0.1.2/tests
copying tests/test_scheduler.py -> mqtt-codec-0.1.2/tests
Writing mqtt-codec-0.1.2/setup.cfg
Creating tar archive
removing 'mqtt-codec-0.1.2' (and everything under it)
$ ls dist
mqtt-codec-0.1.2.tar.gz
$
GPG sign test release artifact:
.. code-block:: none
$ gpg --detach-sign -a dist/mqtt-codec-0.1.2.tar.gz
You need a passphrase to unlock the secret key for
user: "Keegan Callin "
4096-bit RSA key, ID DD53792F, created 2017-01-01 (main key ID 14BC2EFF)
gpg: gpg-agent is not available in this session
$ ls dist
mqtt-codec-0.1.2.tar.gz mqtt-codec-0.1.2.tar.gz.asc
$ gpg --verify dist/mqtt-codec-0.1.2.tar.gz.asc
gpg: assuming signed data in `dist/mqtt-codec-0.1.2.tar.gz'
gpg: Signature made Sat 01 Sep 2018 11:00:31 AM MDT using RSA key ID DD53792F
gpg: Good signature from "Keegan Callin " [ultimate]
Primary key fingerprint: BD51 01F1 9699 A719 E563 6D85 4A4A 7B98 14BC 2EFF
Subkey fingerprint: BE56 D781 0163 488F C7AE 62AC 3914 0AE2 DD53 792F
$
.. https://packaging.python.org/guides/making-a-pypi-friendly-readme/#validating-restructuredtext-markup
(Retrieved 2018-11-28)
Ensure that twine version 1.12.0 or high is installed:
.. code-block:: none
$ twine --version
twine version 1.12.0 (pkginfo: 1.4.2, requests: 2.20.1, setuptools: 40.6.2,
requests-toolbelt: 0.8.0, tqdm: 4.28.1)
Verify that distribution passes twine checks:
.. code-block:: none
$ twine check dist/*
Checking distribution dist/mqtt-codec-1.0.1.tar.gz: Passed
Release artifacts to **TEST** PyPI.
.. code-block:: none
$ twine upload --repository-url https://test.pypi.org/legacy/ dist/*
Uploading distributions to https://test.pypi.org/legacy/
Enter your username: kc
Enter your password:
Uploading mqtt-codec-0.1.2.tar.gz
$
The resulting `TestPyPI entry
`_ should be inspected for
correctness. "The database for TestPyPI may be periodically pruned, so
it is not unusual for user accounts to be deleted [#]_". Packages on
**TEST** PyPI and **real** PyPI cannot be removed upon distributor
demand. On **TEST** PyPI packages may be removed on prune, on **real**
PyPI they will remain forever. A checklist to help verify the PyPI
is:
* Version Number is Correct
* Documentation Link is Correct
* ReST README.rst is rendered correctly on the front page.
After the checklist is complete then it is time to upload to **real**
PyPI and verify that the release is complete. There is no undoing
this operation. Think Carefully.
PEP 508 -- Dependency specification for Python Software Packages
PEP-314 -- Metadata for Python Software Packages v1.1
.. [#] `Test PyPI, Registering Your Account `_,
retrieved 2018-09-07.
Official Release
=================
Create, sign, and push release tag:
.. code-block:: bash
$ git tag -s v0.1.0
$ git push origin v0.1.0
Remove test artifacts:
.. code-block:: bash
$ rm -rf dist build mqtt_codec.egg-info htmlcov
$ ls dist
$
Create official release artifacts.
.. code-block:: none
$ python setup.py egg_info -D -b '' sdist
running sdist
running egg_info
writing requirements to mqtt_codec.egg-info/requires.txt
writing mqtt_codec.egg-info/PKG-INFO
writing top-level names to mqtt_codec.egg-info/top_level.txt
writing dependency_links to mqtt_codec.egg-info/dependency_links.txt
reading manifest file 'mqtt_codec.egg-info/SOURCES.txt'
writing manifest file 'mqtt_codec.egg-info/SOURCES.txt'
running check
creating mqtt-codec-0.1.2
creating mqtt-codec-0.1.2/mqtt_codec
[... removed for brevity ...]
copying tests/test_reactor.py -> mqtt-codec-0.1.2/tests
copying tests/test_scheduler.py -> mqtt-codec-0.1.2/tests
Writing mqtt-codec-0.1.2/setup.cfg
Creating tar archive
removing 'mqtt-codec-0.1.2' (and everything under it)
$ ls dist
mqtt-codec-0.1.2.tar.gz
$
GPG sign official release artifact:
.. code-block:: none
$ gpg --detach-sign -a dist/mqtt-codec-0.1.2.tar.gz
You need a passphrase to unlock the secret key for
user: "Keegan Callin "
4096-bit RSA key, ID DD53792F, created 2017-01-01 (main key ID 14BC2EFF)
gpg: gpg-agent is not available in this session
$ ls dist
mqtt-codec-0.1.2.tar.gz mqtt-codec-0.1.2.tar.gz.asc
$ gpg --verify dist/mqtt-codec-0.1.2.tar.gz.asc
gpg: assuming signed data in `dist/mqtt-codec-0.1.2.tar.gz'
gpg: Signature made Sat 01 Sep 2018 11:00:31 AM MDT using RSA key ID DD53792F
gpg: Good signature from "Keegan Callin " [ultimate]
Primary key fingerprint: BD51 01F1 9699 A719 E563 6D85 4A4A 7B98 14BC 2EFF
Subkey fingerprint: BE56 D781 0163 488F C7AE 62AC 3914 0AE2 DD53 792F
$
The access credentials in `~/.pypirc` contains the username/password
that twine uses for PyPI.
.. code-block:: none
$ cat ~/.pypirc
[distutils]
index-servers =
pypi
[pypi]
username:
password:
$ twine upload dist/*
Distribute Documentation
===========================
Documentation is distributed through
`readthedocs.org `_. After
a release visit the
`mqtt-codec readthedocs Version `_,
page and make sure the correct versions are marked as "Active".
The ``mqtt-codec`` project documentation uses
`PlantUML `_ to draw diagrams and
this package is not support out-of-the-box by `readthedocs`. The
project root directory contains a ``.readthedocs.yml`` file to set the
build `readthedocs` build environment to one that supports PlantUML and
bypass the problem.
Increment Version Number
=========================
The release number in `setup.py` has been consumed and should never be
used again. Take the time to increment the number, commit the change,
then push the change.
.. code-block:: none
$ vi setup.py
$ vi doc/source/conf.py
$ git commit setup.py
$ git push origin master