Skip to content

Repository metadata

Every covered repository declares its metadata in a catalog-info.yaml file at the repository root.

Updated View as MarkdownView on Github

Each covered repository has a catalog-info.yaml file at its root. The file uses the Backstage descriptor format. The DevHub taxonomy page describes the entity kinds. DevHub reads the file. Tools such as the engineering graph (#proj-engineering-graph) can also read it. A person or an agent can then find the owner of a repository, how it runs, and where its documents are.

  • The file is in the repository. It changes in the same pull request as the code it describes.
  • CODEOWNERS is the source of truth for review ownership. spec.owner names the same team. See code ownership.
  • One file can hold more than one entity. Put --- between the entities. If a repository deploys more than one unit, declare one Component for each unit.
  • Check the file with the DevHub entity validator before you merge it.

Choose a field in this order

Before you add a field, look for an existing field for the value. Stop at the first step that has one.

Backstage

Use a field of the Backstage descriptor format or a Backstage well-known annotation. The DevHub taxonomy page covers the fields of each entity kind. The DevHub well-known annotations list covers the annotations. Backstage reserves the backstage.io/ prefix.

DevHub

Use a convention from the DevHub conventions page or taxonomy page. DevHub puts custom properties in spec.kraken.

New

If Backstage and DevHub have no field for the value, propose a new key. See Propose a new key.

Do not use a key that Backstage, DevHub, or this page does not define. Well-known annotations, such as github.com/project-slug, are allowed because they belong to the Backstage step. A new key goes in spec.kraken by default. DevHub asks teams to put custom data there, and its Kraken Spec card shows that object. An annotation is a string, so it cannot hold structured data.

Take hosting as an example. Backstage has no field for the place where a component runs. DevHub has no key for it. The spec.kraken keys in DevHub describe Kraken platform resources, for example nomad_job. So hosting is a new key.

Metadata fields

Use these fields in every Component. The table notes each exception. Backstage defines every field except four. DevHub defines spec.scmdb_ids. The PagerDuty Backstage plugin defines pagerduty.com/service-id. This page defines spec.kraken.hosting and spec.kraken.release.

Field Value Example
apiVersion Always backstage.io/v1alpha1. backstage.io/v1alpha1
kind Always Component. Component
metadata.name The repository name. example-web-app
metadata.description One sentence that tells what the component does. Customer web app for the example trading tools.
metadata.annotations.github.com/project-slug <org>/<repository>. NT-NinjaTrader/example-web-app
metadata.annotations.pagerduty.com/service-id The ID of the PagerDuty service that pages for the component. Required when spec.type is service and spec.lifecycle is production. P123ABC
metadata.links A link to the repository with icon: github. A link to the repository documents with icon: docs. The environment and on-call links. See Links. { url: https://github.com/NT-NinjaTrader/example-web-app, title: GitHub Repository, icon: github, type: repository }
spec.type service, website, or library. Use documentation when the repository only builds documents. Use ui for a mobile app, because Backstage has no value for it and the DevHub taxonomy does. website
spec.lifecycle experimental, production, or deprecated. production
spec.owner The first owner of the CODEOWNERS rule that matches catalog-info.yaml, without the @<org>/ prefix. The Backstage community CODEOWNERS module sets the same value. nt-web
spec.scmdb_ids A list of SC-<number> IDs from SCMDB. DevHub requires it when type is service and lifecycle is production. [SC-12345]
spec.kraken.hosting The platform that serves the component. Required unless spec.type is library. See Hosting. cloudflare-pages
spec.kraken.release The event that deploys a change to production. Required unless spec.type is library. See Release. manual-dispatch-gated

Do not put the link to the repository documents in an annotation. Put it in metadata.links.

DevHub links spec.owner to a group only when a DevHub group has the same reference. A team in CODEOWNERS can have no DevHub group. The file is still valid. Workday teams get a DevHub group automatically. For any other team, use the DevHub template Add a new Group of people. The template adds the group in a namespace that equals its type, for example sub-team. Then write the full reference in spec.owner, for example group:sub-team/nt-web.

metadata.links holds the places that a person needs during an incident or on the first day in a repository. Set type to a value from this table, so that a tool can find a link without the title.

type Target icon Rule
repository The repository. github Required.
documentation The repository documents. docs Required.
production The production URL. externalLink Required when the component has a URL in production.
staging The staging URL. externalLink Optional.
development The development URL. externalLink Optional.
runbook The runbook for the component. docs Optional.
slack The Slack channel for questions and escalation. chat Optional.

To find who gets paged, open the PagerDuty service. Its escalation policy names the rotation and the escalation steps. Do not add a field for the on-call team. spec.owner names the owning team, and the escalation policy names the rotation.

Do not put pagerduty.com/integration-key in the file. It is the Events API routing key. A person who can read the repository can use it to open an incident.

Custom fields

All custom fields are keys of spec.kraken. This page defines only the keys in this section.

Hosting

spec.kraken.hosting names the platform that serves the component. Use one value.

Value Meaning
cloudflare-pages Cloudflare Pages.
cloudflare-worker A Cloudflare Worker.
cloud-run Cloud Run.
gke-core-services Kubernetes on GKE, core-services.
gke-front-end Kubernetes on GKE, front-end.
fern Documents that Fern publishes.
app-store A mobile app that an app store distributes.
standalone-web-server A web server outside Cloudflare and GKE.

Release

spec.kraken.release names the event that deploys a change to production. Use one value. A value that ends in -gated means that a person must approve the deploy first, for example in a GitHub environment.

Value Meaning
push-main A merge to the default branch deploys.
push-main-gated A merge to the default branch deploys after approval.
release-branch A push to an r-* release branch deploys.
release-branch-gated A push to an r-* release branch deploys after approval.
manual-dispatch A person starts the deploy workflow.
manual-dispatch-gated A person starts the deploy workflow. The deploy needs approval.
release-console A person starts the deploy from the release console.
tag A version tag or a tag bump starts the build.
manual-sync A person copies the files to the server.

To add a value to a key, open a pull request that changes this page. An Engineering Navigator must approve it.

Propose a new key

Use this process for a new spec.kraken key or a new annotation. An annotation needs a reason. Name the Backstage or DevHub plugin that reads it. No key is approved until this page defines it.

Check the order

Confirm that Backstage and DevHub have no field for the value. See Choose a field in this order.

Open an issue

Open an issue in NT-NinjaTrader/engineering-standards. Name the key and say where it goes. List the allowed values or the format, and give one example. Say why no Backstage or DevHub field fits. Name the repositories that need the key and the team that keeps its values correct.

Get a review

An Engineering Navigator reviews the issue. The Navigator can ask for more information, agree, or decline.

Open a pull request

After the Navigator agrees, change this page. Add the key to the metadata fields table, define its allowed values, and add an example. Add a changelog entry, and link the issue. A change that is hard to reverse, such as a rename of a key that repositories use, also needs an ADR. See design docs, RFCs and ADRs.

Approve and merge

An Engineering Navigator approves the pull request. The key is approved when the pull request merges. Close the issue then. Do not use the key in a repository before the merge.

Examples

Generate the file

In Claude Code, the engineering-standards plugin writes the file. Use plugin version 0.3.0 or later. The skill reads this page, so its field rules match the rules here. Codex, Cursor, and OpenCode have no equivalent plugin. For these agents, give the agent the prompt in its tab. The agent reads this page and asks you for the values that the repository does not show.

The skill does these things:

  • It reads the repository and asks you for each value that the repository does not show. These values include spec.owner, spec.lifecycle, spec.kraken.hosting, spec.kraken.release, and spec.scmdb_ids.
  • It checks the file against the Backstage schema.
  • It writes catalog-info.yaml and does not commit it. Commit the file on a branch and open a pull request.

The plugin documentation lists the tools and secrets that the skill needs: engineering-standards plugin. An agent that reads this page needs a Cloudflare Access session. See Consult the standards. Check the result with the DevHub entity validator.

Keep the file correct

The owning team keeps the file correct. Change spec.kraken.hosting and spec.kraken.release in the same pull request that changes how the component deploys. When the owning team changes, change the CODEOWNERS rule and spec.owner in the same pull request. When a URL, a runbook, a Slack channel, or the PagerDuty service changes outside the repository, change its entry in the next pull request.

Open questions

References

Navigation

Type to search…

↑↓ navigate↵ selectEsc close