Switch from towncrier to scriv for changelog management
Marco Ricci

Marco Ricci commited on 2024-09-27 21:35:32
Zeige 9 geänderte Dateien mit 74 Einfügungen und 137 Löschungen.


I have found towncrier to be rather painful when used together with
Markdown entries: it feels very much like a reStructuredText-only tool
retrofitted with patchy Markdown support.  In particular, towncrier
blindly concatenates all entries (assumed to be list items) into the
output (and adds the implied issue links afterwards), manually adjusted
for nicer indentation in an ad-hoc fashion.  This fails horribly if the
changelog entry is anything except a single, paragraph-free list item;
it fails in particular for reference-style links and for multi-paragraph
entries.

So switch to scriv, by Ned Batchelder, which is a similar style to
towncrier.  That too has its issues, such as the automatically
generated, non-configurable HTML4-style heading anchor, but it's
somewhat more tolerant/encouraging of manual editing of the changelog
entries and the changelog master file.

Since we're cleaning up the changelog, use this opportunity to fix the
formatting of the existing entries.
... ...
@@ -0,0 +1,5 @@
1
+### Added
2
+
3
+  - Convert changelog management from towncrier to [scriv][].
4
+
5
+[scriv]: https://pypi.org/project/scriv
... ...
@@ -0,0 +1,7 @@
1
+### Added
2
+
3
+  - Add SSH agent spawning support to the test suite.  Use this support to
4
+    test the agent functionality on all known major SSH agent
5
+    implementations automatically. ([#12])
6
+
7
+[#12]: https://github.com/the-13th-letter/derivepassphrase/issues/12
... ...
@@ -0,0 +1,5 @@
1
+### Added
2
+
3
+  - Add [hypothesis][]-based tests to the test suite.
4
+
5
+[hypothesis]: https://pypi.org/project/hypothesis/
... ...
@@ -28,48 +28,53 @@ effectively constitute a new <q>major</q> release.)
28 28
 
29 29
   [REFERENCE]: reference/index.md
30 30
 
31
-<!-- towncrier release notes start -->
31
+<!-- scriv changelog start -->
32 32
 
33 33
 ## 0.2.0 (2024-09-12)
34 34
 
35
-#### Added
35
+### Added
36 36
 
37
-- Support configuration data export from `vault` in v0.2, v0.3 and storeroom
38
-  formats.
37
+  - Support configuration data export from `vault` in v0.2, v0.3 and
38
+    storeroom formats.
39 39
 
40 40
     This feature requires the `cryptography` Python module, but is available
41 41
     even if `vault` is not installed. ([#1])
42 42
 
43 43
 [#1]: https://github.com/the-13th-letter/derivepassphrase/1
44 44
 
45
-#### Fixed
45
+### Fixed
46 46
 
47
-- Deploy versioned documentation with [mike](https://pypi.org/project/mike).
48
-  Set up a "latest" tag and the "0.<var>x</var>" version of the documentation
49
-  with the contents so far.
47
+  - Deploy versioned documentation with [mike][].  Set up a "latest" tag and
48
+    the "0.<var>x</var>" version of the documentation with the contents so
49
+    far.
50 50
 
51
-#### Changed
51
+[mike]: https://pypi.org/project/mike
52
+
53
+### Changed
52 54
 
53 55
   - Changed `sequin` and `ssh_agent_client` to be submodules of
54 56
     `derivepassphrase`.  Further moved `derivepassphrase.Vault` and
55
-  `derivepassphrase.AmbiguousByteRepresentation` into a new submodule `vault`,
56
-  and renamed submodule `ssh_agent_client` to `ssh_agent`. ([#3])
57
-- Changed internal error handling and error messages, to better work in the
58
-  context of a command-line tool. ([#4])
57
+    `derivepassphrase.AmbiguousByteRepresentation` into a new submodule
58
+    `vault`, and renamed submodule `ssh_agent_client` to `ssh_agent`. ([#3])
59
+  - Changed internal error handling and error messages, to better work in
60
+    the context of a command-line tool. ([#4])
59 61
   - Combine and consolidate `derivepassphrase.types` and
60 62
     `derivepassphrase.ssh_agent.types` into a new submodule
61
-  `derivepassphrase._types`.  Despite the name, the module is public. ([#7])
63
+    `derivepassphrase._types`.  Despite the name, the module is public.
64
+    ([#7])
62 65
   - Warn the user when entering (directly, or via configuration
63 66
     editing/importing) a passphrase that is not in the configured Unicode
64 67
     normalization form. (But don't otherwise reject any textual master
65 68
     passphrases.) ([#9])
66
-- Move all existing functionality into a subcommand, in anticipation of other
67
-  passphrase derivation schemes, with different settings.  Automatically
68
-  forward calls without a subcommand to the "vault" subcommand.
69
+  - Move all existing functionality into a subcommand, in anticipation of
70
+    other passphrase derivation schemes, with different settings.
71
+    Automatically forward calls without a subcommand to the "vault"
72
+    subcommand.
69 73
 
70 74
     Also store the settings in a file specific to the respective subsystem,
71
-  instead of globally.  Automatically fall back to, and migrate, the old global
72
-  settings file if no subsystem-specific configuration was found. ([#10])
75
+    instead of globally.  Automatically fall back to, and migrate, the old
76
+    global settings file if no subsystem-specific configuration was found.
77
+    ([#10])
73 78
 
74 79
   - Make `derivepassphrase_export` a subcommand: `derivepassphrase export`.
75 80
     ([#11])
... ...
@@ -81,7 +86,7 @@ effectively constitute a new <q>major</q> release.)
81 86
 [#10]: https://github.com/the-13th-letter/derivepassphrase/10
82 87
 [#11]: https://github.com/the-13th-letter/derivepassphrase/11
83 88
 
84
-#### Deprecated
89
+### Deprecated
85 90
 
86 91
   - Using the implied subcommand or the implied global configuration file is
87 92
     deprecated, and will be removed in v1.0.
... ...
@@ -89,14 +94,15 @@ effectively constitute a new <q>major</q> release.)
89 94
 
90 95
 ## 0.1.3 (2024-07-28)
91 96
 
92
-#### Fixed
97
+### Fixed
93 98
 
94
-- Do not crash upon selecting a key on the command-line if there already is a
95
-  key stored in the configuration. ([#5])
96
-- Create the configuration directory upon saving, if it does not yet exist.
97
-  ([#6])
98
-- Isolate the tests properly and consistently from the user's configuration, so
99
-  that user configuration problems do not cause unrelated test failures. ([#8])
99
+  - Do not crash upon selecting a key on the command-line if there already
100
+    is a key stored in the configuration. ([#5])
101
+  - Create the configuration directory upon saving, if it does not yet
102
+    exist.  ([#6])
103
+  - Isolate the tests properly and consistently from the user's
104
+    configuration, so that user configuration problems do not cause
105
+    unrelated test failures. ([#8])
100 106
   - Add an alternate MkDocs configuration for building the documentation in
101 107
     offline mode.
102 108
   - Fix typing issues according to `mypy`'s strict mode.
... ...
@@ -108,32 +114,33 @@ effectively constitute a new <q>major</q> release.)
108 114
 
109 115
 ## 0.1.2 (2024-07-22)
110 116
 
111
-#### Fixed
117
+### Fixed
112 118
 
113 119
   - Include and exclude the correct files in the `sdist` and `wheel`
114
-  distributions.  (Previously, `sdist` contained VCS artifacts, and `wheel` was
115
-  missing some paths.)
120
+    distributions.  (Previously, `sdist` contained VCS artifacts, and
121
+    `wheel` was missing some paths.)
116 122
   - Lint and reformat all code using [ruff](https://astral.sh/ruff/).
117
-- Mention [`mkdocstrings-python`](https://mkdocstrings.github.io/python/) in
118
-  the documentation's page footer.
119
-- Remove JavaScript and external font loading from documentation website, so
120
-  that the site works even in restricted browser settings.
121
-- Set up a changelog, using [towncrier](https://pypi.org/package/towncrier).
123
+  - Mention [`mkdocstrings-python`](https://mkdocstrings.github.io/python/)
124
+    in the documentation's page footer.
125
+  - Remove JavaScript and external font loading from documentation website,
126
+    so that the site works even in restricted browser settings.
127
+  - Set up a changelog, using
128
+    [towncrier](https://pypi.org/package/towncrier).
122 129
 
123 130
 
124 131
 ## 0.1.1 (2024-07-14)
125 132
 
126
-#### Fixed
133
+### Fixed
127 134
 
128 135
   - Restore the `__version__` attribute in all top-level packages.
129 136
   - Declare compatibility with Python 3.10 in project metadata, and include
130 137
     necessary version-specific dependencies.
131
-- Publish the documentation online, and link to it in the repository metadata
132
-  and the Python package metadata.
138
+  - Publish the documentation online, and link to it in the repository
139
+    metadata and the Python package metadata.
133 140
 
134 141
 
135 142
 ## 0.1.0 (2024-07-14)
136 143
 
137
-#### Added
144
+### Added
138 145
 
139 146
   - Initial release.
... ...
@@ -89,7 +89,7 @@ omit = [
89 89
 
90 90
 [tool.hatch.build.targets.sdist]
91 91
 exclude = [
92
-    'towncrier.d/[0123456789+]*.md',
92
+    'docs/changelog.d/*.md',
93 93
 ]
94 94
 
95 95
 [tool.hatch.build.targets.wheel]
... ...
@@ -157,7 +157,7 @@ cov-report = "coverage report"
157 157
 
158 158
 [tool.hatch.envs.release]
159 159
 extra-dependencies = [
160
-  "towncrier >= 23.11"
160
+  "scriv >= 1.4"
161 161
 ]
162 162
 
163 163
 [tool.hatch.envs.release.scripts]
... ...
@@ -326,43 +326,12 @@ max-doc-length = 72  # for W505
326 326
 [tool.ruff.lint.pydocstyle]
327 327
 convention = 'google'
328 328
 
329
-[tool.towncrier]
330
-package = 'derivepassphrase'
331
-package_dir = 'src'
332
-directory = 'towncrier.d'
333
-filename = 'docs/changelog.md'
334
-template = 'towncrier-template.md'
335
-#title_format = '[{version}](https://github.com/the-13th-letter/derivepassphrase/tree/{version}) – {project_date}'
336
-underlines = ['', '', '']
337
-issue_format = '[#{issue}]: https://github.com/the-13th-letter/derivepassphrase/{issue}'
338
-wrap = true
339
-
340
-[[tool.towncrier.type]]
341
-directory = "security"
342
-name = "Security"
343
-showcontent = true
344
-
345
-[[tool.towncrier.type]]
346
-directory = "added"
347
-name = "Added"
348
-showcontent = true
349
-
350
-[[tool.towncrier.type]]
351
-directory = "fixed"
352
-name = "Fixed"
353
-showcontent = true
354
-
355
-[[tool.towncrier.type]]
356
-directory = "removed"
357
-name = "Removed"
358
-showcontent = true
359
-
360
-[[tool.towncrier.type]]
361
-directory = "changed"
362
-name = "Changed"
363
-showcontent = true
364
-
365
-[[tool.towncrier.type]]
366
-directory = "deprecated"
367
-name = "Deprecated"
368
-showcontent = true
329
+[tool.scriv]
330
+version = "command: hatch version"
331
+format = "md"
332
+fragment_directory = "docs/changelog.d"
333
+output_file = "docs/changelog.md"
334
+insert_marker = "<!-- scriv changelog start -->"
335
+end_marker = "<!-- scriv changelog end -->"
336
+md_header_level = "2"
337
+entry_title_template = "{% if version %}{{ version }} ({% endif %}{{ date.strftime('%Y-%m-%d') }}{% if version %}){% endif %}"
... ...
@@ -1,54 +0,0 @@
1
-{% if render_title %}
2
-## {{ versiondata.version }} ({{ versiondata.date }})
3
-{% endif %}
4
-{% for section, _ in sections.items() %}
5
-{% if section %}
6
-
7
-### {{section}}
8
-{% endif %}
9
-
10
-{% if sections[section] %}
11
-{% for category, val in definitions.items() if category in sections[section] %}
12
-#### {{ definitions[category]['name'] }}
13
-
14
-{% for text, values in sections[section][category].items() %}
15
-- {{ text }}
16
-{%- if values %}
17
-{% if "\n  - " in text or '\n  * ' in text %}
18
-
19
-
20
-  (
21
-{%- else %}
22
-{% if text %} ({% endif %}
23
-{%- endif -%}
24
-{%- for issue in values %}
25
-{{ issue.split(": ", 1)[0] }}{% if not loop.last %}, {% endif %}
26
-{%- endfor %}
27
-{% if text %}){% endif %}
28
-
29
-{% else %}
30
-
31
-{% endif %}
32
-{% endfor %}
33
-
34
-{% if issues_by_category[section][category] and "]: " in issues_by_category[section][category][0] %}
35
-{% for issue in issues_by_category[section][category] %}
36
-{{ issue }}
37
-{% endfor %}
38
-
39
-{% endif %}
40
-{% if sections[section][category]|length == 0 %}
41
-No significant changes.
42
-
43
-{% else %}
44
-{% endif %}
45
-{% endfor %}
46
-{% else %}
47
-No significant changes.
48
-
49
-{% endif %}
50
-{% endfor +%}
51
-{#
52
-This comment adds one more newline at the end of the rendered newsfile content.
53
-In this way the there are 2 newlines between the latest release and the previous release content.
54
-#}
... ...
@@ -1 +0,0 @@
1
-Add [hypothesis](https://pypi.org/project/hypothesis/)-based tests to the test suite.
... ...
@@ -1 +0,0 @@
1
-Add SSH agent spawning support to the test suite.  Use this support to test the agent functionality on all known major SSH agent implementations automatically.
2 0