Roadie Backstage Entity Validator
Published on June 29th, 2022Introduction
Roadie provides many additional utilities to make your experience with Backstage smoother. One of these is the Backstage Entity Validator . With this validator you can confirm that the entity descriptor files you are creating for Backstage conform to the schema and can be ingested by Backstage. The validator does not check the validity of entity references such as the "owner" field.
The Entity Validator is enabled automatically when you install the Roadie GitHub app to your GitHub organization. The validator automatically checks your pull requests and validates Backstage files included in them. The GitHub app check files with .yml or .yaml type and that have an apiVersion containing a string backstage.io, thus indicating that it is a Backstage descriptor file.
Configuration
The validator reads a .roadierc configuration file (YAML format) to control its behaviour. It looks for this file in two places, in order:
- Org-level config:
{your-org}/.github/.roadierc— applies to all repositories in your GitHub organization. The Roadie GitHub app must be installed on the.githubrepo for this to work. If the app isn't installed there or the file doesn't exist, it is silently ignored. - Repo-level config:
.roadiercin the root of the repository being validated — takes precedence over org-level config for repo-specific overrides.
Available options
validator:
disabled: true
exclude:
- "catalog-*.yaml"
validationSchemaUrl: "https://example.com/schemas/entity-validation.json"
| Option | Description |
|---|---|
validator.disabled | Set to true to skip validation entirely for this repo (or org-wide if set in .github). |
validator.exclude | Glob patterns for files to skip. Org and repo exclude lists are merged together. |
validator.validationSchemaUrl | URL to a custom JSON Schema used to validate entity. Useful for enforcing naming conventions or custom annotation rules. |
Precedence rules
When both org-level and repo-level configs exist, they are merged as follows:
| Field | Behaviour |
|---|---|
disabled | Repo overrides org. Setting disabled: false in a repo runs validation even if the org config disables it. |
exclude | Both lists are concatenated — org excludes and repo excludes both apply. |
validationSchemaUrl | Repo overrides org. If the repo specifies a different URL, it wins. |
Examples
Disable validation for all repositories in your org:
# {your-org}/.github/.roadierc
validator:
disabled: true
Use a custom annotation schema org-wide, but allow a specific repo to override it:
# {your-org}/.github/.roadierc
validator:
validationSchemaUrl: "https://raw.githubusercontent.com/my-org/.github/main/schemas/entity-validation.json"
# my-special-repo/.roadierc
validator:
validationSchemaUrl: "https://raw.githubusercontent.com/my-org/.github/main/schemas/strict-validation.json"
Testing a custom schema before rolling it out org-wide
Because a repo-level .roadierc overrides the org-level one, you can safely trial a new schema in a single repository without affecting anyone else:
- Add the schema file to your
.githubrepo (or any public URL) and merge it to the default branch. - In a test repository, add a
.roadiercthat points to the new schema URL:
# my-test-repo/.roadierc
validator:
validationSchemaUrl: "https://raw.githubusercontent.com/my-org/.github/main/schemas/entity-validation-candidate.json"
- Open a pull request in that repo with entity files that should pass, and others that should fail. Verify the check results match your expectations.
- Once you're happy, move the
validationSchemaUrlinto{your-org}/.github/.roadiercto apply it across the org, and remove the repo-level.roadierc.
Custom schema example
The validationSchemaUrl must point to a JSON Schema (draft-07) file. The schema is run against the entire entity object, so you can add extra constraints on any field — metadata.name, metadata.labels, spec.owner, metadata.annotations, etc.
Important: the custom schema is purely additive. It runs on top of Backstage's built-in structural validation (required fields, valid
kind, correctspecshape for each kind). It cannot relax or remove those built-in rules — it can only add stricter ones.
The following example enforces two org-specific rules on top of the standard Backstage validation:
metadata.namemust be lowercase kebab-case with an optional team prefix separated by a dot (e.g.payments.checkout-service)- All annotation keys must be prefixed with either
backstage.io/ormy-org.com/
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://raw.githubusercontent.com/my-org/.github/main/schemas/entity-validation.json",
"type": "object",
"properties": {
"metadata": {
"type": "object",
"properties": {
"name": {
"type": "string",
"pattern": "^([a-z0-9]+\\.)?[a-z0-9][a-z0-9-]*[a-z0-9]$",
"description": "Entity names must be lowercase kebab-case, optionally prefixed with a team name and dot (e.g. payments.checkout-service)"
},
"annotations": {
"type": "object",
"patternProperties": {
"^(backstage\\.io|my-org\\.com)/": {
"type": "string"
}
},
"additionalProperties": false
}
}
}
}
}
With this schema in place, a PR containing the following would fail validation because the name uses uppercase and the annotation key is not from an allowed domain:
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: MyCheckoutService
annotations:
internal/owner: payments-team
spec:
type: service
lifecycle: production
owner: group:payments
Schemas
The validator is based on the published Backstage schemas which can be referred to in the Backstage docs along with two additional Kinds - Repository and Product. A list of Kinds available in Roadie can be found here.