This project has been archived by its maintainers, and is no longer receiving any updates.
sqlmesh-ff
Configurable fitness functions plugin for SQLMesh projects.
Ships SQLMesh linter rules (classification macros, SQL complexity, metadata, naming) and architectural checks (layer integrity, custom exclusions, schema contracts, dependency graph) with a unified Rich lint report.
Installation
# Install directly from GitHub:
uv add git+https://github.com/tjirab/sqlmesh-ff.git
# Or from a local checkout:
uv add ../sqlmesh-ff
Quick start
- Add
fitness_functions.yamlto your SQLMesh project root (see Configuration). - Add a small
config.pybootstrap (see Where configuration lives) — SQLMesh requires the loader as a Python class and cannot loadconfig.pyandconfig.yamlin the same folder. - Run lint:
sqlmesh-ff lint
Where configuration lives
There are three layers. Only the YAML/JSON files in your project are user-editable settings.
| Layer | File | Role | You edit this? |
|---|---|---|---|
| Plugin defaults | sqlmesh_ff/config.py (installed package) |
Pydantic schema and built-in defaults (e.g. fan_out_warn: 15) |
No — library code, never overwritten |
| SQLMesh project | settings.yaml |
Gateways, linter.rules, variables, CI/CD bot |
Yes — normal SQLMesh config |
| Fitness functions | fitness_functions.yaml |
Thresholds, rule toggles, column naming/type rules, paths to JSON data | Yes — main FF config |
| Loader bootstrap | config.py (project root) |
Loads settings.yaml and registers FitnessLoader |
Rarely — ~15 lines of wiring |
| Contract data | linter_contract_groups.json, linter_exclusions.json |
Repo-specific schema parity and dependency exclusions | Yes — project data |
Merge order for fitness settings: plugin defaults → fitness_functions.yaml → optional loader_kwargs overrides in config.py. Your YAML always wins over plugin defaults. The project config.py does not hold fitness thresholds — it only points at fitness_functions.yaml.
Why config.py exists: SQLMesh accepts loader: FitnessLoader only as a Python class, not as a YAML string. Because SQLMesh rejects having both config.py and config.yaml in one folder, projects use settings.yaml (SQLMesh settings) plus config.py (loader registration).
Example bootstrap:
from pathlib import Path
from sqlmesh.core.config import Config
from sqlmesh.utils.yaml import load as yaml_load
from sqlmesh_ff.loader import FitnessLoader
_settings = yaml_load(Path(__file__).parent / "settings.yaml")
config = Config.parse_obj(_settings).update_with({
"loader": FitnessLoader,
"loader_kwargs": {"fitness_functions_config": "fitness_functions.yaml"},
})
Enable individual SQLMesh rules in settings.yaml under linter.rules / linter.warn_rules.
Configuration
Fitness function settings live in fitness_functions.yaml at the project root. Override the file path or individual keys via loader_kwargs in config.py (advanced — most projects only set fitness_functions_config).
Example fitness_functions.yaml
contract_groups_path: linter_contract_groups.json
exclusions_path: linter_exclusions.json
layers:
order: [sources, derived, core, marts, export]
checks:
layer_integrity: { enabled: true }
custom_exclusions: { enabled: true }
schema_contracts: { enabled: true }
dependency_graph:
enabled: true
fan_out_warn: 15
fan_out_fail: 25
fan_in_warn: 10
rules:
classification_macros:
enabled: true
skip_layers: [sources]
columns:
product_type: "@product_type\\b|@PRODUCT_TYPE\\b"
sql_complexity:
enabled: true
thresholds:
decision_points: [15, 25]
cte_count: [8, 12]
join_count: [8, 12]
line_count: [250, 400]
mart_naming:
enabled: true
layer_name: marts
rule: prefix_with_subdirectory
column_names:
enabled: true
replacements: {}
column_types:
enabled: true
rules: []
equivalent_types:
text: [text, varchar]
metadata:
owner: true
description: true
grain: true
filename_equals_modelname:
enabled: true
Project-specific JSON
Keep repo-specific contract and exclusion data in your project:
linter_contract_groups.json— cross-model schema parity groupslinter_exclusions.json— blocked dependency patterns and allowed exceptions
Reference their paths from fitness_functions.yaml. The plugin ships generic engines only; examples live in this README.
Rule name mapping
SQLMesh uses lowercase class names in linter.rules:
| Config key | SQLMesh rule name |
|---|---|
classification_macros |
classificationmacros |
sql_complexity |
sqlcomplexity |
mart_naming |
martmodelnamingconvention |
column_names |
columnnames |
column_types |
columntypes |
metadata.owner |
nomissingowner |
metadata.description |
nomissingdescription |
metadata.grain |
nomissinggrain |
filename_equals_modelname |
filenameequalsmodelname |
CLI
sqlmesh-ff lint [--project PATH] [--config PATH] [--checks CHECK,...] [--fail-level error|warning] [--group-by connascence|model]
- Default: all enabled checks plus SQLMesh linter rules
--checks layer_integrity,custom_exclusions: run subset (for pre-push hooks)--fail-level warning: treat warnings as failures--group-by connascence|model: change how violations are grouped in the report (default:connascence)
Integration example
Example overrides. api_request should always be named api_call. _id columns should always be of type text and is_ columns should always be of type boolean.
column_names:
replacements:
api_request: api_call
column_types:
rules:
- name: id_is_text
pattern: "_id$"
data_type: text
- name: boolean
pattern: "^is_"
data_type: boolean
Examples
A complete, runnable example project showcasing the configuration of sqlmesh-ff rules, exclusions, contracts, and a continuous integration workflow is located in the examples/ directory.
To run the linter against the example project locally, run:
sqlmesh-ff lint --project examples/minimal-sqlmesh-project
See examples/minimal-sqlmesh-project/fitness_functions.yaml to inspect the configured rules.
Development
Initialize your local environment and configure the Git pre-push hook:
make init
Run linter, tests, or check diff coverage:
make lint
make test
make coverage
Releases and PR titles
Releases are automated with release-please on merges to main. Use Conventional Commits in PR titles so changelog entries and semver bumps are correct.
PR titles must start with a type prefix, for example:
feat: add dependency graph fan-in checkfix: remove unused import in loader testsdocs: document fitness_functions.yaml merge orderci: add release-please workflow
Supported types include feat, fix, docs, style, refactor, perf, test, build, ci, and chore. The PR title check in CI enforces this format.
Metadata
Release files for sqlmesh-ff 0.1.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| sqlmesh_ff-0.1.3.tar.gz | 104.8 kB | With provenance | Details for sqlmesh_ff-0.1.3.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| sqlmesh_ff-0.1.3-py3-none-any.whl | Python 3 | none | any | Details for sqlmesh_ff-0.1.3-py3-none-any.whl |
Total release size: 134.4 kB
Release files / sqlmesh_ff-0.1.3.tar.gz
| Download URL | sqlmesh_ff-0.1.3.tar.gz |
|---|---|
| Size | 104.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c955b9b1d4a0a13ab1d0c3aa203df11fc7f5b17a54f9e8f6acefe8073835f7cf
|
|
BLAKE2b-256 checksum How to use checksums |
2961988e6c64c62d1e0406c68e341fecefec005ec5a25ca94be39bc9a5165615
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 27, 2026.
Transparency logRelease files / sqlmesh_ff-0.1.3-py3-none-any.whl
| Download URL | sqlmesh_ff-0.1.3-py3-none-any.whl |
|---|---|
| Size | 29.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
67e930ea5c13c5a36097e5d32dd271ffc0778b3b7ada4f55c8fa8521ed716e14
|
|
BLAKE2b-256 checksum How to use checksums |
18f6f63cd5408a27be90cb7628a65cd1daa8d98bcfa43b0de2bb99ff443aa467
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 27, 2026.
Transparency logSecurity for sqlmesh-ff 0.1.3
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for sqlmesh_ff-0.1.3.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 27, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.