{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://ferrflow.com/schema/ferrflow.json",
"title": "FerrFlow Configuration",
"description": "Configuration file for FerrFlow — universal semantic versioning for monorepos and classic repos.",
"type": "object",
"properties": {
"$schema": {
"type": "string",
"description": "JSON Schema reference for editor autocompletion."
},
"workspace": {
"type": "object",
"description": "Workspace-level settings.",
"properties": {
"remote": {
"type": "string",
"description": "Git remote name.",
"default": "origin"
},
"branch": {
"type": "string",
"description": "Main branch name.",
"default": "main"
},
"anonymous_telemetry": {
"type": "boolean",
"description": "Send anonymous usage statistics to improve FerrFlow. No identifying data is collected.",
"default": true
},
"telemetry": {
"type": "boolean",
"description": "Deprecated: use anonymous_telemetry instead.",
"default": true
},
"versioning": {
"type": "string",
"description": "Default versioning strategy for all packages.",
"enum": ["semver", "calver", "calver-short", "calver-seq", "sequential", "zerover"],
"default": "semver"
},
"tagTemplate": {
"type": "string",
"description": "Tag template. Use {name} for package name and {version} for version. Default: 'v{version}' for single repos, '{name}@v{version}' for monorepos.",
"examples": ["v{version}", "{name}@v{version}", "{name}/v{version}", "release-{version}"]
},
"recoverMissedReleases": {
"type": "boolean",
"description": "Compare files against the last tag instead of just the last commit, recovering missed releases in monorepos.",
"default": false
},
"releaseCommitMode": {
"type": "string",
"description": "How to commit version bumps and changelog updates. 'commit' pushes directly to the branch, 'pr' creates a pull request, 'none' skips committing entirely.",
"enum": ["commit", "pr", "none"],
"default": "commit"
},
"releaseCommitScope": {
"type": "string",
"description": "In monorepo mode, whether to create a single grouped commit for all packages or one commit per package. Only affects behavior when multiple packages are bumped.",
"enum": ["grouped", "per-package"],
"default": "grouped"
},
"autoMergeReleases": {
"type": "boolean",
"description": "Automatically merge release PRs when releaseCommitMode is 'pr'.",
"default": true
},
"skipCi": {
"type": "boolean",
"description": "Append [skip ci] to the release commit message. Defaults to true in 'commit' mode, false in 'pr' mode."
},
"commitSkipMarkers": {
"type": "array",
"description": "Markers in a commit subject line that cause FerrFlow to skip the commit when computing the next version. Matched case-insensitively, subject line only. Defaults to ['[skip ci]', '[ci skip]', '[no ci]', '[skip actions]', '[actions skip]'].",
"items": { "type": "string" }
},
"floatingTags": {
"type": "array",
"description": "Floating tag levels to create/move on each release. Each level produces a tag pointing to the latest matching release (e.g. 'major' creates a v1 tag for v1.2.3).",
"items": {
"type": "string",
"enum": ["major", "minor"]
},
"default": []
},
"forge": {
"type": "string",
"description": "Git forge type. 'auto' detects from the remote URL. Use 'github' or 'gitlab' to override (useful for self-hosted instances with custom domains).",
"enum": ["auto", "github", "gitlab"],
"default": "auto"
},
"orphanedTagStrategy": {
"type": "string",
"enum": ["warn", "treeHash", "message"],
"description": "How to handle tags pointing to orphaned commits (after rebase + force-push). 'warn' logs a warning and skips. 'treeHash' attempts recovery by matching the commit's tree hash. 'message' attempts recovery by matching the commit message.",
"default": "warn"
},
"hooks": {
"$ref": "#/$defs/hooks"
},
"registries": {
"type": "object",
"description": "Named registry credentials referenced by package.publishers[]. Lets users declare 'the Kellnr token lives in CARGO_REGISTRIES_KELLNR_TOKEN' once and reuse it across every cargo / npm / docker publisher.",
"additionalProperties": {
"type": "object",
"properties": {
"url": { "type": "string" },
"tokenEnv": { "type": "string", "description": "Name of the env var holding the registry token. The token value is never read from config." }
},
"additionalProperties": false
}
},
"branches": {
"type": "array",
"description": "Map branches to pre-release channels. When FerrFlow runs on a branch matching a configured name/pattern, it uses the corresponding channel.",
"items": {
"type": "object",
"required": ["name"],
"properties": {
"name": {
"type": "string",
"description": "Branch name or glob pattern (e.g. 'main', 'release/*')."
},
"channel": {
"oneOf": [
{ "type": "boolean", "const": false, "description": "Stable release (no pre-release suffix)." },
{ "type": "string", "description": "Pre-release channel name (e.g. 'beta', 'dev', 'rc')." }
],
"description": "false for stable releases, string for pre-release channel name.",
"default": false
},
"prereleaseIdentifier": {
"type": "string",
"description": "Strategy for the pre-release identifier after the channel name.",
"enum": ["increment", "timestamp", "short-hash", "timestamp-hash"],
"default": "increment"
}
},
"additionalProperties": false
}
}
},
"additionalProperties": false
},
"package": {
"type": "array",
"description": "List of packages to version. Use one entry for single repos, multiple for monorepos.",
"items": {
"type": "object",
"required": ["name", "path"],
"properties": {
"name": {
"type": "string",
"description": "Package name, used in tags and changelog headers."
},
"path": {
"type": "string",
"description": "Path to the package root, relative to the repo root. Use \".\" for single repos."
},
"changelog": {
"type": ["string", "null"],
"description": "Path to the changelog file, relative to the repo root."
},
"versionedFiles": {
"type": "array",
"description": "Files that contain the package version to update on release.",
"items": {
"type": "object",
"required": ["path", "format"],
"properties": {
"path": {
"type": "string",
"description": "Path to the version file, relative to the repo root."
},
"format": {
"type": "string",
"description": "File format used to locate and update the version field.",
"enum": [
"csproj",
"toml",
"json",
"xml",
"gradle",
"gomod",
"helm",
"chartyaml",
"pubspecyaml",
"mixexs",
"gemspec",
"packageswift",
"txt"
]
},
"selector": {
"type": "string",
"description": "Optional selector to disambiguate which version is bumped. xml: a slash-delimited tag path like '/project/version' (or '//tag' for first-anywhere); txt: a regex with one capture group around the version. Without a selector, xml uses a Maven-aware default (first <version> direct child of root)."
}
},
"additionalProperties": false
}
},
"sharedPaths": {
"type": "array",
"description": "Paths whose changes should trigger a version bump for this package (monorepo only).",
"items": {
"type": "string"
}
},
"dependsOn": {
"type": "array",
"description": "Package names this package depends on. When a dependency is bumped, this package gets a patch bump automatically.",
"items": {
"type": "string"
}
},
"versioning": {
"type": "string",
"description": "Versioning strategy for this package. Overrides workspace default.",
"enum": ["semver", "calver", "calver-short", "calver-seq", "sequential", "zerover"]
},
"tagTemplate": {
"type": "string",
"description": "Tag template for this package. Use {name} for package name and {version} for version. Overrides workspace default.",
"examples": ["v{version}", "{name}@v{version}", "{name}/v{version}", "release-{version}"]
},
"floatingTags": {
"type": "array",
"description": "Floating tag levels for this package. Overrides workspace default.",
"items": {
"type": "string",
"enum": ["major", "minor"]
}
},
"hooks": {
"$ref": "#/$defs/hooks"
},
"publishers": {
"type": "array",
"description": "Declarative publish targets evaluated after the GitHub Release is created. Each entry is a self-contained intent — see $defs/publisher for the kinds.",
"items": { "$ref": "#/$defs/publisher" },
"default": []
}
},
"additionalProperties": false
}
}
},
"$defs": {
"publisher": {
"oneOf": [
{
"type": "object",
"required": ["kind"],
"properties": {
"kind": { "const": "cargo" },
"registry": { "type": "string" },
"allowDirty": { "type": "boolean", "default": false },
"noVerify": { "type": "boolean", "default": false, "description": "Pass cargo publish --no-verify. Set for multi-crate batch releases so inter-dependent crates don't fail on registry-index propagation timing." }
},
"additionalProperties": false
},
{
"type": "object",
"required": ["kind"],
"properties": {
"kind": { "const": "npm" },
"registry": { "type": "string" },
"tag": { "type": "string" },
"access": { "type": "string", "enum": ["public", "restricted"] }
},
"additionalProperties": false
},
{
"type": "object",
"required": ["kind", "image"],
"properties": {
"kind": { "const": "docker" },
"image": { "type": "string" },
"tags": { "type": "array", "items": { "type": "string" }, "default": ["{version}"] },
"platforms": { "type": "array", "items": { "type": "string" } },
"context": { "type": "string", "default": "." },
"dockerfile": { "type": "string", "default": "Dockerfile" },
"sign": { "type": "string", "enum": ["none", "sigstore"], "default": "none" }
},
"additionalProperties": false
},
{
"type": "object",
"required": ["kind", "registry"],
"properties": {
"kind": { "const": "helm" },
"chart": { "type": "string", "default": "." },
"registry": { "type": "string" }
},
"additionalProperties": false
},
{
"type": "object",
"required": ["kind", "path"],
"properties": {
"kind": { "const": "github-release-asset" },
"path": { "type": "string" },
"displayName": { "type": "string" }
},
"additionalProperties": false
},
{
"type": "object",
"required": ["kind", "url"],
"properties": {
"kind": { "const": "webhook" },
"url": { "type": "string" },
"body": {},
"headers": { "type": "object", "additionalProperties": { "type": "string" } }
},
"additionalProperties": false
}
]
},
"hooks": {
"type": "object",
"description": "Shell commands executed at lifecycle points during release.",
"properties": {
"preBump": {
"type": "string",
"description": "Run after bump calculation, before writing version files."
},
"postBump": {
"type": "string",
"description": "Run after writing version files, before changelog generation."
},
"preCommit": {
"type": "string",
"description": "Run after changelog generation, before git commit."
},
"prePublish": {
"type": "string",
"description": "Run after commit and tag, before push."
},
"postPublish": {
"type": "string",
"description": "Run after push and release creation."
},
"onFailure": {
"type": "string",
"description": "Behavior when a hook exits non-zero.",
"enum": ["abort", "continue"],
"default": "abort"
}
},
"additionalProperties": false
}
},
"additionalProperties": false
}