python-semantic-release 9.2.1__py3-none-any.whl → 9.2.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-semantic-release
3
- Version: 9.2.1
3
+ Version: 9.2.2
4
4
  Summary: Automatic Semantic Versioning for Python projects
5
5
  Author-email: Rolf Erik Lekang <me@rolflekang.com>
6
6
  License: MIT
@@ -1,4 +1,4 @@
1
- semantic_release/__init__.py,sha256=bJVwtLvzG4msFOn0HdwAXWwB5EwPQ3I39rraXXrlhw0,870
1
+ semantic_release/__init__.py,sha256=UY60uqsKwT97THCS1FDDtGpgKytMBM6Hi3uMAfzJrLI,870
2
2
  semantic_release/__main__.py,sha256=vXOARLV7KHeVXgpOMU0Q-8wovpdsOrtTsycxulI5xIE,106
3
3
  semantic_release/const.py,sha256=Z1o2QNh60wSLeF-_1TemMBjU3ZXbV0XghnUFsbTVfOs,831
4
4
  semantic_release/enums.py,sha256=D5B_reQGGKQQT22HO5PUtvn2Bok3fkht6TfJtXkmAUg,1020
@@ -10,17 +10,18 @@ semantic_release/changelog/release_history.py,sha256=ShzZpxTjhxka6TMbzOzYzG3EuCH
10
10
  semantic_release/changelog/template.py,sha256=JqZcjdozM9-059Sa8PfiHxYNeyZFa0jxk_beyRLv5sU,4640
11
11
  semantic_release/cli/__init__.py,sha256=gwAYhZO-4TR0tKCkQ4GqutWsL--0CII2_dcbrElI4M4,419
12
12
  semantic_release/cli/common.py,sha256=cVQUI7Uaac_nJ7VEXuJ7Q9pVJpuMVRvE7bBl_i96g20,1439
13
- semantic_release/cli/config.py,sha256=eSNqPv5G-ta3OkD0Wd9p5s2_XbwGTI50YhpWElcahHs,15854
13
+ semantic_release/cli/config.py,sha256=lBkTlc2x4PkCj7aGJn6DahsF_LH7Fsy-5OiTW61wRzA,16070
14
14
  semantic_release/cli/const.py,sha256=S8oNNpSaKdZxcAs7PAKEjQHic0czoJBGd7XHo57FOzw,39
15
15
  semantic_release/cli/github_actions_output.py,sha256=stGWcuMtelY0qM2E_-IfofP6UvsQ6czsO7qpMfnRJI4,2102
16
16
  semantic_release/cli/masking_filter.py,sha256=DxqjiJyABlzwwwZ1r8JGQpb6QrF00StJFm0-2-s5Fv0,3071
17
17
  semantic_release/cli/util.py,sha256=FyXaBkeL7nXKjy3X9rQLEwvn7p46xPekp2V8Z-5MVrk,3755
18
18
  semantic_release/cli/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
- semantic_release/cli/commands/changelog.py,sha256=vIJKTy8vPh7xGzJ3jEz-1z9evuJrHVg-Wqmms-c6G_k,4040
20
- semantic_release/cli/commands/generate_config.py,sha256=BwtwFhh80bkOUUNnR2ArC51YfPKI_y4HMD7C1oAFREA,1695
21
- semantic_release/cli/commands/main.py,sha256=LBbHbDNIctb35bUQsklefXVPN9bhY-LlrQFF1nNTMLg,5049
22
- semantic_release/cli/commands/publish.py,sha256=CvhZ4Z8CTPS-4f7kWH-xJ5JTk3jlJ-p8Mg7y2KC4SnY,1492
23
- semantic_release/cli/commands/version.py,sha256=lFXRUPM-amJaRNSaneV5olrf6UEYN_mCeBN_y7jGssk,22416
19
+ semantic_release/cli/commands/changelog.py,sha256=Tk9DprnY9mDQXSE1krQd8oILn3W6dKN_stWx9EbLjhU,4087
20
+ semantic_release/cli/commands/cli_context.py,sha256=fOLTUKb4UnZGQ6zVhftuvdfZ7fK7bDDIvj7Ud5yU98c,3443
21
+ semantic_release/cli/commands/generate_config.py,sha256=2xZOu3NpyhBp0pWr7d8ugKl_kjqQgpSsSMHq5wHTfrE,1699
22
+ semantic_release/cli/commands/main.py,sha256=LuL-O0LGonI5fQTZn0AUtYv2Ei_CYyNqYHMF_wN4InI,2900
23
+ semantic_release/cli/commands/publish.py,sha256=_pz7rKx65tCH7J2uyWiBghQ61MmmIbxhF9bE4AkE0N8,1703
24
+ semantic_release/cli/commands/version.py,sha256=1YfdvAkaammmgVRCFcGPujM2fNUvl5DN8xL3utGOzKE,22461
24
25
  semantic_release/commit_parser/__init__.py,sha256=cv5HFBdw7OJd4Laj4Ex8ZZ5Tml8GwXgQcXW6Pasr2Ao,615
