Skip to content

Catalog as code

The catalog is most accurate when it lives next to the code it describes. Instead of maintaining entities by hand, teams commit a componecat.yaml file to their repository, and Componecat ingests it — automatically, and continuously.

This is the recommended way to populate the catalog at scale: each team owns its own entries, and the catalog updates itself as the code changes.

A descriptor declares one or more entities. At its simplest:

apiVersion: componecat/v1
kind: component
metadata:
name: payment-gateway
namespace: payments
description: Processes card transactions
owner: team-payments
lifecycle: production
tags: [payments, pci, critical]
spec:
fields:
languages: [go, protobuf]
interfaces:
- kind: api
name: Payment API
protocol: grpc
url: grpc://payments.internal:443
relationships:
- kind: depends-on
target: resource://datastores/payments-db

To declare more than one entity in a file, separate them with ---. See Multiple entities in one file.

For every field the descriptor accepts, see the descriptor file reference.

Componecat finds and ingests descriptors four ways:

  • On push (webhook). Once your Git provider’s webhook points at Componecat, a push that touches a componecat.yaml re-ingests it in near real time. This is how edits to a descriptor reach the catalog.
  • On a schedule (scan). A periodic scan crawls your configured organizations and repositories and ingests descriptors the catalog doesn’t know about yet, so a new repository is picked up without anyone wiring anything.
  • On refresh. Refresh on an entity’s Repository tab re-reads its descriptor along with the repository’s details: the descriptor the entity is synced from, or else a componecat.yaml at the repository root. Linking an entity to a repository does the same. This needs the Git integration’s scanning turned on, and is the quickest way to pick up an edit without a webhook.
  • Manually. You can always create entities directly in the UI or through the APIs. Manually created entities are marked as such and are never overwritten by descriptor sync.

An entity is managed by a descriptor or by an integration such as Vendorian vendor sync, never both: a descriptor that points at an integration-managed entity isn’t ingested.

Both automatic paths run off a Git integration. See Repository scanning for connecting one, choosing the scan schedule and file pattern, and wiring up the webhook.

One repository can declare many entities. Place a componecat.yaml at each relevant path (at any depth), and Componecat ingests each independently — a push that touches several of them enqueues one ingestion per file, and scheduled scans fan out the same way.

Ingestion is independent per descriptor: a mistake in one file doesn’t block the others. And a descriptor can reference an entity that a sibling descriptor in the same push defines — the ordering doesn’t matter. If a relationship’s target doesn’t exist yet, Componecat records it and completes it automatically once the target is ingested. An as-yet-unresolved target is surfaced as a warning, never a hard failure.

A scheduled scan only picks up files the catalog doesn’t track yet. Once any entity from a file is in the catalog, changes to that file, including a new document or the fix for a document that failed, arrive by push or by Refresh on an entity synced from it.

Deleting a document from a file marks the entity it declared as Missing, the same as deleting the whole file. The entity isn’t deleted, and declaring it again restores it. Renaming an entity in its document counts as removing the old name and adding the new one. If a document in the file is too broken to tell which entity it declares, nothing is marked missing until it’s fixed.

A descriptor that would add a new entity past your organization’s catalog entity limit isn’t ingested. Entities already in the catalog keep syncing, and the next scan picks up the new descriptor once you’re back under the limit. See Plans and limits.

If the same entity is changed both by descriptor sync and by a manual edit, a per-entity conflict strategy decides the outcome: the descriptor wins, the manual change wins, or the conflict is queued as a pending change for someone to review.

A descriptor that can’t be applied — an owner that matches no team, a kind your organization doesn’t define, a value that fails validation — leaves the entity unchanged. Every attempt is recorded in the integration’s ingestion log with the reason, including failures with no entity to show them on, such as a new descriptor that doesn’t parse. When there is an entity, the reason also appears on its Repository tab:

  • For an entity already synced from the descriptor, the Sync Status card shows Error and the message.
  • For an entity the descriptor names but has never synced into — the same kind, namespace, and name — an error banner shows the descriptor’s path and the message. Fix the descriptor, then push it or select Refresh on the tab: until it ingests, every scheduled scan retries it too.