Skip to content

Commit a6ff904

Browse files
bjoernricksgreenbonebot
authored andcommitted
Add: Add --project-type to release create and all version CLI commands
Allow to define which project types to consider when reading and updating the version of a project. Valid project types are: - cargo - cmake - go - pyproject - java - npm
1 parent e6ee003 commit a6ff904

File tree

8 files changed

+167
-20
lines changed

8 files changed

+167
-20
lines changed

pontos/release/_parser.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
from pontos.enum import enum_choice, enum_type, to_choices
2020
from pontos.git._git import DEFAULT_TAG_PREFIX
21+
from pontos.version.commands import ProjectType
2122
from pontos.version.schemes import (
2223
VERSIONING_SCHEMES,
2324
PEP440VersioningScheme,
@@ -95,6 +96,13 @@ def add_create_parser(
9596
help="Optional last release version. Will be determined if not set.",
9697
type=str,
9798
)
99+
create_parser.add_argument(
100+
"--project-types",
101+
help="Project types to use for version information. Default is to consider all project types.",
102+
nargs="*",
103+
choices=enum_choice(ProjectType),
104+
type=enum_type(ProjectType),
105+
)
98106

99107
next_version_group = create_parser.add_mutually_exclusive_group()
100108

pontos/release/create.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from dataclasses import dataclass
88
from enum import IntEnum, auto
99
from pathlib import Path
10-
from typing import Literal, Optional, SupportsInt, Union
10+
from typing import Iterable, Literal, Optional, SupportsInt, Union
1111

1212
import httpx
1313

@@ -20,6 +20,7 @@
2020
from pontos.release.command import AsyncCommand
2121
from pontos.terminal import Terminal
2222
from pontos.version import Version, VersionError
23+
from pontos.version.commands import ProjectType
2324
from pontos.version.helper import get_last_release_version
2425
from pontos.version.project import Project
2526
from pontos.version.schemes import VersioningScheme
@@ -181,6 +182,7 @@ async def async_run( # type: ignore[override]
181182
update_project: bool = True,
182183
github_pre_release: bool = False,
183184
changelog: Optional[str] = None,
185+
project_types: Optional[Iterable[ProjectType]] = None,
184186
) -> CreateReleaseReturnValue:
185187
"""
186188
Create a release
@@ -217,6 +219,8 @@ async def async_run( # type: ignore[override]
217219
release
218220
changelog: An optional changelog. If not set a changelog will be
219221
gathered from the git commits since the last release.
222+
project_types: Project types to use for version information.
223+
Default is to consider all project types.
220224
"""
221225
self.git_tag_prefix = git_tag_prefix or ""
222226
self.repository = repository
@@ -274,7 +278,9 @@ async def async_run( # type: ignore[override]
274278

275279
if update_project:
276280
try:
277-
project = Project(versioning_scheme)
281+
project = Project(
282+
versioning_scheme, project_types=project_types
283+
)
278284
except PontosError as e:
279285
self.print_error(f"Unable to determine project settings. {e}")
280286
return CreateReleaseReturnValue.PROJECT_SETTINGS_NOT_FOUND
@@ -445,4 +451,5 @@ def create_release(
445451
update_project=args.update_project,
446452
github_pre_release=args.github_pre_release,
447453
changelog=changelog_file.read_text() if changelog_file else None,
454+
project_types=args.project_types,
448455
)

pontos/version/_main.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@ def main(args: Optional[List[str]] = None) -> NoReturn:
2727
parsed_args = parse_args(args)
2828

2929
try:
30-
project = Project(parsed_args.versioning_scheme)
30+
project = Project(
31+
parsed_args.versioning_scheme,
32+
project_types=parsed_args.project_types,
33+
)
3134
except PontosError:
3235
print("No project found.", file=sys.stderr)
3336
sys.exit(VersionExitCode.NO_PROJECT)

pontos/version/_parser.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88

99
import shtab
1010

11+
from pontos.enum import enum_choice, enum_type
1112
from pontos.errors import PontosError
13+
from pontos.version.commands import ProjectType
1214
from pontos.version.schemes import (
1315
VERSIONING_SCHEMES,
1416
VersioningScheme,
@@ -52,6 +54,13 @@ def initialize_default_parser() -> argparse.ArgumentParser:
5254
default="pep440",
5355
type=versioning_scheme_argument_type,
5456
)
57+
verify_parser.add_argument(
58+
"--project-types",
59+
help="Project types to use for version information. Default is to consider all project types.",
60+
nargs="*",
61+
choices=enum_choice(ProjectType),
62+
type=enum_type(ProjectType),
63+
)
5564

5665
show_parser = subparsers.add_parser(
5766
"show", help="Show version information of the current project"
@@ -64,6 +73,13 @@ def initialize_default_parser() -> argparse.ArgumentParser:
6473
default="pep440",
6574
type=versioning_scheme_argument_type,
6675
)
76+
show_parser.add_argument(
77+
"--project-types",
78+
help="Project types to use for version information. Default is to consider all project types.",
79+
nargs="*",
80+
choices=enum_choice(ProjectType),
81+
type=enum_type(ProjectType),
82+
)
6783

6884
update_parser = subparsers.add_parser(
6985
"update", help="Update version in the current project"
@@ -80,6 +96,13 @@ def initialize_default_parser() -> argparse.ArgumentParser:
8096
default="pep440",
8197
type=versioning_scheme_argument_type,
8298
)
99+
update_parser.add_argument(
100+
"--project-types",
101+
help="Project types to use for version information. Default is to consider all project types.",
102+
nargs="*",
103+
choices=enum_choice(ProjectType),
104+
type=enum_type(ProjectType),
105+
)
83106
update_parser.add_argument(
84107
"--force",
85108
help="Don't check if version is already set. "
@@ -112,6 +135,13 @@ def initialize_default_parser() -> argparse.ArgumentParser:
112135
default="pep440",
113136
type=versioning_scheme_argument_type,
114137
)
138+
next_parser.add_argument(
139+
"--project-types",
140+
help="Project types to use for version information. Default is to consider all project types.",
141+
nargs="*",
142+
choices=enum_choice(ProjectType),
143+
type=enum_type(ProjectType),
144+
)
115145
return parser
116146

117147

pontos/version/commands/__init__.py

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
# SPDX-License-Identifier: GPL-3.0-or-later
44
#
55

6-
from typing import Iterable, Tuple, Type
6+
from typing import Iterable, Optional, Type
7+
8+
from pontos.enum import StrEnum
79

810
from ._cargo import CargoVersionCommand
911
from ._cmake import CMakeVersionCommand
@@ -21,21 +23,36 @@
2123
"JavaVersionCommand",
2224
"PythonVersionCommand",
2325
"CargoVersionCommand",
26+
"ProjectType",
2427
"get_commands",
2528
)
2629

27-
__COMMANDS: Tuple[Type[VersionCommand]] = ( # type: ignore[assignment]
28-
CMakeVersionCommand,
29-
GoVersionCommand,
30-
JavaVersionCommand,
31-
JavaScriptVersionCommand,
32-
PythonVersionCommand,
33-
CargoVersionCommand,
34-
)
30+
31+
class ProjectType(StrEnum):
32+
CMAKE = "cmake"
33+
CARGO = "cargo"
34+
GO = "go"
35+
JAVA = "java"
36+
NPM = "npm"
37+
PYPROJECT = "pyproject"
38+
39+
40+
_COMMANDS: dict[ProjectType, Type[VersionCommand]] = {
41+
ProjectType.CMAKE: CMakeVersionCommand,
42+
ProjectType.CARGO: CargoVersionCommand,
43+
ProjectType.GO: GoVersionCommand,
44+
ProjectType.JAVA: JavaVersionCommand,
45+
ProjectType.NPM: JavaScriptVersionCommand,
46+
ProjectType.PYPROJECT: PythonVersionCommand,
47+
}
3548

3649

37-
def get_commands() -> Iterable[Type[VersionCommand]]:
50+
def get_commands(
51+
names: Optional[Iterable[ProjectType]] = None,
52+
) -> list[Type[VersionCommand]]:
3853
"""
3954
Returns the available VersionCommands
4055
"""
41-
return __COMMANDS
56+
if not names:
57+
return list(_COMMANDS.values())
58+
return [command for name, command in _COMMANDS.items() if name in names]

pontos/version/project.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44
#
55

66

7-
from typing import List, Literal, Type, Union
7+
from typing import Iterable, Literal, Optional, Type, Union
88

99
from ._errors import ProjectError
1010
from ._version import Version, VersionUpdate
11-
from .commands import VersionCommand, get_commands
11+
from .commands import ProjectType, VersionCommand, get_commands
1212
from .schemes import VersioningScheme
1313

1414
__all__ = ("Project",)
@@ -28,21 +28,28 @@ class Project:
2828
"""
2929

3030
def __init__(
31-
self, versioning_scheme: Union[VersioningScheme, Type[VersioningScheme]]
31+
self,
32+
versioning_scheme: Union[VersioningScheme, Type[VersioningScheme]],
33+
*,
34+
project_types: Optional[Iterable[ProjectType]] = None,
3235
) -> None:
3336
"""
3437
Creates a new project instance
3538
3639
Args:
3740
versioning_scheme: Scheme for version handling
41+
project_types: Project types to use for version information.
42+
Default is to consider all project types.
3843
3944
Raises:
4045
ProjectError: If no fitting VersionCommand could be found
4146
"""
4247
self._versioning_scheme = versioning_scheme
43-
self._commands = self._gather_commands()
48+
self._commands = self._gather_commands(project_types)
4449

45-
def _gather_commands(self) -> List[VersionCommand]:
50+
def _gather_commands(
51+
self, project_type: Optional[Iterable[ProjectType]]
52+
) -> list[VersionCommand]:
4653
"""
4754
Initialize the project with the fitting VersionCommands of the current
4855
working directory
@@ -51,7 +58,7 @@ def _gather_commands(self) -> List[VersionCommand]:
5158
ProjectError: If no fitting VersionCommand could be found
5259
"""
5360
commands = []
54-
for cmd in get_commands():
61+
for cmd in get_commands(project_type):
5562
command = cmd(versioning_scheme=self._versioning_scheme)
5663
if command.project_found():
5764
commands.append(command)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# SPDX-FileCopyrightText: 2023-2025 Greenbone AG
2+
#
3+
# SPDX-License-Identifier: GPL-3.0-or-later
4+
5+
import unittest
6+
7+
from pontos.version.commands import _COMMANDS, ProjectType, get_commands
8+
9+
10+
class GetCommandsTestCase(unittest.TestCase):
11+
def test_get_all_commands(self):
12+
commands = get_commands()
13+
self.assertEqual(set(commands), set(_COMMANDS.values()))
14+
15+
def test_get_specific_commands(self):
16+
selected_types = [ProjectType.CMAKE, ProjectType.JAVA]
17+
commands = get_commands(selected_types)
18+
self.assertEqual(
19+
set(commands),
20+
{_COMMANDS[ProjectType.CMAKE], _COMMANDS[ProjectType.JAVA]},
21+
)
22+
23+
def test_get_no_commands(self):
24+
from pontos.version.commands import get_commands
25+
26+
commands = get_commands([])
27+
self.assertEqual(set(commands), set(_COMMANDS.values()))

tests/version/test_project.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import unittest
77

88
from pontos.testing import temp_directory, temp_python_module
9+
from pontos.version.commands import ProjectType
910
from pontos.version.project import Project, ProjectError
1011
from pontos.version.schemes import PEP440VersioningScheme
1112

@@ -145,3 +146,50 @@ def test_all(self):
145146
self.assertEqual(update.new, new_version)
146147

147148
self.assertEqual(len(update.changed_files), 5)
149+
150+
def test_go_project_with_missing_go_project_type(self):
151+
current_version = PEP440VersioningScheme.parse_version("1.2.3")
152+
153+
with (
154+
temp_directory(change_into=True) as temp_dir,
155+
self.assertRaisesRegex(
156+
ProjectError, "No project settings file found"
157+
),
158+
):
159+
project_file = temp_dir / "go.mod"
160+
project_file.touch()
161+
version_file = temp_dir / "version.go"
162+
version_file.write_text(f'var version = "{current_version}"')
163+
164+
Project(
165+
PEP440VersioningScheme,
166+
project_types=[
167+
ProjectType.CMAKE,
168+
ProjectType.JAVA,
169+
ProjectType.NPM,
170+
ProjectType.PYPROJECT,
171+
ProjectType.CARGO,
172+
],
173+
)
174+
175+
def test_go_project_with_go_project_type(self):
176+
current_version = PEP440VersioningScheme.parse_version("1.2.3")
177+
new_version = PEP440VersioningScheme.parse_version("1.2.4")
178+
179+
with temp_directory(change_into=True) as temp_dir:
180+
project_file = temp_dir / "go.mod"
181+
project_file.touch()
182+
version_file = temp_dir / "version.go"
183+
version_file.write_text(f'var version = "{current_version}"')
184+
185+
project = Project(
186+
PEP440VersioningScheme, project_types=[ProjectType.GO]
187+
)
188+
self.assertEqual(project.get_current_version(), current_version)
189+
190+
update = project.update_version(new_version)
191+
192+
self.assertEqual(update.previous, current_version)
193+
self.assertEqual(update.new, new_version)
194+
195+
self.assertEqual(len(update.changed_files), 1)

0 commit comments

Comments
 (0)