Skip to content

Commit

Permalink
Merge pull request OCA#607 from acsone/master-fix-towncrier-md
Browse files Browse the repository at this point in the history
[FIX] oca-towncrier: Add support for Mardown format
  • Loading branch information
sbidoul committed Mar 17, 2024
2 parents 451de41 + 3349f4b commit d0c8b4d
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 16 deletions.
4 changes: 3 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@
"requests",
"toml>=0.10.0", # for oca-towncrier
"tomli ; python_version < '3.11'", # from 3.11 tomllib is in stdlib
"towncrier>=21.3", # for oca-towncrier
"towncrier>=21.3; python_version < '3.8'", # for oca-towncrier
# for oca-towncrier with MarkDow support
"towncrier>=23.11; python_version >= '3.8'",
"selenium",
"twine",
"wheel",
Expand Down
48 changes: 45 additions & 3 deletions tests/test_towncrier.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,27 @@
# License AGPLv3 (https://www.gnu.org/licenses/agpl-3.0-standalone.html)
# Copyright (c) 2018 ACSONE SA/NV

import sys
import textwrap

import pytest
import toml
from click.testing import CliRunner
from tools.oca_towncrier import _make_issue_format, _prepare_config, oca_towncrier


def test_make_issue_format():
assert (
_make_issue_format("OCA", "repo")
_make_issue_format("OCA", "repo", "rst")
== "`#{issue} <https://github.com/OCA/repo/issues/{issue}>`_"
)
assert (
_make_issue_format("OCA", "repo", "md")
== "[#{issue}](https://github.com/OCA/repo/issues/{issue})"
)


