Changelog

Ce qu’on a
livré.

Chaque fonctionnalité, correctif et amélioration de FerrFlow, la CLI de versioning et le site autour.

RSS
── OCTOBRE 2026 ──

FerrFlow: init lists the packages of your workspace

ferrflow init now reads Cargo, Go and Gradle workspaces as well as npm and pnpm ones, and offers to scaffold one package per member instead of asking you to type them.

FerrFlow: hooks can no longer hang a release

Every hook now has a timeout, 15 minutes by default, after which FerrFlow kills it and everything it started. Hooks also run with stdin closed, so a command that would prompt fails at once instead of waiting forever.

FerrFlow: JSON output names date and sequence strategies as you configure them

check --json and release --json reported bump_type as calvershortseq for a calver-short-seq package, and why --json did the same for strategy. They now use the configured spelling, such as calver-short-seq. Scripts matching the old value need updating.

FerrFlow: a hotfix no longer moves the latest alias backward

With latestTag set, releasing 1.2.4 after 2.0.0 pointed latest at 1.2.4. latest now stays on the highest version; the hotfix release still goes through, and --force moves the alias back if you want it to.

FerrFlow: clearer wording in why and doctor

ferrflow why no longer prints "forced bump forced", and ferrflow doctor shows a declared strategy with its config spelling, such as calver-short instead of calvershort.

FerrFlow: a backtick in a version no longer breaks the PR preview table

The release preview comment wrapped versions in a code span that a backtick could close early, scrambling the table. Version cells now use a fence long enough for whatever they contain.

FerrFlow: release PRs are found again on branches with special characters

A target branch containing &, # or + broke the lookup for the existing release PR on GitHub and GitLab, so FerrFlow opened a second one. A failed branch update on GitHub also reported the wrong error.

FerrFlow: rehearse a release with shadow-release

ferrflow shadow-release runs the real release pipeline in a throwaway clone, hooks included, and stops before anything is pushed or published. Use it to check that a release would go through before running it.

── SEPTEMBRE 2026 ──

FerrFlow: versions read from files never carry stray whitespace

A version written with padding or a line break inside its quotes came back with the whitespace attached and could not become a tag. package.json, Cargo.toml, pyproject.toml and Chart.yaml read with the helm format now trim it; mix.exs, gemspec, Gradle and Package.swift reject it with a clear error.

FerrFlow: the Helm publisher reads the right chart name

In a Chart.yaml listing dependencies or maintainers before the chart name, the Helm publisher could take a dependency name for the chart and check or push the wrong reference. Only the top-level name key counts now.

FerrFlow: migrating from semantic-release keeps your tags

ferrflow migrate turned tagFormat "v${version}" into tagTemplate "v{{version}}", which FerrFlow renders as v{1.2.0}. It now writes "v{version}", so the migrated config finds the tags semantic-release created.

FerrFlow: a hotfix no longer drags a floating tag backward

Releasing 1.4.2 after 1.5.0 silently moved v1 back to 1.4.2. The guard meant to stop that never fired. It does now: the release stops before anything is pushed, and --force lets the alias move.

FerrFlow: a versionTemplate starting with v no longer resets on every release

A versionTemplate whose first literal was v never read the previous version back, so every release started again from zero. v1.2.3 with a patch bump produced v0.0.1, release after release.

FerrFlow: versionTemplate now tells you about a bad literal instead of git

A versionTemplate whose literal text carried a space, a tab or a character git reserves produced a version that could not become a tag, and the run died at git tag with a message about ref names. The template is now checked where it is read.

FerrFlow: a txt selector no longer eats the spaces around your version

A versioned file read through a txt selector whose capture included padding lost all of that padding on the first release, because the write replaced the whole capture. It now replaces only what the read returned.

FerrFlow: the release pull request title now fits the forge

A monorepo releasing enough packages at once built a title longer than the 255 characters a merge request accepts, so the release PR was never opened and the run still exited green. The title is capped, the full list stays in the description, and a rejected PR now fails the release.

FerrFlow: GITHUB_TOKEN only reaches remotes that are GitHub

A push to a remote FerrFlow could not identify used to carry GITHUB_TOKEN as its password, so a self-hosted forge or an unknown host received a GitHub credential. Each forge now pushes with its own token, and an unrecognised host gets none.

FerrFlow: a schema for per-package config files

Files pulled in through include now have their own JSON schema, so editors autocomplete and validate them like the root config. It is served at ferrflow.com/schema/ferrflow-package.json and bundled in the binary behind ferrflow schema --package.

FerrFlow: the documentation is now open to pull requests

