comver 0.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- comver/__init__.py +33 -0
- comver/__main__.py +13 -0
- comver/_cli.py +38 -0
- comver/_parser.py +132 -0
- comver/_regex/__init__.py +17 -0
- comver/_regex/_process.py +41 -0
- comver/_regex/match.py +83 -0
- comver/_regex/semantic.py +97 -0
- comver/_subcommand.py +174 -0
- comver/_version.py +772 -0
- comver/error.py +82 -0
- comver/plugin.py +241 -0
- comver/py.typed +0 -0
- comver/py.typed.license +4 -0
- comver/type_definitions.py +27 -0
- comver-0.2.0.dist-info/METADATA +329 -0
- comver-0.2.0.dist-info/RECORD +19 -0
- comver-0.2.0.dist-info/WHEEL +4 -0
- comver-0.2.0.dist-info/entry_points.txt +5 -0
comver/error.py
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: © 2025 open-nudge <https://github.com/open-nudge>
|
|
2
|
+
# SPDX-FileContributor: szymonmaszke <github@maszke.co>
|
|
3
|
+
#
|
|
4
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
|
|
6
|
+
"""Custom exceptions of `comver`."""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ComverError(Exception):
|
|
12
|
+
"""Base class for all exceptions raised by `comver`."""
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class MessageUnrecognizedError(ComverError):
|
|
16
|
+
"""Raised when the message is not recognized by any regexes."""
|
|
17
|
+
|
|
18
|
+
def __init__(self, message: str) -> None:
|
|
19
|
+
"""Initialize the error.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
message:
|
|
23
|
+
The message which was not recognized by any regexes.
|
|
24
|
+
|
|
25
|
+
"""
|
|
26
|
+
self.message: str = message
|
|
27
|
+
|
|
28
|
+
super().__init__(
|
|
29
|
+
f"Message '{message}' is not recognized by any of the provided regexes."
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class VersionFormatError(ComverError):
|
|
34
|
+
"""Raised when the string version is not properly formatted.
|
|
35
|
+
|
|
36
|
+
Proper format should consist of three dot-separated elements,
|
|
37
|
+
e.g. `7.23.1`.
|
|
38
|
+
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
def __init__(self, version: str) -> None:
|
|
42
|
+
"""Initialize the error.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
version:
|
|
46
|
+
String version with incorrect formatting.
|
|
47
|
+
|
|
48
|
+
"""
|
|
49
|
+
self.version: str = version
|
|
50
|
+
|
|
51
|
+
super().__init__(
|
|
52
|
+
f"Version should consist of three dot separated elements (MAJOR.MINOR.PATCH), got: {version}"
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class VersionNotNumericError(ComverError):
|
|
57
|
+
"""Raised when the string version contains non-numeric elements.
|
|
58
|
+
|
|
59
|
+
Proper format should consist of three dot-separated numeric elements,
|
|
60
|
+
e.g. `7.23.1`. This error is raised, if there is a version like
|
|
61
|
+
`1.2.0a1`.
|
|
62
|
+
|
|
63
|
+
Warning:
|
|
64
|
+
Only
|
|
65
|
+
[semantic Python versioning](https://packaging.python.org/en/latest/discussions/versioning/)
|
|
66
|
+
is allowed, e.g. no `1.2.0a1` for alpha releases
|
|
67
|
+
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
def __init__(self, version: str) -> None:
|
|
71
|
+
"""Initialize the error.
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
version:
|
|
75
|
+
Properly formatted string version with non-numeric elements.
|
|
76
|
+
|
|
77
|
+
"""
|
|
78
|
+
self.version: str = version
|
|
79
|
+
|
|
80
|
+
super().__init__(
|
|
81
|
+
f"One of the MAJOR, MINOR, PATCH is not an integer. Expected <INT>.<INT>.<INT>, got: {version}"
|
|
82
|
+
)
|
comver/plugin.py
ADDED
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: © 2025 open-nudge <https://github.com/open-nudge>
|
|
2
|
+
# SPDX-FileContributor: szymonmaszke <github@maszke.co>
|
|
3
|
+
#
|
|
4
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
|
|
6
|
+
"""Extensions and plugins integrating `comver` with third party systems.
|
|
7
|
+
|
|
8
|
+
Most of the extensions are tailored to the Python ecosystem, and its
|
|
9
|
+
packagae managers specifically.
|
|
10
|
+
|
|
11
|
+
__Currently supported third party tools:__
|
|
12
|
+
|
|
13
|
+
- [`pdm`](https://pdm-project.org/en/latest/) package manager.
|
|
14
|
+
- [`hatch`](https://hatch.pypa.io/1.9/plugins/version-source/reference/)
|
|
15
|
+
package manager.
|
|
16
|
+
|
|
17
|
+
Warning:
|
|
18
|
+
Check out guidelines and tutorials for information about CLI/plugin
|
|
19
|
+
usage and suggested configuration. This section should be of interest
|
|
20
|
+
to people wanting to use the API directly (e.g. new integrations).
|
|
21
|
+
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from __future__ import annotations
|
|
25
|
+
|
|
26
|
+
import typing
|
|
27
|
+
|
|
28
|
+
from importlib.util import find_spec
|
|
29
|
+
|
|
30
|
+
from comver._version import Version, VersionCommit
|
|
31
|
+
|
|
32
|
+
if typing.TYPE_CHECKING:
|
|
33
|
+
import git
|
|
34
|
+
|
|
35
|
+
from comver.type_definitions import OptionalStringsOrPatterns
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def pdm( # noqa: PLR0913
|
|
39
|
+
message_includes: OptionalStringsOrPatterns = None,
|
|
40
|
+
message_excludes: OptionalStringsOrPatterns = None,
|
|
41
|
+
path_includes: OptionalStringsOrPatterns = None,
|
|
42
|
+
path_excludes: OptionalStringsOrPatterns = None,
|
|
43
|
+
author_name_includes: OptionalStringsOrPatterns = None,
|
|
44
|
+
author_name_excludes: OptionalStringsOrPatterns = None,
|
|
45
|
+
author_email_includes: OptionalStringsOrPatterns = None,
|
|
46
|
+
author_email_excludes: OptionalStringsOrPatterns = None,
|
|
47
|
+
major_regexes: OptionalStringsOrPatterns = None,
|
|
48
|
+
minor_regexes: OptionalStringsOrPatterns = None,
|
|
49
|
+
patch_regexes: OptionalStringsOrPatterns = None,
|
|
50
|
+
unrecognized_message: typing.Literal["ignore", "error"] | None = None,
|
|
51
|
+
repository: str | git.Repo | None = None,
|
|
52
|
+
) -> str:
|
|
53
|
+
"""Entrypoint for `pdm`'s `[tool.pdm.version]` `pyproject.toml` specifier.
|
|
54
|
+
|
|
55
|
+
Example `pyproject.toml` usage:
|
|
56
|
+
|
|
57
|
+
```toml
|
|
58
|
+
[build-system]
|
|
59
|
+
build-backend = "pdm.backend"
|
|
60
|
+
|
|
61
|
+
requires = [
|
|
62
|
+
"comver>=0.1.0",
|
|
63
|
+
"pdm-backend>=2",
|
|
64
|
+
]
|
|
65
|
+
|
|
66
|
+
[tool.pdm.version]
|
|
67
|
+
source = "call"
|
|
68
|
+
getter = "commition.plugin.pdm:git"
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
This function uses
|
|
72
|
+
[`Version.from_git_configured`][comver._version.Version.from_git_configured]
|
|
73
|
+
under the hood, __but only outputs the last yielded version `iterable`__.
|
|
74
|
+
|
|
75
|
+
Tip:
|
|
76
|
+
Plugin can be configured by `[tool.comver]` section.
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
message_includes:
|
|
80
|
+
Commit message regexes against which the commit is included.
|
|
81
|
+
Default: From config OR all paths are included.
|
|
82
|
+
message_excludes:
|
|
83
|
+
Commit message regexes against which the commit is excluded.
|
|
84
|
+
Default: From config OR no paths are excluded.
|
|
85
|
+
path_includes:
|
|
86
|
+
Path regexes against which the commit is included.
|
|
87
|
+
Default: From config OR all paths are included.
|
|
88
|
+
path_excludes:
|
|
89
|
+
Path regexes against which the commit is excluded.
|
|
90
|
+
Default: From config OR no paths are excluded.
|
|
91
|
+
author_name_includes:
|
|
92
|
+
Commit author names regexes against
|
|
93
|
+
which the commit is included.
|
|
94
|
+
Default: From config OR all names are included.
|
|
95
|
+
author_name_excludes:
|
|
96
|
+
Commit author names regexes against
|
|
97
|
+
which the commit is excluded.
|
|
98
|
+
Default: From config OR no names are excluded.
|
|
99
|
+
author_email_includes:
|
|
100
|
+
Commit author email regexes against
|
|
101
|
+
which the commit is included.
|
|
102
|
+
Default: From config OR all emails are included.
|
|
103
|
+
author_email_excludes:
|
|
104
|
+
Commit author email regexes against
|
|
105
|
+
which the commit is excluded.
|
|
106
|
+
Default: From config OR no emails are excluded.
|
|
107
|
+
major_regexes:
|
|
108
|
+
The regexes by which the major version is found.
|
|
109
|
+
Default: From config OR matches `feat!:` and `fix!:`
|
|
110
|
+
messages OR `BREAKING CHANGE` anywhere in the message.
|
|
111
|
+
minor_regexes:
|
|
112
|
+
The regex for the minor version.
|
|
113
|
+
Default: From config OR matches messages starting with `feat:`.
|
|
114
|
+
patch_regexes:
|
|
115
|
+
The regex for the patch version.
|
|
116
|
+
Default: From config OR matches messages starting with `fix:`.
|
|
117
|
+
unrecognized_message:
|
|
118
|
+
The behavior for unrecognized messages. It can be
|
|
119
|
+
either "exclude" or "error".
|
|
120
|
+
Default: From config OR "ignore"
|
|
121
|
+
repository:
|
|
122
|
+
The `git` repository.
|
|
123
|
+
Default: From config OR will be searched
|
|
124
|
+
in the parent directories.
|
|
125
|
+
|
|
126
|
+
Returns:
|
|
127
|
+
Calculated version as string (compatible with `pdm` interface).
|
|
128
|
+
|
|
129
|
+
"""
|
|
130
|
+
version = VersionCommit()
|
|
131
|
+
for version in Version.from_git_configured( # noqa: B007
|
|
132
|
+
message_includes=message_includes,
|
|
133
|
+
message_excludes=message_excludes,
|
|
134
|
+
path_includes=path_includes,
|
|
135
|
+
path_excludes=path_excludes,
|
|
136
|
+
author_name_includes=author_name_includes,
|
|
137
|
+
author_name_excludes=author_name_excludes,
|
|
138
|
+
author_email_includes=author_email_includes,
|
|
139
|
+
author_email_excludes=author_email_excludes,
|
|
140
|
+
major_regexes=major_regexes,
|
|
141
|
+
minor_regexes=minor_regexes,
|
|
142
|
+
patch_regexes=patch_regexes,
|
|
143
|
+
unrecognized_message=unrecognized_message,
|
|
144
|
+
repository=repository,
|
|
145
|
+
):
|
|
146
|
+
pass
|
|
147
|
+
|
|
148
|
+
return str(version.version)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
if find_spec("hatchling"):
|
|
152
|
+
from hatchling.plugin import hookimpl
|
|
153
|
+
from hatchling.version.source.plugin.interface import VersionSourceInterface
|
|
154
|
+
|
|
155
|
+
class ComverVersionSource(VersionSourceInterface):
|
|
156
|
+
"""Get the project version for the `hatchling` build backend.
|
|
157
|
+
|
|
158
|
+
This class implements the `VersionSourceInterface` from Hatchling
|
|
159
|
+
and allows integration of the `comver` plugin with Hatch-based
|
|
160
|
+
projects.
|
|
161
|
+
|
|
162
|
+
Tip:
|
|
163
|
+
See [plugins](https://hatch.pypa.io/1.13/plugins/version-source/reference/)
|
|
164
|
+
for more information
|
|
165
|
+
|
|
166
|
+
This function uses
|
|
167
|
+
[`Version.from_git_configured`][comver._version.Version.from_git_configured]
|
|
168
|
+
under the hood, __but only outputs the last version
|
|
169
|
+
yielded from `iterable`__.
|
|
170
|
+
|
|
171
|
+
> [!IMPORTANT]
|
|
172
|
+
> Plugin can also be configured by `[tool.hatch.version]`, not only
|
|
173
|
+
> `[tool.comver`]. The former takes precedence if both exist.
|
|
174
|
+
|
|
175
|
+
"""
|
|
176
|
+
|
|
177
|
+
PLUGIN_NAME: str = "comver" # pyright: ignore [reportIncompatibleUnannotatedOverride]
|
|
178
|
+
|
|
179
|
+
def get_version_data(self) -> dict[str, str]: # pyright: ignore [reportImplicitOverride]
|
|
180
|
+
"""Get the version data to be used by Hatchling.
|
|
181
|
+
|
|
182
|
+
Returns:
|
|
183
|
+
A dictionary with the resolved version string,
|
|
184
|
+
under the "version" key.
|
|
185
|
+
"""
|
|
186
|
+
version = VersionCommit()
|
|
187
|
+
for version in Version.from_git_configured( # noqa: B007
|
|
188
|
+
message_includes=self.config.get("message_includes"), # pyright: ignore [reportUnknownArgumentType]
|
|
189
|
+
message_excludes=self.config.get("message_excludes"), # pyright: ignore [reportUnknownArgumentType]
|
|
190
|
+
path_includes=self.config.get("path_includes"), # pyright: ignore [reportUnknownArgumentType]
|
|
191
|
+
path_excludes=self.config.get("path_excludes"), # pyright: ignore [reportUnknownArgumentType]
|
|
192
|
+
author_name_includes=self.config.get("author_name_includes"), # pyright: ignore [reportUnknownArgumentType]
|
|
193
|
+
author_name_excludes=self.config.get("author_name_excludes"), # pyright: ignore [reportUnknownArgumentType]
|
|
194
|
+
author_email_includes=self.config.get("author_email_includes"), # pyright: ignore [reportUnknownArgumentType]
|
|
195
|
+
author_email_excludes=self.config.get("author_email_excludes"), # pyright: ignore [reportUnknownArgumentType]
|
|
196
|
+
repository=self.root,
|
|
197
|
+
):
|
|
198
|
+
pass
|
|
199
|
+
|
|
200
|
+
return {"version": str(version.version)}
|
|
201
|
+
|
|
202
|
+
def set_version( # pyright: ignore [reportIncompatibleMethodOverride, reportImplicitOverride]
|
|
203
|
+
self,
|
|
204
|
+
_: str,
|
|
205
|
+
__: dict[str, str],
|
|
206
|
+
) -> typing.NoReturn: # pragma: no cover
|
|
207
|
+
"""Setting the version is not supported by the comver plugin.
|
|
208
|
+
|
|
209
|
+
This method exists to fulfill the interface, but always raises
|
|
210
|
+
`NotImplementedError`.
|
|
211
|
+
|
|
212
|
+
Args:
|
|
213
|
+
_:
|
|
214
|
+
The version string (ignored).
|
|
215
|
+
__:
|
|
216
|
+
Additional data (ignored).
|
|
217
|
+
|
|
218
|
+
Raises:
|
|
219
|
+
NotImplementedError:
|
|
220
|
+
Always raised to indicate that setting the
|
|
221
|
+
version is unsupported.
|
|
222
|
+
"""
|
|
223
|
+
error = "comver plugin does not support setting the version."
|
|
224
|
+
raise NotImplementedError(error)
|
|
225
|
+
|
|
226
|
+
@hookimpl
|
|
227
|
+
def hatch_register_version_source() -> type[ComverVersionSource]:
|
|
228
|
+
"""Automatically register hatchling plugin.
|
|
229
|
+
|
|
230
|
+
Note:
|
|
231
|
+
This function is called implicitly to register
|
|
232
|
+
`comver` for `hatchling` backend.
|
|
233
|
+
|
|
234
|
+
Returns:
|
|
235
|
+
ComverVersionSource class
|
|
236
|
+
|
|
237
|
+
"""
|
|
238
|
+
return ComverVersionSource
|
|
239
|
+
|
|
240
|
+
else: # pragma: no cover
|
|
241
|
+
pass
|
comver/py.typed
ADDED
|
File without changes
|
comver/py.typed.license
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: © 2025 open-nudge <https://github.com/open-nudge>
|
|
2
|
+
# SPDX-FileContributor: szymonmaszke <github@maszke.co>
|
|
3
|
+
#
|
|
4
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
|
|
6
|
+
"""Type definitions of `comver`.
|
|
7
|
+
|
|
8
|
+
Important:
|
|
9
|
+
This module is a simplification for `typing` of complex types
|
|
10
|
+
and should be used __eventually__ by third party plugin developers.
|
|
11
|
+
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import re
|
|
17
|
+
|
|
18
|
+
from collections.abc import Iterable
|
|
19
|
+
|
|
20
|
+
StringOrPattern = str | re.Pattern[str]
|
|
21
|
+
"""Either `string` or compiled `re.Pattern`."""
|
|
22
|
+
|
|
23
|
+
StringsOrPatterns = Iterable[StringOrPattern]
|
|
24
|
+
"""Iterable of `StringOrPattern`."""
|
|
25
|
+
|
|
26
|
+
OptionalStringsOrPatterns = Iterable[StringOrPattern] | None
|
|
27
|
+
"""Iterable of `StringOrPattern` or `None`."""
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: comver
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Commit-based semantic versioning - highly configurable and tag-free.
|
|
5
|
+
Author: open-nudge
|
|
6
|
+
Maintainer: open-nudge
|
|
7
|
+
License-Expression: Apache-2.0
|
|
8
|
+
Classifier: Development Status :: 2 - Pre-Alpha
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: Programming Language :: Python
|
|
11
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
17
|
+
Classifier: Typing :: Typed
|
|
18
|
+
Project-URL: Changelog, https://github.com/open-nudge/comver/blob/master/CHANGELOG.md
|
|
19
|
+
Project-URL: Documentation, https://open-nudge.github.io/comver
|
|
20
|
+
Project-URL: Homepage, https://open-nudge.github.io/comver
|
|
21
|
+
Project-URL: Issues, https://github.com/open-nudge/comver/issues
|
|
22
|
+
Project-URL: Repository, https://github.com/open-nudge/comver
|
|
23
|
+
Requires-Python: >=3.11
|
|
24
|
+
Requires-Dist: loadfig>=0.1.0
|
|
25
|
+
Requires-Dist: GitPython>=3
|
|
26
|
+
Provides-Extra: hatchling
|
|
27
|
+
Requires-Dist: hatchling>=1.27.0; extra == "hatchling"
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
<!--
|
|
31
|
+
SPDX-FileCopyrightText: © 2025 open-nudge <https://github.com/open-nudge>
|
|
32
|
+
SPDX-FileContributor: szymonmaszke <github@maszke.co>
|
|
33
|
+
|
|
34
|
+
SPDX-License-Identifier: Apache-2.0
|
|
35
|
+
-->
|
|
36
|
+
|
|
37
|
+
# comver
|
|
38
|
+
|
|
39
|
+
<!-- mkdocs remove start -->
|
|
40
|
+
|
|
41
|
+
<!-- vale off -->
|
|
42
|
+
|
|
43
|
+
<!-- pyml disable-num-lines 30 line-length-->
|
|
44
|
+
|
|
45
|
+
<p align="center">
|
|
46
|
+
<em>Commit-based semantic versioning - highly configurable and tag-free.</em>
|
|
47
|
+
</p>
|
|
48
|
+
|
|
49
|
+
<div align="center">
|
|
50
|
+
|
|
51
|
+
<a href="https://pypi.org/project/comver">
|
|
52
|
+
</a>
|
|
53
|
+
<a href="https://pypi.org/project/comver">
|
|
54
|
+
</a>
|
|
55
|
+
<a href="https://opensource.org/licenses/Apache-2.0">
|
|
56
|
+
</a>
|
|
57
|
+
<a>
|
|
58
|
+
</a>
|
|
59
|
+
<a href="https://scorecard.dev/viewer/?uri=github.com/open-nudge/comver">
|
|
60
|
+
</a>
|
|
61
|
+
|
|
62
|
+
</div>
|
|
63
|
+
|
|
64
|
+
<p align="center">
|
|
65
|
+
✨ <a href="#features">Features</a>
|
|
66
|
+
🚀 <a href="#quick-start">Quick start</a>
|
|
67
|
+
📚 <a href="https://open-nudge.github.io/comver">Documentation</a>
|
|
68
|
+
🤝 <a href="#contribute">Contribute</a>
|
|
69
|
+
👍 <a href="https://github.com/open-nudge/comver/blob/main/ADOPTERS.md">Adopters</a>
|
|
70
|
+
📜 <a href="#legal">Legal</a>
|
|
71
|
+
</p>
|
|
72
|
+
<!-- vale on -->
|
|
73
|
+
|
|
74
|
+
______________________________________________________________________
|
|
75
|
+
|
|
76
|
+
<!-- mkdocs remove end -->
|
|
77
|
+
|
|
78
|
+
## Features
|
|
79
|
+
|
|
80
|
+
__comver__ is a tool for calculating __[semantic versioning](https://semver.org/)__
|
|
81
|
+
of your project __using only commit messages__ - no tags required!
|
|
82
|
+
|
|
83
|
+
- __Separation of concerns__: versioning focuses on technical aspects,
|
|
84
|
+
not marketing. You can now use tags solely for communication.
|
|
85
|
+
- __Highly configurable__: include only relevant commits by filtering via
|
|
86
|
+
`message`, `author`, `email`, __or even commit path__.
|
|
87
|
+
- __Immutable__: version is calculated directly from the commit history.
|
|
88
|
+
Tags can now be used more meaningfully (e.g., to mark a major milestone
|
|
89
|
+
or release).
|
|
90
|
+
- __Batteries-included__: integrate with [pdm](https://pdm-project.org/en/latest/),
|
|
91
|
+
[Hatch](https://hatch.pypa.io/latest/) or [uv](https://docs.astral.sh/uv/).
|
|
92
|
+
- __Verifiable__: verify that a specific version was generated from a
|
|
93
|
+
given commit chain - more resistant to tampering like
|
|
94
|
+
[dependency substitution attacks](https://docs.aws.amazon.com/codeartifact/latest/ug/dependency-substitution-attacks.html)
|
|
95
|
+
|
|
96
|
+
## Why?
|
|
97
|
+
|
|
98
|
+
Semantic versioning based on Git tags has a few limitations:
|
|
99
|
+
|
|
100
|
+
- Teams may avoid bumping the `major` version due to the
|
|
101
|
+
perceived weight of the change.
|
|
102
|
+
[__Double versioning scheme__](https://open-nudge.github.io/comver/tutorials/why);
|
|
103
|
+
one version for technical changes, another for public releases is
|
|
104
|
+
a viable mitigation.
|
|
105
|
+
- Tag creation by `bot`s (e.g. during automated releases) lead to problems
|
|
106
|
+
with `branch protection` (see [here](https://github.com/orgs/community/discussions/25305)).
|
|
107
|
+
- Not all commits are relevant for release versions
|
|
108
|
+
(e.g., CI changes, bot updates, or tooling config),
|
|
109
|
+
yet many schemes count them in. With filtering, `comver` can exclude
|
|
110
|
+
such noise.
|
|
111
|
+
- Tags are mutable by default and can be re-pointed. By calculating the version
|
|
112
|
+
based on commits, and combining it with the commit
|
|
113
|
+
`sha` and a config `checksum`, you get verifiable and reproducible results.
|
|
114
|
+
|
|
115
|
+
## Quick start
|
|
116
|
+
|
|
117
|
+
> [!NOTE]
|
|
118
|
+
> You can jump straight into the action and check `comver`
|
|
119
|
+
> [tutorials](https://open-nudge.github.io/comver/tutorials).
|
|
120
|
+
|
|
121
|
+
### Installation
|
|
122
|
+
|
|
123
|
+
```sh
|
|
124
|
+
> pip install comver
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Calculate version
|
|
128
|
+
|
|
129
|
+
> [!IMPORTANT]
|
|
130
|
+
> Although written in Python, comver can be used
|
|
131
|
+
> with any programming language.
|
|
132
|
+
|
|
133
|
+
If your commits follow the Conventional Commits format, run:
|
|
134
|
+
|
|
135
|
+
```sh
|
|
136
|
+
> comver calculate
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
This will output a version string in the `MAJOR.MINOR.PATCH` format:
|
|
140
|
+
|
|
141
|
+
```sh
|
|
142
|
+
23.1.3 # Output
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
> [!IMPORTANT]
|
|
146
|
+
> You can use [plugins](https://open-nudge.github.io/comver/tutorials/plugins)
|
|
147
|
+
> to integrate this versioning scheme
|
|
148
|
+
> with [`pdm`](https://github.com/pdm-project/pdm) or
|
|
149
|
+
> [`hatch`](https://github.com/pypa/hatch). More below!
|
|
150
|
+
|
|
151
|
+
<!-- mkdocs remove start -->
|
|
152
|
+
|
|
153
|
+
### Configuration
|
|
154
|
+
|
|
155
|
+
Configuration can be done either in `pyproject.toml`
|
|
156
|
+
(recommended for `Python`-first project) or in a separate
|
|
157
|
+
`.comver.toml` file (recommended for non-python projects):
|
|
158
|
+
|
|
159
|
+
<table>
|
|
160
|
+
<tr>
|
|
161
|
+
<th>pyproject.toml</th>
|
|
162
|
+
<th>.comver.toml</th>
|
|
163
|
+
</tr>
|
|
164
|
+
<tr>
|
|
165
|
+
<td>
|
|
166
|
+
|
|
167
|
+
```toml
|
|
168
|
+
[tool.comver]
|
|
169
|
+
# Only commits to these paths are considered
|
|
170
|
+
path_includes = [
|
|
171
|
+
"src/*",
|
|
172
|
+
"pyproject.toml",
|
|
173
|
+
]
|
|
174
|
+
|
|
175
|
+
# Commits done by GitHub Actions bot are discarded
|
|
176
|
+
author_name_excludes = [
|
|
177
|
+
"github-actions[bot]",
|
|
178
|
+
]
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
</td>
|
|
182
|
+
<td>
|
|
183
|
+
|
|
184
|
+
```toml
|
|
185
|
+
# No [tool.comver] needed here
|
|
186
|
+
# Source only commits considered
|
|
187
|
+
path_includes = [
|
|
188
|
+
"src/*",
|
|
189
|
+
]
|
|
190
|
+
|
|
191
|
+
# Commits messages with [no version] are discarded
|
|
192
|
+
message_excludes = [
|
|
193
|
+
".*\[no version\].*",
|
|
194
|
+
".*\[skipversion\].*",
|
|
195
|
+
]
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
</td>
|
|
199
|
+
</tr>
|
|
200
|
+
</table>
|
|
201
|
+
|
|
202
|
+
> [!TIP]
|
|
203
|
+
> See suggested configuration examples [here](https://open-nudge.github.io/comver/tutorials/configuration)
|
|
204
|
+
|
|
205
|
+
### Integrations
|
|
206
|
+
|
|
207
|
+
> [!NOTE]
|
|
208
|
+
> You can use `comver` with [`uv`](https://github.com/astral-sh/uv)
|
|
209
|
+
> by selecting the appropriate [build backend](https://docs.astral.sh/uv/concepts/build-backend/#choosing-a-build-backend),
|
|
210
|
+
> such as `hatchling`.
|
|
211
|
+
|
|
212
|
+
To integrate `comver` with [`pdm`](https://pdm-project.org/en/latest/)
|
|
213
|
+
or [`hatch`](https://hatch.pypa.io/latest/) add the following to
|
|
214
|
+
your `pyproject.toml`:
|
|
215
|
+
|
|
216
|
+
<table>
|
|
217
|
+
<tr>
|
|
218
|
+
<th>PDM</th>
|
|
219
|
+
<th>Hatch</th>
|
|
220
|
+
</tr>
|
|
221
|
+
<tr>
|
|
222
|
+
<td>
|
|
223
|
+
|
|
224
|
+
```toml
|
|
225
|
+
# Register comver for the build process
|
|
226
|
+
[build-system]
|
|
227
|
+
build-backend = "pdm.backend"
|
|
228
|
+
|
|
229
|
+
requires = [
|
|
230
|
+
"pdm-backend",
|
|
231
|
+
"comver>=0.1.0",
|
|
232
|
+
]
|
|
233
|
+
|
|
234
|
+
# Setup versioning for PDM
|
|
235
|
+
[tool.pdm.version]
|
|
236
|
+
source = "call"
|
|
237
|
+
getter = "comver.plugin:pdm"
|
|
238
|
+
|
|
239
|
+
# Comver-specific settings
|
|
240
|
+
[tool.comver]
|
|
241
|
+
...
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
</td>
|
|
245
|
+
<td>
|
|
246
|
+
|
|
247
|
+
```toml
|
|
248
|
+
# Register comver for the build process
|
|
249
|
+
[build-system]
|
|
250
|
+
build-backend = "hatchling.build"
|
|
251
|
+
|
|
252
|
+
requires = [
|
|
253
|
+
"comver>=0.1.0",
|
|
254
|
+
"hatchling",
|
|
255
|
+
]
|
|
256
|
+
|
|
257
|
+
# Setup versioning for Hatchling
|
|
258
|
+
[tool.hatch.version]
|
|
259
|
+
source = "comver"
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
# Comver-specific settings
|
|
263
|
+
[tool.comver]
|
|
264
|
+
...
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
</td>
|
|
268
|
+
</tr>
|
|
269
|
+
</table>
|
|
270
|
+
|
|
271
|
+
> [!TIP]
|
|
272
|
+
> See more in the [documentation](https://open-nudge.github.io/comver/tutorials/plugins)
|
|
273
|
+
|
|
274
|
+
### Verification
|
|
275
|
+
|
|
276
|
+
To verify that a version was produced from the same Git tree and configuration,
|
|
277
|
+
first use the calculate command with additional flags:
|
|
278
|
+
|
|
279
|
+
```sh
|
|
280
|
+
comver calculate --sha --checksum
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
This outputs three space-separated values:
|
|
284
|
+
|
|
285
|
+
```sh
|
|
286
|
+
<VERSION> <SHA> <CHECKSUM>
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
> [!TIP]
|
|
290
|
+
> Append `--format=json` for machine-friendly output
|
|
291
|
+
|
|
292
|
+
Before the next release provide these values to the `comver verify`
|
|
293
|
+
to ensure the version was previously generated from the
|
|
294
|
+
same codebase and config:
|
|
295
|
+
|
|
296
|
+
```sh
|
|
297
|
+
comver verify <VERSION> <SHA> <CHECKSUM>
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
If inconsistencies are found, you'll receive feedback, for example:
|
|
301
|
+
|
|
302
|
+
> Provided checksum and the checksum of configuration do not match.
|
|
303
|
+
|
|
304
|
+
> [!TIP]
|
|
305
|
+
> Explore verification workflows in the [tutorials](https://open-nudge.github.io/comver/tutorials/verification)
|
|
306
|
+
|
|
307
|
+
<!-- md-dead-link-check: off -->
|
|
308
|
+
|
|
309
|
+
## Contribute
|
|
310
|
+
|
|
311
|
+
We welcome your contributions! Start here:
|
|
312
|
+
|
|
313
|
+
- [Code of Conduct](/CODE_OF_CONDUCT.md)
|
|
314
|
+
- [Contributing Guide](/CONTRIBUTING.md)
|
|
315
|
+
- [Roadmap](/ROADMAP.md)
|
|
316
|
+
- [Changelog](/CHANGELOG.md)
|
|
317
|
+
- [Report security vulnerabilities](/SECURITY.md)
|
|
318
|
+
- [Open an Issue](https://github.com/open-nudge/comver/issues)
|
|
319
|
+
|
|
320
|
+
## Legal
|
|
321
|
+
|
|
322
|
+
- This project is licensed under the _Apache 2.0 License_ - see
|
|
323
|
+
the [LICENSE](/LICENSE.md) file for details.
|
|
324
|
+
- This project is copyrighted by _open-nudge_ - the
|
|
325
|
+
appropriate copyright notice is included in each file.
|
|
326
|
+
|
|
327
|
+
<!-- mkdocs remove end -->
|
|
328
|
+
|
|
329
|
+
<!-- md-dead-link-check: on -->
|