Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Releases run with `bot: true` now push correctly even when your release branch i

### Why it happened

`actions/checkout` persists your workflow's `GITHUB_TOKEN` as an `http.<server>.extraheader` git config entry. An HTTP extra-header outranks a credential helper, so even though FerrFlow swaps in its OIDC-minted bot token, git kept sending the original `GITHUB_TOKEN` on every push. The release commit therefore landed as `github-actions[bot]`. Which is not a bypass actor: and the ruleset rejected it.
`actions/checkout` persists your workflow's `GITHUB_TOKEN` as an `http.<server>.extraheader` git config entry. An HTTP extra-header outranks a credential helper, so even though FerrFlow swaps in its OIDC-minted bot token, git kept sending the original `GITHUB_TOKEN` on every push. The release commit therefore landed as `github-actions[bot]`, which is not a bypass actor, and the ruleset rejected it.

### What changes

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: 'FerrFlow: declarative publishers: publish to cargo, npm, docker, helm & more on release'
summary: 'FerrFlow can now publish your packages to registries declaratively from ferrflow.json: cargo, npm, docker (multi-arch + Sigstore), helm, GitHub release assets and webhooks: replacing hand-rolled postPublish shell hooks. Shipped across FerrFlow v5.4–v5.7.'
title: 'FerrFlow: declarative publishers (publish to cargo, npm, docker, helm & more on release)'
summary: '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.'
date: 2026-06-16T10:00:00Z
product: ferrflow
type: new
Expand Down
4 changes: 2 additions & 2 deletions docs/site/changelog/2026-06-25-ferrflow-jobs-flag.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ prLink: https://github.com/FerrLabs/FerrFlow/pull/598
docsLink: https://ferrflow.com/docs/reference/cli/#global-flags
---

Since FerrFlow started planning packages and creating releases in parallel, two needs emerged: capping CPU use on small CI runners, and keeping benchmark numbers reproducible regardless of a machine's core count. The new global `--jobs <N>` flag: or the `FERRFLOW_JOBS` env var, with the flag taking precedence: covers both.
Since FerrFlow started planning packages and creating releases in parallel, two needs emerged: capping CPU use on small CI runners, and keeping benchmark numbers reproducible regardless of a machine's core count. The new global `--jobs <N>` flag (or the `FERRFLOW_JOBS` env var, with the flag taking precedence) covers both.

- **Default (unset):** all logical cores, exactly as before.
- **`--jobs N`:** caps per-package planning to N threads, and bounds the release-creation HTTP pool by N too: so `--jobs 1` makes the whole run single-threaded.
- **`--jobs N`:** caps per-package planning to N threads, and bounds the release-creation HTTP pool by N too, so `--jobs 1` makes the whole run single-threaded.

```bash
# Pin to one thread: deterministic, light on a 2-core runner
Expand Down
4 changes: 2 additions & 2 deletions docs/site/changelog/2026-06-25-ferrflow-publish-tag-scope.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
---
title: 'FerrFlow: ferrflow publish auto-scopes to the triggering tag'
summary: '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.'
summary: '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.'
date: 2026-06-25T11:00:00Z
product: ferrflow
type: new
prLink: https://github.com/FerrLabs/FerrFlow/pull/602
docsLink: https://ferrflow.com/docs/reference/cli/#ferrflow-publish
---

`ferrflow publish` runs your declarative publishers in a separate CI job. Until now it published one named package or all of them: which meant a tag-triggered job had to parse `api@v2.2.1` and pass `api` itself. No more: `ferrflow publish` reads the triggering tag (`GITHUB_REF` / `CI_COMMIT_TAG`) and publishes just that package.
`ferrflow publish` runs your declarative publishers in a separate CI job. Until now it published one named package or all of them, which meant a tag-triggered job had to parse `api@v2.2.1` and pass `api` itself. No more: `ferrflow publish` reads the triggering tag (`GITHUB_REF` / `CI_COMMIT_TAG`) and publishes just that package.

So a single workflow handles a whole monorepo. Every package publishes on its own tag, with zero per-package wiring:

Expand Down
4 changes: 2 additions & 2 deletions docs/site/changelog/2026-06-26-ferrflow-arm-targets.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
---
title: 'FerrFlow: Windows arm64 and Linux armv7 prebuilt binaries'
summary: '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.'
summary: '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.'
date: 2026-06-26T10:00:00Z
product: ferrflow
type: new
prLink: https://github.com/FerrLabs/FerrFlow/pull/607
docsLink: https://ferrflow.com/docs/verifying-releases/
---

ARM64 was already covered on Linux and macOS, but not Windows: and 32-bit ARM Linux had no build at all. This release closes both gaps, taking the target matrix to seven.
ARM64 was already covered on Linux and macOS, but not Windows, and 32-bit ARM Linux had no build at all. This release closes both gaps, taking the target matrix to seven.

Two new targets ship with every release, signed with Sigstore and listed in the SBOM exactly like the existing five:

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: 'FerrFlow: Migrate from semantic-release in one command'
summary: '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.'
summary: '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.'
date: 2026-07-16T09:00:00Z
product: ferrflow
type: new
Expand All @@ -23,7 +23,7 @@ It maps what has a FerrFlow equivalent:
- `@semantic-release/exec` → hooks (`prepareCmd` → `preBump`, `publishCmd` → `postPublish`, and the rest)
- `@semantic-release/github` / `gitlab` → `forge`

The point is what it does with the rest. Anything without a FerrFlow equivalent is **surfaced, never guessed**: `@semantic-release/npm`, custom `commit-analyzer` release rules, and `repositoryUrl` are each reported with a note on what to do, not silently dropped. The command prints a summary of what mapped, what it ignored, and what needs a manual look: and it won't overwrite a config you already have.
The point is what it does with the rest. Anything without a FerrFlow equivalent is **surfaced, never guessed**: `@semantic-release/npm`, custom `commit-analyzer` release rules, and `repositoryUrl` are each reported with a note on what to do, not silently dropped. The command prints a summary of what mapped, what it ignored, and what needs a manual look, and it won't overwrite a config you already have.

```
Migrated semantic-release config from .releaserc → ferrflow.json
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: 'FerrFlow: Telemetry removed. The CLI no longer phones home'
summary: '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.'
summary: '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.'
date: 2026-07-17T15:00:00Z
product: ferrflow
type: new
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: 'FerrFlow: Robust BREAKING CHANGE detection'
summary: '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.'
summary: '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.'
date: 2026-07-18T11:00:00Z
product: ferrflow
type: fix
Expand All @@ -12,7 +12,7 @@ A breaking change that FerrFlow doesn't recognise is quietly misclassified: it s