def test_prepare_config(tmp_path):
with _prepare_config(str(tmp_path), "OCA", "repo") as fn:
with _prepare_config(str(tmp_path), "OCA", "repo") as (fn, result_file):
with open(fn) as f:
pyproject = toml.load(f)
assert set(pyproject["tool"]["towncrier"].keys()) == {
Expand Down Expand Up @@ -60,3 +65,40 @@ def test_oca_towncrier(tmp_path):
- Bugfix description. (`#50 <https://github.com/OCA/therepo/issues/50>`_)
"""
)


@pytest.mark.skipif(
sys.version_info < (3, 8), reason="MarkDow support requires python3.8 or higher"
)
def test_oca_towncrier_md(tmp_path):
addon_path = tmp_path / "addon_a"
readme_path = addon_path / "readme"
history_path = readme_path / "HISTORY.md"
news_path = readme_path / "newsfragments"
news_path.mkdir(parents=True)
(news_path / "50.bugfix").write_text("Bugfix description.")
(readme_path / "description.md").write_text("Some description")
runner = CliRunner()
runner.invoke(
oca_towncrier,
[
"--addon-dir",
str(addon_path),
"--version",
"14.0.1.0.1",
"--date",
"2021-12-31",
"--repo",
"therepo",
],
)
assert history_path.exists()
assert history_path.read_text() == textwrap.dedent(
"""\
## 14.0.1.0.1 (2021-12-31)
#### Bugfixes
- Bugfix description. ([#50](https://github.com/OCA/therepo/issues/50))
"""
)
52 changes: 40 additions & 12 deletions tools/oca_towncrier.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,34 +16,62 @@
from .manifest import read_manifest


def _make_issue_format(org, repo):
return "`#{{issue}} <https://github.com/{org}/{repo}/issues/{{issue}}>`_".format(
org=org, repo=repo
def _make_issue_format(org, repo, fragment_format):
if fragment_format == "md":
return f"[#{{issue}}](https://github.com/{org}/{repo}/issues/{{issue}})"
return f"`#{{issue}} <https://github.com/{org}/{repo}/issues/{{issue}}>`_"


def _get_towncrier_template(fragment_format):
return os.path.join(
os.path.dirname(__file__), f"towncrier-template.{fragment_format}"
)


def _get_towncrier_template():
return os.path.join(os.path.dirname(__file__), "towncrier-template.rst")
def _get_readme_fragment_format(addon_dir):
"""Detect the format of the readme fragment to generate (md or rst)"""
fragment_format = "rst"
readme_dir = os.path.join(addon_dir, "readme")
if not os.path.isdir(readme_dir):
return fragment_format
files = os.listdir(readme_dir)
files = [
f
for f in files
if not f.startswith(".") and os.path.isfile(os.path.join(readme_dir, f))
]
# The first file found with a .md or .rst extension will determine the format
for f in files:
if f.endswith(".md"):
fragment_format = "md"
break
if f.endswith(".rst"):
fragment_format = "rst"
break
return fragment_format


@contextlib.contextmanager
def _prepare_config(addon_dir, org, repo):
"""Inject towncrier options in pyproject.toml"""
# first detect expected format (we support both md and rst)
fragment_format = _get_readme_fragment_format(addon_dir)
with tempfile.NamedTemporaryFile(dir=addon_dir, mode="w") as config_file:
result_file = os.path.join("readme", f"HISTORY.{fragment_format}")
config = {
"tool": {
"towncrier": {
"template": _get_towncrier_template(),
"underlines": ["~"],
"issue_format": _make_issue_format(org, repo),
"template": _get_towncrier_template(fragment_format),
"underlines": ["~" if fragment_format == "rst" else ""],
"issue_format": _make_issue_format(org, repo, fragment_format),
"directory": "readme/newsfragments",
"filename": "readme/HISTORY.rst",
"filename": result_file,
}
}
}
toml.dump(config, config_file)
config_file.flush()
yield config_file.name
yield config_file.name, result_file


@click.command(
Expand Down Expand Up @@ -82,7 +110,7 @@ def oca_towncrier(addon_dirs, version, date, org, repo, commit):
if not any(not f.startswith(".") for f in os.listdir(news_dir)):
continue
addon_version = version or read_manifest(addon_dir)["version"]
with _prepare_config(addon_dir, org, repo) as config_file_name:
with _prepare_config(addon_dir, org, repo) as (config_file_name, result_file):
subprocess.call(
[
sys.executable,
Expand All @@ -99,7 +127,7 @@ def oca_towncrier(addon_dirs, version, date, org, repo, commit):
cwd=addon_dir,
)
paths.append(news_dir)
paths.append(os.path.join(addon_dir, "readme", "HISTORY.rst"))
paths.append(os.path.join(addon_dir, result_file))
if commit:
commit_if_needed(paths, message="[UPD] changelog", add=False)

Expand Down
65 changes: 65 additions & 0 deletions tools/towncrier-template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
{% if render_title %}
{% if versiondata.name %}
## {{ versiondata.name }} {{ versiondata.version }} ({{ versiondata.date }})
{% else %}
## {{ versiondata.version }} ({{ versiondata.date }})
{% endif %}
{% endif %}
{% for section, _ in sections.items() %}
{% if section %}

### {{section}}
{% endif %}

{% if sections[section] %}
{% for category, val in definitions.items() if category in sections[section] %}
#### {{ definitions[category]['name'] }}

{% if definitions[category]['showcontent'] %}
{% for text, values in sections[section][category].items() %}
- {{ text }}
{%- if values %}
{% if "\n - " in text or '\n * ' in text %}


(
{%- else %}
(
{%- endif -%}
{%- for issue in values %}
{{ issue.split(": ", 1)[0] }}{% if not loop.last %}, {% endif %}
{%- endfor %}
)
{% else %}

{% endif %}
{% endfor %}

{% else %}
- {% for issue in sections[section][category][''] %}
{{ issue.split(": ", 1)[0] }}{% if not loop.last %}, {% endif %}
{% endfor %}


{% endif %}
{% if issues_by_category[section][category] and "]: " in issues_by_category[section][category][0] %}
{% for issue in issues_by_category[section][category] %}
{{ issue }}
{% endfor %}

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

{% else %}
{% endif %}
{% endfor %}
{% else %}
No significant changes.

{% endif %}
{% endfor +%}
{#
This comment adds one more newline at the end of the rendered newsfile content.
In this way the there are 2 newlines between the latest release and the previous release content.
#}

0 comments on commit d0c8b4d

Please sign in to comment.