Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Setup towncrier for release notes generation #492

Merged
merged 2 commits into from
Feb 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ jobs:
strategy:
matrix:
tox_env:
- py37
- py38
- py39
- py310
- py311
- py312
runs-on: ubuntu-latest
29 changes: 24 additions & 5 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
# https://www.sphinx-doc.org/en/master/usage/configuration.html

import os
import re
import sys

topdir = os.path.abspath("../")
Expand Down Expand Up @@ -48,6 +49,7 @@
"sphinx.ext.extlinks",
"sphinx.ext.viewcode",
"sphinx.ext.napoleon",
"myst_parser",
]

# Add any paths that contain templates here, relative to this directory.
Expand Down Expand Up @@ -92,14 +94,31 @@
# -- Extension configuration -------------------------------------------------

autodoc_mock_imports = ["gssapi", "requests_gssapi"]
source_suffix = {
".rst": "restructuredtext",
".md": "markdown",
}

myst_enable_extensions = [
"colon_fence",
]
myst_heading_anchors = 3

# -- Options for intersphinx extension ---------------------------------------

# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {"python": ("https://docs.python.org/3", None)}

extlinks = {
"commit": ("https://github.com/fedora-infra/fasjson-client/commit/%s", "%s"),
"issue": ("https://github.com/fedora-infra/fasjson-client/issues/%s", "#%s"),
"pr": ("https://github.com/fedora-infra/fasjson-client/pull/%s", "PR#%s"),
}
github_url = "https://github.com/fedora-infra/fasjson-client"


def changelog_github_links(app, docname, source):
if docname != "release_notes":
return
github_issue_re = re.compile(r"#(\d+)")
for docnr, doc in enumerate(source):
source[docnr] = github_issue_re.sub(f"[#\\1]({github_url}/issues/\\1)", doc)


def setup(app):
app.connect("source-read", changelog_github_links)
49 changes: 49 additions & 0 deletions docs/contributing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,52 @@ License
Licensed under `lgpl-3.0`_

.. _lgpl-3.0: https://opensource.org/licenses/lgpl-3.0.html


Release Notes
-------------

To add entries to the release notes, create a file in the ``news`` directory in the
``source.type`` name format, where the ``source`` part of the filename is:

* ``42`` when the change is described in issue ``42``
* ``PR42`` when the change has been implemented in pull request ``42``, and
there is no associated issue
* ``Cabcdef`` when the change has been implemented in changeset ``abcdef``, and
there is no associated issue or pull request.

And where the extension ``type`` is one of:

* ``bic``: for backwards incompatible changes
* ``dependency``: for dependency changes
* ``feature``: for new features
* ``bug``: for bug fixes
* ``dev``: for development improvements
* ``docs``: for documentation improvements
* ``other``: for other changes

The content of the file will end up in the release notes. It should not end with a ``.``
(full stop).

If it is not present already, add a file in the ``news`` directory named ``username.author``
where ``username`` is the first part of your commit's email address, and containing the name
you want to be credited as. There is a script to generate a list of authors that we run
before releasing, but creating the file manually allows you to set a custom name.

A preview of the release notes can be generated with
``towncrier --draft``.

Release Process
^^^^^^^^^^^^^^^

#. Update the version in ``pyproject.toml`` by running ``poetry version major|minor|patch``
depending on the contents of the release.
#. Run ``poetry install`` to update the package's metadata.
#. Add missing authors to the release notes fragments by changing to the ``news`` directory and
running the ``get-authors.py`` script, but check for duplicates and errors
#. Generate the release notes by running ``poetry run towncrier build`` (in the base directory)
#. Adjust the release notes in ``docs/release_notes.md``.
#. Generate the docs with ``tox -r -e docs`` and check them in ``docs/_build/html``.
#. Commit the changes
#. Create the release and tag in the Github webui

9 changes: 9 additions & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,12 @@ on open-api specs (version 2.0).
:caption: Contributor Guide

contributing


.. Release Notes

.. toctree::
:maxdepth: 2
:caption: Release Notes

release_notes
41 changes: 41 additions & 0 deletions docs/release_notes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Release notes

<!-- towncrier release notes start -->

## v1.0.8

Released on 2023-03-29.

### Changes

