Skip to content

Commit feb65c5

Browse files
committed
feat: add postrelease version
1 parent 5857050 commit feb65c5

16 files changed

+614
-187
lines changed

commitizen/cli.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,12 @@ def __call__(
257257
"help": "specify non-negative integer for dev. release",
258258
"type": int,
259259
},
260+
{
261+
"name": ["--postrelease"],
262+
"action": "store_true",
263+
"default": False,
264+
"help": "mark as a post release",
265+
},
260266
{
261267
"name": ["--increment"],
262268
"help": "manually 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
@@ -166,6 +167,7 @@ def _validate_arguments(self, current_version: VersionProtocol) -> None:
166167
(self.arguments["increment"], "--increment"),
167168
(self.arguments["prerelease"], "--prerelease"),
168169
(self.arguments["devrelease"] is not None, "--devrelease"),
170+
(self.arguments["postrelease"], "--postrelease"),
169171
(self.arguments["local_version"], "--local-version"),
170172
(self.arguments["build_metadata"], "--build-metadata"),
171173
(self.arguments["major_version_zero"], "--major-version-zero"),
@@ -227,11 +229,15 @@ def _resolve_increment_and_new_version(
227229
if increment is None and self.arguments["allow_no_commit"]:
228230
increment = "PATCH"
229231

232+
if self.arguments["postrelease"]:
233+
increment = None
234+
230235
return increment, current_version.bump(
231236
increment,
232237
prerelease=self.arguments["prerelease"],
233238
prerelease_offset=self.bump_settings["prerelease_offset"],
234239
devrelease=self.arguments["devrelease"],
240+
postrelease=self.arguments["postrelease"],
235241
is_local_version=self.arguments["local_version"],
236242
build_metadata=self.arguments["build_metadata"],
237243
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: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,29 @@ Commitizen supports the [PEP 440][pep440] version format, which includes several
103103
1.0.0b2.dev1 # Development release 1 of beta 2
104104
```
105105

106-
> **Note**: `post` releases (e.g., `1.0.0.post1`) are not currently supported.
106+
#### Post-releases
107+
```text
108+
1.0.0.post0 # Post-release 0
109+
1.0.0.post1 # Post-release 1
110+
```
111+
112+
#### Combined Pre-release and Post-release
113+
```text
114+
1.0.0a1.post0 # Alpha release 1 with a post-release
115+
1.0.0rc1.post1 # Release candidate 1 with a post-release
116+
```
117+
118+
#### Combined Post-release and Development
119+
```text
120+
1.0.0.post0.dev0 # Post-release 0 with development release 0
121+
1.0.0.post1.dev1 # Post-release 1 with development release 1
122+
```
123+
124+
#### Combined Post-release, Pre-release and Development
125+
```text
126+
1.0.0a1.post0.dev0 # Alpha release 1 Post-release 0 with development release 0
127+
1.0.0rc1.post1.dev1 # Release candidate 1 Post-release 1 with development release 1
128+
```
107129

108130
## Command line options
109131

@@ -149,6 +171,47 @@ by their precedence and showcase how a release might flow through a development
149171
- `1.1.0rc0` after bumping the release candidate
150172
- `1.1.0` next feature release
151173

174+
### `--devrelease`
175+
176+
The bump is a development-release bump. A development release appends a `.devN` segment to the
177+
current version where `N` is a non-negative integer. Use `--devrelease <N>` to explicitly set the
178+
development release number. When combined with prereleases or post-releases the `.devN` segment is
179+
placed after those segments (for example `1.0.0a1.dev0` or `1.0.0.post0.dev0`).
180+
181+
Examples:
182+
183+
```bash
184+
# create a development release
185+
cz bump --devrelease 0 --yes # 1.0.0 -> 1.0.0.dev0
186+
187+
# increment a development release (with new commits)
188+
cz bump --devrelease 1 --yes # 1.0.0 -> 1.0.0.dev1
189+
190+
# combined with a prerelease
191+
cz bump --prerelease alpha --devrelease 0 --yes # 1.1.0 -> 1.1.0a0.dev0
192+
```
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+
202+
Examples:
203+
204+
```bash
205+
# create post-release
206+
cz bump --postrelease --yes # 0.1.0 -> 0.1.0.post0
207+
208+
# increment post-release (requires new commits)
209+
cz bump --postrelease --yes # 0.1.0.post0 -> 0.1.0.post1
210+
211+
# finalize to next release (normal bump)
212+
cz bump --yes # 0.1.0.post1 -> 0.1.1
213+
```
214+
152215
### `--increment-mode`
153216

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

0 commit comments

Comments
 (0)