python-semantic-release 10.3.0__py3-none-any.whl → 10.5.2__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.
- {python_semantic_release-10.3.0.dist-info → python_semantic_release-10.5.2.dist-info}/METADATA +12 -10
- {python_semantic_release-10.3.0.dist-info → python_semantic_release-10.5.2.dist-info}/RECORD +23 -19
- semantic_release/changelog/context.py +1 -1
- semantic_release/cli/commands/version.py +90 -16
- semantic_release/cli/config.py +8 -3
- semantic_release/cli/github_actions_output.py +21 -6
- semantic_release/cli/masking_filter.py +1 -3
- semantic_release/commit_parser/__init__.py +23 -0
- semantic_release/commit_parser/conventional/__init__.py +17 -0
- semantic_release/commit_parser/conventional/options.py +72 -0
- semantic_release/commit_parser/conventional/options_monorepo.py +90 -0
- semantic_release/commit_parser/{conventional.py → conventional/parser.py} +85 -127
- semantic_release/commit_parser/conventional/parser_monorepo.py +467 -0
- semantic_release/errors.py +16 -0
- semantic_release/gitproject.py +187 -20
- semantic_release/version/algorithm.py +5 -18
- semantic_release/version/declarations/pattern.py +2 -2
- semantic_release/version/translator.py +23 -5
- semantic_release/version/version.py +9 -0
- {python_semantic_release-10.3.0.dist-info → python_semantic_release-10.5.2.dist-info}/WHEEL +0 -0
- {python_semantic_release-10.3.0.dist-info → python_semantic_release-10.5.2.dist-info}/entry_points.txt +0 -0
- {python_semantic_release-10.3.0.dist-info → python_semantic_release-10.5.2.dist-info}/licenses/LICENSE +0 -0
- {python_semantic_release-10.3.0.dist-info → python_semantic_release-10.5.2.dist-info}/top_level.txt +0 -0
{python_semantic_release-10.3.0.dist-info → python_semantic_release-10.5.2.dist-info}/METADATA
RENAMED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-semantic-release
|
|
3
|
-
Version: 10.
|
|
3
|
+
Version: 10.5.2
|
|
4
4
|
Summary: Automatic Semantic Versioning for Python projects
|
|
5
|
-
Author-email: Rolf Erik Lekang <me@rolflekang.com>
|
|
5
|
+
Author-email: Rolf Erik Lekang <me@rolflekang.com>, codejedi365 <codejedi365@gmail.com>
|
|
6
6
|
License: MIT
|
|
7
7
|
Project-URL: changelog, https://github.com/python-semantic-release/python-semantic-release/blob/master/CHANGELOG.md
|
|
8
8
|
Project-URL: documentation, https://python-semantic-release.readthedocs.io
|
|
@@ -17,7 +17,8 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.11
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.12
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
-
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
21
|
+
Requires-Python: ~=3.8
|
|
21
22
|
Description-Content-Type: text/x-rst
|
|
22
23
|
License-File: LICENSE
|
|
23
24
|
Requires-Dist: click~=8.1.0
|
|
@@ -26,7 +27,7 @@ Requires-Dist: gitpython~=3.0
|
|
|
26
27
|
Requires-Dist: requests~=2.25
|
|
27
28
|
Requires-Dist: jinja2~=3.1
|
|
28
29
|
Requires-Dist: python-gitlab<7.0.0,>=4.0.0
|
|
29
|
-
Requires-Dist: tomlkit~=0.
|
|
30
|
+
Requires-Dist: tomlkit~=0.13.0
|
|
30
31
|
Requires-Dist: dotty-dict~=1.3
|
|
31
32
|
Requires-Dist: importlib-resources~=6.0
|
|
32
33
|
Requires-Dist: pydantic~=2.0
|
|
@@ -35,11 +36,12 @@ Requires-Dist: shellingham~=1.5
|
|
|
35
36
|
Requires-Dist: Deprecated~=1.2
|
|
36
37
|
Provides-Extra: build
|
|
37
38
|
Requires-Dist: build~=1.2; extra == "build"
|
|
39
|
+
Requires-Dist: tomlkit~=0.13.0; extra == "build"
|
|
38
40
|
Provides-Extra: docs
|
|
39
|
-
Requires-Dist: Sphinx~=
|
|
40
|
-
Requires-Dist: sphinxcontrib-apidoc==0.
|
|
41
|
+
Requires-Dist: Sphinx~=7.4; extra == "docs"
|
|
42
|
+
Requires-Dist: sphinxcontrib-apidoc==0.6.0; extra == "docs"
|
|
41
43
|
Requires-Dist: sphinx-autobuild==2024.2.4; extra == "docs"
|
|
42
|
-
Requires-Dist: furo~=
|
|
44
|
+
Requires-Dist: furo~=2025.9; extra == "docs"
|
|
43
45
|
Provides-Extra: test
|
|
44
46
|
Requires-Dist: coverage[toml]~=7.0; extra == "test"
|
|
45
47
|
Requires-Dist: filelock~=3.15; extra == "test"
|
|
@@ -48,9 +50,9 @@ Requires-Dist: freezegun~=1.5; extra == "test"
|
|
|
48
50
|
Requires-Dist: pyyaml~=6.0; extra == "test"
|
|
49
51
|
Requires-Dist: pytest~=8.3; extra == "test"
|
|
50
52
|
Requires-Dist: pytest-clarity~=1.0; extra == "test"
|
|
51
|
-
Requires-Dist: pytest-cov<
|
|
53
|
+
Requires-Dist: pytest-cov<8.0.0,>=5.0.0; extra == "test"
|
|
52
54
|
Requires-Dist: pytest-env~=1.0; extra == "test"
|
|
53
|
-
Requires-Dist: pytest-lazy-fixtures~=1.
|
|
55
|
+
Requires-Dist: pytest-lazy-fixtures~=1.4; extra == "test"
|
|
54
56
|
Requires-Dist: pytest-mock~=3.0; extra == "test"
|
|
55
57
|
Requires-Dist: pytest-order~=1.3; extra == "test"
|
|
56
58
|
Requires-Dist: pytest-pretty~=1.2; extra == "test"
|
|
@@ -58,7 +60,7 @@ Requires-Dist: pytest-xdist~=3.0; extra == "test"
|
|
|
58
60
|
Requires-Dist: responses~=0.25.0; extra == "test"
|
|
59
61
|
Requires-Dist: requests-mock~=1.10; extra == "test"
|
|
60
62
|
Provides-Extra: dev
|
|
61
|
-
Requires-Dist: pre-commit~=3
|
|
63
|
+
Requires-Dist: pre-commit~=4.3; extra == "dev"
|
|
62
64
|
Requires-Dist: tox~=4.11; extra == "dev"
|
|
63
65
|
Requires-Dist: ruff==0.6.1; extra == "dev"
|
|
64
66
|
Provides-Extra: mypy
|
{python_semantic_release-10.3.0.dist-info → python_semantic_release-10.5.2.dist-info}/RECORD
RENAMED
|
@@ -1,40 +1,44 @@
|
|
|
1
|
-
python_semantic_release-10.
|
|
1
|
+
python_semantic_release-10.5.2.dist-info/licenses/LICENSE,sha256=NE85nszX252sdQdu0xgS9qwfYES0k8qS6gW3uO4jRGE,1083
|
|
2
2
|
semantic_release/__init__.py,sha256=tRJWhrn_dUt0QycXD2DoJSfEP5uwmxngH7jvbG2i-hA,1317
|
|
3
3
|
semantic_release/__main__.py,sha256=pksxr6g1vkKq98Q1lShsxG8tk55IMiSMHzAHKyFU5x0,1704
|
|
4
4
|
semantic_release/const.py,sha256=wInJR7vcOgT1ysm5VuJQ6lD_ZGYnCwRVKz7Uz3htQc4,861
|
|
5
5
|
semantic_release/enums.py,sha256=vrEw1UNRcNrFjPqOFnuUzfeoqKj0ChixVVlyk5fqbng,1744
|
|
6
|
-
semantic_release/errors.py,sha256=
|
|
7
|
-
semantic_release/gitproject.py,sha256=
|
|
6
|
+
semantic_release/errors.py,sha256=FyocaqHbRhux-iNmCf9nI7awyUaGKjG9_5C_QDvhEas,3399
|
|
7
|
+
semantic_release/gitproject.py,sha256=qF4GVZh-aaS4bVV3OmFQLmXMAxHNFyZCwUaWPtUmZ1k,16546
|
|
8
8
|
semantic_release/globals.py,sha256=IBhBbhZr2jx8dmpySnnu9m9jOGYu9Yu-vqHvAGQxgnw,464
|
|
9
9
|
semantic_release/helpers.py,sha256=2uQXOiuiemiviVD52SH2FF6cn14p_gqvREeHvP7dexw,10012
|
|
10
10
|
semantic_release/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
11
|
semantic_release/changelog/__init__.py,sha256=Bg6Xe5Vt32rWoMscW-hd4sUwiZqzWmsg4CD1EhMesMY,262
|
|
12
|
-
semantic_release/changelog/context.py,sha256=
|
|
12
|
+
semantic_release/changelog/context.py,sha256=234LLcB_uuGaQ5N_zTbcQYF27ZwYIBmicIWkhFs7-aQ,5993
|
|
13
13
|
semantic_release/changelog/release_history.py,sha256=kX6D9VReq85wnHz0D6JpmJJCfWA6axV6RToSM0O5laU,10602
|
|
14
14
|
semantic_release/changelog/template.py,sha256=eqOjtVfBbksgTK4CAZOajfkaAcKueJ-FhFv99U3-J5E,5695
|
|
15
15
|
semantic_release/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
16
16
|
semantic_release/cli/changelog_writer.py,sha256=2jP5b0LK61Y2tb22GQSFFmwHwXd2WjbopgsMAmsQsfY,9284
|
|
17
17
|
semantic_release/cli/cli_context.py,sha256=Nop71LdVCJOeSUHgTXunMyK3xAu_QKQC2cRp1QBVkX0,4134
|
|
18
|
-
semantic_release/cli/config.py,sha256=
|
|
18
|
+
semantic_release/cli/config.py,sha256=zNXlJHZBnFk2GEemgCg2Yw42EWihtFMot1twI7bEN-g,33668
|
|
19
19
|
semantic_release/cli/const.py,sha256=h7XE2D0D__TAZSrUUtVszwvzpkHTMOiQCf97XQNbEvA,163
|
|
20
|
-
semantic_release/cli/github_actions_output.py,sha256=
|
|
21
|
-
semantic_release/cli/masking_filter.py,sha256=
|
|
20
|
+
semantic_release/cli/github_actions_output.py,sha256=yC0nsMvEFGACjDwB8DdmGKwNGI8aIIhDxRHrmcS7tzA,5410
|
|
21
|
+
semantic_release/cli/masking_filter.py,sha256=7t7XFL7Iy4QTvaYevZ-jnTkJBz15GoBw1vjW3hihe38,3159
|
|
22
22
|
semantic_release/cli/util.py,sha256=4rf4xDHb7l-XpdcFNtslFz1xHslnBu6cTgWHXVnQXQs,3746
|
|
23
23
|
semantic_release/cli/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
24
24
|
semantic_release/cli/commands/changelog.py,sha256=wJfd4VVfrGnu2jnIpG25cdVcbXIX-ElKl3b2jdtPPa0,5391
|
|
25
25
|
semantic_release/cli/commands/generate_config.py,sha256=2xZOu3NpyhBp0pWr7d8ugKl_kjqQgpSsSMHq5wHTfrE,1699
|
|
26
26
|
semantic_release/cli/commands/main.py,sha256=u1zhkkvKCZ2TtUqjzvdFTe5UZsvfws_pjqqo6CY0bBo,4351
|
|
27
27
|
semantic_release/cli/commands/publish.py,sha256=CE_LJTxFnc337MfpsfdJopi7QCwwE13GqGNQ-dNgWis,2871
|
|
28
|
-
semantic_release/cli/commands/version.py,sha256=
|
|
29
|
-
semantic_release/commit_parser/__init__.py,sha256=
|
|
28
|
+
semantic_release/cli/commands/version.py,sha256=1zJ96_WSQh4bY_75P3eTJTfwrEZcJGHf7XJO2yA66SA,29459
|
|
29
|
+
semantic_release/commit_parser/__init__.py,sha256=uCC2YI-EDPUAa6TwWYJA8TS7baWE2bXrLEGcrhJKofI,1323
|
|
30
30
|
semantic_release/commit_parser/_base.py,sha256=DLsHnbXG-39JkUbcnsBCSV2GmV35w1rasyoMhK8G0UE,3058
|
|
31
31
|
semantic_release/commit_parser/angular.py,sha256=MY_fo9F4EZ-ac8wYzBR0uD94O5Li2D-8zEMR01wss4c,18534
|
|
32
|
-
semantic_release/commit_parser/conventional.py,sha256=Iyy8txkshK8HikizFVa7pnJHBSWDhOhF45zR866QxQM,18672
|
|
33
32
|
semantic_release/commit_parser/emoji.py,sha256=0VecUMMcj43UaKDZ2GaFFUG26zOJAvXsEobTHaXNkk0,17749
|
|
34
33
|
semantic_release/commit_parser/scipy.py,sha256=gA9TfmrxGVvtv6kki6N_9abJx-_WlpBsSX2TBh0YgPw,19463
|
|
35
34
|
semantic_release/commit_parser/tag.py,sha256=bVO2XghM0G_eW2rG9Xc2q5TPsjtxr-xcHK5RpE1u_HM,3537
|
|
36
35
|
semantic_release/commit_parser/token.py,sha256=1_q8mJ4SRu7kNfa-Nxr8fEyuvCfjPgiPEitqSP1KR5g,7904
|
|
37
36
|
semantic_release/commit_parser/util.py,sha256=hcLjc16o7l6y_5Hfl8IxmF4ijaJD62JdjdB2DJWAe-g,3959
|
|
37
|
+
semantic_release/commit_parser/conventional/__init__.py,sha256=JHPL3S6trM4Le9MXnXc6iPYxxQnE4j0LG83_BWIomOw,602
|
|
38
|
+
semantic_release/commit_parser/conventional/options.py,sha256=AnRgTRMF-3X5QonTqq6bqJEbmGgQBzppyRZ79hct28g,2598
|
|
39
|
+
semantic_release/commit_parser/conventional/options_monorepo.py,sha256=7OCpuaYhw01bfoffTGfPgEWzRRyVsdsq_n2eo8Dt8-8,3210
|
|
40
|
+
semantic_release/commit_parser/conventional/parser.py,sha256=Pex26cvMqAKx9NPH3KROYg7k76R0Nsbs4aHor5SbMZg,16671
|
|
41
|
+
semantic_release/commit_parser/conventional/parser_monorepo.py,sha256=nVAc_gK4tJ5UM_rd9KbXgBWeBgrI_q2-vav3_4748r8,21189
|
|
38
42
|
semantic_release/data/templates/conventional/md/.release_notes.md.j2,sha256=DlMVAJMGqE27TwJ-2kviYaFhd3uWqXiU6Ikl15Ukne8,2512
|
|
39
43
|
semantic_release/data/templates/conventional/md/CHANGELOG.md.j2,sha256=FZmrQ-qOIoSoJmAa_NFaRelfmqUpypU2xlDeScdGOf4,729
|
|
40
44
|
semantic_release/data/templates/conventional/md/.components/changelog_header.md.j2,sha256=qNxTuSr59CV_yyimVU_RYp5azCnK0l6nJ03Zf0u5Ugg,166
|
|
@@ -64,17 +68,17 @@ semantic_release/hvcs/remote_hvcs_base.py,sha256=QtkjdMy9l-c7UOtyPz25cqVOkCk4IU-
|
|
|
64
68
|
semantic_release/hvcs/token_auth.py,sha256=ZjT56-NIPB4OKIt1qwHCu1TavXnrWFIBl9ARlg56hgU,663
|
|
65
69
|
semantic_release/hvcs/util.py,sha256=PUNV4yUlpzDtNCFmh2joaPdU4JyfUBnVp0zaQsT9EDQ,2871
|
|
66
70
|
semantic_release/version/__init__.py,sha256=CLhtGQry9dLIij5XyRa9ZevxU_1p8tjMTSQ-K_GMpWM,270
|
|
67
|
-
semantic_release/version/algorithm.py,sha256=
|
|
71
|
+
semantic_release/version/algorithm.py,sha256=IxgYNF78W7qdMzdV4WsoljwfJgB-sn2XdfkevD0aZlo,16254
|
|
68
72
|
semantic_release/version/declaration.py,sha256=eot_lUyFaEhzK4bPncfv9tahf51LdxZP6EaS54h3aAs,3635
|
|
69
|
-
semantic_release/version/translator.py,sha256=
|
|
70
|
-
semantic_release/version/version.py,sha256=
|
|
73
|
+
semantic_release/version/translator.py,sha256=iIfu3WreB9qqPHgqJLILbBluVQQNcpP0DEsnn_WzAaM,3689
|
|
74
|
+
semantic_release/version/version.py,sha256=Y3Qqqv7CypirikT7jNqqFMNAvR2UjV-VQx-c2G0mZc0,14519
|
|
71
75
|
semantic_release/version/declarations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
72
76
|
semantic_release/version/declarations/enum.py,sha256=3n5Py9DoFkmItIdsmtQrJgmAhepTv_1EnogzSdXu1Wg,244
|
|
73
77
|
semantic_release/version/declarations/i_version_replacer.py,sha256=oP6BxJuxwI44roI6448tomShv1sMoy9ry8TlhhIQtfc,2416
|
|
74
|
-
semantic_release/version/declarations/pattern.py,sha256=
|
|
78
|
+
semantic_release/version/declarations/pattern.py,sha256=sKk0uQpJjWVZc8RJUjxQoEPUvFLxXNGGBow5h1IqCTM,8378
|
|
75
79
|
semantic_release/version/declarations/toml.py,sha256=2K4DtX5Qq1iHT8cG8mISPTMmp50w6Av0KmLAKZPYqq8,4931
|
|
76
|
-
python_semantic_release-10.
|
|
77
|
-
python_semantic_release-10.
|
|
78
|
-
python_semantic_release-10.
|
|
79
|
-
python_semantic_release-10.
|
|
80
|
-
python_semantic_release-10.
|
|
80
|
+
python_semantic_release-10.5.2.dist-info/METADATA,sha256=RMojFB6HaaUcQbydFl05KFC6aIj2OhRVxHRRVeqZrqI,4064
|
|
81
|
+
python_semantic_release-10.5.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
82
|
+
python_semantic_release-10.5.2.dist-info/entry_points.txt,sha256=kzkCyDJsMOwgpFwEWKE9wxN1tXaUP6g6GIO4xtc0QuE,162
|
|
83
|
+
python_semantic_release-10.5.2.dist-info/top_level.txt,sha256=qYA24nyg3eP-ti5UW7Vuj2aXVmM0wqVHx4mREdRZNAA,17
|
|
84
|
+
python_semantic_release-10.5.2.dist-info/RECORD,,
|
|
@@ -10,7 +10,7 @@ from typing import TYPE_CHECKING
|
|
|
10
10
|
import click
|
|
11
11
|
import shellingham # type: ignore[import]
|
|
12
12
|
from click_option_group import MutuallyExclusiveOptionGroup, optgroup
|
|
13
|
-
from git import Repo
|
|
13
|
+
from git import GitCommandError, Repo
|
|
14
14
|
from requests import HTTPError
|
|
15
15
|
|
|
16
16
|
from semantic_release.changelog.release_history import ReleaseHistory
|
|
@@ -18,15 +18,23 @@ from semantic_release.cli.changelog_writer import (
|
|
|
18
18
|
generate_release_notes,
|
|
19
19
|
write_changelog_files,
|
|
20
20
|
)
|
|
21
|
-
from semantic_release.cli.github_actions_output import
|
|
21
|
+
from semantic_release.cli.github_actions_output import (
|
|
22
|
+
PersistenceMode,
|
|
23
|
+
VersionGitHubActionsOutput,
|
|
24
|
+
)
|
|
22
25
|
from semantic_release.cli.util import noop_report, rprint
|
|
23
26
|
from semantic_release.const import DEFAULT_SHELL, DEFAULT_VERSION
|
|
24
27
|
from semantic_release.enums import LevelBump
|
|
25
28
|
from semantic_release.errors import (
|
|
26
29
|
BuildDistributionsError,
|
|
30
|
+
DetachedHeadGitError,
|
|
27
31
|
GitCommitEmptyIndexError,
|
|
32
|
+
GitFetchError,
|
|
28
33
|
InternalError,
|
|
34
|
+
LocalGitError,
|
|
29
35
|
UnexpectedResponse,
|
|
36
|
+
UnknownUpstreamBranchError,
|
|
37
|
+
UpstreamBranchChangedError,
|
|
30
38
|
)
|
|
31
39
|
from semantic_release.gitproject import GitProject
|
|
32
40
|
from semantic_release.globals import logger
|
|
@@ -72,10 +80,13 @@ def is_forced_prerelease(
|
|
|
72
80
|
)
|
|
73
81
|
|
|
74
82
|
|
|
75
|
-
def last_released(
|
|
83
|
+
def last_released(
|
|
84
|
+
repo_dir: Path, tag_format: str, add_partial_tags: bool = False
|
|
85
|
+
) -> tuple[Tag, Version] | None:
|
|
76
86
|
with Repo(str(repo_dir)) as git_repo:
|
|
77
87
|
ts_and_vs = tags_and_versions(
|
|
78
|
-
git_repo.tags,
|
|
88
|
+
git_repo.tags,
|
|
89
|
+
VersionTranslator(tag_format=tag_format, add_partial_tags=add_partial_tags),
|
|
79
90
|
)
|
|
80
91
|
|
|
81
92
|
return ts_and_vs[0] if ts_and_vs else None
|
|
@@ -446,7 +457,11 @@ def version( # noqa: C901
|
|
|
446
457
|
if print_last_released or print_last_released_tag:
|
|
447
458
|
# TODO: get tag format a better way
|
|
448
459
|
if not (
|
|
449
|
-
last_release := last_released(
|
|
460
|
+
last_release := last_released(
|
|
461
|
+
config.repo_dir,
|
|
462
|
+
tag_format=config.tag_format,
|
|
463
|
+
add_partial_tags=config.add_partial_tags,
|
|
464
|
+
)
|
|
450
465
|
):
|
|
451
466
|
logger.warning("No release tags found.")
|
|
452
467
|
return
|
|
@@ -467,10 +482,14 @@ def version( # noqa: C901
|
|
|
467
482
|
major_on_zero = runtime.major_on_zero
|
|
468
483
|
no_verify = runtime.no_git_verify
|
|
469
484
|
opts = runtime.global_cli_options
|
|
485
|
+
add_partial_tags = config.add_partial_tags
|
|
470
486
|
gha_output = VersionGitHubActionsOutput(
|
|
471
|
-
hvcs_client
|
|
472
|
-
|
|
473
|
-
|
|
487
|
+
gh_client=hvcs_client if isinstance(hvcs_client, Github) else None,
|
|
488
|
+
mode=(
|
|
489
|
+
PersistenceMode.TEMPORARY
|
|
490
|
+
if opts.noop or (not commit_changes and not create_tag)
|
|
491
|
+
else PersistenceMode.PERMANENT
|
|
492
|
+
),
|
|
474
493
|
released=False,
|
|
475
494
|
)
|
|
476
495
|
|
|
@@ -485,6 +504,17 @@ def version( # noqa: C901
|
|
|
485
504
|
logger.info("Forcing use of %s as the prerelease token", prerelease_token)
|
|
486
505
|
translator.prerelease_token = prerelease_token
|
|
487
506
|
|
|
507
|
+
# Check if the repository is shallow and unshallow it if necessary
|
|
508
|
+
# This ensures we have the full history for commit analysis
|
|
509
|
+
project = GitProject(
|
|
510
|
+
directory=runtime.repo_dir,
|
|
511
|
+
commit_author=runtime.commit_author,
|
|
512
|
+
credential_masker=runtime.masker,
|
|
513
|
+
)
|
|
514
|
+
if project.is_shallow_clone():
|
|
515
|
+
logger.info("Repository is a shallow clone, converting to full clone...")
|
|
516
|
+
project.git_unshallow(noop=opts.noop)
|
|
517
|
+
|
|
488
518
|
# Only push if we're committing changes
|
|
489
519
|
if push_changes and not commit_changes and not create_tag:
|
|
490
520
|
logger.info("changes will not be pushed because --no-commit disables pushing")
|
|
@@ -543,7 +573,8 @@ def version( # noqa: C901
|
|
|
543
573
|
|
|
544
574
|
# Update GitHub Actions output value with new version & set delayed write
|
|
545
575
|
gha_output.version = new_version
|
|
546
|
-
|
|
576
|
+
if isinstance(hvcs_client, Github):
|
|
577
|
+
ctx.call_on_close(gha_output.write_if_possible)
|
|
547
578
|
|
|
548
579
|
# Make string variant of version or appropriate tag as necessary
|
|
549
580
|
version_to_print = str(new_version) if not print_only_tag else new_version.as_tag()
|
|
@@ -676,12 +707,6 @@ def version( # noqa: C901
|
|
|
676
707
|
license_name="" if not isinstance(license_cfg, str) else license_cfg,
|
|
677
708
|
)
|
|
678
709
|
|
|
679
|
-
project = GitProject(
|
|
680
|
-
directory=runtime.repo_dir,
|
|
681
|
-
commit_author=runtime.commit_author,
|
|
682
|
-
credential_masker=runtime.masker,
|
|
683
|
-
)
|
|
684
|
-
|
|
685
710
|
# Preparing for committing changes; we always stage files even if we're not committing them in order to support a two-stage commit
|
|
686
711
|
project.git_add(paths=all_paths_to_add, noop=opts.noop)
|
|
687
712
|
if commit_changes:
|
|
@@ -697,13 +722,14 @@ def version( # noqa: C901
|
|
|
697
722
|
)
|
|
698
723
|
except GitCommitEmptyIndexError:
|
|
699
724
|
logger.info("No local changes to add to any commit, skipping")
|
|
725
|
+
commit_changes = False
|
|
700
726
|
|
|
701
727
|
# Tag the version after potentially creating a new HEAD commit.
|
|
702
728
|
# This way if no source code is modified, i.e. all metadata updates
|
|
703
729
|
# are disabled, and the changelog generation is disabled or it's not
|
|
704
730
|
# modified, then the HEAD commit will be tagged as a release commit
|
|
705
731
|
# despite not being made by PSR
|
|
706
|
-
if
|
|
732
|
+
if create_tag:
|
|
707
733
|
project.git_tag(
|
|
708
734
|
tag_name=new_version.as_tag(),
|
|
709
735
|
message=new_version.as_tag(),
|
|
@@ -720,6 +746,33 @@ def version( # noqa: C901
|
|
|
720
746
|
)
|
|
721
747
|
|
|
722
748
|
if commit_changes:
|
|
749
|
+
# Verify that the upstream branch has not changed before pushing
|
|
750
|
+
# This prevents conflicts if another commit was pushed while we were preparing the release
|
|
751
|
+
# We check HEAD~1 because we just made a release commit
|
|
752
|
+
try:
|
|
753
|
+
project.verify_upstream_unchanged(
|
|
754
|
+
local_ref="HEAD~1",
|
|
755
|
+
upstream_ref=config.remote.name,
|
|
756
|
+
noop=opts.noop,
|
|
757
|
+
)
|
|
758
|
+
except UpstreamBranchChangedError as exc:
|
|
759
|
+
click.echo(str(exc), err=True)
|
|
760
|
+
click.echo(
|
|
761
|
+
"Upstream branch has changed. Please pull the latest changes and try again.",
|
|
762
|
+
err=True,
|
|
763
|
+
)
|
|
764
|
+
ctx.exit(1)
|
|
765
|
+
except (
|
|
766
|
+
DetachedHeadGitError,
|
|
767
|
+
GitCommandError,
|
|
768
|
+
UnknownUpstreamBranchError,
|
|
769
|
+
GitFetchError,
|
|
770
|
+
LocalGitError,
|
|
771
|
+
) as exc:
|
|
772
|
+
click.echo(str(exc), err=True)
|
|
773
|
+
click.echo("Unable to verify upstream due to error!", err=True)
|
|
774
|
+
ctx.exit(1)
|
|
775
|
+
|
|
723
776
|
# TODO: integrate into push branch
|
|
724
777
|
with Repo(str(runtime.repo_dir)) as git_repo:
|
|
725
778
|
active_branch = git_repo.active_branch.name
|
|
@@ -737,6 +790,27 @@ def version( # noqa: C901
|
|
|
737
790
|
tag=new_version.as_tag(),
|
|
738
791
|
noop=opts.noop,
|
|
739
792
|
)
|
|
793
|
+
# Create or update partial tags for releases
|
|
794
|
+
if add_partial_tags and not prerelease:
|
|
795
|
+
partial_tags = [new_version.as_major_tag(), new_version.as_minor_tag()]
|
|
796
|
+
# If build metadata is set, also retag the version without the metadata
|
|
797
|
+
if build_metadata:
|
|
798
|
+
partial_tags.append(new_version.as_patch_tag())
|
|
799
|
+
|
|
800
|
+
for partial_tag in partial_tags:
|
|
801
|
+
project.git_tag(
|
|
802
|
+
tag_name=partial_tag,
|
|
803
|
+
message=f"{partial_tag} => {new_version.as_tag()}",
|
|
804
|
+
isotimestamp=commit_date.isoformat(),
|
|
805
|
+
noop=opts.noop,
|
|
806
|
+
force=True,
|
|
807
|
+
)
|
|
808
|
+
project.git_push_tag(
|
|
809
|
+
remote_url=remote_url,
|
|
810
|
+
tag=partial_tag,
|
|
811
|
+
noop=opts.noop,
|
|
812
|
+
force=True,
|
|
813
|
+
)
|
|
740
814
|
|
|
741
815
|
# Update GitHub Actions output value now that release has occurred
|
|
742
816
|
gha_output.released = True
|
semantic_release/cli/config.py
CHANGED
|
@@ -39,6 +39,7 @@ from semantic_release.cli.masking_filter import MaskingFilter
|
|
|
39
39
|
from semantic_release.commit_parser import (
|
|
40
40
|
AngularCommitParser,
|
|
41
41
|
CommitParser,
|
|
42
|
+
ConventionalCommitMonorepoParser,
|
|
42
43
|
ConventionalCommitParser,
|
|
43
44
|
EmojiCommitParser,
|
|
44
45
|
ParseResult,
|
|
@@ -71,9 +72,10 @@ class HvcsClient(str, Enum):
|
|
|
71
72
|
GITEA = "gitea"
|
|
72
73
|
|
|
73
74
|
|
|
74
|
-
_known_commit_parsers:
|
|
75
|
-
"conventional": ConventionalCommitParser,
|
|
75
|
+
_known_commit_parsers: dict[str, type[CommitParser[Any, Any]]] = {
|
|
76
76
|
"angular": AngularCommitParser,
|
|
77
|
+
"conventional": ConventionalCommitParser,
|
|
78
|
+
"conventional-monorepo": ConventionalCommitMonorepoParser,
|
|
77
79
|
"emoji": EmojiCommitParser,
|
|
78
80
|
"scipy": ScipyCommitParser,
|
|
79
81
|
"tag": TagCommitParser,
|
|
@@ -364,6 +366,7 @@ class RawConfig(BaseModel):
|
|
|
364
366
|
remote: RemoteConfig = RemoteConfig()
|
|
365
367
|
no_git_verify: bool = False
|
|
366
368
|
tag_format: str = "v{version}"
|
|
369
|
+
add_partial_tags: bool = False
|
|
367
370
|
publish: PublishConfig = PublishConfig()
|
|
368
371
|
version_toml: Optional[Tuple[str, ...]] = None
|
|
369
372
|
version_variables: Optional[Tuple[str, ...]] = None
|
|
@@ -825,7 +828,9 @@ class RuntimeContext:
|
|
|
825
828
|
|
|
826
829
|
# version_translator
|
|
827
830
|
version_translator = VersionTranslator(
|
|
828
|
-
tag_format=raw.tag_format,
|
|
831
|
+
tag_format=raw.tag_format,
|
|
832
|
+
prerelease_token=branch_config.prerelease_token,
|
|
833
|
+
add_partial_tags=raw.add_partial_tags,
|
|
829
834
|
)
|
|
830
835
|
|
|
831
836
|
build_cmd_env = {}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
|
+
from enum import Enum
|
|
4
5
|
from re import compile as regexp
|
|
5
6
|
from typing import TYPE_CHECKING
|
|
6
7
|
|
|
@@ -13,12 +14,18 @@ if TYPE_CHECKING:
|
|
|
13
14
|
from semantic_release.hvcs.github import Github
|
|
14
15
|
|
|
15
16
|
|
|
17
|
+
class PersistenceMode(Enum):
|
|
18
|
+
TEMPORARY = "temporary"
|
|
19
|
+
PERMANENT = "permanent"
|
|
20
|
+
|
|
21
|
+
|
|
16
22
|
class VersionGitHubActionsOutput:
|
|
17
23
|
OUTPUT_ENV_VAR = "GITHUB_OUTPUT"
|
|
18
24
|
|
|
19
25
|
def __init__(
|
|
20
26
|
self,
|
|
21
|
-
gh_client: Github,
|
|
27
|
+
gh_client: Github | None = None,
|
|
28
|
+
mode: PersistenceMode = PersistenceMode.PERMANENT,
|
|
22
29
|
released: bool | None = None,
|
|
23
30
|
version: Version | None = None,
|
|
24
31
|
commit_sha: str | None = None,
|
|
@@ -26,6 +33,7 @@ class VersionGitHubActionsOutput:
|
|
|
26
33
|
prev_version: Version | None = None,
|
|
27
34
|
) -> None:
|
|
28
35
|
self._gh_client = gh_client
|
|
36
|
+
self._mode = mode
|
|
29
37
|
self._released = released
|
|
30
38
|
self._version = version
|
|
31
39
|
self._commit_sha = commit_sha
|
|
@@ -98,16 +106,23 @@ class VersionGitHubActionsOutput:
|
|
|
98
106
|
raise TypeError("output 'prev_version' should be a Version")
|
|
99
107
|
self._prev_version = value
|
|
100
108
|
|
|
109
|
+
@property
|
|
110
|
+
def gh_client(self) -> Github:
|
|
111
|
+
if not self._gh_client:
|
|
112
|
+
raise ValueError("GitHub client not set, cannot create links")
|
|
113
|
+
return self._gh_client
|
|
114
|
+
|
|
101
115
|
def to_output_text(self) -> str:
|
|
102
116
|
missing: set[str] = set()
|
|
103
117
|
if self.version is None:
|
|
104
118
|
missing.add("version")
|
|
105
119
|
if self.released is None:
|
|
106
120
|
missing.add("released")
|
|
107
|
-
if self.released
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
121
|
+
if self.released:
|
|
122
|
+
if self.release_notes is None:
|
|
123
|
+
missing.add("release_notes")
|
|
124
|
+
if self._mode is PersistenceMode.PERMANENT and self.commit_sha is None:
|
|
125
|
+
missing.add("commit_sha")
|
|
111
126
|
|
|
112
127
|
if missing:
|
|
113
128
|
raise ValueError(
|
|
@@ -119,7 +134,7 @@ class VersionGitHubActionsOutput:
|
|
|
119
134
|
"version": str(self.version),
|
|
120
135
|
"tag": self.tag,
|
|
121
136
|
"is_prerelease": str(self.is_prerelease).lower(),
|
|
122
|
-
"link": self.
|
|
137
|
+
"link": self.gh_client.create_release_url(self.tag) if self.tag else "",
|
|
123
138
|
"previous_version": str(self.prev_version) if self.prev_version else "",
|
|
124
139
|
"commit_sha": self.commit_sha if self.commit_sha else "",
|
|
125
140
|
}
|
|
@@ -62,9 +62,7 @@ class MaskingFilter(LoggingFilter):
|
|
|
62
62
|
|
|
63
63
|
def mask(self, msg: str) -> str:
|
|
64
64
|
if not isinstance(msg, str):
|
|
65
|
-
logger.debug(
|
|
66
|
-
"cannot mask object of type %s", type(msg)
|
|
67
|
-
)
|
|
65
|
+
logger.debug("cannot mask object of type %s", type(msg))
|
|
68
66
|
return msg
|
|
69
67
|
for mask, values in self._redact_patterns.items():
|
|
70
68
|
repl_string = (
|
|
@@ -7,6 +7,8 @@ from semantic_release.commit_parser.angular import (
|
|
|
7
7
|
AngularParserOptions,
|
|
8
8
|
)
|
|
9
9
|
from semantic_release.commit_parser.conventional import (
|
|
10
|
+
ConventionalCommitMonorepoParser,
|
|
11
|
+
ConventionalCommitMonorepoParserOptions,
|
|
10
12
|
ConventionalCommitParser,
|
|
11
13
|
ConventionalCommitParserOptions,
|
|
12
14
|
)
|
|
@@ -28,3 +30,24 @@ from semantic_release.commit_parser.token import (
|
|
|
28
30
|
ParseResult,
|
|
29
31
|
ParseResultType,
|
|
30
32
|
)
|
|
33
|
+
|
|
34
|
+
__all__ = [
|
|
35
|
+
"CommitParser",
|
|
36
|
+
"ParserOptions",
|
|
37
|
+
"AngularCommitParser",
|
|
38
|
+
"AngularParserOptions",
|
|
39
|
+
"ConventionalCommitParser",
|
|
40
|
+
"ConventionalCommitParserOptions",
|
|
41
|
+
"ConventionalCommitMonorepoParser",
|
|
42
|
+
"ConventionalCommitMonorepoParserOptions",
|
|
43
|
+
"EmojiCommitParser",
|
|
44
|
+
"EmojiParserOptions",
|
|
45
|
+
"ScipyCommitParser",
|
|
46
|
+
"ScipyParserOptions",
|
|
47
|
+
"TagCommitParser",
|
|
48
|
+
"TagParserOptions",
|
|
49
|
+
"ParsedCommit",
|
|
50
|
+
"ParseError",
|
|
51
|
+
"ParseResult",
|
|
52
|
+
"ParseResultType",
|
|
53
|
+
]
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
from semantic_release.commit_parser.conventional.options import (
|
|
2
|
+
ConventionalCommitParserOptions,
|
|
3
|
+
)
|
|
4
|
+
from semantic_release.commit_parser.conventional.options_monorepo import (
|
|
5
|
+
ConventionalCommitMonorepoParserOptions,
|
|
6
|
+
)
|
|
7
|
+
from semantic_release.commit_parser.conventional.parser import ConventionalCommitParser
|
|
8
|
+
from semantic_release.commit_parser.conventional.parser_monorepo import (
|
|
9
|
+
ConventionalCommitMonorepoParser,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"ConventionalCommitParser",
|
|
14
|
+
"ConventionalCommitParserOptions",
|
|
15
|
+
"ConventionalCommitMonorepoParser",
|
|
16
|
+
"ConventionalCommitMonorepoParserOptions",
|
|
17
|
+
]
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from itertools import zip_longest
|
|
4
|
+
from typing import Tuple
|
|
5
|
+
|
|
6
|
+
from pydantic.dataclasses import dataclass
|
|
7
|
+
|
|
8
|
+
from semantic_release.commit_parser._base import ParserOptions
|
|
9
|
+
from semantic_release.enums import LevelBump
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass
|
|
13
|
+
class ConventionalCommitParserOptions(ParserOptions):
|
|
14
|
+
"""Options dataclass for the ConventionalCommitParser."""
|
|
15
|
+
|
|
16
|
+
minor_tags: Tuple[str, ...] = ("feat",)
|
|
17
|
+
"""Commit-type prefixes that should result in a minor release bump."""
|
|
18
|
+
|
|
19
|
+
patch_tags: Tuple[str, ...] = ("fix", "perf")
|
|
20
|
+
"""Commit-type prefixes that should result in a patch release bump."""
|
|
21
|
+
|
|
22
|
+
other_allowed_tags: Tuple[str, ...] = (
|
|
23
|
+
"build",
|
|
24
|
+
"chore",
|
|
25
|
+
"ci",
|
|
26
|
+
"docs",
|
|
27
|
+
"style",
|
|
28
|
+
"refactor",
|
|
29
|
+
"test",
|
|
30
|
+
)
|
|
31
|
+
"""Commit-type prefixes that are allowed but do not result in a version bump."""
|
|
32
|
+
|
|
33
|
+
allowed_tags: Tuple[str, ...] = (
|
|
34
|
+
*minor_tags,
|
|
35
|
+
*patch_tags,
|
|
36
|
+
*other_allowed_tags,
|
|
37
|
+
)
|
|
38
|
+
"""
|
|
39
|
+
All commit-type prefixes that are allowed.
|
|
40
|
+
|
|
41
|
+
These are used to identify a valid commit message. If a commit message does not start with
|
|
42
|
+
one of these prefixes, it will not be considered a valid commit message.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
default_bump_level: LevelBump = LevelBump.NO_RELEASE
|
|
46
|
+
"""The minimum bump level to apply to valid commit message."""
|
|
47
|
+
|
|
48
|
+
parse_squash_commits: bool = True
|
|
49
|
+
"""Toggle flag for whether or not to parse squash commits"""
|
|
50
|
+
|
|
51
|
+
ignore_merge_commits: bool = True
|
|
52
|
+
"""Toggle flag for whether or not to ignore merge commits"""
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def tag_to_level(self) -> dict[str, LevelBump]:
|
|
56
|
+
"""A mapping of commit tags to the level bump they should result in."""
|
|
57
|
+
return self._tag_to_level
|
|
58
|
+
|
|
59
|
+
def __post_init__(self) -> None:
|
|
60
|
+
self._tag_to_level: dict[str, LevelBump] = {
|
|
61
|
+
str(tag): level
|
|
62
|
+
for tag, level in [
|
|
63
|
+
# we have to do a type ignore as zip_longest provides a type that is not specific enough
|
|
64
|
+
# for our expected output. Due to the empty second array, we know the first is always longest
|
|
65
|
+
# and that means no values in the first entry of the tuples will ever be a LevelBump. We
|
|
66
|
+
# apply a str() to make mypy happy although it will never happen.
|
|
67
|
+
*zip_longest(self.allowed_tags, (), fillvalue=self.default_bump_level),
|
|
68
|
+
*zip_longest(self.patch_tags, (), fillvalue=LevelBump.PATCH),
|
|
69
|
+
*zip_longest(self.minor_tags, (), fillvalue=LevelBump.MINOR),
|
|
70
|
+
]
|
|
71
|
+
if "|" not in str(tag)
|
|
72
|
+
}
|