You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/plans/2026-05-16-semantic-versioning-script.md
+43Lines changed: 43 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -201,6 +201,43 @@ If the business requires per-module sequential snapshot numbers, do not derive t
201
201
202
202
For the first implementation, avoid stateful snapshot counters. Use `CI_PIPELINE_IID` for unique snapshots and keep state only for immutable releases/RCs.
203
203
204
+
### Release rerun and idempotency strategy
205
+
206
+
Release jobs are different from snapshots: releases and RCs are immutable version reservations. Running the same release job multiple times must not accidentally advance `1.4.8` to `1.4.9` or `1.5.0-rc.1` to `1.5.0-rc.2` just because the job was retried.
207
+
208
+
Recommended behavior:
209
+
210
+
1. Determine whether the current commit already has a module-scoped release tag before calculating a new version.
211
+
2. If the expected release tag already exists and points to the same commit, treat the rerun as idempotent success and reuse that version.
212
+
3. If the tag exists but points to a different commit, fail hard. Never move release tags automatically.
213
+
4. If the package/version already exists, verify it belongs to the same commit/build metadata; then either skip publishing or fail depending on `--if-exists skip|fail`.
214
+
5. Only calculate the next version when no release tag already exists for the current commit and release mode.
215
+
216
+
Efficient GitLab API checks:
217
+
218
+
- Use `GET /projects/:id/repository/commits/:sha/refs?type=tag` to check tags that point at the current commit.
219
+
- Filter those refs by the module tag template, for example `payment-service/v*`.
220
+
- Use the Tags API with a module prefix only when no current-commit tag is found and the script needs to calculate the next release/RC.
221
+
222
+
Release job policy matrix:
223
+
224
+
| Situation | Behavior |
225
+
| --- | --- |
226
+
| Manual job retry in the same pipeline after tag was created | Reuse existing tag/version and exit success |
227
+
| Whole pipeline rerun on the same commit after tag was created | Reuse existing tag/version and exit success |
228
+
| Release tag exists for same version but different commit | Fail; human must resolve |
229
+
| Artifact/package version already exists for same commit | Skip publish or exit success based on policy |
230
+
| Artifact/package version exists but commit/digest differs | Fail; immutable artifact conflict |
231
+
| No release tag exists for current commit | Calculate next release/RC from filtered GitLab tags |
232
+
233
+
For even stronger safety, support an explicit target version:
234
+
235
+
```bash
236
+
--target-version 1.4.8
237
+
```
238
+
239
+
When `--target-version` is provided, the script should validate and use that version instead of calculating the next one. This is useful for manual release jobs, approvals, and reruns.
240
+
204
241
### Branch/mode strategy
205
242
206
243
Support both auto-detection and explicit mode:
@@ -308,6 +345,12 @@ Options:
308
345
--snapshot-include-branch
309
346
Include the sanitized branch slug in snapshot versions.
310
347
348
+
--target-version VERSION
349
+
Explicit immutable release/RC version to validate and use instead of calculating.
350
+
351
+
--if-exists skip|fail
352
+
Behavior when release artifact/package already exists. Default: fail.
353
+
311
354
--fetch-tags
312
355
Run git fetch --tags before reading tags. Intended only for small repos.
0 commit comments