25
26
  semantic_release/commit_parser/_base.py,sha256=aDS0dhFosT5i11tA5Ez8BTeikk6jwXjSEpJnJC5D2cs,2609
26
27
  semantic_release/commit_parser/angular.py,sha256=bS7Wrzpg_6zFil5Y4GIZkeGDPhvWQdTlFdWTtGVcpp0,4393
@@ -44,10 +45,10 @@ semantic_release/version/algorithm.py,sha256=K9WkPRur0x5baXsqEi8kvaDfxduG4WNUiAL
44
45
  semantic_release/version/declaration.py,sha256=f6Ld7hIhrqvDrRBapJHr-KDimuyo-4IG8009Zu9BIgU,7357
45
46
  semantic_release/version/translator.py,sha256=P1noIsVBn8u6zNOFjG0xKYOWapxqf_PHSMvMeLJ9kXg,3050
46
47
  semantic_release/version/version.py,sha256=6PCtSbLP88U1daoxnCwHc--YguZo4waGNLqJ5JfeczE,14175
47
- python_semantic_release-9.2.1.dist-info/AUTHORS.rst,sha256=XOReVvpymEFUPsS2QPH97jlfJBVrxwS2eu8-jVAe4gk,230
48
- python_semantic_release-9.2.1.dist-info/LICENSE,sha256=NE85nszX252sdQdu0xgS9qwfYES0k8qS6gW3uO4jRGE,1083
49
- python_semantic_release-9.2.1.dist-info/METADATA,sha256=thUtW1xFlJYtbob07qyQU4AIoWpAyyrDdCMYTHP80_k,5365
50
- python_semantic_release-9.2.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
51
- python_semantic_release-9.2.1.dist-info/entry_points.txt,sha256=qojUBx_Ywf4u7KgP6NWlDaBDymZVUGQ7m5wF2duC2F0,95
52
- python_semantic_release-9.2.1.dist-info/top_level.txt,sha256=qYA24nyg3eP-ti5UW7Vuj2aXVmM0wqVHx4mREdRZNAA,17
53
- python_semantic_release-9.2.1.dist-info/RECORD,,
48
+ python_semantic_release-9.2.2.dist-info/AUTHORS.rst,sha256=XOReVvpymEFUPsS2QPH97jlfJBVrxwS2eu8-jVAe4gk,230
49
+ python_semantic_release-9.2.2.dist-info/LICENSE,sha256=NE85nszX252sdQdu0xgS9qwfYES0k8qS6gW3uO4jRGE,1083
50
+ python_semantic_release-9.2.2.dist-info/METADATA,sha256=b41gxhINO5-3krE8YC0-_sQSa8G4L5zFuOlMd9Rsd0A,5365
51
+ python_semantic_release-9.2.2.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
52
+ python_semantic_release-9.2.2.dist-info/entry_points.txt,sha256=qojUBx_Ywf4u7KgP6NWlDaBDymZVUGQ7m5wF2duC2F0,95
53
+ python_semantic_release-9.2.2.dist-info/top_level.txt,sha256=qYA24nyg3eP-ti5UW7Vuj2aXVmM0wqVHx4mREdRZNAA,17
54
+ python_semantic_release-9.2.2.dist-info/RECORD,,
@@ -24,7 +24,7 @@ from semantic_release.version import (
24
24
  tags_and_versions,
25
25
  )
26
26
 
27
- __version__ = "9.2.1"
27
+ __version__ = "9.2.2"
28
28
 
29
29
 
30
30
  def setup_hook(argv: list[str]) -> None:
