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
8 changes: 8 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,14 @@ release, publishing a binary to crates.io and eight npm packages for a typo, and
withdrawn. A pull request that ships code and its documentation together takes the code's type, as
usual.

A user-facing change also gets an entry in the public changelog at
[ferrflow.com/changelog](https://ferrflow.com/changelog/), in the same pull request: one file per change
in `docs/site/changelog/`, named `YYYY-MM-DD-slug.md`, with `title`, `summary`, `date`,
`product: ferrflow`, `type` (`new`, `fix`, `perf`, `breaking`, `deprecation` or `security`) and an
optional `prLink` and `docsLink` in the frontmatter, then a few sentences on what changed, why, and
how to use it. Internal refactors, test-only and CI-only changes, and dependency bumps that change
nothing for users do not get one.

Never edit `docs/site/docs-vN/` or `docs/site/docs-fr-vN/`. Those record what a past major actually
documented, mistakes included, because someone pinned to that major reads them to understand the
binary they are running. CI rejects a pull request that modifies one, and allows adding a new one.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ updates your version files, writes the changelog, and cuts the tagged release. A
[![Socket Badge](https://badge.socket.dev/cargo/package/ferrflow/latest)](https://socket.dev/cargo/package/ferrflow)
[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/FerrLabs/FerrFlow/badge)](https://scorecard.dev/viewer/?uri=github.com/FerrLabs/FerrFlow)

[Documentation](https://ferrflow.com/docs) | [Changelog](https://ferrlabs.com/changelog/) | [GitHub App](https://github.com/apps/ferrflow)
[Documentation](https://ferrflow.com/docs) | [Changelog](https://ferrflow.com/changelog/) | [GitHub App](https://github.com/apps/ferrflow)

</div>

Expand Down
11 changes: 11 additions & 0 deletions docs/site/changelog/2026-04-24-ferrflow-changelog-ordering.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
title: 'FerrFlow: changelog ordering fix'
summary: 'Changelog entries are now sorted by commit date instead of alphabetically inside each section.'
date: 2026-04-24T11:15:00Z
product: 'ferrflow'
type: 'fix'
---

Changelog entries were sorted alphabetically inside each section instead of by commit date. They are now grouped by date descending, which matches what every other release tool does and what humans actually expect.

Affects everyone running v4.x. Re-run `ferrflow changelog` to regenerate the file with the corrected ordering.
11 changes: 11 additions & 0 deletions docs/site/changelog/2026-04-28-ferrflow-editorial-hero.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
title: 'FerrFlow: editorial hero on the landing page'
summary: 'New display headline (Fraunces 900, italic accent), softer paper background, monospace eyebrows.'
date: 2026-04-28T20:59:00Z
product: 'ferrflow'
type: 'new'
---

The FerrFlow landing page now leads with an editorial hero: large display headline in Fraunces, italic accent line, monospace eyebrow markers. First step of the FerrLabs design system rollout for ferrflow.com.

Same content, more confident voice. Nothing changed in the CLI itself.
22 changes: 22 additions & 0 deletions docs/site/changelog/2026-04-29-ferrflow-docs-claude-style.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
title: 'FerrFlow: docs au style Claude'
summary: 'ferrflow.com/docs/ adopte le langage visuel de docs.claude.com: fond off-white, accent FerrFlow orange, code blocks soft-dark, callouts à barre accent, layout 3 colonnes, composants <Card>/<CardGroup>/<Note>.'
date: 2026-04-29T16:30:00Z
product: 'ferrflow'
type: 'new'
---

La doc Starlight par défaut faisait son boulot mais avait l'air générique. On adopte le langage visuel des docs Anthropic, en gardant l'orange FerrFlow comme accent unique au lieu de la clay Anthropic.

Ce qui change visuellement :

- **Fond off-white `#fafafa`** (light) / **near-black `#0a0a0a`** (dark) avec texte zinc.
- **Inter system stack** pour le corps, Fraunces gardé pour les titres.
- **Accent FerrFlow orange `#e8733a`** (light) / `#ef8a55` (dark) pour les liens, focus rings, sidebar active item.
- **Code blocks soft-dark `#1c1c1c`** même en light mode, 12px rounded, label langue top-left, bouton copy top-right au hover.
- **Callouts à carte teintée** avec barre accent 4px à gauche : `<Note>`, `<Tip>`, `<Warning>`, `<Info>`.
- **Composants Mintlify-style** `<Card>` et `<CardGroup cols={2|3}>` pour les grilles de valeur.
- **Breadcrumb small-caps** "Section › Page" au-dessus du H1.
- **Widget "Was this page helpful?"** + lien "Edit on GitHub" en bas de chaque page.

Layout, sidebar versions/langues, ExpressiveCode, FR translations et snapshots `v0/v1/v2/v3` héritent automatiquement (le CSS est global). Pagefind search inchangée. La modale Cmd+K garde son style Starlight pour l'instant.
16 changes: 16 additions & 0 deletions docs/site/changelog/2026-04-29-ferrflow-editorial-body.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
title: 'FerrFlow: editorial features grid, install grid, dark CTA'
summary: 'The body of ferrflow.com now matches the new editorial design: six feature cards in a single bordered grid, four install methods side by side, dark contrast CTA block.'
date: 2026-04-29T11:23:00Z
product: 'ferrflow'
type: 'new'
---

The ferrflow.com landing page is now fully on the editorial design system, end to end. The hero refresh shipped a few days ago; this one finishes the body:

- **Stats strip**: hairline row listing the 13 file formats FerrFlow reads natively (Cargo.toml, package.json, pyproject.toml, pom.xml, *.csproj, build.gradle, Chart.yaml, pubspec.yaml, mix.exs, *.gemspec, Package.swift, go.mod, composer.json).
- **Features section**: `№ 02` numbered, six feature cards in a single bordered container with hairline dividers. No more colored icon boxes.
- **Install section**: `№ 03`, four install methods side by side (Cargo / npm / Docker / GitHub Action), each with a mono `$` prompt in accent orange.
- **CTA block**: `№ 04`, dark contrast block with an 8px orange border-left, big Fraunces title with italic accent, two pill CTAs.

Old terminal mock and 5-feature icon grid removed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
---
title: 'FerrFlow v4.2: pre-release channels'
summary: 'Ship `alpha`, `beta`, and `rc` releases without touching your floating tags.'
date: 2026-04-29T09:00:00Z
product: 'ferrflow'
type: 'new'
docsLink: 'https://ferrflow.com/docs/guides/prerelease-channels'
---

You can now ship `alpha`, `beta`, and `rc` releases without touching your floating tags. Add `--prerelease=beta` to the CLI or set `prerelease.channel` in `.ferrflow` and FerrFlow will tag `v4.2.0-beta.1`, `v4.2.0-beta.2` and so on without bumping `latest`.

```bash
ferrflow release --prerelease=beta
```

## Why we built it

Three teams asked for it last quarter. Every one of them was using a hacky `--no-publish` workaround. This fixes the workaround.

## What changes

- New `prerelease.channel` config field (string, no default).
- New `--prerelease=<channel>` CLI flag (overrides config).
- Floating tags (`latest`, `next`) stay pinned to non-prerelease versions.
- Generated changelogs include a `Pre-releases` section under each major.

No breaking changes. Existing repos get the feature for free on next bump to `v4.2.0`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
title: 'FerrFlow: DO_NOT_TRACK env var + first-run telemetry notice'
summary: 'Telemetry now honours DO_NOT_TRACK=1 alongside FERRFLOW_TELEMETRY=0, and the first invocation prints a one-line notice pointing to ferrlabs.com/telemetry.'
date: 2026-05-05T19:30:00Z
product: ferrflow
type: new
docsLink: https://ferrlabs.com/telemetry
---

Two small additions to make the FerrFlow CLI's anonymous telemetry friendlier and more discoverable.

**`DO_NOT_TRACK=1`** now disables anonymous telemetry, exactly like `FERRFLOW_TELEMETRY=0`. Same precedence: `DO_NOT_TRACK` wins if set to `1`/`true`/`yes`/`on`. Adopting the [Console Do Not Track](https://consoledonottrack.com/) standard means a single env var in your shell profile turns off telemetry for FerrFlow, Bun, Astro, Next.js, Vite, Deno and the rest of the dev tools that honour it. No need to learn one variable per CLI.

**First-run notice.** The first time you run the CLI on a machine, it prints one line to stderr:

```
Anonymous telemetry on. See https://ferrlabs.com/telemetry: opt out: FERRFLOW_TELEMETRY=0 or DO_NOT_TRACK=1
```

A marker file in `$XDG_STATE_HOME/ferrflow/.telemetry-notice-shown` (or `~/Library/Application Support/ferrflow/` on macOS, `%LOCALAPPDATA%\ferrflow\` on Windows, override with `FERRFLOW_STATE_DIR`) suppresses it on subsequent runs. We never silently re-enable telemetry between versions; if you opted out, the notice doesn't print and nothing is sent.

Part of [FerrLabs-Cloud#166](https://github.com/FerrLabs/FerrLabs-Cloud/issues/166).
29 changes: 29 additions & 0 deletions docs/site/changelog/2026-06-07-ferrflow-bot-release-rulesets.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
title: 'FerrFlow: bot releases now work under branch rulesets (v5.2.2)'
summary: 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.
date: 2026-06-07T11:00:00Z
product: ferrflow
type: fix
prLink: https://github.com/FerrLabs/FerrFlow/pull/539
---

Releases run with `bot: true` now push correctly even when your release branch is protected by a GitHub ruleset that bypasses `ferrflow[bot]`. Before this fix, the release commit could be rejected with `GH013: required status checks are expected` even though `ferrflow[bot]` was listed as a bypass actor. Shipped in **FerrFlow v5.2.2**: pinning the major (`FerrLabs/FerrFlow@v5`) picks it up automatically.

### 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.

### What changes

FerrFlow now resets that persisted extra-header on its own git invocations, so its bot token is the only credential on the wire and the push lands as `ferrflow[bot]`. This works regardless of your `actions/checkout` version and no longer requires `persist-credentials: false` on the checkout step.

```yaml
- uses: actions/checkout@v6
with:
fetch-depth: 0
- uses: FerrLabs/FerrFlow@v5
with:
bot: true
```

No config changes needed: upgrade to `@v5` (or pin `@v5.2.2` explicitly) and protected release branches just work.
40 changes: 40 additions & 0 deletions docs/site/changelog/2026-06-16-ferrflow-declarative-publishers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
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.'
date: 2026-06-16T10:00:00Z
product: ferrflow
type: new
docsLink: https://ferrflow.com/docs/configuration/config-file/#publishers
---

FerrFlow now publishes your packages to registries declaratively. Instead of wiring a `postPublish` shell hook that shells out to `cargo publish`, `npm publish`, or `docker buildx`, you describe the intent in `ferrflow.json` and FerrFlow runs it after the GitHub Release is created: per package, idempotently, and crash-resume safe.

Six publisher kinds are supported:

- **cargo**: `cargo publish` to crates.io or a private registry, with `allowDirty` and `noVerify`.
- **npm**: `npm publish` with a scoped, throwaway `.npmrc` so your project's `.npmrc` is never touched.
- **docker**: `docker buildx build --push` with multi-arch (`{version}`/`{major}`/`{minor}`/`latest` tag templates), and optional `sign: sigstore` (`cosign`).
- **helm**: `helm package` + `helm push` to an OCI registry.
- **github-release-asset**: attach a sidecar file (SBOM, signature, …) to the release with `--clobber`.
- **webhook**: POST to Slack/Discord/your own endpoint with `{name}`, `{version}`, `{tag}` and `{env:NAME}` interpolation.

```json title="ferrflow.json"
{
"workspace": {
"registries": {
"kellnr": { "tokenEnv": "CARGO_REGISTRIES_KELLNR_TOKEN" }
}
},
"package": [{
"name": "my-crate",
"path": "crates/my-crate",
"publishers": [
{ "kind": "cargo", "registry": "kellnr", "noVerify": true }
]
}]
}
```

Registry tokens are referenced by env-var name (`tokenEnv`): the token value never lives in the config file, so `ferrflow.json` stays safe to commit. Every command publisher also takes an `args` array, a verbatim escape hatch for flags FerrFlow doesn't model natively (`--locked`, `--provenance`, `--build-arg`, …).

Publishers are idempotent: an already-published version is detected and skipped, so a re-run after a partial failure picks up exactly where it left off. The block is additive: your existing `postPublish` hooks keep working while you migrate. See the [publishers documentation](https://ferrflow.com/docs/configuration/config-file/#publishers) for the full reference.
24 changes: 24 additions & 0 deletions docs/site/changelog/2026-06-25-ferrflow-jobs-flag.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
title: 'FerrFlow: control parallelism with --jobs / FERRFLOW_JOBS'
summary: '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.'
date: 2026-06-25T10:00:00Z
product: ferrflow
type: new
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.

- **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.

```bash
# Pin to one thread: deterministic, light on a 2-core runner
ferrflow --jobs 1 release

# Or via the environment
FERRFLOW_JOBS=4 ferrflow release
```

It works with every command, since it's a global flag.
35 changes: 35 additions & 0 deletions docs/site/changelog/2026-06-25-ferrflow-publish-tag-scope.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
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.'
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.

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

```yaml title=".github/workflows/publish.yml"
on:
push:
tags: ['v*', '*@v*'] # single-repo and monorepo per-package tags
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: FerrLabs/FerrFlow@v5
with:
mode: publish # self-scopes to the tag that fired
```

The selection rules:

- **`ferrflow publish`**: triggering tag → that package; otherwise every package (unchanged, so the existing release→publish job is unaffected).
- **`ferrflow publish api web`**: explicit packages (now more than one).
- **`ferrflow publish --all`**: every package, ignoring any tag scope.

Scope is by package name / tag, not conventional-commit scope, and the version is still read from package state: the tag's version suffix is just informational.
24 changes: 24 additions & 0 deletions docs/site/changelog/2026-06-26-ferrflow-arm-targets.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
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.'
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.

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

- **`aarch64-pc-windows-msvc`** → `ferrflow-windows-arm64.zip` / `@ferrflow/win32-arm64`: Windows on ARM (Surface Pro X/11, Snapdragon X laptops, Dev Kit 2023).
- **`armv7-unknown-linux-musleabihf`** → `ferrflow-linux-armv7.tar.gz` / `@ferrflow/linux-arm`: 32-bit ARM Linux (Raspberry Pi on a 32-bit OS, older SBCs).

The npm wrapper resolves the right binary automatically through `optionalDependencies`, so nothing changes in how you install:

```bash
npm install -D ferrflow
```

On a Windows-on-ARM or armv7 machine npm now pulls the native package instead of failing. Prebuilt archives are also on the [GitHub release page](https://github.com/FerrLabs/FerrFlow/releases), and the GitHub Action installs the matching binary for the runner's architecture.
32 changes: 32 additions & 0 deletions docs/site/changelog/2026-07-13-ferrflow-hook-points.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
title: 'FerrFlow: Six new release hook points: post-commit, pre-tag, post-tag, pre-release, on-success, on-error'
summary: '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.'
date: 2026-07-13T09:00:00Z
product: ferrflow
type: new
prLink: https://github.com/FerrLabs/FerrFlow/pull/657
docsLink: https://ferrflow.com/docs/configuration/config-file#hooks
---

FerrFlow already ran shell hooks at `pre_bump`, `post_bump`, `pre_commit`, `pre_publish`, and `post_publish`. That left gaps around the most delicate part of a release: the commit, the tag, and the push. This release fills them.

- **`post_commit`**: after the release commit, before tagging.
- **`pre_tag`**: after the commit, immediately before `git tag`. Smoke-test the bumped tree before the tag lands.
- **`post_tag`**: after tags are created, before push. This is the natural place to `cargo publish`: the tag exists locally but isn't pushed yet, so a failed publish is recoverable by dropping the local tag instead of rewriting remote history.
- **`pre_release`**: after the release pull request opens, before merge (`releaseCommitMode: pr` only). Post a review ping or run cross-repo validation.
- **`on_success`**: once, after the whole release finishes cleanly. Trigger a downstream deploy.
- **`on_error`**: once, when a release fails. It receives the failing error code in `FERRFLOW_ERROR_CODE`, so a Slack alert can link straight to the error reference.

```json
{
"workspace": {
"hooks": {
"postTag": "cargo publish",
"onSuccess": "curl -X POST $DEPLOY_WEBHOOK",
"onError": "curl -X POST $SLACK_WEBHOOK -d \"release failed: $FERRFLOW_ERROR_CODE\""
}
}
}
```

Per-package hooks (`post_commit`, `pre_tag`, `post_tag`) run once per released package; the once-per-run hooks (`pre_release`, `on_success`, `on_error`) fire a single time for the whole invocation. Note that `on_error` (the reactive hook) is distinct from `on_failure`, which stays what it always was: the `abort` / `continue` strategy for how a failing hook is handled.
Loading
Loading