@ferrflow/doc 7.21.3 → 7.21.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -254,13 +254,15 @@ jobs:
|
|
|
254
254
|
|
|
255
255
|
## Concurrency safety
|
|
256
256
|
|
|
257
|
-
Since v5.2, `ferrflow release` acquires
|
|
257
|
+
Since v5.2, `ferrflow release` acquires `ferrflow.lock` atomically (`O_CREAT|O_EXCL`) at the start of every mutating run. The lockfile lives in the repository's common git dir, which is `.git/` in an ordinary checkout and the main checkout's `.git/` when you run from a linked worktree, so all the worktrees of one repository share a single lock. That is what you want: they push to the same remote and compete on the same refs, so a per-worktree lock would not prevent anything. A second concurrent invocation on the same repo fails fast with a clear error rather than racing on git refs: the classic failure mode is a manually-triggered release firing at the same time as a cron-driven `auto-release`, producing half-pushed tag sets, non-fast-forward rejects, or duplicate draft releases.
|
|
258
258
|
|
|
259
259
|
You don't need to wire anything up. The lock is automatic on every `release` invocation. Read-only commands (`check`, `status`, `version`, `tag`) skip it.
|
|
260
260
|
|
|
261
|
-
If a previous run crashed without releasing the lock, the next invocation takes it over
|
|
261
|
+
If a previous run crashed without releasing the lock, the next invocation reads the host and PID stamped inside the lockfile and takes it over as soon as it can see that the owner is gone. On the machine that wrote the lock that is immediate, with no waiting: a crashed CI job does not leave the next one blocked. By the same token a release that is still running keeps its lock however long it takes, so a large monorepo publishing for hours is never interrupted by a timeout.
|
|
262
262
|
|
|
263
|
-
|
|
263
|
+
The 6 hour staleness timeout is only the fallback for a lock this machine cannot ask about, meaning one written by a different host on a shared filesystem, or a lockfile too damaged to read. To take a lock over sooner in that case, run `ferrflow release --force-unlock`, or delete `ferrflow.lock` from the git dir manually.
|
|
264
|
+
|
|
265
|
+
<aside class="ferr-aside ferr-aside--note"><div class="ferr-aside__body"><p>The lock is per-repo, scoped to the common git dir. It covers every linked worktree, but it does not protect across separate clones of the same repo: if you run releases concurrently from two different runners against two different checkouts of the same remote, the lock won't see the other side. Use a single release runner, or serialize at the CI level (<code>concurrency:</code> in GitHub Actions, <code>interruptible: false</code> in GitLab).</p>
|
|
264
266
|
</div></aside>
|
|
265
267
|
|
|
266
268
|
## Crash-resume
|
|
@@ -205,13 +205,15 @@ jobs:
|
|
|
205
205
|
|
|
206
206
|
## Securite de concurrence
|
|
207
207
|
|
|
208
|
-
Depuis la v5.2, `ferrflow release` acquiert
|
|
208
|
+
Depuis la v5.2, `ferrflow release` acquiert `ferrflow.lock` de maniere atomique (`O_CREAT|O_EXCL`) au debut de chaque execution mutante. Le lockfile se trouve dans le git dir commun du depot, c'est-a-dire `.git/` dans un checkout ordinaire et le `.git/` du checkout principal quand vous lancez depuis un worktree lie, si bien que tous les worktrees d'un depot partagent un seul verrou. C'est le comportement voulu : ils poussent vers le meme remote et se disputent les memes refs, donc un verrou par worktree n'empecherait rien. Une seconde invocation concurrente sur le meme depot echoue immediatement avec une erreur claire au lieu de courir contre les refs git. Le scenario classique est une release declenchee manuellement qui demarre en meme temps qu'un `auto-release` planifie en cron, ce qui produit des jeux de tags poussés à moitié, des refus non fast-forward ou des draft releases dupliquees.
|
|
209
209
|
|
|
210
210
|
Rien à brancher. Le verrou est automatique sur chaque invocation `release`. Les commandes en lecture seule (`check`, `status`, `version`, `tag`) ne le prennent pas.
|
|
211
211
|
|
|
212
|
-
Si une execution
|
|
212
|
+
Si une execution precedente a plante sans relacher le verrou, l'invocation suivante lit l'hote et le PID inscrits dans le lockfile et le reprend des qu'elle constate que le proprietaire a disparu. Sur la machine qui a ecrit le verrou, c'est immediat, sans attente : un job CI qui a plante ne bloque pas le suivant. Symetriquement, une release toujours en cours garde son verrou aussi longtemps qu'il faut, donc un gros monorepo qui publie pendant des heures n'est jamais interrompu par un delai d'expiration.
|
|
213
213
|
|
|
214
|
-
|
|
214
|
+
Le delai de peremption de 6 heures ne sert que de repli pour un verrou sur lequel cette machine ne peut rien savoir, c'est-a-dire ecrit par un autre hote sur un systeme de fichiers partage, ou dans un lockfile trop abime pour etre lu. Pour reprendre un tel verrou plus tot, lancez `ferrflow release --force-unlock`, ou supprimez `ferrflow.lock` du git dir a la main.
|
|
215
|
+
|
|
216
|
+
<aside class="ferr-aside ferr-aside--note"><div class="ferr-aside__body"><p>Le verrou est par-depot, scope au git dir commun. Il couvre tous les worktrees lies, mais il ne protege pas entre des clones separes du meme depot : si vous lancez des releases simultanees depuis deux runners differents contre deux checkouts du meme remote, le verrou ne voit pas l'autre cote. Utilisez un seul runner de release, ou serialisez au niveau CI (<code>concurrency:</code> dans GitHub Actions, <code>interruptible: false</code> dans GitLab).</p>
|
|
215
217
|
</div></aside>
|
|
216
218
|
|
|
217
219
|
## Reprise apres crash
|