Skip to content

Furious-Meteors/openframe-tooling

Repository files navigation

openframe-tooling

PyPI version Python versions Tests License Docs

Installation · Getting Started · PyPI · Changelog


openframe-tooling is the developer tooling family of the OpenFrame Microservice Development Suite — a monorepo of three independent tools that keep services in the ecosystem honest: schema-compatible across service boundaries, scaffolded consistently, and documented truthfully. Each tool is versioned and published independently under its own PyPI name; install only what you need, or install openframe-tooling[all] for the full set.

As of this release, all three tools are published at 0.1.0:

Tool What it does
openframe-schemas Publishes @contract-decorated Pydantic models to a versioned registry and detects breaking changes between versions — a CI gate against silent cross-service drift.
openframe-cli Scaffolds new OpenFrame services from Copier templates — hexagonal architecture, ApplicationBootstrap wiring, and boundary tests generated correct from day one.
openframe-docs Doc-truth CI — derives documentation claims from source (version pins, code-block signatures, import paths) instead of trusting prose that drifts.

All three build on the @contract marker and port contracts shipped in openframe-core, and openframe-cli scaffolds services that wire openframe-adapters. 0.1.0 is an experimental first release — APIs may still change ahead of 1.0.


Installation

Granular — one specific tool

pip install openframe-tooling[schemas]   # cross-service schema governance
pip install openframe-tooling[cli]       # service scaffolding
pip install openframe-tooling[docs]      # doc-truth CI

Everything

pip install openframe-tooling[all]       # all three tools

Direct — skip the meta-package

Each tool is a standalone PyPI package; the meta-package is a convenience, not a requirement.

pip install openframe-schemas            # core mechanic
pip install openframe-schemas[cli]       # + the openframe-schemas CLI

pip install openframe-cli                # scaffolding CLI (copier + typer + rich)

pip install openframe-docs               # doc-truth checkers (typer + rich only —
                                          # infrastructure-free, no openframe-core dep)

Tool inventory

Package Install Status Description
[schemas] openframe-schemas Published — 0.1.0 Publishes @contract-decorated Pydantic models to a versioned registry and detects breaking changes between versions
[cli] openframe-cli Published — 0.1.0 Scaffolds new OpenFrame services from Copier templates — hexagonal architecture, ApplicationBootstrap wiring, and tests/test_architecture.py enforced from generation
[docs] openframe-docs Published — 0.1.0 Doc-truth CI — derives documentation claims from source: version pins, code-block call signatures, and import paths, each independently CI-gateable

Repository layout

openframe-tooling/
├── meta/openframe-tooling/    # metadata-only install-surface package ([schemas]/[cli]/[docs]/[all])
├── packages/
│   ├── openframe-schemas/     # export → registry → diff, plus the `openframe-schemas` CLI
│   ├── openframe-cli/         # `openframe new service` / `openframe check` + Copier templates
│   └── openframe-docs/        # check-pins / check-sigs / check-imports + the `openframe-docs` CLI
└── scripts/                   # shared CI utilities (read_pkg_meta.py)

Each package under packages/ is independently versioned, tested (app-test.yml across Python 3.11–3.14), and published to PyPI (python-build.yml) on push to production.


Quick start

Import — identical regardless of how you installed

# Whether you ran pip install openframe-tooling[schemas]
# or pip install openframe-schemas directly, the import is always the same:
from openframe.schemas import export_schema, ContractRegistry, diff_schemas

openframe-schemas — govern a cross-service contract

The @contract decorator lives in openframe-core (openframe.core.schemas) — it's stdlib-only and adds no dependency to your domain layer. It attaches metadata and returns the class unchanged; openframe-schemas is the machinery that reads that metadata.

from datetime import datetime
from openframe.core.schemas import contract
from pydantic import BaseModel

@contract(name="item", version="1.0")
class Item(BaseModel):
    id: str
    name: str
    description: str | None = None
    status: str = "active"
    created_at: datetime | None = None

Export and publish:

from openframe.schemas import export_schema, ContractRegistry

schema = export_schema(Item)
# {"properties": {...}, "required": [...], "x-contract-name": "item", "x-contract-version": "1.0"}

registry = ContractRegistry("./contracts")   # a directory of JSON files, committed to your repo
registry.publish(schema)                     # writes ./contracts/item/1.0.json

Diff — catch breaking changes before a consumer does:

from openframe.schemas import diff_schemas

old = registry.get("item", "1.0")
new = export_schema(ItemV1_1)   # e.g. "name" renamed to "title"

result = diff_schemas(old, new)
if result.is_breaking:
    for change in result.breaking:
        print(f"  - {change.field}: {change.reason}")
    # - name: field removed

CLI — wire it in as a CI gate:

pip install openframe-schemas[cli]

openframe-schemas publish --model myservice.domain.item:Item --registry ./contracts
# Published item v1.0

