Skip to content

Commit 4b29982

Browse files
committed
feat: add postrelease version
1 parent bc1542c commit 4b29982

16 files changed

+864
-198
lines changed

commitizen/cli.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,12 @@ def __call__(
263263
"help": "Specify non-negative integer for dev release.",
264264
"type": int,
265265
},
266+
{
267+
"name": ["--postrelease"],
268+
"action": "store_true",
269+
"default": False,
270+
"help": "Mark as a post release",
271+
},
266272
{
267273
"name": ["--increment"],
268274
"help": "Specify the desired increment.",

commitizen/commands/bump.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ class BumpArgs(Settings, total=False):
4646
changelog: bool
4747
check_consistency: bool
4848
devrelease: int | None
49+
postrelease: bool
4950
dry_run: bool
5051
file_name: str
5152
files_only: bool | None
@@ -167,6 +168,7 @@ def _validate_arguments(self, current_version: VersionProtocol) -> None:
167168
(self.arguments["increment"], "--increment"),
168169
(self.arguments["prerelease"], "--prerelease"),
169170
(self.arguments["devrelease"] is not None, "--devrelease"),
171+
(self.arguments["postrelease"], "--postrelease"),
170172
(self.arguments["local_version"], "--local-version"),
171173
(self.arguments["build_metadata"], "--build-metadata"),
172174
(self.arguments["major_version_zero"], "--major-version-zero"),
@@ -228,11 +230,15 @@ def _resolve_increment_and_new_version(
228230
if increment is None and self.arguments["allow_no_commit"]:
229231
increment = "PATCH"
230232

233+
if self.arguments["postrelease"]:
234+
increment = None
235+
231236
return increment, current_version.bump(
232237
increment,
233238
prerelease=self.arguments["prerelease"],
234239
prerelease_offset=self.bump_settings["prerelease_offset"],
235240
devrelease=self.arguments["devrelease"],
241+
postrelease=self.arguments["postrelease"],
236242
is_local_version=self.arguments["local_version"],
237243
build_metadata=self.arguments["build_metadata"],
238244
exact_increment=self.arguments["increment_mode"] == "exact",

commitizen/defaults.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ def get_tag_regexes(
158158
"patch": r"(?P<patch>\d+)",
159159
"prerelease": r"(?P<prerelease>\w+\d+)?",
160160
"devrelease": r"(?P<devrelease>\.dev\d+)?",
161+
"postrelease": r"(?P<postrelease>\.post\d+)?",
161162
}
162163
return {
163164
**{f"${k}": v for k, v in regexes.items()},

commitizen/version_schemes.py

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,16 @@ def prerelease(self) -> str | None:
7575
"""The prerelease potion of the version is this is a prerelease."""
7676
raise NotImplementedError("must be implemented")
7777

78+
@property
79+
def is_postrelease(self) -> bool:
80+
"""Whether this version is a post-release."""
81+
raise NotImplementedError("must be implemented")
82+
83+
@property
84+
def postrelease(self) -> str | None:
85+
"""The postrelease potion of the version is this is a postrelease."""
86+
raise NotImplementedError("must be implemented")
87+
7888
@property
7989
def public(self) -> str:
8090
"""The public portion of the version."""
@@ -124,6 +134,7 @@ def bump(
124134
prerelease: Prerelease | None = None,
125135
prerelease_offset: int = 0,
126136
devrelease: int | None = None,
137+
postrelease: bool = False,
127138
is_local_version: bool = False,
128139
build_metadata: str | None = None,
129140
exact_increment: bool = False,
@@ -164,6 +175,13 @@ def prerelease(self) -> str | None:
164175
return f"{self.pre[0]}{self.pre[1]}"
165176
return None
166177

178+
@property
179+
def postrelease(self) -> str | None:
180+
# version.post is needed for mypy check
181+
if self.is_postrelease and self.post is not None:
182+
return f"post{self.post}"
183+
return None
184+
167185
def generate_prerelease(
168186
self, prerelease: str | None = None, offset: int = 0
169187
) -> str:
@@ -206,6 +224,19 @@ def generate_devrelease(self, devrelease: int | None) -> str:
206224

207225
return f"dev{devrelease}"
208226

227+
def generate_postrelease(self, postrelease: bool = False) -> str:
228+
"""Generate postrelease"""
229+
if not postrelease:
230+
return ""
231+
232+
# version.post is needed for mypy check
233+
if self.is_postrelease and self.post is not None:
234+
new_postrelease_number = self.post + 1
235+
else:
236+
new_postrelease_number = 0
237+
238+
return f"post{new_postrelease_number}"
239+
209240
def generate_build_metadata(self, build_metadata: str | None) -> str:
210241
"""Generate build-metadata
211242
@@ -240,6 +271,7 @@ def bump(
240271
prerelease: Prerelease | None = None,
241272
prerelease_offset: int = 0,
242273
devrelease: int | None = None,
274+
postrelease: bool = False,
243275
is_local_version: bool = False,
244276
build_metadata: str | None = None,
245277
exact_increment: bool = False,
@@ -272,9 +304,10 @@ def bump(
272304
self if base == current_base else cast("BaseVersion", self.scheme(base))
273305
).generate_prerelease(prerelease, offset=prerelease_offset)
274306

275-
# TODO: post version
307+
post_version = self.generate_postrelease(postrelease)
308+
276309
return self.scheme(
277-
f"{base}{pre_version}{dev_version}{self.generate_build_metadata(build_metadata)}"
310+
f"{base}{pre_version}{post_version}{dev_version}{self.generate_build_metadata(build_metadata)}"
278311
) # type: ignore[return-value]
279312

280313
def _get_increment_base(

docs/commands/bump.md

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,29 @@ Commitizen supports the [PEP 440][pep440] version format, which includes several
116116
1.0.0b2.dev1 # Development release 1 of beta 2
117117
```
118118

119-
> **Note**: `post` releases (e.g., `1.0.0.post1`) are not currently supported.
119+
#### Post-releases
120+
```text
121+
1.0.0.post0 # Post-release 0
122+
1.0.0.post1 # Post-release 1
123+
```
124+
125+
#### Combined Pre-release and Post-release
126+
```text
127+
1.0.0a1.post0 # Alpha release 1 with a post-release
128+
1.0.0rc1.post1 # Release candidate 1 with a post-release
129+
```
130+
131+
#### Combined Post-release and Development
132+
```text
133+
1.0.0.post0.dev0 # Post-release 0 with development release 0
134+
1.0.0.post1.dev1 # Post-release 1 with development release 1
135+
```
136+
137+
#### Combined Post-release, Pre-release and Development
138+
```text
139+
1.0.0a1.post0.dev0 # Alpha release 1 Post-release 0 with development release 0
140+
1.0.0rc1.post1.dev1 # Release candidate 1 Post-release 1 with development release 1
141+
```
120142

121143
## Command line options
122144

@@ -162,6 +184,21 @@ by their precedence and showcase how a release might flow through a development
162184
- `1.1.0rc0` after bumping the release candidate
163185
- `1.1.0` next feature release
164186

187+
### `--devrelease`
188+
189+
The bump is a development-release bump. A development release appends a `.devN` segment to the
190+
current version where `N` is a non-negative integer. Use `--devrelease <N>` to explicitly set the
191+
development release number. When combined with prereleases or post-releases the `.devN` segment is
192+
placed after those segments (for example `1.0.0a1.dev0` or `1.0.0.post0.dev0`).
193+
194+
### `--postrelease`
195+
196+
A post-release preserves the current base version and appends a `.postN` segment. Use the
197+
`--postrelease` boolean flag to create or increment a post-release. Post-releases start at
198+
`.post0` and increment the post number on subsequent `--postrelease` bumps (new commits required
199+
for subsequent increments). To promote a post-release to the next final version, run a normal bump
200+
without `--postrelease`.
201+
165202
### `--increment-mode`
166203

167204
#### `--increment-mode=linear` (default)

0 commit comments

Comments
 (0)