@@ -16,7 +16,7 @@ from semantic_release.cli.common import (
16
16
  from semantic_release.cli.util import noop_report
17
17
 
18
18
  if TYPE_CHECKING:
19
- from semantic_release.cli.config import RuntimeContext
19
+ from semantic_release.cli.commands.cli_context import CliContextObj
20
20
  from semantic_release.version import Version
21
21
 
22
22
  log = logging.getLogger(__name__)
@@ -34,10 +34,11 @@ log = logging.getLogger(__name__)
34
34
  default=None,
35
35
  help="Post the generated release notes to the remote VCS's release for this tag",
36
36
  )
37
- @click.pass_context
38
- def changelog(ctx: click.Context, release_tag: str | None = None) -> None:
37
+ @click.pass_obj
38
+ def changelog(cli_ctx: CliContextObj, release_tag: str | None = None) -> None:
39
39
  """Generate and optionally publish a changelog for your project"""
40
- runtime: RuntimeContext = ctx.obj
40
+ ctx = click.get_current_context()
41
+ runtime = cli_ctx.runtime_ctx
41
42
  repo = runtime.repo
42
43
  parser = runtime.commit_parser
43
44
  translator = runtime.version_translator
@@ -0,0 +1,100 @@
1
+ from __future__ import annotations
2
+
3
+ import logging
4
+ from pathlib import Path
5
+ from typing import TYPE_CHECKING
6
+
7
+ import click
8
+ from click.core import ParameterSource
9
+ from git import InvalidGitRepositoryError
10
+ from pydantic import ValidationError
11
+
12
+ from semantic_release.cli.config import (
13
+ RawConfig,
14
+ RuntimeContext,
15
+ )
16
+ from semantic_release.cli.util import load_raw_config_file, rprint
17
+ from semantic_release.errors import InvalidConfiguration, NotAReleaseBranch
18
+
19
+ if TYPE_CHECKING:
20
+ from semantic_release.cli.config import GlobalCommandLineOptions
21
+
22
+ class CliContext(click.Context):
23
+ obj: CliContextObj
24
+
25
+
26
+ class CliContextObj:
27
+ def __init__(
28
+ self,
29
+ ctx: click.Context,
30
+ logger: logging.Logger,
31
+ global_opts: GlobalCommandLineOptions,
32
+ ) -> None:
33
+ self._runtime_ctx: RuntimeContext | None = None
34
+ self.ctx = ctx
35
+ self.logger = logger
36
+ self.global_opts = global_opts
37
+
38
+ @property
39
+ def runtime_ctx(self) -> RuntimeContext:
40
+ """
41
+ Lazy load the runtime context. This is done to avoid configuration loading when
42
+ the command is not run. This is useful for commands like `--help` and `--version`
43
+ """
44
+ if self._runtime_ctx is None:
45
+ self._runtime_ctx = self._init_runtime_ctx()
46
+ return self._runtime_ctx
47
+
48
+ def _init_runtime_ctx(self) -> RuntimeContext:
49
+ config_path = Path(self.global_opts.config_file)
50
+ conf_file_exists = config_path.exists()
51
+ was_conf_file_user_provided = bool(
52
+ self.ctx.get_parameter_source("config_file")
53
+ not in (
54
+ ParameterSource.DEFAULT,
55
+ ParameterSource.DEFAULT_MAP,
56
+ )
57
+ )
58
+
59
+ try:
60
+ if was_conf_file_user_provided and not conf_file_exists:
61
+ raise FileNotFoundError(
62
+ f"File {self.global_opts.config_file} does not exist"
63
+ )
64
+
65
+ config_obj = (
66
+ {} if not conf_file_exists else load_raw_config_file(config_path)
67
+ )
68
+ if not config_obj:
69
+ self.logger.info(
70
+ "configuration empty, falling back to default configuration"
71
+ )
72
+
73
+ raw_config = RawConfig.model_validate(config_obj)
74
+ runtime = RuntimeContext.from_raw_config(
75
+ raw_config,
76
+ global_cli_options=self.global_opts,
77
+ )
78
+ except NotAReleaseBranch as exc:
79
+ rprint(f"[bold {'red' if self.global_opts.strict else 'orange1'}]{exc!s}")
80
+ # If not strict, exit 0 so other processes can continue. For example, in
81
+ # multibranch CI it might be desirable to run a non-release branch's pipeline
82
+ # without specifying conditional execution of PSR based on branch name
83
+ self.ctx.exit(2 if self.global_opts.strict else 0)
84
+ except FileNotFoundError as exc:
85
+ click.echo(str(exc), err=True)
86
+ self.ctx.exit(2)
87
+ except (
88
+ ValidationError,
89
+ InvalidConfiguration,
90
+ InvalidGitRepositoryError,
91
+ ) as exc:
92
+ click.echo(str(exc), err=True)
93
+ self.ctx.exit(1)
94
+
95
+ # This allows us to mask secrets in the logging
96
+ # by applying it to all the configured handlers
97
+ for handler in logging.getLogger().handlers:
98
+ handler.addFilter(runtime.masker)
99
+
100
+ return runtime
@@ -38,7 +38,7 @@ def generate_config(fmt: str = "toml", is_pyproject_toml: bool = False) -> None:
38
38
  your needs. For example, to append the default configuration to your pyproject.toml
