======================= Distributing haka-mqtt ======================= The release procedure was created using information from these core sources: * `PEP 503 - Simple Repository API `_ * `Python Packaging User Guide `_ * `Twine `_ Documentation =============== 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' $ Make sure copyright dates in ``doc/source/conf.py`` are correct: .. code-block:: bash $ grep -i copyright doc/source/conf.py copyright = u'2018 - 2019, Keegan Callin' $ Verify requirements document at ``doc/source/requirements.rst`` matches ``setup.py`` (and not the other way around). Test Release =============== Clean build directory and ensure there are no old build artifacts. .. code-block:: none $ rm -rf dist build haka_mqtt.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 haka 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/haka-mqtt:/haka-mqtt python:3.7-alpine3.8 pip install /haka-mqtt Processing /haka-mqtt Building wheels for collected packages: haka-mqtt, mqtt-codec Running setup.py bdist_wheel for haka-mqtt: started Running setup.py bdist_wheel for haka-mqtt: finished with status 'done' Stored in directory: /root/.cache/pip/wheels/c5/b3/fa/e30017929f15cb43137c499453ff45f3754db112f34a52cb9d 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/b7/6b/0f/5fb8026a75541fb9fcdec2f3fc33b75aad929b48e85eca68a9 Successfully built haka-mqtt mqtt-codec Installing collected packages: mqtt-codec, haka-mqtt Successfully installed haka-mqtt-0.3.0-uncontrolled-20181217 mqtt-codec-1.0.1 Return code 0 Removing container id b9d481a9f49b966fa6708e1ef9fda16d0142b35a7613fc794a43105b0eb6eb2b. Removing temp directory /tmp/tmput2xuulf. > 10/10 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 haka_mqtt.egg-info/requires.txt writing haka_mqtt.egg-info/PKG-INFO writing top-level names to haka_mqtt.egg-info/top_level.txt writing dependency_links to haka_mqtt.egg-info/dependency_links.txt reading manifest file 'haka_mqtt.egg-info/SOURCES.txt' writing manifest file 'haka_mqtt.egg-info/SOURCES.txt' running check creating haka-mqtt-0.1.2 creating haka-mqtt-0.1.2/haka_mqtt [... removed for brevity ...] copying tests/test_reactor.py -> haka-mqtt-0.1.2/tests copying tests/test_scheduler.py -> haka-mqtt-0.1.2/tests Writing haka-mqtt-0.1.2/setup.cfg Creating tar archive removing 'haka-mqtt-0.1.2' (and everything under it) $ ls dist haka-mqtt-0.1.2.tar.gz $ GPG signatures are created for test release artifacts. .. code-block:: none $ gpg2 --detach-sign -a dist/* 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 haka-mqtt-0.1.2.tar.gz haka-mqtt-0.1.2.tar.gz.asc $ gpg2 --verify dist/*.asc gpg: assuming signed data in `dist/haka-mqtt-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 higher 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/haka-mqtt-1.0.0.tar.gz: Passed Release artifacts are uploaded 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 haka-mqtt-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 release page follows: * 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 haka_mqtt.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 haka_mqtt.egg-info/requires.txt writing haka_mqtt.egg-info/PKG-INFO writing top-level names to haka_mqtt.egg-info/top_level.txt writing dependency_links to haka_mqtt.egg-info/dependency_links.txt reading manifest file 'haka_mqtt.egg-info/SOURCES.txt' writing manifest file 'haka_mqtt.egg-info/SOURCES.txt' running check creating haka-mqtt-0.1.2 creating haka-mqtt-0.1.2/haka_mqtt [... removed for brevity ...] copying tests/test_reactor.py -> haka-mqtt-0.1.2/tests copying tests/test_scheduler.py -> haka-mqtt-0.1.2/tests Writing haka-mqtt-0.1.2/setup.cfg Creating tar archive removing 'haka-mqtt-0.1.2' (and everything under it) $ ls dist haka-mqtt-0.1.2.tar.gz $ GPG sign official release artifact: .. code-block:: none $ gpg2 --detach-sign -a dist/* 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 haka-mqtt-0.1.2.tar.gz haka-mqtt-0.1.2.tar.gz.asc $ gpg2 --verify dist/*.asc gpg: assuming signed data in `dist/haka-mqtt-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 `haka-mqtt readthedocs project `_, select "Versions" click on "inactive" versions and make sure that the correct versions are marked as "Active". The ``haka-mqtt`` 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