Back to Kibana

@kbn/api-contracts

packages/kbn-api-contracts/README.md

9.4.07.3 KB
Original Source

@kbn/api-contracts

Detects breaking changes in Kibana's public REST APIs that affect the Terraform provider, by comparing OpenAPI specs between the PR branch and the base branch using oasdiff.

Overview

This package runs in CI on every PR. It compares the current branch's OAS files against the base branch (e.g. main) to detect breaking API changes, then filters to only those affecting Terraform provider APIs.

Flow:

git show base OAS → oasdiff diff → parse → filter to TF APIs → apply allowlist → report → notify owners

Key components:

  1. src/diff/ - Breaking change detection via oasdiff

    • run_oasdiff.ts - Shells out to oasdiff diff with two OAS files
    • parse_oasdiff.ts - Converts oasdiff JSON output to BreakingChange[]
    • breaking_rules.ts - Allowlist filtering
  2. src/terraform/ - Terraform impact analysis and ownership

    • check_terraform_impact.ts - Matches breaking changes against TF provider APIs, carries owners
    • load_terraform_apis.ts - Loads TF API inventory (including owners) from terraform_provider_apis.yaml
  3. src/report/ - Error formatting and user guidance

    • format_failure.ts - Generates actionable error reports
    • links.ts - Documentation and support links
  4. src/allowlist/ - Escape hatch for approved breaking changes

    • load_allowlist.ts - Loads and validates allowlist.json
  5. src/input/ - OAS file loading (exported as public API)

    • load_oas.ts - Reads and validates OpenAPI spec YAML files
  6. scripts/ - CLI entry point

    • check_contracts.ts - Orchestrates the full pipeline

Breaking Change Rules

oasdiff detects these as breaking:

Change Typeoasdiff ID(s)Example
Path removedapi-path-removed-without-deprecationDELETE /api/spaces/space removed entirely
Method removedapi-removed-without-deprecation, api-removed-before-sunsetPOST removed from /api/fleet/agents
Request property removedrequest-property-removed ⚠️Request body field name removed
Parameter removedrequest-parameter-removed ⚠️Query param filter removed from GET /api/agents
Response property removedresponse-required-property-removed, response-optional-property-removed ⚠️Response field id removed from 200 response
Required property addednew-required-request-propertyNew required email field on request body
Optional made requiredrequest-parameter-became-requiredfilter query param becomes required
Type changedresponse-property-type-changedid changed from string to number

⚠️ oasdiff classifies these as warnings, but they are promoted to blocking here because Terraform provider configurations depend on these fields.

Allowlist

For approved breaking changes, add entries to allowlist.json:

json
{
  "entries": [
    {
      "path": "/api/saved_objects/{type}/{id}",
      "method": "delete",
      "reason": "Intentional removal as part of saved objects migration",
      "approvedBy": "elastic/kibana-core",
      "prUrl": "https://github.com/elastic/kibana/pull/12345",
      "expiresAt": "2026-12-31"
    }
  ]
}

Required fields: path, method, reason, approvedBy Optional fields: prUrl, expiresAt

API Ownership

Each entry in terraform_provider_apis.yaml has an owners field listing the GitHub team handle(s) responsible for that API (derived from .github/CODEOWNERS):

yaml
- path: /api/spaces/space
  methods: [GET, POST]
  resource: elasticstack_kibana_space
  owners: ['@elastic/kibana-security']

When adding a new Terraform-consumed API, always set owners to the team that owns the plugin/package registering the route.

CI notifications

When the contracts check fails (i.e. there are non-allowlisted TF-impacting breaking changes), CI automatically posts (or updates) a PR comment that @mentions the owning teams for the affected endpoints. No comment is posted when the check passes. This ensures the right people are notified and can decide whether to fix the change or add an approved allowlist entry.

Usage

CI (automatic)

Runs via .buildkite/scripts/steps/checks/api_contracts.sh on every PR. Compares against $BUILDKITE_PULL_REQUEST_BASE_BRANCH (defaults to main).

Local development

bash
# Check stack contracts against main
node scripts/check_api_contracts.js \
  --distribution stack \
  --specPath oas_docs/output/kibana.yaml

# Check serverless contracts against a specific commit
node scripts/check_api_contracts.js \
  --distribution serverless \
  --specPath oas_docs/output/kibana.serverless.yaml \
  --mergeBase <commit-sha>

Flags:

  • --distribution (required) - stack or serverless
  • --specPath - Path to current OAS file (auto-detected from distribution)
  • --baseBranch - Branch to compare against (default: main)
  • --mergeBase - Merge base commit SHA (used in CI, skips remote resolution)
  • --allowlistPath - Override allowlist path
  • --terraformApisPath - Override TF API inventory path
  • --reportPath - Write a JSON impact report to this path (used by CI for PR notifications)

Prerequisites: oasdiff must be installed and available in PATH (or set OASDIFF_BIN):

bash
brew install oasdiff
# or: curl -fsSL https://raw.githubusercontent.com/oasdiff/oasdiff/main/install.sh | sh

Handling CI Failures

When the check fails, CI posts a PR comment tagging the owning teams for the affected endpoints.

  1. Review the report - identifies which endpoints, what changed, and who owns them
  2. If unintentional: fix the code to maintain compatibility
  3. If intentional: add an allowlist entry with team approval and coordinate with @elastic/terraform-provider

Troubleshooting

"No base OAS found - skipping check"

The base branch OAS file isn't available. This happens on:

  • First PR to a new branch before oas_docs/output/ is committed
  • Shallow clones missing the base ref

The script auto-detects the elastic/kibana remote (falls back to origin) and tries git fetch {remote} {branch} --depth=1 as a fallback. If --mergeBase is provided, remote resolution is skipped entirely.

oasdiff not found

Install oasdiff locally or set OASDIFF_BIN to the binary path. In CI, oasdiff is pre-installed on the agent image.

Type errors or module resolution failures

bash
yarn kbn bootstrap
yarn test:type_check --project packages/kbn-api-contracts/tsconfig.json

Testing

bash
# Unit tests
yarn test:jest packages/kbn-api-contracts

# Type check
yarn test:type_check --project packages/kbn-api-contracts/tsconfig.json