Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 26528eb

Browse filesBrowse files
authored
feat(config): enable default environment token per hvcs (python-semantic-release#774)
1 parent 38046d5 commit 26528eb
Copy full SHA for 26528eb

File tree

Expand file treeCollapse file tree

7 files changed

+72
-19
lines changed
Filter options
Expand file treeCollapse file tree

7 files changed

+72
-19
lines changed

‎semantic_release/cli/config.py

Copy file name to clipboardExpand all lines: semantic_release/cli/config.py
+29-19Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@
66
from dataclasses import dataclass
77
from enum import Enum
88
from pathlib import Path
9-
from typing import Any, ClassVar, Dict, List, Optional, Tuple, Union
9+
from typing import Any, ClassVar, Dict, List, Optional, Tuple, Type, Union
1010

1111
from git import Actor
1212
from git.repo.base import Repo
1313
from jinja2 import Environment
14-
from pydantic import BaseModel
14+
from pydantic import BaseModel, model_validator
1515
from typing_extensions import Literal
1616

17+
from semantic_release import hvcs
1718
from semantic_release.changelog import environment
1819
from semantic_release.cli.const import DEFAULT_CONFIG_FILE
1920
from semantic_release.cli.masking_filter import MaskingFilter
@@ -29,7 +30,6 @@
2930
from semantic_release.const import COMMIT_MESSAGE, DEFAULT_COMMIT_AUTHOR, SEMVER_REGEX
3031
from semantic_release.errors import InvalidConfiguration, NotAReleaseBranch
3132
from semantic_release.helpers import dynamic_import
32-
from semantic_release.hvcs import Gitea, Github, Gitlab, HvcsBase
3333
from semantic_release.version import VersionTranslator
3434
from semantic_release.version.declaration import (
3535
PatternVersionDeclaration,
@@ -46,6 +46,21 @@ class HvcsClient(str, Enum):
4646
GITEA = "gitea"
4747

4848

49+
_known_commit_parsers = {
50+
"angular": AngularCommitParser,
51+
"emoji": EmojiCommitParser,
52+
"scipy": ScipyCommitParser,
53+
"tag": TagCommitParser,
54+
}
55+
56+
57+
_known_hvcs: Dict[HvcsClient, Type[hvcs.HvcsBase]] = {
58+
HvcsClient.GITHUB: hvcs.Github,
59+
HvcsClient.GITLAB: hvcs.Gitlab,
60+
HvcsClient.GITEA: hvcs.Gitea,
61+
}
62+
63+
4964
class EnvConfigVar(BaseModel):
5065
env: str
5166
default: Optional[str] = None
@@ -90,13 +105,22 @@ class BranchConfig(BaseModel):
90105

91106
class RemoteConfig(BaseModel):
92107
name: str = "origin"
93-
token: MaybeFromEnv = EnvConfigVar(env="GH_TOKEN")
108+
token: MaybeFromEnv = ""
94109
url: Optional[MaybeFromEnv] = None
95110
type: HvcsClient = HvcsClient.GITHUB
96111
domain: Optional[str] = None
97112
api_domain: Optional[str] = None
98113
ignore_token_for_push: bool = False
99114

115+
@model_validator(mode="after")
116+
def set_default_token(self) -> "RemoteConfig":
117+
# Set the default token name for the given VCS when no user input is given
118+
if not self.token and self.type in _known_hvcs:
119+
default_token_name = _known_hvcs[self.type].DEFAULT_ENV_TOKEN_NAME
120+
if default_token_name:
121+
self.token = EnvConfigVar(env=default_token_name)
122+
return self
123+
100124

101125
class PublishConfig(BaseModel):
102126
dist_glob_patterns: Tuple[str, ...] = ("dist/*",)
@@ -172,20 +196,6 @@ def _recursive_getattr(obj: Any, path: str) -> Any:
172196
return out
173197

174198

175-
_known_commit_parsers = {
176-
"angular": AngularCommitParser,
177-
"emoji": EmojiCommitParser,
178-
"scipy": ScipyCommitParser,
179-
"tag": TagCommitParser,
180-
}
181-
182-
_known_hvcs = {
183-
HvcsClient.GITHUB: Github,
184-
HvcsClient.GITLAB: Gitlab,
185-
HvcsClient.GITEA: Gitea,
186-
}
187-
188-
189199
@dataclass
190200
class RuntimeContext:
191201
_mask_attrs_: ClassVar[List[str]] = ["hvcs_client.token"]
@@ -200,7 +210,7 @@ class RuntimeContext:
200210
commit_message: str
201211
changelog_excluded_commit_patterns: Tuple[re.Pattern[str], ...]
202212
version_declarations: Tuple[VersionDeclarationABC, ...]
203-
hvcs_client: HvcsBase
213+
hvcs_client: hvcs.HvcsBase
204214
changelog_file: Path
205215
ignore_token_for_push: bool
206216
template_environment: Environment

‎semantic_release/hvcs/__init__.py

Copy file name to clipboardExpand all lines: semantic_release/hvcs/__init__.py
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@
33
from semantic_release.hvcs.github import Github
44
from semantic_release.hvcs.gitlab import Gitlab
55
from semantic_release.hvcs.token_auth import TokenAuth
6+
7+
__all__ = ["Gitea", "Github", "Gitlab", "HvcsBase", "TokenAuth"]

‎semantic_release/hvcs/_base.py

Copy file name to clipboardExpand all lines: semantic_release/hvcs/_base.py
+2Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ class HvcsBase:
3333
checking for NotImplemented around every method call.
3434
"""
3535

36+
DEFAULT_ENV_TOKEN_NAME = "HVCS_TOKEN"
37+
3638
def __init__(
3739
self,
3840
remote_url: str,

‎semantic_release/hvcs/gitea.py

Copy file name to clipboardExpand all lines: semantic_release/hvcs/gitea.py
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class Gitea(HvcsBase):
3636
DEFAULT_DOMAIN = "gitea.com"
3737
DEFAULT_API_PATH = "/api/v1"
3838
DEFAULT_API_DOMAIN = f"{DEFAULT_DOMAIN}{DEFAULT_API_PATH}"
39+
DEFAULT_ENV_TOKEN_NAME = "GITEA_TOKEN"
3940

4041
# pylint: disable=super-init-not-called
4142
def __init__(

‎semantic_release/hvcs/github.py

Copy file name to clipboardExpand all lines: semantic_release/hvcs/github.py
+1Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class Github(HvcsBase):
3737
DEFAULT_DOMAIN = "github.com"
3838
DEFAULT_API_DOMAIN = "api.github.com"
3939
DEFAULT_UPLOAD_DOMAIN = "uploads.github.com"
40+
DEFAULT_ENV_TOKEN_NAME = "GH_TOKEN"
4041

4142
def __init__(
4243
self,

‎semantic_release/hvcs/gitlab.py

Copy file name to clipboardExpand all lines: semantic_release/hvcs/gitlab.py
+4Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ class Gitlab(HvcsBase):
3838
API domain
3939
"""
4040

41+
DEFAULT_ENV_TOKEN_NAME = "GITLAB_TOKEN"
42+
# purposefully not CI_JOB_TOKEN as it is not a personal access token,
43+
# It is missing the permission to push to the repository, but has all others (releases, packages, etc.)
44+
4145
DEFAULT_DOMAIN = "gitlab.com"
4246

4347
def __init__(

‎tests/unit/semantic_release/cli/test_config.py

Copy file name to clipboardExpand all lines: tests/unit/semantic_release/cli/test_config.py
+33Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,48 @@
1+
from __future__ import annotations
2+
3+
from typing import TYPE_CHECKING
14
from unittest import mock
25

36
import pytest
47
import tomlkit
8+
from pydantic import ValidationError
59

610
from semantic_release.cli.config import (
11+
EnvConfigVar,
712
GlobalCommandLineOptions,
13+
HvcsClient,
814
RawConfig,
915
RuntimeContext,
1016
)
1117
from semantic_release.const import DEFAULT_COMMIT_AUTHOR
1218

19+
if TYPE_CHECKING:
20+
from typing import Any
21+
22+
23+
@pytest.mark.parametrize("remote_config, expected_token", [
24+
({ "type": HvcsClient.GITHUB.value }, EnvConfigVar(env="GH_TOKEN")),
25+
({ "type": HvcsClient.GITLAB.value }, EnvConfigVar(env="GITLAB_TOKEN")),
26+
({ "type": HvcsClient.GITEA.value }, EnvConfigVar(env="GITEA_TOKEN")),
27+
({}, EnvConfigVar(env="GH_TOKEN")), # default not provided -> means Github
28+
])
29+
def test_load_hvcs_default_token(remote_config: dict[str, Any], expected_token):
30+
raw_config = RawConfig.model_validate({
31+
"remote": remote_config,
32+
})
33+
assert expected_token == raw_config.remote.token
34+
35+
36+
@pytest.mark.parametrize("remote_config", [
37+
{ "type": "nonexistent" }
38+
])
39+
def test_invalid_hvcs_type(remote_config: dict[str, Any]):
40+
with pytest.raises(ValidationError) as excinfo:
41+
RawConfig.model_validate({
42+
"remote": remote_config,
43+
})
44+
assert "remote.type" in str(excinfo.value)
45+
1346

1447
def test_default_toml_config_valid(example_project):
1548
default_config_file = example_project / "default.toml"

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.