39
39
  file, you can use the following command:
40
40
 
41
- semantic-release generate-config -f toml >> pyproject.toml
41
+ semantic-release generate-config --pyproject >> pyproject.toml
42
42
  """
43
43
  # due to possible IntEnum values (which are not supported by tomlkit.dumps, see sdispater/tomlkit#237),
44
44
  # we must ensure the transformation of the model to a dict uses json serializable values
@@ -1,26 +1,21 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import logging
4
- from pathlib import Path
5
4
 
5
+ # from typing import TYPE_CHECKING
6
6
  import click
7
- from click.core import ParameterSource
8
- from git import InvalidGitRepositoryError
9
- from git.repo.base import Repo
10
- from pydantic import ValidationError
11
7
  from rich.console import Console
12
8
  from rich.logging import RichHandler
13
9
 
14
10
  import semantic_release
15
- from semantic_release.cli.commands.generate_config import generate_config
16
- from semantic_release.cli.config import (
17
- GlobalCommandLineOptions,
18
- RawConfig,
19
- RuntimeContext,
20
- )
11
+ from semantic_release.cli.commands.cli_context import CliContextObj
12
+ from semantic_release.cli.config import GlobalCommandLineOptions
21
13
  from semantic_release.cli.const import DEFAULT_CONFIG_FILE
22
- from semantic_release.cli.util import load_raw_config_file, rprint
23
- from semantic_release.errors import InvalidConfiguration, NotAReleaseBranch
14
+ from semantic_release.cli.util import rprint
15
+
16
+ # if TYPE_CHECKING:
17
+ # pass
18
+
24
19
 
25
20
  FORMAT = "[%(name)s] %(levelname)s %(module)s.%(funcName)s: %(message)s"
26
21
 
@@ -94,19 +89,8 @@ def main(
94
89
  ],
95
90
  )
96
91
 
97
- log = logging.getLogger(__name__)
98
-
99
- if ctx.invoked_subcommand == generate_config.name:
100
- # generate-config doesn't require any of the usual setup,
101
- # so exit out early and delegate to it
102
- log.debug("Forwarding to %s", generate_config.name)
103
- return
104
-
105
- log.debug("logging level set to: %s", logging.getLevelName(log_level))
106
- try:
107
- repo = Repo(".", search_parent_directories=True)
108
- except InvalidGitRepositoryError:
109
- ctx.fail("Not in a valid Git repository")
92
+ logger = logging.getLogger(__name__)
93
+ logger.debug("logging level set to: %s", logging.getLevelName(log_level))
110
94
 
111
95
  if noop:
112
96
  rprint(
@@ -115,51 +99,9 @@ def main(
115
99
  )
116
100
 
117
101
  cli_options = GlobalCommandLineOptions(
118
- noop=noop,
119
- verbosity=verbosity,
120
- config_file=config_file,
121
- strict=strict,
102
+ noop=noop, verbosity=verbosity, config_file=config_file, strict=strict
122
103
  )
123
- log.debug("global cli options: %s", cli_options)
124
-
125
- config_path = Path(config_file)
126
- # default no config loaded
127
- config_text = {}
128
- if not config_path.exists():
129
- if ctx.get_parameter_source("config_file") not in (
130
- ParameterSource.DEFAULT,
131
- ParameterSource.DEFAULT_MAP,
132
- ):
133
- ctx.fail(f"File {config_file} does not exist")
134
-
135
- log.info(
136
- "configuration file %s not found, using default configuration",
137
- config_file,
138
- )
139
104
 
140
- else:
141
- try:
142
- config_text = load_raw_config_file(config_path)
143
- except InvalidConfiguration as exc:
144
- ctx.fail(str(exc))
105
+ logger.debug("global cli options: %s", cli_options)
145
106
 
146
- try:
147
- raw_config = RawConfig.model_validate(config_text)
148
- runtime = RuntimeContext.from_raw_config(
149
- raw_config, repo=repo, global_cli_options=cli_options
150
- )
151
- except NotAReleaseBranch as exc:
152
- rprint(f"[bold {'red' if strict else 'orange1'}]{exc!s}")
153
- # If not strict, exit 0 so other processes can continue. For example, in
154
- # multibranch CI it might be desirable to run a non-release branch's pipeline
155
- # without specifying conditional execution of PSR based on branch name
156
- ctx.exit(2 if strict else 0)
157
- except (ValidationError, InvalidConfiguration) as exc:
158
- click.echo(str(exc), err=True)
159
- ctx.exit(1)
160
- ctx.obj = runtime
161
-
162
- # This allows us to mask secrets in the logging
163
- # by applying it to all the configured handlers
164
- for handler in logging.getLogger().handlers:
165
- handler.addFilter(runtime.masker)
107
+ ctx.obj = CliContextObj(ctx, logger, cli_options)
@@ -1,10 +1,17 @@
1
+ from __future__ import annotations
2
+
1
3
  import logging
4
+ from typing import TYPE_CHECKING
2
5
 
3
6
  import click
4
7
 
5
8
  from semantic_release.cli.util import noop_report
6
9
  from semantic_release.version import tags_and_versions
7
10
 
11
+ if TYPE_CHECKING:
12
+ from semantic_release.cli.commands.cli_context import CliContextObj
13
+
14
+
8
15
  log = logging.getLogger(__name__)
9
16
 
10
17
 
@@ -20,10 +27,11 @@ log = logging.getLogger(__name__)
20
27
  help="The tag associated with the release to publish to",
21
28
  default="latest",
22
29
  )
23
- @click.pass_context
24
- def publish(ctx: click.Context, tag: str = "latest") -> None:
30
+ @click.pass_obj
31
+ def publish(cli_ctx: CliContextObj, tag: str = "latest") -> None:
25
32
  """Build and publish a distribution to a VCS release."""
26
- runtime = ctx.obj
33
+ ctx = click.get_current_context()
34
+ runtime = cli_ctx.runtime_ctx
27
35
  repo = runtime.repo
28
36
  hvcs_client = runtime.hvcs_client
29
37
  translator = runtime.version_translator
@@ -5,7 +5,7 @@ import os
5
5
  import subprocess
6
6
  from contextlib import nullcontext
7
7
  from datetime import datetime
8
- from typing import TYPE_CHECKING, ContextManager, Iterable
8
+ from typing import TYPE_CHECKING
9
9
 
10
10
  import click
11
11
  import shellingham # type: ignore[import]
@@ -28,10 +28,12 @@ from semantic_release.version import Version, next_version, tags_and_versions
28
28
  log = logging.getLogger(__name__)
29
29
 
30
30
  if TYPE_CHECKING: # pragma: no cover
31
+ from typing import ContextManager, Iterable
32
+
31
33
  from git import Repo
32
34
  from git.refs.tag import Tag
33
35
 
34
- from semantic_release.cli.config import RuntimeContext
36
+ from semantic_release.cli.commands.cli_context import CliContextObj
35
37
  from semantic_release.version import VersionTranslator
36
38
  from semantic_release.version.declaration import VersionDeclarationABC
37
39
 
@@ -213,9 +215,9 @@ def shell(cmd: str, *, check: bool = True) -> subprocess.CompletedProcess:
213
215
  is_flag=True,
214
216
  help="Skip building the current project",
215
217
  )
216
- @click.pass_context
218
+ @click.pass_obj
217
219
  def version( # noqa: C901
218
- ctx: click.Context,
220
+ cli_ctx: CliContextObj,
219
221
  print_only: bool = False,
220
222
  print_only_tag: bool = False,
221
223
  print_last_released: bool = False,
@@ -231,22 +233,27 @@ def version( # noqa: C901
231
233
  build_metadata: str | None = None,
232
234
  skip_build: bool = False,
233
235
  ) -> str:
234
- r"""
236
+ """
235
237
  Detect the semantically correct next version that should be applied to your
236
238
  project.
237
239
 
238
- \b
239
240
  By default:
240
- * Write this new version to the project metadata locations
241
- specified in the configuration file
242
- * Create a new commit with these locations and any other assets configured
243
- to be included in a release
244
- * Tag this commit according the configured format, with a tag that uniquely
245
- identifies the version being released.
246
- * Push the new tag and commit to the remote for the repository
247
- * Create a release (if supported) in the remote VCS for this tag
241
+
242
+ * Write this new version to the project metadata locations specified
243
+ in the configuration file
244
+
245
+ * Create a new commit with these locations and any other assets configured
246
+ to be included in a release
247
+
248
+ * Tag this commit according the configured format, with a tag that uniquely
249
+ identifies the version being released.
250
+
251
+ * Push the new tag and commit to the remote for the repository
252
+
253
+ * Create a release (if supported) in the remote VCS for this tag
248
254
  """
