• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

OCA / maintainer-tools / 13228537945

09 Feb 2025 06:34PM UTC coverage: 35.131%. Remained the same
13228537945

Pull #644

github

web-flow
Merge 8b3aeb3fa into 16f1fc1f8
Pull Request #644: Ignore archived projects

437 of 1188 branches covered (36.78%)

645 of 1836 relevant lines covered (35.13%)

3.48 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.88
/tools/oca_towncrier.py
1
#!/usr/bin/env python
2
# Copyright (c) 2019 ACSONE SA/NV
3
# License AGPLv3 (https://www.gnu.org/licenses/agpl-3.0-standalone.html)
4

5
import contextlib
10✔
6
import datetime
10✔
7
import os
10✔
8
import subprocess
10✔
9
import sys
10✔
10
import tempfile
10✔
11

12
import click
10✔
13
import toml
10✔
14

15
from .gitutils import commit_if_needed
10✔
16
from .manifest import read_manifest
10✔
17

18

19
def _make_issue_format(org, repo, fragment_format):
10✔
20
    if fragment_format == "md":
10✔
21
        return f"[#{{issue}}](https://github.com/{org}/{repo}/issues/{{issue}})"
10✔
22
    return f"`#{{issue}} <https://github.com/{org}/{repo}/issues/{{issue}}>`_"
10✔
23

24

25
def _get_towncrier_template(fragment_format):
10✔
26
    return os.path.join(
10✔
27
        os.path.dirname(__file__), f"towncrier-template.{fragment_format}"
28
    )
29

30

31
def _get_readme_fragment_format(addon_dir):
10✔
32
    """Detect the format of the readme fragment to generate (md or rst)"""
33
    fragment_format = "rst"
10✔
34
    readme_dir = os.path.join(addon_dir, "readme")
10✔
35
    if not os.path.isdir(readme_dir):
10✔
36
        return fragment_format
10✔
37
    files = os.listdir(readme_dir)
10✔
38
    files = [
10✔
39
        f
40
        for f in files
41
        if not f.startswith(".") and os.path.isfile(os.path.join(readme_dir, f))
42
    ]
43
    # The first file found with a .md or .rst extension will determine the format
44
    for f in files:
10!
45
        if f.endswith(".md"):
8✔
46
            fragment_format = "md"
8!
47
            break
8✔
48
        if f.endswith(".rst"):
×
49
            fragment_format = "rst"
×
50
            break
×
51
    return fragment_format
10✔
52

53

54
@contextlib.contextmanager
10✔
55
def _prepare_config(addon_dir, org, repo):
8✔
56
    """Inject towncrier options in pyproject.toml"""
57
    # first detect expected format (we support both md and rst)
58
    fragment_format = _get_readme_fragment_format(addon_dir)
10✔
59
    with tempfile.NamedTemporaryFile(dir=addon_dir, mode="w") as config_file:
10✔
60
        result_file = os.path.join("readme", f"HISTORY.{fragment_format}")
10✔
61
        config = {
10✔
62
            "tool": {
63
                "towncrier": {
64
                    "template": _get_towncrier_template(fragment_format),
65
                    "underlines": ["~" if fragment_format == "rst" else ""],
66
                    "issue_format": _make_issue_format(org, repo, fragment_format),
67
                    "directory": "readme/newsfragments",
68
                    "filename": result_file,
69
                }
70
            }
71
        }
72
        toml.dump(config, config_file)
10✔
73
        config_file.flush()
10✔
74
        yield config_file.name, result_file
10✔
75

76

77
@click.command(
10✔
78
    help=(
79
        "Generate readme/HISTORY.rst from towncrier newsfragments "
80
        "stored in readme/newfragments/. This script is meant to be run "
81
        "before oca-gen-addon-readme. See https://pypi.org/project/towncrier/ "
82
        "for more information and the naming and format of newfragment files."
83
    )
84
)
85
@click.option(
10✔
86
    "--addon-dir",
87
    "addon_dirs",
88
    type=click.Path(dir_okay=True, file_okay=False, exists=True),
89
    multiple=True,
90
    help="Directory where addon manifest is located. This option may be repeated.",
91
)
92
@click.option("--version")
10✔
93
@click.option("--date")
10✔
94
@click.option(
10✔
95
    "--org", default="OCA", help="GitHub organization name.", show_default=True
96
)
97
@click.option("--repo", required=True, help="GitHub repository name.")
10✔
98
@click.option(
10✔
99
    "--commit/--no-commit",
100
    help="git commit changes, if any (a git add is done in any case).",
101
)
102
def oca_towncrier(addon_dirs, version, date, org, repo, commit):
8✔
103
    if not date:
10✔
104
        date = datetime.date.today().isoformat()
×
105
    paths = []
10✔
106
    for addon_dir in addon_dirs:
10✔
107
        news_dir = os.path.join(addon_dir, "readme", "newsfragments")
10✔
108
        if not os.path.isdir(news_dir):
10✔
109
            continue
×
110
        if not any(not f.startswith(".") for f in os.listdir(news_dir)):
10✔
111
            continue
×
112
        addon_version = version or read_manifest(addon_dir)["version"]
10✔
113
        with _prepare_config(addon_dir, org, repo) as (config_file_name, result_file):
10✔
114
            subprocess.call(
10✔
115
                [
116
                    sys.executable,
117
                    "-m",
118
                    "towncrier",
119
                    "--config",
120
                    config_file_name,
121
                    "--version",
122
                    addon_version,
123
                    "--date",
124
                    date,
125
                    "--yes",
126
                ],
127
                cwd=addon_dir,
128
            )
129
        paths.append(news_dir)
10✔
130
        paths.append(os.path.join(addon_dir, result_file))
10✔
131
    if commit:
10✔
132
        commit_if_needed(paths, message="[UPD] changelog", add=False)
×
133

134

135
if __name__ == "__main__":
10✔
136
    oca_towncrier()
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc