mcpField
I
infrahub-managing-checks

infrahub-managing-checks

github.com/opsmillTesting & quality27153 installsUpdated 2d ago
Repository

About infrahub-managing-checks

A guidance skill for developers creating and debugging Infrahub checks: Python and GraphQL validations used in proposed-change pipelines. It emphasizes choosing schema constraints where suitable and provides implementation, registration, and testing guidance.

Key features

  1. 01Explains global and targeted checks
  2. 02Guides GraphQL query and Python class creation
  3. 03Covers .infrahub.yml registration
  4. 04Describes YAML-driven and local testing
  5. 05Highlights schema constraints and query pitfalls

Use cases

  1. 01Create checks that block invalid proposed changes
  2. 02Validate relationships and cross-object rules
  3. 03Troubleshoot failed checks and pipeline behavior

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/opsmill/infrahub-skills --skill infrahub-managing-checks

After installing, type/infrahub-managing-checksin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

examples.md
reference.md
rules/
_sections.md
_template.md
api-error-surfaces.md
api-reference.md
architecture-types.md
patterns-common.md
patterns-relationship-traversal.md
patterns-shared-module.md
python-validate.md
registration-config.md
testing-commands.md
testing-proposed-change-commit.md
testing-resource-framework.md

Details

From the project README

Infrahub Check Creator

Overview

Expert guidance for creating Infrahub checks. Checks are user-defined validation logic (Python + GraphQL) that run as part of a proposed change pipeline. If a check logs any errors, the proposed change cannot be merged.

Project Context

Infrahub config: !cat .infrahub.yml 2>/dev/null || echo "No .infrahub.yml found"

Existing checks: !find . -name "*.py" -path "*/checks/*" 2>/dev/null | head -20

Existing queries: !find . -name "*.gql" -path "*/queries/*" 2>/dev/null | head -20

When to Use

  • Writing validation logic for proposed changes
  • Creating data quality guards (e.g., rack collision detection)
  • Building global checks that validate all objects of a type
  • Building targeted checks that validate specific grouped objects
  • Debugging check failures or understanding the check lifecycle

Rule Categories

PriorityCategoryPrefixDescription
CRITICALArchitecturearchitecture-Three components, global vs targeted, execution flow
CRITICALPython Classpython-InfrahubCheck base class, validate(), log_error/log_info
HIGHAPI Referenceapi-Class attributes, instance properties, methods, lifecycle, and which API surfaces a rejection (a GraphQL error is a 200)
HIGHRegistrationregistration-.infrahub.yml config, query name matching, parameters
MEDIUM (HIGH for patterns-shared-module)Patternspatterns-Error collection, shared utilities, scoped validation, relationship-traversal validation, sharing a module across artifact types
HIGHTestingtesting-Resources Testing Framework (YAML-driven tests), infrahubctl check commands, which repository commit a proposed change's checks run

Schema Features This Skill Depends On

A check is only useful if it can fetch and validate the right data. Most check failures at deploy time are actually schema-side gaps:

If the check...The schema (or .infrahub.yml) must...See
Reads an attribute via GraphQLExpose it on the schema node with the same name (name__value-shaped paths)../infrahub-managing-schemas/rules/attribute-defaults-and-types.md
Walks a relationship to validate related objectsHave both sides of the relationship defined with matching identifiers; otherwise the traversal returns nothing../infrahub-managing-schemas/rules/relationship-identifiers.md
Validates a node against a related node's state (child vs parent lifecycle, peer consistency)Fetch the related node's comparison attribute in the query by traversing the relationship; a check runs one query with no lazy fetchrules/patterns-relationship-traversal.md
Is targeted (per-object)Register a CoreStandardGroup as targets: in .infrahub.yml and map parameters: to bind GraphQL variablesrules/registration-config.md
Needs the GraphQL response keyed to typed nodesSelect id and __typename in the query — the SDK relies on both../infrahub-common/graphql-queries.md
Should never block a merge but only annotateUse self.log_info() instead of log_error(); log_warning() does not existrules/python-validate.md

Before writing Python

If a cheaper layer can express the constraint, use it. A schema constraint runs at load time on every write path; a Python check runs only inside the proposed- change pipeline, so bad data created via other paths slips through. Walk this short ladder before reaching for InfrahubCheck:

SignalCheaper layerSee rule
Validating uniqueness, presence, allowed values, or regex on a single attributeSchema constraint (uniqueness_constraints, optional: false, kind: Dropdown choices, regex)yagni-python-validator-vs-schema-constraint
Check whose body is a GraphQL query plus a single if len(...) > 0: raiseOne .gql file plus 5 lines of Pythonyagni-redundant-check-that-graphql-can-answer
Enforcing that a relationship is single-peered or non-optionalSchema cardinality: one, kind: Parent / Component, optional: falseyagni-python-validator-vs-schema-constraint

Only when none of these apply should you write a Python check. The cross-node business rules, out-of-band reconciliations, and stateful assertions in rules/python-validate.md are the legitimate use cases.

When the check reads objects through the SDK (rather than only its GraphQL query), type those calls with generated protocol classes rather than string kinds — client.get(DcimDevice, ...), not kind="DcimDevice". Match the --sync protocol variant to the check's client. See protocols-adopt-typed-kinds.

Check Basics

Every check has three components:

  1. GraphQL query (.gql file) -- fetches the data to validate, and is registered under the top-level queries: section of .infrahub.yml
  2. Python class -- inherits from InfrahubCheck, sets query = "<query_name>", implements validate()
  3. Configuration -- declared in .infrahub.yml under check_definitions (which does not take a query: field — see below)
from infrahub_sdk.checks import InfrahubCheck


class MyCheck(InfrahubCheck):
    query = "my_query"  # Must match queries[].name in .infrahub.yml

    def validate(self, data: dict) -> None:
        # Validation logic here
        if something_is_wrong:
            self.log_error(
                message="Problem description"
            )

Where the query is bound: the Python class (query = "..."), not check_definitions. The repository config model uses extra="forbid", so putting query: under check_definitions: makes the whole repo config fail validation. This is the most common confusion vs. generator_definitions:, which does take a top-level query:. See rules/registration-config.md.

Workflow

Follow these steps when creating a check:

  1. Understand the validation goal — What data condition should block a proposed change? Determine whether this is a global check (all objects of a type) or targeted (specific group). Read rules/architecture-types.md.
  2. Write the GraphQL query — Create a .gql file that fetches the data to validate. Read ../infrahub-common/graphql-queries.md for query patterns. If the rule compares a node against a related node's state (child vs parent lifecycle, peer consistency), the query must fetch that related attribute by traversing the relationship now — a check runs one query with no later fetch. See rules/patterns-relationship-traversal.md.
  3. Implement the Python class — Inherit from InfrahubCheck, implement validate(). Read rules/python-validate.md for the class pattern and rules/api-reference.md for available methods. If the check calls back into Infrahub, read rules/api-error-surfaces.md too: a rejected GraphQL request still returns HTTP 200, so branching on a status code makes the check pass on the failure it exists to catch. If the logic is shared with a generator or a transform, read rules/patterns-shared-module.md before reaching for a relative import.
  4. Register in .infrahub.yml — Add the check under check_definitions. The query name must match the Python class query attribute. See rules/registration-config.md.
  5. Add tests — Create YAML-driven test definitions (smoke, unit, integration) alongside the check so it is validated automatically in the proposed change pipeline. Read rules/testing-resource-framework.md.
  6. Test locally — Run infrahubctl check to validate against a feature branch. See rules/testing-commands.md. To run a changed check against an existing proposed change, read rules/testing-proposed-change-commit.md: the pipeline runs the code at the source branch's repository commit, not main's, and a branch rebase does not move it on a branch synced with Git.

Supporting References

Comments

Markdown supported