249
- runtime: RuntimeContext = ctx.obj
255
+ ctx = click.get_current_context()
256
+ runtime = cli_ctx.runtime_ctx
250
257
  repo = runtime.repo
251
258
  translator = runtime.version_translator
252
259
 
@@ -9,13 +9,13 @@ from enum import Enum
9
9
  from pathlib import Path
10
10
  from typing import Any, ClassVar, Dict, List, Literal, Optional, Tuple, Type, Union
11
11
 
12
- from git import Actor
12
+ from git import Actor, InvalidGitRepositoryError
13
13
  from git.repo.base import Repo
14
14
  from jinja2 import Environment
15
15
  from pydantic import BaseModel, Field, RootModel, ValidationError, model_validator
16
16
 
17
- # For Python 3.8 compatibility
18
- from typing_extensions import Annotated
17
+ # For Python 3.8, 3.9, 3.10 compatibility
18
+ from typing_extensions import Annotated, Self
19
19
 
20
20
  from semantic_release import hvcs
21
21
  from semantic_release.changelog import environment
@@ -119,7 +119,7 @@ class RemoteConfig(BaseModel):
119
119
  ignore_token_for_push: bool = False
120
120
 
121
121
  @model_validator(mode="after")
122
- def set_default_token(self) -> RemoteConfig:
122
+ def set_default_token(self) -> Self:
123
123
  # Set the default token name for the given VCS when no user input is given