- Drop support for Python 3.6 to update dependencies, and add support for Python 3.10 and 3.11
- Update dependencies
- Fix Sphinx config
- Fix CI
- Allow additional operation arguments in `list_all_entities`
- Register the `X-Fields` mask format
- Restore compatibility with `requests` < 2.26.0 to support RHEL9

### Contributors

Many thanks to the contributors of bug reports, pull requests, and pull request
reviews for this release:

- Akashdeep Dhar
- Aurélien Bompard
- Carl George

## v1.0.7

Released on 2022-05-11.

### Development Improvements

- add and configure packit (#268)

### Contributors

Many thanks to the contributors of bug reports, pull requests, and pull request
reviews for this release:

- Stephen Coady
58 changes: 58 additions & 0 deletions news/_template.md.j2
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{% macro reference(value) -%}
{%- if value.startswith("PR") -%}
PR #{{ value[2:] }}
{%- elif value.startswith("C") -%}
[{{ value[1:] }}](https://github.com/fedora-infra/fasjson-client/commits/{{ value[1:] }})
{%- else -%}
#{{ value }}
{%- endif -%}
{%- endmacro -%}

{{- top_line -}}

Released on {{ versiondata.date }}. This is a {major|feature|bugfix} release that adds [short summary].

{% for section, _ in sections.items() -%}
{%- if section -%}
## {{section}}
{%- endif -%}

{%- if sections[section] -%}
{%- for category, val in definitions.items() if category in sections[section] and category != "author" -%}
### {{ definitions[category]['name'] }}

{% if definitions[category]['showcontent'] -%}
{%- for text, values in sections[section][category].items() %}
- {{ text }} ({% for value in values -%}
{{ reference(value) }}
{%- if not loop.last %}, {% endif -%}
{%- endfor %}).
{% endfor -%}
{%- else -%}
- {{ sections[section][category]['']|sort|join(', ') }}

{% endif -%}
{%- if sections[section][category]|length == 0 %}
No significant changes.

{% else -%}
{%- endif %}

{% endfor -%}
{%- if sections[section]["author"] %}
## {{definitions['author']["name"]}}

Many thanks to the contributors of bug reports, pull requests, and pull request
reviews for this release:

{% for text, values in sections[section]["author"].items() -%}
- {{ text }}
{% endfor -%}
{%- endif -%}

{% else -%}
No significant changes.


{% endif -%}
{%- endfor -%}
74 changes: 74 additions & 0 deletions news/get-authors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#!/usr/bin/env python3

"""
This script browses through git commit history (starting at latest tag), collects all authors of
commits and creates fragment for `towncrier`_ tool.

It's meant to be run during the release process, before generating the release notes.

Example::

$ python get_authors.py

.. _towncrier: https://github.com/hawkowl/towncrier/

Authors:
Aurelien Bompard
Michal Konecny
"""

import os
from argparse import ArgumentParser
from subprocess import check_output


EXCLUDE = [
"dependabot[bot]",
"dependabot-preview[bot]",
"Weblate (bot)",
"renovate[bot]",
]

last_tag = check_output(
"git tag | sort -n | tail -n 1", shell=True, universal_newlines=True
).strip()

args_parser = ArgumentParser()
args_parser.add_argument(
"until",
nargs="?",
default="HEAD",
help="Consider all commits until this one (default: %(default)s).",
)
args_parser.add_argument(
"since",
nargs="?",
default=last_tag,
help="Consider all commits since this one (default: %(default)s).",
)
args = args_parser.parse_args()

authors = {}
log_range = args.since + ".." + args.until
output = check_output(
["git", "log", log_range, "--format=%ae\t%an"], universal_newlines=True
)
print(last_tag)
for line in output.splitlines():
email, fullname = line.split("\t")
email = email.split("@")[0].replace(".", "")
if email in authors:
continue
authors[email] = fullname

for nick, fullname in authors.items():
if fullname in EXCLUDE or fullname.endswith("[bot]"):
continue
filename = f"{nick}.author"
if os.path.exists(filename):
print(f"Author Already Created {fullname} ({nick})")
continue
print(f"Adding author {fullname} ({nick})")
with open(filename, "w") as f:
f.write(fullname)
f.write("\n")
Loading