openframe-schemas check --model myservice.domain.item:Item --registry ./contracts
# PASS — item v1.1 is backward-compatible with v1.0
#   + tags: optional field added
# .github/workflows/contract-check.yml
- name: Check contract compatibility
  run: openframe-schemas check --model src.domain.item:Item --registry ./contracts
  # exits 1 on a breaking change — fails the job

openframe-cli — scaffold a new service

pip install openframe-tooling[cli]

openframe new service items-postgres --adapter openframe-adapters-db-postgres
# ✓ Generated items-postgres/
# ├── src/domain/items_postgres.py    (@contract decorated)
# ├── src/bootstrap/app.py            (ApplicationBootstrap)
# ├── tests/test_architecture.py      (boundary enforcement from day 1)
# └── ... (11 more files)

cd items-postgres && pip install -e ".[dev]"
pytest tests/test_domain.py tests/test_service.py tests/test_architecture.py
# passes immediately — no human editing required

--stage 2 scaffolds a multi-adapter service (persistence + cache + queue), mirroring research-pipeline's three-adapter ApplicationBootstrap wiring:

openframe new service research-pipeline --stage 2 --entity Artifact \
  -a openframe-adapters-db-mongo:persistence \
  -a openframe-adapters-db-redis:cache \
  -a openframe-adapters-queue-kafka:queue

openframe check runs in CI against any generated service — architecture boundary tests always, plus openframe-schemas/openframe-docs checks if those packages happen to be installed:

openframe check ./items-postgres

openframe-docs — catch documentation drift in CI

Three independent checkers, each usable standalone — Checker 1 can be added to CI before Checkers 2 and 3 exist:

pip install openframe-tooling[docs]

# Checker 1 — README version-pin claims vs. the real pyproject.toml version
openframe-docs check-pins --package openframe-core \
  --source ./openframe-core --check ./openframe-adapters

# Checker 2 — README code-block calls vs. real installed signatures
openframe-docs check-sigs --readme ./openframe-adapters/README.md \
  --package openframe-adapters-queue-kafka

# Checker 3 — README import statements vs. what actually resolves
openframe-docs check-imports --readme ./openframe-core/README.md \
  --package openframe-core

Each exits non-zero on drift and prints a per-finding path:line report, so any one can be wired into CI as its own gate:

# .github/workflows/doc-truth.yml
- name: Check README pins are not stale
  run: openframe-docs check-pins --package openframe-core --source . --check .

Design philosophy

openframe-schemas handles three things and nothing else:

  1. Export — turn a @contract-decorated Pydantic model into a tagged JSON Schema dict
  2. Registry — a directory of versioned JSON files, committed alongside the domain models it governs
  3. Diff — classify field-level changes between two versions as breaking or safe

openframe-cli handles one thing: parameterising the templates that already exist in the validation framework and putting them behind a single command, so "doing it right" costs the same as "doing it at all." No new architectural patterns are invented — the generated service is the proven service.

openframe-docs handles three independent checks and nothing else — no ecosystem table generation, no docstring-driven reference generation, no mkdocs integration (all Phase 2). Each checker reads real source (a pyproject.toml version, an installed signature, an importable path) and compares it to a documentation claim; it never trusts the claim on its own.

Everything else across all three tools — OpenAPI/AsyncAPI generation, typed client stubs, a hosted schema registry, openframe new adapter, interactive TUI mode — is deliberately out of scope for 0.1.0.

# openframe-schemas handles this:
schema = export_schema(Item)          # model → tagged JSON Schema
registry.publish(schema)              # one JSON file, committed to your repo
result = diff_schemas(old, new)       # breaking vs. safe, field by field

# You handle this directly:
# migrating existing duplicated domain models (e.g. Item defined separately
# in two services) onto one shared @contract-decorated model is a service-
# level decision — openframe-schemas only proves whether they'd diverge.

Breaking-change rules (openframe-schemas)

Change Classification
Field present in old, absent in new Breaking — field removed
Field's type changed Breaking — type changed
Field optional in old, required in new Breaking — became required
New field, required Breaking — new field added as required
New field, optional Safe — optional field added
Field required in old, optional in new Safe — became optional

Nested model diffing is out of scope for Phase 1 — only top-level properties are compared. x-contract-name / x-contract-version are metadata, not schema fields, and are always ignored when diffing.


Ecosystem

Package Install Description
openframe-core pip install openframe-core Ports · tracing · telemetry · exceptions · config · the @contract marker
openframe-adapters pip install openframe-adapters[all] Database and queue adapters — Postgres, Mongo, Redis, Kafka, and more
openframe-tooling pip install openframe-tooling[all] Developer tooling — schema governance, service scaffolding, doc-truth CI

License

MIT — see LICENSE.

About

Developer tooling for the OpenFrame Microservice Suite — cross-service schema governance, service scaffolding, and doc-truth CI.

Topics

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors