Skip to content

Commit ed180f7

Browse files
committed
docs: define release rerun idempotency
1 parent acb0814 commit ed180f7

1 file changed

Lines changed: 43 additions & 0 deletions

File tree

docs/plans/2026-05-16-semantic-versioning-script.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,43 @@ If the business requires per-module sequential snapshot numbers, do not derive t
201201

202202
For the first implementation, avoid stateful snapshot counters. Use `CI_PIPELINE_IID` for unique snapshots and keep state only for immutable releases/RCs.
203203

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+
204241
### Branch/mode strategy
205242

206243
Support both auto-detection and explicit mode:
@@ -308,6 +345,12 @@ Options:
308345
--snapshot-include-branch
309346
Include the sanitized branch slug in snapshot versions.
310347
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+
311354
--fetch-tags
312355
Run git fetch --tags before reading tags. Intended only for small repos.
313356

0 commit comments

Comments
 (0)