Newly detected as breaking:

- **Case-insensitive footers**: `breaking-change:`, `breaking change:`, `Breaking Change:`: alongside the spec's `BREAKING CHANGE:` and `BREAKING-CHANGE:`.
- **Case-insensitive footers**: `breaking-change:`, `breaking change:`, `Breaking Change:`, alongside the spec's `BREAKING CHANGE:` and `BREAKING-CHANGE:`.
- **`!` inside the scope**: `feat(api!):`, the common typo for `feat(api)!:`.

Detection stays strict where it matters, so a stray mention never triggers an accidental major bump: the footer still has to start a line and be followed by a colon **and a space**, the plural `BREAKING CHANGES:` and prose mentions are ignored, and a `!` that isn't right before the closing paren (`feat(a!b):`) is not a marker.
Expand Down
2 changes: 1 addition & 1 deletion docs/site/changelog/2026-07-18-ferrflow-commit-graph.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ type: perf
prLink: https://github.com/FerrLabs/FerrFlow/pull/728
---

FerrFlow's tag scans and commit walks already read a git commit-graph when one exists, but a fresh clone. Every CI checkout: has a pack and no graph, so the speedup never kicked in where FerrFlow runs most.
FerrFlow's tag scans and commit walks already read a git commit-graph when one exists, but a fresh clone (every CI checkout) has a pack and no graph, so the speedup never kicked in where FerrFlow runs most.

Now, on a cold `check` (cache miss) or a real `release`, if the repository has no commit-graph and a history larger than ~1000 commits, FerrFlow writes one with `git commit-graph write --reachable`. On a 200-package, 10k-commit monorepo that trims the walk-heavy portion of a run by roughly 30% on every subsequent invocation.

Expand Down
6 changes: 3 additions & 3 deletions docs/site/changelog/2026-07-18-ferrflow-doctor.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
---
title: 'FerrFlow: ferrflow doctor'
summary: '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.'
summary: '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.'
date: 2026-07-18T09:00:00Z
product: ferrflow
type: new
prLink: https://github.com/FerrLabs/FerrFlow/pull/725
docsLink: https://ferrflow.com/docs/reference/cli#ferrflow-doctor
---

