Linting & Code Quality
Relevant source files
The following files were used as context for generating this wiki page:
Linting and code quality standards in the opsmill.infrahub collection ensure codebase consistency, documentation accuracy, and compliance with Ansible module requirements. The project employs a multi-layered verification strategy that spans Python code, Markdown prose, YAML configurations, and Ansible-specific sanity checks.
This quality framework acts as a gate for all contributions, with automated checks integrated into both the local development environment via invoke tasks and the Continuous Integration (CI) pipeline. Successful execution of these tools is a prerequisite for merging code into the develop and stable branches.
Sources: dev/constitution.md:73-77, AGENTS.md:27-39
Technical Quality Stack
The project utilizes a specific set of tools to enforce various aspects of code quality.
| Layer | Tool | Purpose |
|---|---|---|
| Python | Ruff | Formatter and Linter (replaces pep8 and others) |
| Python | mypy | Static type checking |
| Python | autoflake | Removes unused imports and variables |
| Markdown | rumdl | Structure and formatting linting |
| YAML | yamllint | YAML file and front-matter validation |
| Prose | Vale | Style consistency for documentation site |
| Ansible | ansible-test sanity | Compliance with Ansible module standards |
| Ansible | ansible-lint | Ansible-specific best practices |
Sources: dev/guidelines/python.md:4-6, dev/guidelines/markdown.md:12-20, AGENTS.md:14-22, dev/constitution.md:73-77
Python Code Quality
Python quality is primarily managed through Ruff, which is configured in pyproject.toml. The project adopts a "strict-by-default" approach by selecting all rules while maintaining specific exclusions for compatibility and practical development.
Formatting and Linting Standards
- Line Length: The target line length is 120 characters, with a hard limit of 150 characters for
pycodestylecompliance. - Complexity: McCabe complexity is capped at a maximum of 19.
- Indentation: The project uses spaces for indentation.
- Quote Style: Double quotes are required for strings.
- Type Hints: Modern type hints (e.g.,
str | None) are preferred, supported byfrom __future__ import annotations.
Sources: dev/guidelines/python.md:10-23, dev/guidelines/python.md:65-68, pyproject.toml:137-142
Ruff Configuration and Ignores
The project enables preview = true and select = ["ALL"]. Several categories are permanently ignored to avoid conflicts or manual overhead:
COM812: Trailing comma (conflicts with formatter).CPY: Copyright notices (handled manually).D: Docstring conventions.FBT: Boolean trap.ISC: Implicit string concatenation.
Specific files like plugins/**/*.py have unique ignores (e.g., ANN201, UP001) to maintain compatibility with Ansible's internal parsing requirements.
Sources: dev/guidelines/python.md:29-54, pyproject.toml:158-185
Static Type Checking (mypy)
CI runs uv run mypy . to verify type safety. Crucially, invoke lint does not run mypy; developers must execute it manually.
- Excluded Files: The largest file,
plugins/module_utils/infrahub_utils.py, is currently excluded from type checking. - Strictness:
warn_return_any,disallow_untyped_defs, andwarn_unused_ignoresare enabled.
Sources: dev/guidelines/python.md:72-88, pyproject.toml:86-96
Documentation and Prose Quality
The quality of documentation is enforced through specialized linters that check both technical structure and linguistic style.
Markdown and YAML
- rumdl: Validates Markdown structure. It excludes the
docs/directory (managed by Vale) and specific rules likeMD013(line length) andMD033(inline HTML) to support MDX/React components. - yamllint: Ensures all YAML files and embedded front matter are valid. This is particularly important for the
DOCUMENTATIONblocks inside Python plugins.
Sources: dev/guidelines/markdown.md:12-25, dev/guidelines/markdown.md:31-36
Vale Prose Linting
Vale enforces the Infrahub prose style defined in .vale/styles/. It primarily targets the Docusaurus site content within docs/**/*.{md,mdx}.
Sources: dev/guidelines/markdown.md:15-18, dev/guidelines/documentation.md:122-124
Ansible Sanity and Boilerplate
The ansible-test sanity suite is a non-negotiable quality gate that validates the collection against Ansible's internal standards.
Required Python Boilerplate
To pass sanity checks, every plugin file must include specific headers to ensure Python 2/3 compatibility, despite the project's Python 3.11+ requirement:
from __future__ import absolute_import, annotations, division, print_function
__metaclass__ = type
Sources: dev/constitution.md:11-15, dev/guides/debugging-sanity-failures.md:22-31
Documentation Accuracy Guardrail
Plugin documentation (DOCUMENTATION, EXAMPLES, RETURN) is defined as module-level YAML strings. These are the single source of truth.
- Any change to these strings requires running
invoke generate-doc. - Generated MDX files in
docs/docs/references/plugins/must never be hand-edited.
Sources: dev/constitution.md:83-87, dev/guidelines/documentation.md:8-15, AGENTS.md:110-112
Quality Workflow and Automation
The development workflow uses invoke tasks to sequence quality checks. The CI pipeline replicates these checks to prevent regression.
Execution Flow
The following diagram illustrates the standard local quality check sequence before a Pull Request.
The diagram shows the sequence of commands required to satisfy the project's quality gates.
Sources: AGENTS.md:43-46, tasks/linter.py:9-25
Invoke Task Definitions
invoke lint: Runsautoflake,ruff(check/diff),yamllint, andrumdl. It is not purely a check;autoflakemodifies files in place.invoke format: Runsruff formatandruff check --fixto automatically resolve style issues.invoke tests-sanity: Executesansible-test sanitywithin a Docker container to ensure environment consistency.
Sources: tasks/linter.py:9-30, tasks/linter.py:73-80, dev/guidelines/testing.md:18-24
Summary of Quality Gates
The following table summarizes the primary gates and their associated actions.
| Gate | Command | Consequence of Failure |
|---|---|---|
| Linting | invoke lint | Rejected by CI python-lint job |
| Typing | uv run mypy . | Rejected by CI python-lint job |
| Ansible Compliance | invoke tests-sanity | Rejected by CI Ansible tests job |
| Changelog | N/A | PR fails if news fragment missing in changelog/ |
| Documentation | invoke generate-doc | Out-of-sync docs site; potential CI failure |
Sources: AGENTS.md:41-48, dev/guidelines/testing.md:195-200, AGENTS.md:53-55