124
124
  if not self.token and self.type in _known_hvcs:
125
125
  default_token_name = _known_hvcs[self.type].DEFAULT_ENV_TOKEN_NAME
@@ -155,7 +155,7 @@ class RawConfig(BaseModel):
155
155
  version_variables: Optional[Tuple[str, ...]] = None
156
156
 
157
157
  @model_validator(mode="after")
158
- def set_default_opts(self) -> RawConfig:
158
+ def set_default_opts(self) -> Self:
159
159
  # Set the default parser options for the given commit parser when no user input is given
160
160
  if not self.commit_parser_options and self.commit_parser:
161
161
  parser_opts_type = None
@@ -291,14 +291,17 @@ class RuntimeContext:
291
291
 
292
292
  @classmethod
293
293
  def from_raw_config(
294
- cls, raw: RawConfig, repo: Repo, global_cli_options: GlobalCommandLineOptions
294
+ cls, raw: RawConfig, global_cli_options: GlobalCommandLineOptions
295
295
  ) -> RuntimeContext:
296
296
  ##
297
297
  # credentials masking for logging
298
298
  masker = MaskingFilter(_use_named_masks=raw.logging_use_named_masks)
299
299
 
300
300
  try:
301
+ repo = Repo(".", search_parent_directories=True)
301
302
  active_branch = repo.active_branch.name
303
+ except InvalidGitRepositoryError as err:
304
+ raise InvalidGitRepositoryError("No valid git repository found!") from err
302
305
  except TypeError as err:
303
306
  raise NotAReleaseBranch(
304
307
  "Detached HEAD state cannot match any release groups; "