When a release behaved unexpectedly: a wrong bump, a tag that didn't move, no commits detected: the only recourse was `--verbose` and staring at logs. `ferrflow doctor` gives you a first-class health check instead.
When a release behaved unexpectedly (a wrong bump, a tag that didn't move, no commits detected), the only recourse was `--verbose` and staring at logs. `ferrflow doctor` gives you a first-class health check instead.

```bash
ferrflow doctor # human report
Expand All @@ -18,4 +18,4 @@ ferrflow doctor --online # also check the GitHub API rate limit

It runs a series of read-only checks and groups them into five sections: **Repo** (git repository, commit history, clean working tree, remote, tags), **Config** (which config file wins, whether it parses, plus the full `ferrflow validate` suite), **Versioning** (strategy and each package's version), **Forge** (detected forge and whether an auth token is present), and **CI** (workflow files, and whether a workflow pins the FerrFlow action). Every check is green, a warning, or an error.

Run it on a fresh checkout and it explains exactly what's missing before your first release; run it on a misconfigured repo and it pinpoints the file or value at fault. The exit code is scriptable: `0` all green, `1` warnings, `2` errors: and `--format json` has a stable shape you can assert on in CI.
Run it on a fresh checkout and it explains exactly what's missing before your first release; run it on a misconfigured repo and it pinpoints the file or value at fault. The exit code is scriptable (`0` all green, `1` warnings, `2` errors), and `--format json` has a stable shape you can assert on in CI.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: 'FerrFlow: ferrflow schema'
summary: '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.'
summary: '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.'
date: 2026-07-18T10:00:00Z
product: ferrflow
type: new
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ Now, when FerrFlow doesn't recognise the remote's hostname, it probes the host's
- a GitHub Enterprise instance,
- or a Gitea / Forgejo instance.

The probe is unauthenticated, short (a ~2s timeout), best-effort, and cached: so a run checks a given host at most once, and a hostname FerrFlow already knows never touches the network. You only need to set `forge` explicitly now if your host isn't reachable over HTTPS or you'd rather skip the probe.
The probe is unauthenticated, short (a ~2s timeout), best-effort, and cached, so a run checks a given host at most once, and a hostname FerrFlow already knows never touches the network. You only need to set `forge` explicitly now if your host isn't reachable over HTTPS or you'd rather skip the probe.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: 'FerrFlow: Hooks see the whole release batch'
summary: '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.'
summary: '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.'
date: 2026-07-20T16:00:00Z
product: ferrflow
type: new
Expand Down
4 changes: 2 additions & 2 deletions docs/site/changelog/2026-07-20-ferrflow-rich-hook-context.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: 'FerrFlow: Richer context for release hooks'
summary: 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.
summary: 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.
date: 2026-07-20T12:00:00Z
product: ferrflow
type: new
Expand All @@ -14,7 +14,7 @@ Every hook now gets the full picture. Shell hooks read new `FERRFLOW_*` environm

- `changelog`: the rendered changelog section for this bump, in markdown.
- `commits`: the commits in the bump as structured objects (`hash`, `message`, `type`, `scope`, `breaking`), so you can branch on a breaking change instead of grepping a string.
- `bumpedFiles`. Every file the release actually modified, with its format.
- `bumpedFiles`: every file the release actually modified, with its format.
- `monorepo` and `isPrerelease`: flags to tell a workspace release apart from a single-package one, and a channel pre-release from a stable one.

`commits` and `bumpedFiles` arrive as real arrays in function hooks (`FERRFLOW_COMMITS_JSON` / `FERRFLOW_BUMPED_FILES_JSON` as JSON for shell hooks, ready to pipe through `jq`):
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: 'FerrFlow: Post-publish hooks get the release URL'
summary: '`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.'
summary: '`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.'
date: 2026-07-21T08:00:00Z
product: ferrflow
type: new
Expand Down
2 changes: 1 addition & 1 deletion docs/site/changelog/2026-07-21-ferrflow-hosted-api.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: 'FerrFlow: Hosted API for validate, preview, schema and releases'
summary: '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.'
summary: '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.'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: the comma before "over HTTP" makes it read as if only the latest-release lookup is over HTTP. The original colon applied it to the whole list.

Suggested change
summary: '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.'
summary: '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.'

date: 2026-07-21T16:00:00Z
product: ferrflow
type: new
Expand Down
4 changes: 2 additions & 2 deletions docs/site/changelog/2026-07-21-ferrflow-migrate-js-yaml.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: 'FerrFlow: Migrate reads JS and YAML configs'
summary: '`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.'
summary: '`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.'
date: 2026-07-21T14:00:00Z
product: ferrflow
type: new
Expand All @@ -10,7 +10,7 @@ docsLink: https://ferrflow.com/docs/reference/cli

Plenty of semantic-release and standard-version setups keep their config in JavaScript (`release.config.js`) or YAML (`.releaserc.yaml`) rather than JSON. `ferrflow migrate` used to read JSON only and told you to convert the rest by hand first.

Now it reads them directly. A JavaScript config is evaluated with `node`. It imports the config, resolves it if it's a function, and reads the result: the same way FerrFlow already runs your `ferrflow.js` config, run locally against your own repo. A YAML config is parsed straight through. Both then feed the existing converters, so the mapping and the mapped/ignored/review report are identical to the JSON path.
Now it reads them directly. A JavaScript config is evaluated with `node`, which imports the config, resolves it if it's a function, and reads the result, the same way FerrFlow already runs your `ferrflow.js` config, locally against your own repo. A YAML config is parsed straight through. Both then feed the existing converters, so the mapping and the mapped/ignored/review report are identical to the JSON path.

```bash
ferrflow migrate # auto-detects .releaserc.js, .releaserc.yaml, release.config.js, …
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: 'FerrFlow: Migrate from changesets, release-please & standard-version'
summary: '`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.'
summary: '`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.'
date: 2026-07-21T13:00:00Z
product: ferrflow
type: new
Expand Down
Loading
Loading