The pages behind ferrflow.com/docs live in the public FerrFlow repository. A wrong flag name, a stale example or a paragraph that never quite landed can now be fixed by anyone, and the fix goes live when it merges.

FerrFlow: Ansible Galaxy collections get a version file format

`galaxy.yml` carries a top-level `version:` like `Chart.yaml` and `pubspec.yaml` do, but versioning one meant falling back to the plain-text format and a hand-written regex. It is a first-class format now.

FerrFlow: your own commits set the floor for a bump, not the answer

A package with a fix of its own shipped as a patch even when a dependency in the same release took a minor. It now takes the stronger of the two. Expect larger bumps where a shared package and its consumers are released together.

FerrFlow: a dependent now takes the strongest bump reaching it

A package fed by two dependency edges of different strength took whichever arrived first, so it could ship as a patch while a package it depends on moved a minor. Expect larger bumps if your graph has a diamond in it.

FerrFlow: a changelog your hook rewrote is now what gets published

A `postBump` hook could already rewrite CHANGELOG.md and have it committed, but the tag, the release body and the release commit kept the text generated before the hook ran. They now agree.

FerrFlow: doctor now catches a lockfile that disagrees with its manifest

A package whose manifest and lockfile record different versions cannot build with `--locked`, and `ferrflow doctor` used to report it as healthy. It now says so, and warns before the drift happens.

FerrFlow: see what a release drags along before you run it

In a monorepo, releasing a widely depended-on package pulls others out with it. `ferrflow graph --impact` names them, with the version each would get, before anything is tagged.

── AOÛT 2026 ──

FerrFlow: a package release no longer carries other packages' commits

In a monorepo, each package collected every commit since its own last tag, whatever those commits touched. That padded the changelog with other packages' work and, less visibly, let their commits decide the version bump.

FerrFlow: calver-short-seq, and a warning when a release is held back

A date-only version scheme can only publish once a day, and the second attempt was indistinguishable from having nothing to release. FerrFlow now says so out loud, and calver-short-seq gives the compact year a sequence counter.

FerrFlow: a crash no longer leaves the release lock or a registry token behind

The release binary is built to abort on panic, which skips the cleanup that runs when a release ends normally. A crash left the lock file in place, blocking the repository for half an hour, and could leave a scoped npm token on disk.

FerrFlow: check no longer serves a stale plan after an uncommitted edit

The cache behind ferrflow check keyed on the commit, the tags and the config, but not on the version files it actually reads. Editing a version without committing returned the previous answer for up to five minutes. Interrupted runs also left temp files that nothing ever cleaned up.

FerrFlow: the crates.io link after a publish points at your crate again

FerrFlow built the crates.io link from the package name in its own config rather than the one in Cargo.toml. A workspace routinely uses short names against prefixed crates, and short crate names are long since taken, so the link led to an unrelated crate instead of yours.

FerrFlow: the npm link after a publish points at your package again

FerrFlow built the npmjs.com link from the package name in its own config rather than the one in package.json. In a monorepo those differ by default, and the short names are all taken on npm, so the link led to a stranger's package instead of yours.

FerrFlow: an annotated tag already on the remote no longer blocks the push

FerrFlow compared the commit a tag points at against the tag object itself, so any annotated tag already on the remote looked like it had moved. The push failed with a message about a difference that was not there, telling you to delete a perfectly healthy tag.

FerrFlow: undo a release that failed partway

A release that dies after pushing tags used to leave you reconstructing what it did from a job log, then deleting refs by hand. ferrflow rollback reads the checkpoint that run left behind and undoes exactly what it did, refusing the parts that cannot be undone.

FerrFlow: a config without a workspace block now keeps its defaults

Omitting the workspace block from a config file silently dropped every workspace default. The remote became an empty string and the release failed at the push; the target branch became empty and said nothing at all.

FerrFlow: release commits from the bot now show as verified

Commits authored by ferrflow[bot] showed as unverified, and no signing key could fix it because a GitHub App cannot register one. With bot: true on GitHub, the release commit is now authored through GitHub itself, which signs it.

FerrFlow: a failed push now says what actually went wrong

Every push failure was reported as "pushed onto a stale branch" and answered by regenerating the release commit three times, whatever the real cause. Transient server errors are now retried where they belong, real races are detected by their actual wording, and permanent failures surface immediately.

FerrFlow: release PRs are tagged when they merge, not when they open

In pr mode FerrFlow tagged and published the moment it opened the release PR, on the commit before the version bump. The PR then reported nothing left to release and was never updated again. Tagging now happens after the merge, on the commit that carries the bump.

