diff --git a/cliff.toml b/cliff.toml new file mode 100644 index 0000000..5522e29 --- /dev/null +++ b/cliff.toml @@ -0,0 +1,57 @@ +# configuration file for git-cliff (0.1.0) + +[changelog] +# changelog header +header = """ +# Changelog +All notable changes to this project will be documented in this file.\n +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).\n +""" +# template for the changelog body +# https://tera.netlify.app/docs/#introduction +body = """ +{% if version %}\ + ## [{{ version | trim_start_matches(pat="v") }}](https://github.com/tembo-pages/tembo-core/commits/{{ version }}) - {{ timestamp | date(format="%Y-%m-%d") }} + {% if previous.version %}\ + [Compare with {{ previous.version }}](https://github.com/tembo-pages/tembo-core/compare/v{{ version }}...{{ previous.version }}) + {% endif %}\ +{% else %}\ + ## [unreleased] +{% endif %}\ +{% for group, commits in commits | group_by(attribute="group") %} + ### {{ group | upper_first }} + {% for commit in commits %} + - {{ commit.message | upper_first }} ([{{ commit.id | truncate(length=6, end="") }}](https://github.com/tembo-pages/tembo-core/commit/{{ commit.id }}))\ + {% endfor %} +{% endfor %}\n +""" +# remove the leading and trailing whitespaces from the template +trim = true +# changelog footer +footer = """ +""" + +[git] +# allow only conventional commits +# https://www.conventionalcommits.org +conventional_commits = true +# regex for parsing and grouping commits +commit_parsers = [ + { message = "^feat", group = "Features"}, + { message = "^fix", group = "Bug Fixes"}, + { message = "^doc", group = "Documentation"}, + { message = "^perf", group = "Performance"}, + { message = "^refactor", group = "Refactor"}, + { message = "^style", group = "Styling"}, + { message = "^test", group = "Testing"}, + { message = "^chore\\(release\\): prepare for", skip = true}, + { message = "^chore", group = "Miscellaneous Tasks", skip = false}, + { body = ".*security", group = "Security"}, +] +# filter out the commits that are not matched by commit parsers +filter_commits = false +# glob pattern for matching git tags +tag_pattern = "v[0-9]*" +# regex for skipping tags +skip_tags = "v0.1.0-beta.1" diff --git a/duties.py b/duties.py index 0efdb16..a854afe 100644 --- a/duties.py +++ b/duties.py @@ -322,99 +322,23 @@ def check_dependencies(ctx): pty=True, ) - -def _latest(lines: List[str], regex: Pattern) -> Optional[str]: - for line in lines: - match = regex.search(line) - if match: - return match.groupdict()["version"] - return None - - -def _unreleased(versions, last_release): - for index, version in enumerate(versions): - if version.tag == last_release: - return versions[:index] - return versions - - -def update_changelog( - inplace_file: str, - marker: str, - version_regex: str, - commit_style: str, - planned_tag: str, - last_released: str, -) -> None: +@duty +def changelog(ctx, planned_release: Optional[str] = None): """ - Update the given changelog file in place. - Arguments: - inplace_file: The file to update in-place. - marker: The line after which to insert new contents. - version_regex: A regular expression to find currently documented versions in the file. - template_url: The URL to the Jinja template used to render contents. - commit_style: The style of commit messages to parse. - """ - from git_changelog.build import Changelog - from jinja2.sandbox import SandboxedEnvironment + Generate a changelog with git-cliff. - env = SandboxedEnvironment(autoescape=False) - template = env.from_string(changelog_template()) - changelog = Changelog(".", style=commit_style) - - if len(changelog.versions_list) == 1: - last_version = changelog.versions_list[0] - print(last_version.planned_tag) - if last_version.planned_tag is None: - planned_tag = planned_tag - last_version.tag = planned_tag - last_version.url += planned_tag - last_version.compare_url = last_version.compare_url.replace("HEAD", planned_tag) - - with open(inplace_file, "r") as changelog_file: - lines = changelog_file.read().splitlines() - - # last_released = _latest(lines, re.compile(version_regex)) - last_released = last_released - print(last_released) - if last_released: - changelog.versions_list = _unreleased(changelog.versions_list, last_released) - rendered = template.render(changelog=changelog, inplace=True) - lines[lines.index(marker)] = rendered - - with open(inplace_file, "w") as changelog_file: # noqa: WPS440 - changelog_file.write("\n".join(lines).rstrip("\n") + "\n") - - -# @duty -def changelog(planned_tag, last_released): - """ - Update the changelog in-place with latest commits. - Arguments: + Args: ctx: The context instance (passed automatically). + planned_release (str, optional): The planned release version. Example: v1.0.2 """ - # print( - # ctx.run( - # update_changelog, - # kwargs={ - # "inplace_file": "CHANGELOG.md", - # "marker": "", - # "version_regex": r"^## \[v?(?P[^\]]+)", - # "commit_style": "angular", - # }, - # title="Updating changelog", - # pty=True, - # ) - # ) + if planned_release is not None: + changelog = ctx.run(["git", "cliff", "--tag", planned_release]) + else: + changelog = ctx.run(["git", "cliff"]) - update_changelog( - inplace_file="CHANGELOG.md", - marker="", - version_regex=r"^## \[v?(?P[^\]]+)", - commit_style="angular", - planned_tag=planned_tag, - last_released=last_released - ) + changelog_file = pathlib.Path(".") / "CHANGELOG.md" + with changelog_file.open("w", encoding="utf-8") as changelog_contents: + changelog_contents.write(changelog) @@ -432,55 +356,3 @@ def rm_tree(directory: pathlib.Path): else: rm_tree(child) directory.rmdir() - - -def changelog_template() -> str: - return """ -{% if not inplace -%} -# Changelog -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) -and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). - -{% endif %} -{% macro render_commit(commit) -%} -- {{ commit.style.subject|default(commit.subject) }} ([{{ commit.hash|truncate(7, True, '') }}]({{ commit.url }}) by {{ commit.author_name }}). -{%- if commit.text_refs.issues_not_in_subject %} References: {% for issue in commit.text_refs.issues_not_in_subject -%} -{% if issue.url %}[{{ issue.ref }}]({{ issue.url }}){%else %}{{ issue.ref }}{% endif %}{% if not loop.last %}, {% endif -%} -{%- endfor -%}{%- endif -%} -{%- endmacro -%} - -{%- macro render_section(section) -%} -### {{ section.type or "Misc" }} -{% for commit in section.commits|sort(attribute='author_date',reverse=true)|unique(attribute='subject') -%} -{{ render_commit(commit) }} -{% endfor %} -{%- endmacro -%} - -{%- macro render_version(version) -%} -{%- if version.tag or version.planned_tag -%} -## [{{ version.tag or version.planned_tag }}]({{ version.url }}){% if version.date %} - {{ version.date }}{% endif %} - -[Compare with {{ version.previous_version.tag|default("first commit") }}]({{ version.compare_url }}) -{%- else -%} -## Unrealeased - -[Compare with latest]({{ version.compare_url }}) -{%- endif %} - -{% for type, section in version.sections_dict|dictsort -%} -{%- if type and type in changelog.style.DEFAULT_RENDER -%} -{{ render_section(section) }} -{% endif -%} -{%- endfor -%} -{%- endmacro -%} - -{% for version in changelog.versions_list -%} -{{ render_version(version) }} -{%- endfor -%} - """ - - -if __name__ == "__main__": - changelog("1.0.1", "1.0.0")