diff --git a/.github/chronographer.yml b/.github/chronographer.yml new file mode 100644 index 00000000..24168796 --- /dev/null +++ b/.github/chronographer.yml @@ -0,0 +1,11 @@ +--- +enforce_name: + suffix: .md +exclude: + bots: + - dependabot-preview + - dependabot + - patchback + humans: + - pyup-bot +... diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fe72f45..6a6de608 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,23 @@ # Changelog +[//]: # (DO-NOT-REMOVE-versioning-promise-START) + +```{note} +The change notes follow [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +except for the title formatting, and this project adheres to [Semantic +Versioning](https://semver.org/spec/v2.0.0.html). +``` + + + + + ## 0.18.1 - 2022-27-09 Full Changelog: [v0.18.0...v0.18.1](https://github.com/executablebooks/MyST-Parser/compare/v0.18.0...v0.18.1) diff --git a/docs/changelog-fragments.d/.CHANGELOG-TEMPLATE.md.j2 b/docs/changelog-fragments.d/.CHANGELOG-TEMPLATE.md.j2 new file mode 100644 index 00000000..6d83795e --- /dev/null +++ b/docs/changelog-fragments.d/.CHANGELOG-TEMPLATE.md.j2 @@ -0,0 +1,31 @@ + +{% for section, _ in sections.items() %} +{% set title_prefix = underlines[0] %} +{% if section %} +{{ title_prefix }} {{ section }} +{% set title_prefix = underlines[1] %} +{% endif %} + +{% if sections[section] %} +{% for category, val in definitions.items() if category in sections[section] %} +{{ title_prefix }} {{ definitions[category]['name'] }} +{% if definitions[category]['showcontent'] %} + +{% for text, values in sections[section][category].items() %} +* {{ text }}\ + ({{ values|join(',\n ') }}) +{% endfor -%} + +{% else %} +* {{ sections[section][category]['']|join(', ') }} +{% endif %} + +{% if sections[section][category]|length == 0 %} +No significant changes. +{% endif %} +{% endfor %} + +{% else %} +No significant changes. +{% endif %} +{% endfor %} diff --git a/docs/changelog-fragments.d/.gitignore b/docs/changelog-fragments.d/.gitignore new file mode 100644 index 00000000..46978d22 --- /dev/null +++ b/docs/changelog-fragments.d/.gitignore @@ -0,0 +1,25 @@ +* +!.CHANGELOG-TEMPLATE.md.j2 +!.gitignore +!README.md +!*.bugfix +!*.bugfix.md +!*.bugfix.*.md +!*.breaking +!*.breaking.md +!*.breaking.*.md +!*.deprecation +!*.deprecation.md +!*.deprecation.*.md +!*.doc +!*.doc.md +!*.doc.*.md +!*.feature +!*.feature.md +!*.feature.*.md +!*.internal +!*.internal.md +!*.internal.*.md +!*.misc +!*.misc.md +!*.misc.*.md diff --git a/docs/changelog-fragments.d/454.misc.md b/docs/changelog-fragments.d/454.misc.md new file mode 100644 index 00000000..d4652c91 --- /dev/null +++ b/docs/changelog-fragments.d/454.misc.md @@ -0,0 +1,4 @@ +Added changelog fragment management infrastructure using [Towncrier] +-- by {user}`webknjaz` + +[Towncrier]: https://github.com/twisted/towncrier diff --git a/docs/changelog-fragments.d/README.md b/docs/changelog-fragments.d/README.md new file mode 100644 index 00000000..bb9677a6 --- /dev/null +++ b/docs/changelog-fragments.d/README.md @@ -0,0 +1,79 @@ + + +(_myst_parser_adding_changelog_fragments)= + +## Adding change notes with your PRs + +It is very important to maintain a log for news of how +updating to the new version of the software will affect +end-users. This is why we enforce collection of the change +fragment files in pull requests as per [Towncrier philosophy]. + +The idea is that when somebody makes a change, they must record +the bits that would affect end-users only including information +that would be useful to them. Then, when the maintainers publish +a new release, they'll automatically use these records to compose +a change log for the respective version. It is important to +understand that including unnecessary low-level implementation +related details generates noise that is not particularly useful +to the end-users most of the time. And so such details should be +recorded in the Git history rather than a changelog. + +## Alright! So how do I add a news fragment? + +To submit a change note about your PR, add a text file into the +`docs/changelog-fragments.d/` folder. It should contain an +explanation of what applying this PR will change in the way +end-users interact with the project. One sentence is usually +enough but feel free to add as many details as you feel necessary +for the users to understand what it means. + +**Use the past tense** for the text in your fragment because, +combined with others, it will be a part of the "news digest" +telling the readers **what changed** in a specific version of +the library *since the previous version*. You should also use +[MyST Markdown] syntax for highlighting code (inline or block), +linking parts of the docs or external sites. +At the end, sign your change note by adding ```-- by +{user}`github-username``` (replace `github-username` with +your own!). + +Finally, name your file following the convention that Towncrier +understands: it should start with the number of an issue or a +PR followed by a dot, then add a patch type, like `feature`, +`bugfix`, `doc`, `misc` etc., and add `.md` as a suffix. If you +need to add more than one fragment, you may add an optional +sequence number (delimited with another period) between the type +and the suffix. + +## Examples for changelog entries adding to your Pull Requests + +File `docs/changelog-fragments.d/666.doc.md`: + +```md +Added a `{user}` role to Sphinx config -- by {user}`webknjaz` +``` + +File `docs/changelog-fragments.d/116.feature.md`: + +```md +Added support for nested module options (suboptions) +-- by {user}`tomaciazek` +``` + +File `docs/changelog-fragments.d/140.bugfix.md`: + +```md +Implemented opening standalone Ansible files that have no workspace +associated -- by {user}`ganeshrn` +``` + +```{tip} +See `pyproject.toml` for all available categories +(`tool.towncrier.type`). +``` + +[MyST Markdown]: +https://myst-parser.rtfd.io/en/latest/syntax/syntax.html +[Towncrier philosophy]: +https://towncrier.rtfd.io/en/actual-freaking-docs/#philosophy diff --git a/docs/conf.py b/docs/conf.py index 199a32a4..ac879885 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -5,17 +5,39 @@ # https://www.sphinx-doc.org/en/master/usage/configuration.html from datetime import date +from functools import partial +from pathlib import Path +from setuptools_scm import get_version from sphinx.application import Sphinx -from myst_parser import __version__ +# -- Path setup -------------------------------------------------------------- +PROJECT_ROOT_DIR = Path(__file__).parents[1].resolve() # pylint: disable=no-member +get_scm_version = partial(get_version, root=PROJECT_ROOT_DIR) # -- Project information ----------------------------------------------------- +github_url = "https://github.com" +github_repo_org = "ansible" +github_repo_name = "ansible-language-server" +github_repo_slug = f"{github_repo_org}/{github_repo_name}" +github_repo_url = f"{github_url}/{github_repo_slug}" +github_sponsors_url = f"{github_url}/sponsors" + project = "MyST Parser" copyright = f"{date.today().year}, Executable Book Project" author = "Executable Book Project" -version = __version__ + +# The short X.Y version +version = ".".join( + get_scm_version(local_scheme="no-local-version",).split( + "." + )[:3], +) + +# The full version, including alpha/beta/rc tags +release = get_scm_version() + master_doc = "index" language = "en" @@ -28,12 +50,14 @@ extensions = [ "myst_parser", "sphinx.ext.autodoc", + "sphinx.ext.extlinks", "sphinx.ext.intersphinx", "sphinx.ext.viewcode", "sphinx_design", "sphinxext.rediraffe", "sphinxcontrib.mermaid", "sphinxext.opengraph", + "sphinxcontrib.towncrier", # provides `towncrier-draft-entries` directive ] # Add any paths that contain templates here, relative to this directory. @@ -42,7 +66,12 @@ # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. -exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] +exclude_patterns = [ + "_build", + "Thumbs.db", + ".DS_Store", + "changelog-fragments.d/**", # Towncrier-managed change notes +] # -- Options for HTML output ------------------------------------------------- @@ -93,6 +122,12 @@ "attrs_image", ] myst_number_code_blocks = ["typescript"] +myst_substitutions = { + "project": project, + "release": release, + "release_l": f"`{release}`", # Needed in draft changelog for spelling ext + "version": version, +} myst_heading_anchors = 2 myst_footnote_transition = True myst_dmath_double_inline = True @@ -114,6 +149,22 @@ suppress_warnings = ["myst.strikethrough"] +# -- Options for towncrier_draft extension ----------------------------------- + +towncrier_draft_autoversion_mode = "draft" # or: 'sphinx-version', 'sphinx-release' +towncrier_draft_include_empty = True +towncrier_draft_working_directory = PROJECT_ROOT_DIR +# towncrier_draft_config_path = 'pyproject.toml' # relative to cwd + +# -- Options for extlinks extension ------------------------------------------ + +extlinks = { + "issue": (f"{github_repo_url}/issues/%s", "#%s"), # noqa: WPS323 + "pr": (f"{github_repo_url}/pull/%s", "PR #%s"), # noqa: WPS323 + "commit": (f"{github_repo_url}/commit/%s", "%s"), # noqa: WPS323 + "gh": (f"{github_url}/%s", "GitHub: %s"), # noqa: WPS323 + "user": (f"{github_sponsors_url}/%s", "@%s"), # noqa: WPS323 +} intersphinx_mapping = { "python": ("https://docs.python.org/3.7", None), diff --git a/docs/develop/_changelog.md b/docs/develop/_changelog.md index d24e7ac0..21d219b3 100644 --- a/docs/develop/_changelog.md +++ b/docs/develop/_changelog.md @@ -1,4 +1,21 @@ +# Changelog + +```{include} ../../CHANGELOG.md +:end-before: +:start-after: (DO-NOT-REMOVE-versioning-promise-START) + +``` + +```{important} The version marked with __/UNRELEASED DRAFT/__ is not yet released and is under active development +``` + +```{towncrier-draft-entries} +_{subscript}`/UNRELEASED DRAFT/`_ {{ release }} +``` + ```{include} ../../CHANGELOG.md :relative-docs: docs/ :relative-images: +:start-after: + ``` diff --git a/docs/develop/contributing.md b/docs/develop/contributing.md index 7f57052a..760ee623 100644 --- a/docs/develop/contributing.md +++ b/docs/develop/contributing.md @@ -71,6 +71,9 @@ For documentation build tests: >> make html-strict ``` +```{include} ../changelog-fragments.d/README.md +``` + ```{seealso} {ref}`develop/testing` ``` diff --git a/pyproject.toml b/pyproject.toml index 880a4fd4..8dcf3a4b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -54,11 +54,13 @@ linkify = ["linkify-it-py~=1.0"] # Note: This is only required for internal use rtd = [ "ipython", + "setuptools-scm ~= 7.0.5", "sphinx-book-theme", "sphinx-design", "sphinxext-rediraffe~=0.2.7", "sphinxcontrib.mermaid~=0.7.1", "sphinxext-opengraph~=0.6.3", + "sphinxcontrib-towncrier ~= 0.3.0a0", ] testing = [ "beautifulsoup4", @@ -108,3 +110,50 @@ ignore_missing_imports = true [tool.coverage.run] omit = ["*/_docs.py"] + +[tool.towncrier] + directory = "docs/changelog-fragments.d/" + filename = "CHANGELOG.md" + issue_format = "{{issue}}`{issue}`" + start_string = "\n\n" + template = "docs/changelog-fragments.d/.CHANGELOG-TEMPLATE.md.j2" + title_format = "## {version} - {project_date}" + underlines = ["", "", "", ""] + + [[tool.towncrier.section]] + path = "" + + [[tool.towncrier.type]] + directory = "bugfix" + name = "Bugfixes" + showcontent = true + + [[tool.towncrier.type]] + directory = "feature" + name = "Features" + showcontent = true + + [[tool.towncrier.type]] + directory = "deprecation" + name = "Deprecations (removal in next major release)" + showcontent = true + + [[tool.towncrier.type]] + directory = "breaking" + name = "Backward incompatible changes" + showcontent = true + + [[tool.towncrier.type]] + directory = "doc" + name = "Documentation" + showcontent = true + + [[tool.towncrier.type]] + directory = "misc" + name = "Miscellaneous" + showcontent = true + + [[tool.towncrier.type]] + directory = "internal" + name = "Contributor-facing changes" + showcontent = true diff --git a/tox.ini b/tox.ini index 4a0110e6..1a24893f 100644 --- a/tox.ini +++ b/tox.ini @@ -34,6 +34,11 @@ extras = whitelist_externals = rm echo + git +commands_pre = + # Retrieve possibly missing commits: + -git fetch --unshallow + -git fetch --tags commands = clean: rm -rf docs/_build sphinx-build -nW --keep-going -b {posargs:html} docs/ docs/_build/{posargs:html} @@ -52,6 +57,41 @@ commands = -n -b {posargs:html} docs/ docs/_build/{posargs:html} +[testenv:make-changelog] +basepython = python3 +depends = + check-changelog +description = + Generate a changelog from fragments using Towncrier. Getting an + unreleased changelog preview does not require extra arguments. + When invoking to update the changelog, pass the desired version as an + argument after `--`. For example, `tox -e {envname} -- 1.3.2`. +commands = + {envpython} -m \ + towncrier.build \ + --version \ + {posargs:'[UNRELEASED DRAFT]' --draft} +deps = + towncrier == 22.8.0 +isolated_build = true +skip_install = true + + +[testenv:check-changelog] +basepython = {[testenv:make-changelog]basepython} +description = + Check Towncrier change notes +commands = + {envpython} -m \ + towncrier.check \ + --compare-with origin/master \ + {posargs:} +deps = + {[testenv:make-changelog]deps} +isolated_build = {[testenv:make-changelog]isolated_build} +skip_install = {[testenv:make-changelog]skip_install} + + [pytest] addopts = --ignore=setup.py markers =