FerrFlow: one config file per package

A monorepo no longer has to declare every package in a single root config. The new include key points at per-package files, each owning its own settings, and a package path inside one of those files defaults to its directory.

FerrFlow: choose whether the tag or the file is the source of truth

When a package has both a git tag and a version in a versioned file, FerrFlow took whichever was higher. That is still the default, and versionSource now lets a repo say the tags are the record, or that the file is.

FerrFlow: release output says where the current version came from

The version FerrFlow starts from is resolved from a tag, a versioned file, or neither. The release and check output now names the source, so a package whose tag was never pushed is distinguishable from one that has no tags yet.

FerrFlow: lockfiles no longer go stale after a release

updateLockfiles could leave Cargo.lock at the previous version while the release still reported success. Both causes are fixed: the crate name is read from the manifest, and a cold registry cache no longer defeats the update.

FerrFlow: commit formats are configurable, and the defaults are more permissive

workspace.commitFormats lets you declare which commit subjects map to which bump level. The defaults now also recognise Feat:, Fix/, feature: and friends, which is why this ships as v7.

FerrFlow: now MIT licensed

FerrFlow moves from MPL-2.0 to MIT. Fewer obligations for everyone using it; the change ships as v6, so Action pins move from @v5 to @v6.

FerrFlow: the Action verifies the binary it downloads

Releases now ship a signed SHA256SUMS, and the GitHub Action checks the archive against it (and its build provenance) before extracting anything.

FerrFlow: the Action no longer interpolates its inputs into shell

force_version, package and version reached the Action’s run scripts as raw shell source. They now arrive as environment variables and are validated before use.

FerrFlow: the hosted API moves to api.ferrflow.com

The FerrFlow API and the hosted bot token exchange now answer on api.ferrflow.com. The old api.ferrlabs.com host keeps working indefinitely.

FerrFlow: `diff` now shows only the package you asked about

In a monorepo, `ferrflow diff <package> <from>..<to>` filters the range to commits that touched that package, so its commit list and changelog match what a release would actually produce.

── JUILLET 2026 ──

FerrFlow: Migrating from changesets now finds your packages

`ferrflow migrate --from changesets` reads your workspace globs and scaffolds one package entry per workspace package, instead of a single root package you had to expand by hand.

FerrFlow: Releases are signed with a single Sigstore bundle

From v5.48.0 each release artifact ships one `.bundle` instead of a separate `.sig` and `.crt`. Verification is one flag shorter; older releases keep working as before.

FerrFlow: Cabal and CMake version files

FerrFlow now bumps the version in Haskell `*.cabal` files and in the `project()` call of a `CMakeLists.txt`, bringing the supported formats to 16.

FerrFlow: Tags are pushed before releases are published

A release run now pushes its tags to the remote before creating the GitHub or Gitea release, so a failure in between can no longer leave a published release pointing at a tag that never landed, and annotated tag messages are no longer silently replaced.

FerrFlow: Concurrent releases no longer fail with E2006

When two release runs race, the losing run now replans against the version the winner published instead of aborting with E2006, and no longer silently drops the other packages it was about to release.

FerrFlow: Hosted API for validate, preview, schema and releases

