From dda44cee68ac3b99bd8bfe29e7c2c497a2755248 Mon Sep 17 00:00:00 2001 From: Jan Snasel Date: Thu, 4 Jan 2024 14:56:58 +0000 Subject: [PATCH] chore: Towncrier changelog support --- .../{{ cookiecutter.project_slug }}/changes | 1 + .../development/towncrier_template.j2 | 1 + .../pyproject.toml | 54 +++++++++++++++++++ .../{{ cookiecutter.project_slug }}/changes | 1 + .../development/towncrier_template.j2 | 1 + .../pyproject.toml | 54 +++++++++++++++++++ .../pull_request_template.md | 1 + .../.github/workflows/ci.yml | 16 ++++++ .../changes/.gitignore | 1 + .../development/towncrier_template.j2 | 30 +++++++++++ .../docs/dev/contributing.md | 29 ++++++++++ .../pyproject.toml | 54 +++++++++++++++++++ .../{{ cookiecutter.project_slug }}/tasks.py | 13 +++++ 13 files changed, 256 insertions(+) create mode 120000 nautobot-app-chatops/{{ cookiecutter.project_slug }}/changes create mode 120000 nautobot-app-chatops/{{ cookiecutter.project_slug }}/development/towncrier_template.j2 create mode 120000 nautobot-app-ssot/{{ cookiecutter.project_slug }}/changes create mode 120000 nautobot-app-ssot/{{ cookiecutter.project_slug }}/development/towncrier_template.j2 create mode 100644 nautobot-app/{{ cookiecutter.project_slug }}/changes/.gitignore create mode 100644 nautobot-app/{{ cookiecutter.project_slug }}/development/towncrier_template.j2 diff --git a/nautobot-app-chatops/{{ cookiecutter.project_slug }}/changes b/nautobot-app-chatops/{{ cookiecutter.project_slug }}/changes new file mode 120000 index 00000000..0d5fb3db --- /dev/null +++ b/nautobot-app-chatops/{{ cookiecutter.project_slug }}/changes @@ -0,0 +1 @@ +../../nautobot-app/{{ cookiecutter.project_slug }}/changes \ No newline at end of file diff --git a/nautobot-app-chatops/{{ cookiecutter.project_slug }}/development/towncrier_template.j2 b/nautobot-app-chatops/{{ cookiecutter.project_slug }}/development/towncrier_template.j2 new file mode 120000 index 00000000..70270be4 --- /dev/null +++ b/nautobot-app-chatops/{{ cookiecutter.project_slug }}/development/towncrier_template.j2 @@ -0,0 +1 @@ +../../../nautobot-app/{{ cookiecutter.project_slug }}/development/towncrier_template.j2 \ No newline at end of file diff --git a/nautobot-app-chatops/{{ cookiecutter.project_slug }}/pyproject.toml b/nautobot-app-chatops/{{ cookiecutter.project_slug }}/pyproject.toml index 642d118b..74b8449a 100644 --- a/nautobot-app-chatops/{{ cookiecutter.project_slug }}/pyproject.toml +++ b/nautobot-app-chatops/{{ cookiecutter.project_slug }}/pyproject.toml @@ -56,6 +56,7 @@ mkdocs-version-annotations = "1.0.0" # Automatic documentation from sources, for MkDocs mkdocstrings = "0.22.0" mkdocstrings-python = "1.5.2" +towncrier = "~23.6.0" [tool.poetry.extras] all = [ @@ -127,3 +128,56 @@ add_ignore = "D212" [build-system] requires = ["poetry_core>=1.0.0"] build-backend = "poetry.core.masonry.api" + +[tool.towncrier] +package = "nautobot" +directory = "changes" +filename = "docs/admin/release_notes/version_X.Y.md" +template = "development/towncrier_template.j2" +start_string = "" +issue_format = "[#{issue}](https://github.com/nautobot/nautobot/issues/{issue})" + +[[tool.towncrier.type]] +directory = "security" +name = "Security" +showcontent = true + +[[tool.towncrier.type]] +directory = "added" +name = "Added" +showcontent = true + +[[tool.towncrier.type]] +directory = "changed" +name = "Changed" +showcontent = true + +[[tool.towncrier.type]] +directory = "deprecated" +name = "Deprecated" +showcontent = true + +[[tool.towncrier.type]] +directory = "removed" +name = "Removed" +showcontent = true + +[[tool.towncrier.type]] +directory = "fixed" +name = "Fixed" +showcontent = true + +[[tool.towncrier.type]] +directory = "dependencies" +name = "Dependencies" +showcontent = true + +[[tool.towncrier.type]] +directory = "documentation" +name = "Documentation" +showcontent = true + +[[tool.towncrier.type]] +directory = "housekeeping" +name = "Housekeeping" +showcontent = true diff --git a/nautobot-app-ssot/{{ cookiecutter.project_slug }}/changes b/nautobot-app-ssot/{{ cookiecutter.project_slug }}/changes new file mode 120000 index 00000000..0d5fb3db --- /dev/null +++ b/nautobot-app-ssot/{{ cookiecutter.project_slug }}/changes @@ -0,0 +1 @@ +../../nautobot-app/{{ cookiecutter.project_slug }}/changes \ No newline at end of file diff --git a/nautobot-app-ssot/{{ cookiecutter.project_slug }}/development/towncrier_template.j2 b/nautobot-app-ssot/{{ cookiecutter.project_slug }}/development/towncrier_template.j2 new file mode 120000 index 00000000..70270be4 --- /dev/null +++ b/nautobot-app-ssot/{{ cookiecutter.project_slug }}/development/towncrier_template.j2 @@ -0,0 +1 @@ +../../../nautobot-app/{{ cookiecutter.project_slug }}/development/towncrier_template.j2 \ No newline at end of file diff --git a/nautobot-app-ssot/{{ cookiecutter.project_slug }}/pyproject.toml b/nautobot-app-ssot/{{ cookiecutter.project_slug }}/pyproject.toml index 25adf982..2e083c44 100644 --- a/nautobot-app-ssot/{{ cookiecutter.project_slug }}/pyproject.toml +++ b/nautobot-app-ssot/{{ cookiecutter.project_slug }}/pyproject.toml @@ -53,6 +53,7 @@ mkdocs-version-annotations = "1.0.0" # Automatic documentation from sources, for MkDocs mkdocstrings = "0.22.0" mkdocstrings-python = "1.5.2" +towncrier = "~23.6.0" [tool.poetry.extras] all = [ @@ -124,3 +125,56 @@ add_ignore = "D212" [build-system] requires = ["poetry_core>=1.0.0"] build-backend = "poetry.core.masonry.api" + +[tool.towncrier] +package = "nautobot" +directory = "changes" +filename = "docs/admin/release_notes/version_X.Y.md" +template = "development/towncrier_template.j2" +start_string = "" +issue_format = "[#{issue}](https://github.com/nautobot/nautobot/issues/{issue})" + +[[tool.towncrier.type]] +directory = "security" +name = "Security" +showcontent = true + +[[tool.towncrier.type]] +directory = "added" +name = "Added" +showcontent = true + +[[tool.towncrier.type]] +directory = "changed" +name = "Changed" +showcontent = true + +[[tool.towncrier.type]] +directory = "deprecated" +name = "Deprecated" +showcontent = true + +[[tool.towncrier.type]] +directory = "removed" +name = "Removed" +showcontent = true + +[[tool.towncrier.type]] +directory = "fixed" +name = "Fixed" +showcontent = true + +[[tool.towncrier.type]] +directory = "dependencies" +name = "Dependencies" +showcontent = true + +[[tool.towncrier.type]] +directory = "documentation" +name = "Documentation" +showcontent = true + +[[tool.towncrier.type]] +directory = "housekeeping" +name = "Housekeeping" +showcontent = true diff --git a/nautobot-app/{{ cookiecutter.project_slug }}/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md b/nautobot-app/{{ cookiecutter.project_slug }}/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md index 21a3779b..6b0e27f7 100644 --- a/nautobot-app/{{ cookiecutter.project_slug }}/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md +++ b/nautobot-app/{{ cookiecutter.project_slug }}/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md @@ -27,6 +27,7 @@ Please feel free to update todos to keep track of your own notes for WIP PRs. --> - [ ] Explanation of Change(s) +- [ ] Added change log fragment(s) (for more information see [the documentation](https://docs.nautobot.com/projects/core/en/stable/development/#creating-changelog-fragments)) - [ ] Attached Screenshots, Payload Example - [ ] Unit, Integration Tests - [ ] Documentation Updates (when adding/changing features) diff --git a/nautobot-app/{{ cookiecutter.project_slug }}/.github/workflows/ci.yml b/nautobot-app/{{ cookiecutter.project_slug }}/.github/workflows/ci.yml index df83a6f1..f862d986 100644 --- a/nautobot-app/{{ cookiecutter.project_slug }}/.github/workflows/ci.yml +++ b/nautobot-app/{{ cookiecutter.project_slug }}/.github/workflows/ci.yml @@ -229,6 +229,22 @@ jobs: if: "matrix.db-backend == 'mysql'" - name: "Run Tests" run: "poetry run invoke unittest" + changelog: + if: contains(fromJson('["develop","ltm-1.6"]'), github.base_ref) + runs-on: "ubuntu-22.04" + steps: + - name: "Check out repository code" + uses: "actions/checkout@v4" + with: + fetch-depth: "0" + - name: "Setup environment" + uses: "networktocode/gh-action-setup-poetry-environment@v4" + - name: "Check for changelog entry" + run: | + {% raw %-} + git fetch --no-tags origin +refs/heads/${{ github.base_ref }}:refs/remotes/origin/${{ github.base_ref }} + poetry run towncrier check --compare-with origin/${{ github.base_ref }} + {% endraw %} publish_gh: needs: - "unittest" diff --git a/nautobot-app/{{ cookiecutter.project_slug }}/changes/.gitignore b/nautobot-app/{{ cookiecutter.project_slug }}/changes/.gitignore new file mode 100644 index 00000000..f935021a --- /dev/null +++ b/nautobot-app/{{ cookiecutter.project_slug }}/changes/.gitignore @@ -0,0 +1 @@ +!.gitignore diff --git a/nautobot-app/{{ cookiecutter.project_slug }}/development/towncrier_template.j2 b/nautobot-app/{{ cookiecutter.project_slug }}/development/towncrier_template.j2 new file mode 100644 index 00000000..40e1a660 --- /dev/null +++ b/nautobot-app/{{ cookiecutter.project_slug }}/development/towncrier_template.j2 @@ -0,0 +1,30 @@ +{% raw %} +{% if render_title %} +## v{{ versiondata.version }} ({{ versiondata.date }}) + +{% endif %} +{% for section, _ in sections.items() %} +{% if sections[section] %} +{% for category, val in definitions.items() if category in sections[section] %} +{% if sections[section][category]|length != 0 %} +### {{ definitions[category]['name'] }} + +{% if definitions[category]['showcontent'] %} +{% for text, values in sections[section][category].items() %} +{% for item in text.split('\n') %} +- {{ values|join(', ') }} - {{ item.strip() }} +{% endfor %} +{% endfor %} + +{% else %} +- {{ sections[section][category]['']|join(', ') }} + +{% endif %} +{% endif %} +{% endfor %} +{% else %} +No significant changes. + +{% endif %} +{% endfor %} +{% endraw %} diff --git a/nautobot-app/{{ cookiecutter.project_slug }}/docs/dev/contributing.md b/nautobot-app/{{ cookiecutter.project_slug }}/docs/dev/contributing.md index 042fd89d..c1f141ab 100644 --- a/nautobot-app/{{ cookiecutter.project_slug }}/docs/dev/contributing.md +++ b/nautobot-app/{{ cookiecutter.project_slug }}/docs/dev/contributing.md @@ -13,6 +13,35 @@ The project is following Network to Code software development guidelines and is Documentation is built using [mkdocs](https://www.mkdocs.org/). The [Docker based development environment](dev_environment.md#docker-development-environment) automatically starts a container hosting a live version of the documentation website on [http://localhost:8001](http://localhost:8001) that auto-refreshes when you make any changes to your local files. +## Creating Changelog Fragments + +All pull requests to `next` or `develop` must include a changelog fragment file in the `./changes` directory. To create a fragment, use your GitHub issue number and fragment type as the filename. For example, `2362.added`. Valid fragment types are `added`, `changed`, `deprecated`, `fixed`, `removed`, and `security`. The change summary is added to the file in plain text. Change summaries should be complete sentences, starting with a capital letter and ending with a period, and be in past tense. Each line of the change fragment will generate a single change entry in the release notes. Use multiple lines in the same file if your change needs to generate multiple release notes in the same category. If the change needs to create multiple entries in separate categories, create multiple files. + +!!! example + + **Wrong** + ```plaintext title="changes/1234.fixed" + fix critical bug in documentation + ``` + + **Right** + ```plaintext title="changes/1234.fixed" + Fixed critical bug in documentation. + ``` + +!!! example "Multiple Entry Example" + + This will generate 2 entries in the `fixed` category and one entry in the `changed` category. + + ```plaintext title="changes/1234.fixed" + Fixed critical bug in documentation. + Fixed release notes generation. + ``` + + ```plaintext title="changes/1234.changed" + Changed release notes generation. + ``` + ## Branching Policy !!! warning "Developer Note - Remove Me!" diff --git a/nautobot-app/{{ cookiecutter.project_slug }}/pyproject.toml b/nautobot-app/{{ cookiecutter.project_slug }}/pyproject.toml index a3aadbda..ab209e45 100644 --- a/nautobot-app/{{ cookiecutter.project_slug }}/pyproject.toml +++ b/nautobot-app/{{ cookiecutter.project_slug }}/pyproject.toml @@ -52,6 +52,7 @@ mkdocs-version-annotations = "1.0.0" # Automatic documentation from sources, for MkDocs mkdocstrings = "0.22.0" mkdocstrings-python = "1.5.2" +towncrier = "~23.6.0" [tool.poetry.extras] all = [ @@ -123,3 +124,56 @@ add_ignore = "D212" [build-system] requires = ["poetry_core>=1.0.0"] build-backend = "poetry.core.masonry.api" + +[tool.towncrier] +package = "nautobot" +directory = "changes" +filename = "docs/admin/release_notes/version_X.Y.md" +template = "development/towncrier_template.j2" +start_string = "" +issue_format = "[#{issue}](https://github.com/nautobot/nautobot/issues/{issue})" + +[[tool.towncrier.type]] +directory = "security" +name = "Security" +showcontent = true + +[[tool.towncrier.type]] +directory = "added" +name = "Added" +showcontent = true + +[[tool.towncrier.type]] +directory = "changed" +name = "Changed" +showcontent = true + +[[tool.towncrier.type]] +directory = "deprecated" +name = "Deprecated" +showcontent = true + +[[tool.towncrier.type]] +directory = "removed" +name = "Removed" +showcontent = true + +[[tool.towncrier.type]] +directory = "fixed" +name = "Fixed" +showcontent = true + +[[tool.towncrier.type]] +directory = "dependencies" +name = "Dependencies" +showcontent = true + +[[tool.towncrier.type]] +directory = "documentation" +name = "Documentation" +showcontent = true + +[[tool.towncrier.type]] +directory = "housekeeping" +name = "Housekeeping" +showcontent = true diff --git a/nautobot-app/{{ cookiecutter.project_slug }}/tasks.py b/nautobot-app/{{ cookiecutter.project_slug }}/tasks.py index 24b3d3fa..2e36f701 100644 --- a/nautobot-app/{{ cookiecutter.project_slug }}/tasks.py +++ b/nautobot-app/{{ cookiecutter.project_slug }}/tasks.py @@ -612,6 +612,19 @@ def help_task(context): context.run(f"invoke {task_name} --help") +@task( + help={ + "version": "Version of {{ cookiecutter.verbose_name }} to generate the release notes for.", + } +) +def generate_release_notes(context, version=""): + """Generate Release Notes using Towncrier.""" + command = "env DJANGO_SETTINGS_MODULE=nautobot.core.settings towncrier build" + if version: + command += f" --version {version}" + run_command(context, command) + + # ------------------------------------------------------------------------------ # TESTS # ------------------------------------------------------------------------------