Skip to content

Compatibility analysis

Compare two ODCS contract revisions to detect breaking changes before you publish or deploy an update.

Breaking changes include removed schema objects, removed properties, type changes, and other contract changes that would break downstream consumers.

CLI

odcs diff old.yaml new.yaml
odcs diff old.yaml new.yaml --json
Exit code Meaning
0 No breaking changes
1 Breaking changes detected
2 Parse or I/O failure

Text output lists each change with kind, code, message, and path:

[breaking] odcs:compatibility-breaking: removed property 'email' (schema[customers].properties[email])

When there are no changes:

no changes

JSON output

odcs diff examples/compatibility/base.yaml examples/compatibility/breaking-removed-column.yaml --json
{
  "compatible": false,
  "hasBreaking": true,
  "changes": [
    {
      "kind": "breaking",
      "code": "odcs:compatibility-breaking",
      "message": "removed property 'email'",
      "path": "schema[customers].properties[email]"
    }
  ]
}

Python

Both contracts must be parsed first:

import pyodcs

old = pyodcs.parse_file("old.yaml")["contract"]
new = pyodcs.parse_file("new.yaml")["contract"]
assert old is not None and new is not None

report = pyodcs.diff(old, new)
if report["hasBreaking"]:
    for change in report["changes"]:
        print(change["kind"], change["path"], change["message"])

Report shape

Field Type Description
hasBreaking bool True when any change has kind: "breaking"
changes list Each entry has kind, code, message, path

Change kinds include breaking and non-breaking variants (for example additions). Treat hasBreaking as the CI gate signal.

Rust

use odcs::{diff, parse_file};

let old = parse_file("old.yaml")?.into_contract()?;
let new = parse_file("new.yaml")?.into_contract()?;
let report = diff(&old, &new);
if report.has_breaking {
    for change in &report.changes {
        eprintln!("{}: {}", change.path, change.message);
    }
}

CI gate

Fail the job when breaking changes are introduced unintentionally:

#!/bin/sh
set -e
odcs diff contracts/customer-v1.yaml contracts/customer-v2.yaml

Or capture JSON for structured reporting:

odcs diff old.yaml new.yaml --json | jq -e '.hasBreaking | not'

What diff does not do

  • Does not validate either contract (parse errors exit 2)
  • Does not migrate or auto-fix contracts
  • Does not compare against live data or runtime behavior

For validation errors, use odcs validate. For upgrade steps between tool releases, see Migration.