A new hosted API at api.ferrlabs.com/v1/ferrflow/* lets you validate a config, preview version bumps and changelog, fetch the config JSON Schema, and resolve the latest release over HTTP, with results identical to the CLI.

FerrFlow: Compare two versions with `diff`

A new `ferrflow diff v1.4.0..v1.6.0` command shows exactly what went into a version range: the commits and their bumps, the breaking changes, the files touched, and the changelog FerrFlow would generate for the range.

FerrFlow: Migrate reads JS and YAML configs

`ferrflow migrate` now imports JavaScript and YAML release configs directly (`.releaserc.js`, `release.config.js`, `.releaserc.yaml`, `.versionrc.js`, and friends), not just JSON, so you no longer have to hand-convert your config before migrating.

FerrFlow: Migrate from changesets, release-please & standard-version

`ferrflow migrate` now imports configs from changesets, release-please, and standard-version too (not just semantic-release), generating an equivalent `ferrflow.json` and a report of what mapped, what was ignored, and what needs a look.

FerrFlow: One persistent release PR

In `releaseCommitMode: pr`, FerrFlow now keeps a single long-lived release pull request and updates it on each new commit, instead of opening a fresh PR (and leaving a stale one) every time the version changes.

FerrFlow: Post-publish hooks get the release URL

`postPublish` hooks now receive `releaseUrl` (the URL of the GitHub/GitLab release FerrFlow just created), so you can link to it from a Slack notification, a dashboard, or a downstream job.

FerrFlow: Hooks see the whole release batch

Release hooks now receive `allPackages` (every package the run bumps, with its new version and bump type), so a monorepo hook can act on the batch, not just its own package.

FerrFlow: Richer context for release hooks

Release hooks now receive the rendered changelog, the parsed commits, the list of bumped files, and whether the run is a monorepo or pre-release, both as `FERRFLOW_*` env vars and on the JS/TS `ctx` object.

FerrFlow: Auto-detect self-hosted forges

FerrFlow now recognises self-hosted GitLab, GitHub Enterprise, and Gitea/Forgejo instances automatically. No need to set `forge` by hand for a git host on your own domain.

FerrFlow: Bitbucket support

FerrFlow now recognises Bitbucket Cloud repositories and handles their releases. No more scripting a hook to get automatic release tagging on Bitbucket.

FerrFlow: Faster repeat runs via commit-graph

On large repositories, FerrFlow now writes a git commit-graph on the first run so that later `check` and `release` walks are materially faster: a benefit that repeat users (pre-commit hooks, local dev, warm CI runners) get for free.

FerrFlow: Robust BREAKING CHANGE detection

FerrFlow now recognises mixed-case, hyphenated, and lowercase `BREAKING CHANGE` footers, and a `!` typed inside the scope (`feat(api!):`), so a real breaking change no longer slips through and skips the major bump.

FerrFlow: ferrflow schema

A new `ferrflow schema` subcommand prints the config JSON schema that is now bundled into the binary, so editor tooling and pre-commit hooks can validate `.ferrflow.json` completely offline.

FerrFlow: ferrflow doctor

A new `ferrflow doctor` subcommand runs read-only diagnostics on your repo, config, and forge setup and prints a categorised report, so "is my setup sane?" has a first-class answer instead of grepping `--verbose` logs.

FerrFlow: Telemetry removed. The CLI no longer phones home

FerrFlow no longer collects any usage telemetry. The module is gone from the binary entirely, along with the network calls it made on every command, which also makes monorepo commands dramatically faster.

FerrFlow: Linked and fixed package version groups

New `linked` and `fixed` workspace options let a set of monorepo packages share a version: when one bumps, the whole group moves to the same version, the way changesets and lerna do it.

FerrFlow: Migrate from semantic-release in one command

A new `ferrflow migrate` command reads your existing `.releaserc` and generates the equivalent FerrFlow config, mapping tag format, branches, and the common plugins, and surfacing anything without an equivalent instead of guessing.

FerrFlow: Six new release hook points: post-commit, pre-tag, post-tag, pre-release, on-success, on-error

The release lifecycle gains six new hook points so you can run commands at the exact commit/tag/push boundaries: publish between tag and push, notify once when a release finishes, or react to a failure with the error code in hand.

── JUIN 2026 ──

FerrFlow: Windows arm64 and Linux armv7 prebuilt binaries

FerrFlow now ships prebuilt, signed binaries (and matching npm packages) for Windows on ARM (aarch64) and 32-bit ARM Linux (armv7). The release matrix grows from 5 targets to 7, so `npm i ferrflow` and direct downloads now work on Surface/Snapdragon Windows laptops and 32-bit Raspberry Pi / SBCs.

FerrFlow: ferrflow publish auto-scopes to the triggering tag

ferrflow publish now figures out which package to publish from the tag that triggered the run, so one workflow publishes each package on its own tag, no per-package wiring. It also takes multiple package names, and a --all flag to force everything.

FerrFlow: control parallelism with --jobs / FERRFLOW_JOBS

FerrFlow now exposes a global --jobs <N> flag (and FERRFLOW_JOBS env var) to cap how many threads it uses for CPU-parallel work. Default stays all logical cores; --jobs 1 forces single-threaded: handy for constrained CI runners and reproducible benchmarks.

FerrFlow: declarative publishers (publish to cargo, npm, docker, helm & more on release)

FerrFlow can now publish your packages to registries declaratively from ferrflow.json (cargo, npm, docker with multi-arch + Sigstore, helm, GitHub release assets and webhooks), replacing hand-rolled postPublish shell hooks. Shipped across FerrFlow v5.4 to v5.7.

FerrFlow: bot releases now work under branch rulesets (v5.2.2)

The FerrFlow bot identity pushes releases correctly even when the release branch is protected by a ruleset that bypasses ferrflow[bot]. Shipped in FerrFlow v5.2.2.