Python 3.13#7746
Conversation
WalkthroughDockerfiles and GitHub Actions were updated to use Python 3.13.11 via a new PYTHON_VERSION workflow output. pyproject.toml expanded the Python compatibility range to >=3.12,<3.14, added Python 3.13 classifier, and updated multiple dependencies. Many backend modules now access model_fields via class-level attributes (self.class.model_fields). Neo4j configuration uses NotificationDisabledClassification. Test infra was refactored to use build_database/get_database with optional singleton scoping via dependency provider.scope. Generated TypeScript types and OpenAPI schemas were widened to allow additional properties. Pre-merge checks❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
409905c to
347a396
Compare
CodSpeed Performance ReportMerging #7746 will not alter performanceComparing Summary
|
96cb0de to
604719f
Compare
4ec7ddd to
46ff31d
Compare
075e1b2 to
414ccd5
Compare
ebd9c6a to
9976fef
Compare
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
backend/infrahub/cli/db.py (1)
240-254: index() always uses Neo4j index manager, ignoring Memgraph branchIn
index(),index_manageris set for Memgraph and then immediately overwritten:if dbdriver.db_type is DatabaseType.MEMGRAPH: index_manager: IndexManagerBase = IndexManagerMemgraph(db=dbdriver) index_manager = IndexManagerNeo4j(db=dbdriver)This means Memgraph never uses
IndexManagerMemgraph. You probably want anelse:- if dbdriver.db_type is DatabaseType.MEMGRAPH: - index_manager: IndexManagerBase = IndexManagerMemgraph(db=dbdriver) - index_manager = IndexManagerNeo4j(db=dbdriver) + if dbdriver.db_type is DatabaseType.MEMGRAPH: + index_manager: IndexManagerBase = IndexManagerMemgraph(db=dbdriver) + else: + index_manager = IndexManagerNeo4j(db=dbdriver)so each backend gets the correct index manager.
🧹 Nitpick comments (7)
backend/infrahub/core/graph/schema.py (1)
237-261: Align GRAPH_SCHEMA typing with get_graph_schema and constraint consumers
GRAPH_SCHEMAis now annotated asdict[str, dict[str, type[Any]]]whileget_graph_schema()is still declared to returndict[str, dict[str, Any]], andConstraintManagerBase.from_graph_schemaexpectsdict[str, dict[str, type[BaseModel]]]. For clearer mypy/ruff checks and lessAnyleakage, consider tighteningget_graph_schema()(and optionallyGRAPH_SCHEMA) to a compatible type such as:-def get_graph_schema() -> dict[str, dict[str, Any]]: +def get_graph_schema() -> dict[str, dict[str, type[Any]]]:or even a
type[BaseModel]–based signature if you want to reflect the actual classes used.Also applies to: 264-264
backend/infrahub/core/graph/constraints.py (1)
179-208: from_graph_schema typing tightened appropriately; consider aligning GRAPH_SCHEMA producerChanging
from_graph_schemato acceptdict[str, dict[str, type[BaseModel]]]and annotatingproperties_classastype[BaseModel]better reflects that the schema holds model classes and matches howmodel_fieldsis used.To fully benefit from this, you may want
get_graph_schema()/GRAPH_SCHEMA(inbackend/infrahub/core/graph/schema.py) to expose compatible typing instead ofAnyfor the inner type, so callers and this method agree on the schema shape..github/workflows/keyword-scan.yml (1)
19-23: Consider sourcing Python version fromdefine-versionsfor consistencyHard‑coding
python-version: 3.14is fine, but to avoid future drift fromPYTHON_VERSIONindefine-versions.yml, consider wiring this workflow through the sameprepare-environmentindirection used elsewhere and reading${{ needs.prepare-environment.outputs.PYTHON_VERSION }}.backend/tests/unit/api/conftest.py (1)
2-3: Non‑singleton DB override inclientfixture looks correct and consistentUsing
dependency_provider: Providerplus an internal async_db(singleton: bool = True) -> InfrahubDatabasethat delegates tobuild_database(singleton=False)and scoping it viawith dependency_provider.scope(build_database, _db)ensures API tests get a fresh, non‑singletonInfrahubDatabasethrough the DI path without affecting other call sites. This aligns with the updatedbuild_database(singleton: bool = True)contract and the globaldependency_providerfixture inbackend/tests/conftest.py.If you want to make the intent clearer, you could add a short docstring on
_dbstating that thesingletonargument is only there for signature compatibility and is intentionally ignored in favor of always returning a non‑singleton instance, but the current implementation is functionally sound.Also applies to: 13-14, 18-26
backend/infrahub/workers/dependencies.py (1)
63-72:build_database(singleton: bool)implementation correctly separates singleton and non‑singleton pathsThe revised
build_databasecleanly handles both cases:
not singleton→ always constructs a newInfrahubDatabaseand skips_singletonscaching.singletonwith no cache → constructs, caches in_singletons["database"], and returns it.singletonwith cache present → returns the cached instance.This preserves the previous singleton behavior for default callers while enabling tests (and other consumers) to opt out with
singleton=Falsewithout mutating global state.Given this is now part of the public DI surface, it would be helpful to add a short Google‑style docstring explaining the semantics of the
singletonflag and thatsingleton=Falseis primarily intended for scoped/test usage.backend/tests/conftest.py (1)
50-51: DB fixture’s DI‑based non‑singleton override and teardown look correctThe updated
dbfixture now:
- Uses an internal async
_db(singleton: bool = True) -> InfrahubDatabasethat always callsbuild_database(singleton=False), ensuring non‑singleton instances for tests.- Wraps its body in
with provider.scope(build_database, _db):and obtains the database viaawait get_database(), so any DI path depending onbuild_databasewithin this scope transparently uses the overridden factory.- Calls
await add_indexes(db=driver)before yielding andawait driver.close()afterwards, which keeps index setup and connection teardown explicit.This pattern is consistent with the new
build_database(singleton)API and the other test helpers. If you want to further clarify intent, you could add a brief comment or docstring on_dbnoting thatsingletonis present solely for signature compatibility withbuild_database.Also applies to: 59-59, 125-147
backend/tests/helpers/test_app.py (1)
33-34: Scopedbuild_databaseoverride intest_clientmatches the new DI patternImporting
build_databasehere and updating thetest_clientfixture to:
- Accept
dependency_provider: Provideranddb: InfrahubDatabase(ensuring the globaldbfixture runs and the backing DB is initialised/indexed), and- Define
_db(singleton: bool = True) -> InfrahubDatabasedelegating tobuild_database(singleton=False), used withinwith dependency_provider.scope(build_database, _db): async with lifespan(app): ...gives the FastAPI app a non‑singleton
InfrahubDatabasethrough the same DI mechanism used in production code while still relying on the shared test DB server configuration.This is consistent with the
dbfixture changes inbackend/tests/conftest.py. As in other places, the unusedsingletonargument in_dbis there for signature compatibility; if you find it confusing, a short comment/docstring could make that intent explicit, but the current behavior is sound.Also applies to: 139-159
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
uv.lockis excluded by!**/*.lock
📒 Files selected for processing (37)
.devcontainer/Dockerfile(1 hunks).github/workflows/ci.yml(17 hunks).github/workflows/define-versions.yml(1 hunks).github/workflows/keyword-scan.yml(1 hunks).github/workflows/publish-pypi.yml(1 hunks).github/workflows/release.yml(1 hunks).github/workflows/update-compose-file-and-chart.yml(1 hunks).github/workflows/uv-check.yml(1 hunks).github/workflows/version-upgrade.yml(1 hunks)backend/infrahub/cli/db.py(1 hunks)backend/infrahub/core/diff/model/diff.py(1 hunks)backend/infrahub/core/graph/constraints.py(1 hunks)backend/infrahub/core/graph/schema.py(1 hunks)backend/infrahub/core/models.py(5 hunks)backend/infrahub/core/node/standard.py(1 hunks)backend/infrahub/core/schema/attribute_schema.py(1 hunks)backend/infrahub/core/schema/relationship_schema.py(1 hunks)backend/infrahub/core/validators/determiner.py(2 hunks)backend/infrahub/database/__init__.py(2 hunks)backend/infrahub/workers/dependencies.py(1 hunks)backend/tests/benchmark/conftest.py(3 hunks)backend/tests/conftest.py(4 hunks)backend/tests/helpers/test_app.py(2 hunks)backend/tests/helpers/utils.py(1 hunks)backend/tests/integration/diff/test_merge_rollback.py(1 hunks)backend/tests/unit/api/conftest.py(2 hunks)backend/tests/unit/api/test_50_internals.py(3 hunks)backend/tests/unit/core/test_branch_rebase.py(1 hunks)backend/tests/unit/git/conftest.py(1 hunks)backend/tests/unit/git/test_git_repository.py(8 hunks)backend/tests/unit/graphql/mutations/test_branch.py(1 hunks)development/Dockerfile(1 hunks)frontend/app/src/shared/api/rest/types.generated.ts(6 hunks)pyproject.toml(5 hunks)schema/openapi.json(7 hunks)tasks/docs.py(2 hunks)tasks/release.py(1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
**/*.py
📄 CodeRabbit inference engine (.github/instructions/python-docstring.instructions.md)
**/*.py: Always use triple quotes (""") for Python docstrings
Follow Google-style docstring format for Python docstrings
Include brief one-line description in Python docstrings when applicable
Include detailed description in Python docstrings when applicable
Include Args/Parameters section without typing in Python docstrings when applicable
Include Returns section in Python docstrings when applicable
Include Raises section in Python docstrings when applicable
Include Examples section in Python docstrings when applicable
**/*.py: Use type hints for all function parameters and return values in Python
Use Async whenever possible in Python
Useasync deffor asynchronous functions in Python
Useawaitfor asynchronous calls in Python
Use Pydantic models for dataclasses in Python
Use ruff and mypy for type checking and code validation in PythonUse ruff and mypy to validate and lint Python files
Files:
backend/infrahub/core/graph/schema.pybackend/infrahub/cli/db.pybackend/infrahub/core/schema/attribute_schema.pybackend/tests/unit/api/conftest.pybackend/infrahub/core/validators/determiner.pybackend/infrahub/core/node/standard.pybackend/tests/unit/api/test_50_internals.pybackend/tests/integration/diff/test_merge_rollback.pybackend/tests/unit/git/conftest.pytasks/release.pybackend/tests/benchmark/conftest.pybackend/infrahub/core/graph/constraints.pybackend/tests/unit/core/test_branch_rebase.pybackend/tests/helpers/test_app.pybackend/infrahub/core/schema/relationship_schema.pybackend/infrahub/core/models.pybackend/infrahub/workers/dependencies.pytasks/docs.pybackend/infrahub/core/diff/model/diff.pybackend/tests/helpers/utils.pybackend/tests/unit/git/test_git_repository.pybackend/tests/unit/graphql/mutations/test_branch.pybackend/infrahub/database/__init__.pybackend/tests/conftest.py
backend/infrahub/**/*.py
📄 CodeRabbit inference engine (backend/AGENTS.md)
backend/infrahub/**/*.py: Use async/await for all I/O operations to maintain async-first architecture
Type hint all function parameters and returns in Python code
Use Pydantic models for defining data structures instead of plain dictionaries
Use Query class pattern (extending infrahub.core.query.Query) for all database operations instead of unparameterized Cypher queries
Use Google-style docstrings with Args, Returns, and Raises sections for all functions
Use snake_case for function and variable names
Use PascalCase for class names
Use UPPER_SNAKE_CASE for constant definitions
Do not use unparameterized Cypher queries; always use parameterized queries to prevent injection
Do not block the event loop with synchronous I/O operations
Files:
backend/infrahub/core/graph/schema.pybackend/infrahub/cli/db.pybackend/infrahub/core/schema/attribute_schema.pybackend/infrahub/core/validators/determiner.pybackend/infrahub/core/node/standard.pybackend/infrahub/core/graph/constraints.pybackend/infrahub/core/schema/relationship_schema.pybackend/infrahub/core/models.pybackend/infrahub/workers/dependencies.pybackend/infrahub/core/diff/model/diff.pybackend/infrahub/database/__init__.py
backend/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Use type hints for all Python code in the backend
Files:
backend/infrahub/core/graph/schema.pybackend/infrahub/cli/db.pybackend/infrahub/core/schema/attribute_schema.pybackend/tests/unit/api/conftest.pybackend/infrahub/core/validators/determiner.pybackend/infrahub/core/node/standard.pybackend/tests/unit/api/test_50_internals.pybackend/tests/integration/diff/test_merge_rollback.pybackend/tests/unit/git/conftest.pybackend/tests/benchmark/conftest.pybackend/infrahub/core/graph/constraints.pybackend/tests/unit/core/test_branch_rebase.pybackend/tests/helpers/test_app.pybackend/infrahub/core/schema/relationship_schema.pybackend/infrahub/core/models.pybackend/infrahub/workers/dependencies.pybackend/infrahub/core/diff/model/diff.pybackend/tests/helpers/utils.pybackend/tests/unit/git/test_git_repository.pybackend/tests/unit/graphql/mutations/test_branch.pybackend/infrahub/database/__init__.pybackend/tests/conftest.py
backend/tests/**/*.py
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Run backend tests with
pytestor viainvoketasksName test files as
test_<module>.pyand mirror source structure in tests directory
Files:
backend/tests/unit/api/conftest.pybackend/tests/unit/api/test_50_internals.pybackend/tests/integration/diff/test_merge_rollback.pybackend/tests/unit/git/conftest.pybackend/tests/benchmark/conftest.pybackend/tests/unit/core/test_branch_rebase.pybackend/tests/helpers/test_app.pybackend/tests/helpers/utils.pybackend/tests/unit/git/test_git_repository.pybackend/tests/unit/graphql/mutations/test_branch.pybackend/tests/conftest.py
frontend/app/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript types for all frontend code
Files:
frontend/app/src/shared/api/rest/types.generated.ts
{pyproject.toml,uv.lock}
📄 CodeRabbit inference engine (.github/instructions/tooling.instructions.md)
Use uv to manage the Python project and its dependencies
Files:
pyproject.toml
🧠 Learnings (9)
📚 Learning: 2025-11-18T08:30:19.721Z
Learnt from: fatih-acar
Repo: opsmill/infrahub PR: 7669
File: .github/workflows/update-compose-file-and-chart.yml:52-53
Timestamp: 2025-11-18T08:30:19.721Z
Learning: The `uv version` command returns the project version from pyproject.toml (since astral-sh/uv PR #12349). Use `uv version --short` to extract project version for version checks and comparisons in workflows. The old behavior (showing UV's own tool version) is now `uv self version`.
Applied to files:
.github/workflows/uv-check.yml
📚 Learning: 2025-12-01T22:15:47.401Z
Learnt from: CR
Repo: opsmill/infrahub PR: 0
File: .github/instructions/tooling.instructions.md:0-0
Timestamp: 2025-12-01T22:15:47.401Z
Learning: Applies to {pyproject.toml,uv.lock} : Use uv to manage the Python project and its dependencies
Applied to files:
.github/workflows/uv-check.yml.github/workflows/release.yml.github/workflows/update-compose-file-and-chart.yml.github/workflows/version-upgrade.yml.github/workflows/ci.yml
📚 Learning: 2025-12-01T22:15:34.303Z
Learnt from: CR
Repo: opsmill/infrahub PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-01T22:15:34.303Z
Learning: Applies to backend/pyproject.toml : Use `uv` for dependency management in backend Python projects
Applied to files:
.github/workflows/uv-check.yml.github/workflows/release.yml.github/workflows/update-compose-file-and-chart.yml.github/workflows/version-upgrade.yml.github/workflows/ci.ymlpyproject.toml
📚 Learning: 2025-12-01T22:16:13.680Z
Learnt from: CR
Repo: opsmill/infrahub PR: 0
File: backend/AGENTS.md:0-0
Timestamp: 2025-12-01T22:16:13.680Z
Learning: Applies to backend/infrahub/core/schema/generated/**/*.py : Do not edit files in `infrahub/core/schema/generated/` as they are auto-generated
Applied to files:
backend/infrahub/core/schema/attribute_schema.py
📚 Learning: 2025-12-02T08:57:42.248Z
Learnt from: CR
Repo: opsmill/infrahub PR: 0
File: docs/docs/topics/AGENTS.md:0-0
Timestamp: 2025-12-02T08:57:42.248Z
Learning: Applies to docs/docs/topics/**/topics/**/*.mdx : Use consistent Infrahub terminology: 'Branch' (not 'workspace' or 'environment'), 'Schema' (not 'model definition'), 'Proposed change' (not 'pull request'), 'Attribute' (not 'field' or 'property')
Applied to files:
tasks/docs.py
📚 Learning: 2025-12-01T22:16:13.680Z
Learnt from: CR
Repo: opsmill/infrahub PR: 0
File: backend/AGENTS.md:0-0
Timestamp: 2025-12-01T22:16:13.680Z
Learning: Applies to backend/infrahub/**/*.py : Use Query class pattern (extending infrahub.core.query.Query) for all database operations instead of unparameterized Cypher queries
Applied to files:
backend/infrahub/database/__init__.py
📚 Learning: 2025-12-01T22:16:13.680Z
Learnt from: CR
Repo: opsmill/infrahub PR: 0
File: backend/AGENTS.md:0-0
Timestamp: 2025-12-01T22:16:13.680Z
Learning: Applies to backend/infrahub/**/*.py : Type hint all function parameters and returns in Python code
Applied to files:
pyproject.toml
📚 Learning: 2025-12-01T22:16:13.680Z
Learnt from: CR
Repo: opsmill/infrahub PR: 0
File: backend/AGENTS.md:0-0
Timestamp: 2025-12-01T22:16:13.680Z
Learning: Applies to backend/infrahub/**/*.py : Use PascalCase for class names
Applied to files:
pyproject.toml
📚 Learning: 2025-12-01T22:16:13.680Z
Learnt from: CR
Repo: opsmill/infrahub PR: 0
File: backend/AGENTS.md:0-0
Timestamp: 2025-12-01T22:16:13.680Z
Learning: Applies to backend/infrahub/**/*.py : Use UPPER_SNAKE_CASE for constant definitions
Applied to files:
pyproject.toml
🧬 Code graph analysis (9)
backend/infrahub/core/graph/schema.py (1)
backend/infrahub/types.py (1)
Any(312-319)
backend/infrahub/cli/db.py (1)
backend/infrahub/core/graph/schema.py (5)
GraphNodeProperties(37-45)GraphRelationshipProperties(81-84)GraphAttributeProperties(112-115)GraphRelationshipIsPartOf(216-219)GraphRelationshipDefault(222-234)
backend/tests/unit/api/conftest.py (3)
backend/infrahub/workers/dependencies.py (3)
build_database(63-72)build_message_bus(93-100)build_workflow(119-126)backend/tests/unit/git/conftest.py (1)
client(31-32)backend/tests/conftest.py (2)
dependency_provider(121-122)_db(137-138)
backend/infrahub/core/validators/determiner.py (1)
backend/infrahub/core/schema/attribute_parameters.py (1)
AttributeParameters(24-25)
backend/tests/unit/api/test_50_internals.py (1)
backend/tests/unit/api/conftest.py (1)
client(18-26)
backend/tests/unit/core/test_branch_rebase.py (2)
backend/tests/conftest.py (1)
db(126-146)backend/infrahub/workers/dependencies.py (1)
build_database(63-72)
backend/infrahub/workers/dependencies.py (1)
backend/tests/conftest.py (1)
db(126-146)
backend/tests/unit/graphql/mutations/test_branch.py (2)
backend/tests/conftest.py (2)
dependency_provider(121-122)db(126-146)backend/infrahub/workers/dependencies.py (1)
build_database(63-72)
backend/tests/conftest.py (2)
backend/infrahub/database/__init__.py (2)
InfrahubDatabase(141-445)close(310-311)backend/infrahub/workers/dependencies.py (2)
build_database(63-72)get_database(76-77)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Cloudflare Pages
🔇 Additional comments (47)
backend/tests/integration/diff/test_merge_rollback.py (1)
34-45: LGTM! Fixes infinite recursion in test fixture.Storing the original
merge_graphmethod reference before replacing it (line 37) and then calling the stored reference (line 44) prevents infinite recursion. Without this change, line 44 would call the already-patchedself.real_merger.diff_merger.merge_graph, which points back toself.merge_graph(set on line 38), creating an infinite loop.The updated pattern correctly implements method wrapping: store original → replace with wrapper → wrapper calls stored original.
backend/tests/unit/git/conftest.py (1)
612-617: LGTM! Proper mock reusability configuration.The
is_reusable=Trueflag is appropriate here since the mock response uses a regex pattern that matches multiple branches and is likely consumed by multiple tests.backend/tests/unit/git/test_git_repository.py (3)
481-481: LGTM! Selective mocking for prefect requests.The decorator correctly filters out prefect-originated requests from mocking, allowing the test infrastructure to function properly while still mocking application HTTP calls.
506-506: LGTM! Mock reusability configured appropriately.The
is_reusable=Trueflag on the admin status mutation mock enables it to be matched multiple times during test execution.
582-582: LGTM! Consistent selective mocking across prefect-enabled tests.The httpx_mock decorators are uniformly applied across all tests that use the prefect_test_fixture, ensuring that prefect infrastructure requests are not mocked while application HTTP calls remain under test control.
Also applies to: 644-644, 667-667, 703-703, 737-737, 773-773
tasks/release.py (1)
407-420: Class-level model_fields usage in gen_config_env looks goodIterating over
subset.__class__.model_fieldskeeps the recursion and env/default extraction logic unchanged while aligning with class-based metadata access used elsewhere. No issues spotted.backend/infrahub/cli/db.py (1)
606-619: Tuple-based graph_*_schemas and variable renames are fineUsing tuples for
graph_node_schemas/graph_edge_schemasand more specific loop variables is a readability win with no behavioral change; property extraction frommodel_fieldsremains the same.tasks/docs.py (2)
200-210: Class-level parameters.model_fields access is appropriateIterating over
init_schema.parameters.__class__.model_fieldsstill examines the same parameter fields while relying on class metadata, which is consistent with other Pydantic-2-oriented changes. The filtering byjson_schema_extra["update"] == "validate_constraint"is preserved.
494-505: _get_env_vars now correctly relies on settings class metadataUsing
settings.__class__.model_fields.items()keeps env-var discovery semantics intact and makes the introspection independent of instance state. The mapping intoenv_varsremains unchanged.backend/infrahub/core/schema/attribute_schema.py (1)
169-176: update_from_generic’s switch to class-level model_fields is fineLooping over
self.__class__.model_fieldsinstead ofself.model_fieldskeeps the update semantics identical while relying on class metadata, matching the pattern used elsewhere in the codebase.backend/infrahub/core/node/standard.py (1)
257-288: to_db using self.class.model_fields matches existing from_db usageThe switch to iterating over
self.__class__.model_fieldskeeps the to_db serialization behavior the same and is consistent withfrom_db, which already uses class-levelmodel_fields. No issues found.backend/infrahub/core/diff/model/diff.py (1)
21-35: BaseDiffElement.to_graphql class-level model_fields access is correctResolving
field_infoviaself.__class__.model_fields[key]maintains the existing export logic (exclude handling, Enum/Timestamp/Node conversions) while using class metadata as intended. Looks good.backend/infrahub/core/schema/relationship_schema.py (1)
84-91: Class-levelmodel_fieldsusage inupdate_from_genericlooks correctIterating over
self.__class__.model_fieldskeeps behavior consistent with the rest of the codebase and Pydantic’s class-level field metadata; no functional issues spotted.backend/infrahub/core/validators/determiner.py (2)
96-134: Schema property constraint introspection remains sound with class-levelmodel_fieldsUsing
schema.__class__.model_fields.items()for constraint discovery keeps the logic aligned with how fields are declared on the schema type and matches the broader refactor in this PR; no behavioral issues identified.
156-169: Field/parameter constraint discovery correctly moved to class-levelmodel_fieldsSwitching to
field.__class__.model_fieldsandp_value.__class__.model_fieldspreserves the existing semantics while ensuring parameter fields from subclasses (e.g., specificAttributeParametersvariants) are included; try/except still safely handles missing metadata.schema/openapi.json (4)
979-1102: GraphQL query response schemas correctly widened viaadditionalProperties: trueAllowing arbitrary top-level keys in the GraphQL query POST/GET 200 responses matches the dynamic nature of GraphQL results and aligns with the widened frontend types; no API surface change beyond more accurate documentation.
3971-3974:ComputedAttribute-Outputnow models an open object, which matches usageDefining it as
{ "type": "object", "additionalProperties": true }correctly reflects that computed attributes may emit arbitrary key/value pairs; this improves spec accuracy without tightening server behavior.
4478-4583: JSONSchema meta-schema relaxed to accept arbitrary nested schema propertiesAdding
"additionalProperties": trueto the variousJSONSchemaobject/array contexts (properties,items, nesteditems, andadditionalPropertiesbranch) reflects real JSON Schema flexibility and avoids over-constraining tooling generated from this OpenAPI definition; looks intentional and consistent.
5305-5315:QueryPayload.variablescorrectly modeled as a free-form mapChanging
variablesto{ "type": "object", "additionalProperties": true }matches GraphQL’sRecord<string, any>variable bag and aligns with the TS client widening; this is a good compatibility improvement.backend/infrahub/core/models.py (5)
260-307: Constraint routing now uses class-level field metadata; logic unchangedUsing
field.__class__.model_fields[prop_name]and thenprop_field.__class__.model_fields[param_field_name]keeps the existing constraint-routing behavior while standardizing on class-based field metadata; the surrounding try/except still gracefully handles missing or non-model parameter fields.
308-325: Node-level attribute constraint resolution correctly usesschema.__class__.model_fieldsLooking up
node_field_nameviaschema.__class__.model_fieldsis consistent with the rest of the refactor and still drives_process_fieldoff the samejson_schema_extra["update"]hints as before; no functional regression spotted.
417-443: Hash computation overself.__class__.model_fieldsremains deterministic and compatibleIterating over
sorted(self.__class__.model_fields.keys())keeps the hash derivation ordered and based solely on declared model fields, matching prior behavior while standardizing on class-level metadata; no new edge cases identified givenextra="forbid"usage in these models.
569-607:updatenow iterates class-level fields ofother; semantics are preservedLooping over
other.__class__.model_fields.keys()matches the previous intent of only considering declared model fields, and the existing guards (hasattr(self, field_name), type checks, list/HashableModel handling) remain unchanged; cross-type updates should behave as before.
615-617: Diff field-name discovery via class-levelmodel_fieldsis consistent with hashing/updatingReturning
list(self.__class__.model_fields.keys())for_get_field_names_for_diffkeeps diff computation aligned with the same declared field set used byget_hashandupdate, which is desirable for consistent change detection.frontend/app/src/shared/api/rest/types.generated.ts (4)
1306-1308: Looser but still type‑safeComputedAttribute-Outputlooks appropriateWidening
ComputedAttribute-Outputto{ [key: string]: unknown }better reflects a dynamic payload while keeping type safety viaunknowninstead ofany. Given this is generated code, this shape is reasonable and matches TypeScript best practices.
1536-1538: JSONSchema field widening matches generic JSON Schema semanticsUsing
{ [key: string]: unknown }forproperties,items, andadditionalPropertiesaligns better with real JSON Schema objects than the previous “no props” shape, while still avoidingany. This should make consumers’ intent clearer without sacrificing type safety.Also applies to: 1543-1547, 1562-1564
1927-1929:QueryPayload.variablesas a generic map is a sensible GraphQL modelTyping
variablesas{ [key: string]: unknown }matches how GraphQL variables are used in practice and keeps things type‑safe (consumers must narrow). This is a good improvement over an effectively empty record.
2827-2829: Generic GraphQL response maps are reasonable given dynamic query shapesModeling the GraphQL 200
"application/json"bodies as{ [key: string]: unknown }is pragmatic since the schema can’t express per‑query shapes. This pairs well with the widenedQueryPayload.variables; consumers that need stronger typing can define narrower interfaces at call sites.Also applies to: 2874-2876
development/Dockerfile (1)
4-4: Dev image Python version aligned with 3.14.2 baselineUsing
ARG PYTHON_VER=3.14.2matches the centralizedPYTHON_VERSIONoutput and the devcontainer image; this keeps local dev and CI images consistent..devcontainer/Dockerfile (1)
1-1: Devcontainer base image correctly moved to Python 3.14.2Pinning to
python:3.14.2keeps the devcontainer in sync with the development Dockerfile and the workflowPYTHON_VERSIONoutput, avoiding “works in container but not in CI” drift.backend/tests/helpers/utils.py (1)
47-52: Prefect test container tag aligned with Python 3.14Switching to
prefecthq/prefect:3.5.0-python3.14matches the project’s Python baseline and the pinnedprefect==3.5.0dependency, so Prefect tests run against the same major/minor runtime as the rest of the stack..github/workflows/define-versions.yml (1)
7-10: CentralizedPYTHON_VERSIONoutput looks goodAdding
PYTHON_VERSION: "3.14.2"here gives a single source of truth that other workflows can consume, keeping CI, Docker images, andrequires-pythonin sync.backend/tests/benchmark/conftest.py (1)
2-22: Async benchmark helpers updated for newer pytest‑asyncio; double‑check event loop behaviorUsing
inspect.iscoroutinefunctionand dropping theevent_loopfixture in favor ofasyncio.get_event_loop().run_until_complete(...)matches pytest‑asyncio’s newer patterns and should keep these fixtures working under pytest 9.x. However, this now depends on a globally available loop (especially withasyncio_default_fixture_loop_scope = "session"), and synchronous callers ofexec_async/aio_benchmarkwill fail if no loop is set.Please verify that:
- Both sync and async tests using these fixtures still behave as expected under Python 3.14 with the new pytest/pytest‑asyncio versions.
- There are no call sites passing coroutine objects instead of coroutine functions, since the
iscoroutinefunctioncheck would skip those.Also applies to: 25-38
pyproject.toml (3)
6-16: Python version metadata matches the 3.14 rolloutUpdating
requires-pythonto>=3.12,<3.15and adding classifiers for 3.13 and 3.14 is consistent with the Docker images and workflowPYTHON_VERSIONoutput, and keeps 3.15+ explicitly out until tested.
18-21: Dependency and uv source updates look coherent; confirm compatibility is fully captured inuv.lockThe dependency bumps (e.g.
pydantic>=2.12,<2.13,pytest>=9.0,<9.1,pytest-asyncio>=1.3,<1.4, updated OpenTelemetry exporters/instrumentation,aiodataloader==0.4.3,fast-depends==3.0.5,prefect-redis==0.2.7,asyncpg==0.31.0) and the move to git‑backedneo4j/neo4j-rust-extvia[tool.uv.sources]align with the code changes (e.g. new Neo4j notification API) and the “use uv for dependency management” guideline. Based on learnings, this is the right direction.Given that some deps now have wide or no upper bounds (
neo4jvia VCS,pyarrow>=14,numpy>=1.26.2), please make sure:
uv.lockpins concrete versions/commits for all of these so CI and production are reproducible.- The pinned
neo4jversion is the one that supportsNotificationDisabledClassificationandnotifications_disabled_classificationsused inbackend/infrahub/database/__init__.py.- The newer pytest/pytest‑asyncio and OpenTelemetry versions don’t introduce breaking changes in existing tests or telemetry setup.
Also applies to: 23-24, 31-33, 34-34, 41-47, 47-55, 59-61, 63-70, 77-82, 84-115
89-90: Pytest asyncio configuration and dev deps align with new fixtures; validate end‑to‑endBumping
pytest-asyncioto>=1.3,<1.4and addingasyncio_default_fixture_loop_scope = "session"in[tool.pytest.ini_options]matches the fixture changes inbackend/tests/benchmark/conftest.pyand the switch away from the deprecatedevent_loopfixture. This should reduce flakiness but also means a single loop is reused widely.Please run the test suite under Python 3.14 to confirm:
- No deprecation/runtime warnings from pytest‑asyncio regarding fixture modes.
- Fixtures like
exec_async/aio_benchmarkand any others relying on the event loop behave correctly with a session‑scoped loop (no cross‑test interference).Also applies to: 143-147
backend/infrahub/database/__init__.py (1)
16-23: Neo4j notification config correctly migrated toNotificationDisabledClassificationThe import and driver initialization at lines 16-23 and 490-499 are correct. The migration from the old
NotificationDisabledCategoryAPI to the newNotificationDisabledClassificationis complete across the codebase, with no stale references remaining. The Neo4j Python driver version (sourced from the latest git repository) supports this API signature..github/workflows/release.yml (1)
28-33: Use of centralizedPYTHON_VERSIONoutput in release workflow looks correct
check_releasealreadyneeds: prepare-environment, so switchingpython-versionto${{ needs.prepare-environment.outputs.PYTHON_VERSION }}keeps things consistent with other workflows and avoids hard‑coding. No further changes needed..github/workflows/version-upgrade.yml (1)
55-63: Version‑upgrade workflow now correctly follows centralized Python version
migration-testsdepends onprepare-environment, so using${{ needs.prepare-environment.outputs.PYTHON_VERSION }}foractions/setup-pythonis safe and aligns with the new single‑source versioning..github/workflows/update-compose-file-and-chart.yml (1)
36-45: Dynamic Python version in compose/chart updater is consistent with tooling approachUsing
${{ needs.prepare-environment.outputs.PYTHON_VERSION }}here matches the central version definition and theuv‑based workflow everywhere else. This reduces drift between CI and dev images..github/workflows/publish-pypi.yml (1)
41-46: Publish‑to‑PyPI job correctly switched to the shared Python versionReferencing
${{ needs.prepare-environment.outputs.PYTHON_VERSION }}foractions/setup-pythonkeeps package builds aligned with the defined project Python version; the rest of the uv‑based flow is unchanged.backend/tests/unit/core/test_branch_rebase.py (1)
93-103: DB override lambda now correctly matchesbuild_database’ssingletonsignatureAdapting the override to
lambda singleton=True: dbmakes it compatible withbuild_database(singleton: bool = True)while still forcing use of the injecteddbinstance. This keeps the test insulated from the global singleton cache and is consistent with the new dependency pattern shown inbackend/tests/conftest.py.backend/tests/unit/api/test_50_internals.py (1)
96-101: Usingwith client:around TestClient calls is an improvementWrapping the
client.getcalls inwith client:for the search docs tests ensures proper TestClient lifecycle management and resource cleanup in these async tests, consistent with how other tests in this file already use the context manager.Also applies to: 107-116, 118-128
.github/workflows/ci.yml (1)
82-87: Centralizing CI Python version viaprepare-environmentoutputs is coherent across jobsAll updated
actions/setup-python@v6steps now use${{ needs.prepare-environment.outputs.PYTHON_VERSION }}, and each of those jobs already listsprepare-environmentinneeds, so the output is available at runtime. This keeps linting, tests, docs, E2E, benchmarks, and even the commented‑out memgraph job aligned on the same Python version and avoids future drift from hard‑coded values.Also applies to: 170-175, 248-253, 347-352, 401-406, 448-453, 498-503, 542-543, 567-570, 600-604, 666-670, 692-696, 729-733, 766-770, 881-885, 1057-1062, 1153-1157
backend/tests/unit/graphql/mutations/test_branch.py (1)
276-287:local_servicesDB override now matchesbuild_database’s call signatureUpdating the scope override to
lambda singleton=True: dbkeeps the behavior (“reuse this test db instance”) while making it signature‑compatible withbuild_database(singleton: bool = True). This aligns with the new DI pattern and should avoid surprises if the provider starts passingsingletonexplicitly..github/workflows/uv-check.yml (1)
12-16: Aligningpython-versionwithprepare-environmentoutput is the right moveSwitching
actions/setup-pythontopython-version: ${{ needs.prepare-environment.outputs.PYTHON_VERSION }}keeps this workflow in sync with the centrally defined Python version (3.14.2) and mirrors howUV_VERSIONis already sourced from the same job. Just double‑check thatdefine-versions.ymlactually exposes the output under the exact keyPYTHON_VERSIONso this continues to resolve correctly. Based on learnings, this also keeps uv and Python versions aligned.Also applies to: 23-29
backend/tests/conftest.py (1)
13-14: Automatic session‑scoped asyncio marker for async tests is reasonable but may affect explicitly‑marked testsUsing
pytest_collection_modifyitemswithpytest_asyncio.is_async_test(item)to applypytest.mark.asyncio(loop_scope="session")centralizes loop configuration and removes the need for a custom session‑loop fixture, which is a nice cleanup.One thing to keep in mind: tests that already declare their own
@pytest.mark.asyncio(...)(e.g. withloop_scope="function"or"module") will now receive an additional marker. That may or may not be what you want depending on how pytest‑asyncio resolves multiple markers, so it’s worth scanning for such tests and verifying that their intended loop scope is preserved.Also applies to: 113-118
9976fef to
80f26c5
Compare
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (5)
backend/tests/unit/git/test_git_repository.py (1)
481-481: Extract the repeated decorator to reduce duplication.The
@pytest.mark.httpx_mockdecorator with the identicalshould_mocklambda is repeated across 7 test functions (lines 481, 582, 644, 667, 703, 737, 773). While functionally correct, this creates maintenance burden if the filtering logic changes.Define a module-level constant instead:
# At module level, near line 43 HTTPX_MOCK_SHOULD_MOCK = lambda request: "prefect" not in request.headers.get("User-Agent", "") # Then use in tests: @pytest.mark.httpx_mock(should_mock=HTTPX_MOCK_SHOULD_MOCK) async def test_sync_new_branch(...):Alternatively, if this pattern is used across multiple test files, consider creating a custom pytest marker.
backend/tests/unit/core/test_branch_rebase.py (1)
101-102: Consider extracting the dependency scoping pattern into a reusable helper.The comment indicates this scoping pattern could benefit other tests. Consider creating a test fixture or helper function that provides this scoped database pattern.
Would you like me to generate a reusable helper implementation or open an issue to track this refactoring?
pyproject.toml (1)
81-82: Document the rationale for neo4j git-based sources.The neo4j and neo4j-rust-ext dependencies use git sources pointing to specific commits in forks rather than upstream PyPI releases. While this provides reproducibility, it's non-standard and may complicate dependency resolution or maintenance. Clarify in code comments or documentation:
- Why forks are necessary (features not in upstream? bug fixes?)
- Whether upstream releases will be used in the future
- Any compatibility considerations for these specific commits
backend/tests/conftest.py (1)
137-146: Consider removing or using thesingletonparameter in the_dbfactory.The internal
_dbfactory function accepts asingletonparameter with a default value ofTrue, but it's never used—build_database(singleton=False)is always called. This could be confusing to future maintainers.Apply this diff to remove the unused parameter:
- async def _db(singleton: bool = True) -> InfrahubDatabase: + async def _db() -> InfrahubDatabase: return await build_database(singleton=False)Alternatively, if the parameter is intended for future use or interface consistency, pass it through:
async def _db(singleton: bool = True) -> InfrahubDatabase: - return await build_database(singleton=False) + return await build_database(singleton=singleton)backend/tests/helpers/test_app.py (1)
153-158: Consider removing or using thesingletonparameter in the_dbfactory.Similar to the pattern in
backend/tests/conftest.py, the internal_dbfactory function accepts asingletonparameter that is never used. The function always callsbuild_database(singleton=False)regardless of the parameter value.Apply this diff to remove the unused parameter:
- async def _db(singleton: bool = True) -> InfrahubDatabase: + async def _db() -> InfrahubDatabase: return await build_database(singleton=False)Alternatively, if the parameter is intended for interface consistency with
build_database, pass it through:async def _db(singleton: bool = True) -> InfrahubDatabase: - return await build_database(singleton=False) + return await build_database(singleton=singleton)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
uv.lockis excluded by!**/*.lock
📒 Files selected for processing (31)
.devcontainer/Dockerfile(1 hunks).github/workflows/ci.yml(17 hunks).github/workflows/define-versions.yml(1 hunks).github/workflows/publish-pypi.yml(1 hunks).github/workflows/release.yml(1 hunks).github/workflows/update-compose-file-and-chart.yml(1 hunks).github/workflows/uv-check.yml(1 hunks).github/workflows/version-upgrade.yml(1 hunks)backend/infrahub/cli/db.py(1 hunks)backend/infrahub/core/diff/model/diff.py(1 hunks)backend/infrahub/core/graph/constraints.py(1 hunks)backend/infrahub/core/graph/schema.py(2 hunks)backend/infrahub/core/models.py(5 hunks)backend/infrahub/core/node/standard.py(1 hunks)backend/infrahub/core/schema/attribute_schema.py(1 hunks)backend/infrahub/core/schema/relationship_schema.py(1 hunks)backend/infrahub/core/validators/determiner.py(2 hunks)backend/infrahub/database/__init__.py(2 hunks)backend/tests/benchmark/conftest.py(3 hunks)backend/tests/conftest.py(4 hunks)backend/tests/helpers/test_app.py(2 hunks)backend/tests/integration/diff/test_merge_rollback.py(1 hunks)backend/tests/unit/api/conftest.py(2 hunks)backend/tests/unit/core/test_branch_rebase.py(1 hunks)backend/tests/unit/git/conftest.py(1 hunks)backend/tests/unit/git/test_git_repository.py(8 hunks)backend/tests/unit/graphql/mutations/test_branch.py(1 hunks)development/Dockerfile(1 hunks)pyproject.toml(5 hunks)tasks/docs.py(2 hunks)tasks/release.py(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (18)
- tasks/docs.py
- .github/workflows/version-upgrade.yml
- backend/tests/unit/api/conftest.py
- backend/infrahub/core/validators/determiner.py
- backend/infrahub/core/graph/constraints.py
- .github/workflows/update-compose-file-and-chart.yml
- .github/workflows/publish-pypi.yml
- tasks/release.py
- backend/tests/unit/git/conftest.py
- backend/infrahub/core/graph/schema.py
- backend/infrahub/cli/db.py
- backend/tests/unit/graphql/mutations/test_branch.py
- backend/infrahub/core/schema/relationship_schema.py
- .github/workflows/release.yml
- backend/tests/benchmark/conftest.py
- backend/tests/integration/diff/test_merge_rollback.py
- .devcontainer/Dockerfile
- backend/infrahub/core/schema/attribute_schema.py
🧰 Additional context used
📓 Path-based instructions (5)
**/*.py
📄 CodeRabbit inference engine (.github/instructions/python-docstring.instructions.md)
**/*.py: Always use triple quotes (""") for Python docstrings
Follow Google-style docstring format for Python docstrings
Include brief one-line description in Python docstrings when applicable
Include detailed description in Python docstrings when applicable
Include Args/Parameters section without typing in Python docstrings when applicable
Include Returns section in Python docstrings when applicable
Include Raises section in Python docstrings when applicable
Include Examples section in Python docstrings when applicable
**/*.py: Use type hints for all function parameters and return values in Python
Use Async whenever possible in Python
Useasync deffor asynchronous functions in Python
Useawaitfor asynchronous calls in Python
Use Pydantic models for dataclasses in Python
Use ruff and mypy for type checking and code validation in PythonUse ruff and mypy to validate and lint Python files
Files:
backend/infrahub/core/models.pybackend/infrahub/core/diff/model/diff.pybackend/tests/helpers/test_app.pybackend/infrahub/database/__init__.pybackend/tests/unit/core/test_branch_rebase.pybackend/tests/unit/git/test_git_repository.pybackend/infrahub/core/node/standard.pybackend/tests/conftest.py
backend/infrahub/**/*.py
📄 CodeRabbit inference engine (backend/AGENTS.md)
backend/infrahub/**/*.py: Use async/await for all I/O operations to maintain async-first architecture
Type hint all function parameters and returns in Python code
Use Pydantic models for defining data structures instead of plain dictionaries
Use Query class pattern (extending infrahub.core.query.Query) for all database operations instead of unparameterized Cypher queries
Use Google-style docstrings with Args, Returns, and Raises sections for all functions
Use snake_case for function and variable names
Use PascalCase for class names
Use UPPER_SNAKE_CASE for constant definitions
Do not use unparameterized Cypher queries; always use parameterized queries to prevent injection
Do not block the event loop with synchronous I/O operations
Files:
backend/infrahub/core/models.pybackend/infrahub/core/diff/model/diff.pybackend/infrahub/database/__init__.pybackend/infrahub/core/node/standard.py
backend/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Use type hints for all Python code in the backend
Files:
backend/infrahub/core/models.pybackend/infrahub/core/diff/model/diff.pybackend/tests/helpers/test_app.pybackend/infrahub/database/__init__.pybackend/tests/unit/core/test_branch_rebase.pybackend/tests/unit/git/test_git_repository.pybackend/infrahub/core/node/standard.pybackend/tests/conftest.py
backend/tests/**/*.py
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Run backend tests with
pytestor viainvoketasksName test files as
test_<module>.pyand mirror source structure in tests directory
Files:
backend/tests/helpers/test_app.pybackend/tests/unit/core/test_branch_rebase.pybackend/tests/unit/git/test_git_repository.pybackend/tests/conftest.py
{pyproject.toml,uv.lock}
📄 CodeRabbit inference engine (.github/instructions/tooling.instructions.md)
Use uv to manage the Python project and its dependencies
Files:
pyproject.toml
🧠 Learnings (7)
📚 Learning: 2025-12-01T22:16:13.680Z
Learnt from: CR
Repo: opsmill/infrahub PR: 0
File: backend/AGENTS.md:0-0
Timestamp: 2025-12-01T22:16:13.680Z
Learning: Applies to backend/infrahub/**/*.py : Use Pydantic models for defining data structures instead of plain dictionaries
Applied to files:
backend/infrahub/core/models.py
📚 Learning: 2025-12-01T22:15:47.401Z
Learnt from: CR
Repo: opsmill/infrahub PR: 0
File: .github/instructions/tooling.instructions.md:0-0
Timestamp: 2025-12-01T22:15:47.401Z
Learning: Applies to {pyproject.toml,uv.lock} : Use uv to manage the Python project and its dependencies
Applied to files:
.github/workflows/ci.yml.github/workflows/uv-check.yml
📚 Learning: 2025-12-01T22:15:34.303Z
Learnt from: CR
Repo: opsmill/infrahub PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-01T22:15:34.303Z
Learning: Applies to backend/pyproject.toml : Use `uv` for dependency management in backend Python projects
Applied to files:
.github/workflows/ci.ymlpyproject.toml.github/workflows/uv-check.yml
📚 Learning: 2025-12-01T22:16:13.680Z
Learnt from: CR
Repo: opsmill/infrahub PR: 0
File: backend/AGENTS.md:0-0
Timestamp: 2025-12-01T22:16:13.680Z
Learning: Applies to backend/infrahub/**/*.py : Type hint all function parameters and returns in Python code
Applied to files:
pyproject.toml
📚 Learning: 2025-12-01T22:16:13.680Z
Learnt from: CR
Repo: opsmill/infrahub PR: 0
File: backend/AGENTS.md:0-0
Timestamp: 2025-12-01T22:16:13.680Z
Learning: Applies to backend/infrahub/**/*.py : Use PascalCase for class names
Applied to files:
pyproject.toml
📚 Learning: 2025-12-01T22:16:13.680Z
Learnt from: CR
Repo: opsmill/infrahub PR: 0
File: backend/AGENTS.md:0-0
Timestamp: 2025-12-01T22:16:13.680Z
Learning: Applies to backend/infrahub/**/*.py : Use UPPER_SNAKE_CASE for constant definitions
Applied to files:
pyproject.toml
📚 Learning: 2025-11-18T08:30:19.721Z
Learnt from: fatih-acar
Repo: opsmill/infrahub PR: 7669
File: .github/workflows/update-compose-file-and-chart.yml:52-53
Timestamp: 2025-11-18T08:30:19.721Z
Learning: The `uv version` command returns the project version from pyproject.toml (since astral-sh/uv PR #12349). Use `uv version --short` to extract project version for version checks and comparisons in workflows. The old behavior (showing UV's own tool version) is now `uv self version`.
Applied to files:
.github/workflows/uv-check.yml
🧬 Code graph analysis (3)
backend/tests/unit/core/test_branch_rebase.py (3)
backend/tests/conftest.py (2)
dependency_provider(121-122)db(126-146)backend/tests/helpers/test_app.py (1)
dependency_provider(80-81)backend/infrahub/workers/dependencies.py (1)
build_database(63-72)
backend/tests/unit/git/test_git_repository.py (6)
backend/infrahub/message_bus/operations/send/echo.py (1)
request(10-16)backend/infrahub/message_bus/operations/git/file.py (1)
get(14-35)backend/infrahub/services/adapters/cache/__init__.py (1)
get(21-23)backend/infrahub/services/adapters/cache/redis.py (1)
get(29-33)backend/infrahub/services/adapters/cache/nats.py (1)
get(86-94)backend/tests/adapters/cache.py (1)
get(13-14)
backend/tests/conftest.py (3)
backend/infrahub/workers/dependencies.py (2)
build_database(63-72)get_database(76-77)backend/tests/helpers/test_app.py (1)
_db(153-154)backend/tests/unit/api/conftest.py (1)
_db(22-23)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (13)
- GitHub Check: E2E-testing-playwright
- GitHub Check: backend-benchmark
- GitHub Check: backend-tests-unit
- GitHub Check: backend-tests-integration
- GitHub Check: backend-tests-functional
- GitHub Check: json-schema
- GitHub Check: graphql-schema
- GitHub Check: validate-generated-documentation
- GitHub Check: frontend-tests
- GitHub Check: backend-docker-integration
- GitHub Check: documentation
- GitHub Check: backend-validate-generated
- GitHub Check: Cloudflare Pages
🔇 Additional comments (14)
backend/tests/unit/git/test_git_repository.py (2)
506-506: LGTM! Response reusability configured appropriately.The
is_reusable=Trueparameter enables this mock response formutation-repository-update-admin-statusto be used across multiple requests, which appears correct if the admin status endpoint is called more than once duringrepo.sync(). The operational status mock at line 511 remains single-use, suggesting different request patterns for these endpoints.
481-520: Well-structured selective HTTP mocking improvements.The changes successfully implement selective HTTP mocking that allows Prefect-related requests to pass through while mocking other HTTP traffic. This approach:
- Aligns with the existing
non_mocked_hostsfixture (line 45) targeting 127.0.0.1- Maintains test reliability by controlling which requests are mocked
- Preserves all test logic and assertions unchanged
development/Dockerfile (1)
4-4: Python 3.14.2 and Docker image are available. The official Docker imagepython:3.14.2-slim-bookwormis published on Docker Hub, and Python 3.14.2 was released on December 5, 2025. The Dockerfile change is sound..github/workflows/define-versions.yml (1)
9-10: ✓ Centralizing Python version via workflow output.Adding PYTHON_VERSION as a workflow output is a clean approach to maintain a single source of truth for Python versions across the CI/CD pipeline. This ensures consistency and simplifies future version updates.
.github/workflows/uv-check.yml (1)
25-25: ✓ Dynamic Python version reference correctly configured.The workflow properly uses the centralized PYTHON_VERSION output from prepare-environment, with correct dependency declaration. This maintains consistency with the new versioning approach.
.github/workflows/ci.yml (1)
86-86: ✓ Consistent use of dynamic PYTHON_VERSION across all jobs.All references to Python version have been properly updated to use the centralized
needs.prepare-environment.outputs.PYTHON_VERSIONoutput. The changes are consistent in syntax and properly depend on the prepare-environment job. The backend-testcontainers-unit matrix (lines 290–295) correctly retains hard-coded versions for multi-version testing, which is the right approach.Also applies to: 174-174, 252-252, 351-351, 405-405, 452-452, 502-502, 603-603, 669-669, 695-695, 732-732, 769-769, 884-884, 1061-1061, 1156-1156
pyproject.toml (3)
145-145: This setting is already correctly implemented with proper test isolation.The
asyncio_default_fixture_loop_scope = "session"configuration in pyproject.toml is intentional and working as designed. Test isolation is maintained through fixture design:
- Database isolation: The
dbfixture is module-scoped (not session), so each test module gets its own fresh database connection and state is cleared via theempty_databasefixture (which callsdelete_all_nodesand recreates the root node).- Registry isolation: The
reset_registryfixture clears application state between tests.- Consistent async handling: The
pytest_collection_modifyitemshook explicitly marks all async tests with session-scoped loop scope, ensuring consistent behavior.- Proper container scoping: Session-scoped infrastructure fixtures (neo4j, rabbitmq, redis, etc.) are correctly scoped since they manage containers, not test state.
Event loop scope (session) is independent of fixture scope (module/function), so state isolation is preserved. No test failures or isolation issues are evident in the codebase.
19-20: Remove or clarify the unpinned dependency concern — the git sources in[tool.uv.sources]already pin exact versions via revision hashes.Lines 19–20 list
neo4jandneo4j-rust-extwithout version constraints in the dependencies list, but lines 81–82 define them in[tool.uv.sources]with explicit git revisions (revhashes). This is correct uv usage and provides exact, reproducible versions. However,neo4jis sourced from a fork (fatih-acar/neo4j-python-driver) rather than the official repository, with no documentation explaining why. Consider adding a comment to clarify whether the fork is intentional and what it addresses, or confirm that the officialneo4j/neo4j-python-drivershould be used instead.Likely an incorrect or invalid review comment.
23-23: Pytest 9.0 compatibility verified—no breaking changes detected.The upgrade to pytest 9.0.x is complete and compatible with the codebase. All major plugins (pytest-asyncio 1.3+, pytest-cov 7.0.0, pytest-xdist 3.4+) support pytest 9. Custom plugins use only public APIs (no private config access), and Python 3.12+ requirement exceeds pytest 9's minimum. No fixture, assertion introspection, or plugin interaction issues identified.
backend/infrahub/core/diff/model/diff.py (1)
21-35: Class-levelmodel_fieldsaccess into_graphqllooks correctUsing
self.__class__.model_fields[key]keeps field metadata lookup on the class, matching Pydantic’s recommended access pattern and the wider refactor, without changing the filtering/serialization behavior for GraphQL export.Please re-run the existing diff/GraphQL tests to confirm output remains byte-for-byte identical for representative models.
backend/infrahub/core/node/standard.py (1)
257-288:to_dbnow correctly uses class-levelmodel_fieldsIterating over
self.__class__.model_fields.items()cleanly ties the DB payload to the concrete model’s field definitions while preserving the existing exclusion and serialization logic.Please make sure the StandardNode persistence tests (create/update round-trips) still pass under Python 3.14 in CI.
backend/infrahub/core/models.py (1)
260-307: Consistent normalization to class-levelmodel_fieldsacross schema and hash helpersThe switch to
X.__class__.model_fields[...]in_process_attrs_rels,_process_node_attributes,get_hash,update, and_get_field_names_for_diffmakes all schema-diff and HashableModel utilities depend on the concrete class’s field definitions, matching the rest of the refactor and Pydantic v2’s expectations. Error handling and diff/migration semantics remain the same.Please run the schema update validation and hash/diff test suites (including any migration/validator selection tests) to confirm no behavioral deltas under Python 3.14.
Also applies to: 309-325, 417-443, 580-608, 615-639
backend/tests/conftest.py (1)
113-117: LGTM!The pytest collection modifier correctly applies session-scoped asyncio markers to async tests, enabling proper async test execution.
backend/infrahub/database/__init__.py (1)
16-16: The import and usage ofNotificationDisabledClassificationare correct. This represents the current neo4j Python driver API;NotificationDisabledCategoryis the deprecated predecessor. The implementation properly uses the newnotifications_disabled_classificationsparameter with the correct enum value.
Signed-off-by: Fatih Acar <[email protected]>
Some packages require an upgrade in order to install directly from wheels. Signed-off-by: Fatih Acar <[email protected]>
Post dependency w/ Py3.14 upgrade. Signed-off-by: Fatih Acar <[email protected]>
Signed-off-by: Fatih Acar <[email protected]>
Otherwise driver may get closed and fail with an error. Signed-off-by: Fatih Acar <[email protected]>
Signed-off-by: Fatih Acar <[email protected]>
Signed-off-by: Fatih Acar <[email protected]>
Signed-off-by: Fatih Acar <[email protected]>
Signed-off-by: Fatih Acar <[email protected]>
This is required to remove py3.14 deprecation warnings. Signed-off-by: Fatih Acar <[email protected]>
Required for py3.14 deprecation warnings. Signed-off-by: Fatih Acar <[email protected]>
Signed-off-by: Fatih Acar <[email protected]>
Also use stricter version pinning for Python. Signed-off-by: Fatih Acar <[email protected]>
Signed-off-by: Fatih Acar <[email protected]>
mypy typing issue. Signed-off-by: Fatih Acar <[email protected]>
80f26c5 to
b96e0ab
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
backend/tests/conftest.py (1)
137-147: db fixture lifecycle via provider.scope is sound; consider clarifying_dboverrideThe module-scoped
dbfixture now:
- Adjusts
config.SETTINGSfor neo4j/memgraph.- Overrides
build_databasewithinprovider.scopeusing the local async_db, which always callsbuild_database(singleton=False).- Acquires a database via
await get_database(), adds indexes, yields it, and then closes it.This cleanly encapsulates database setup/teardown and ensures tests don’t use the global singleton from
build_database, which is appropriate for isolation.One small clarity nit:
_db(singleton: bool = True)ignores itssingletonparameter and always passessingleton=Falsetobuild_database. If the intent is “never use the singleton in tests”, consider either:
- Adding a short comment about intentionally forcing
singleton=False, or- Forwarding the argument (
return await build_database(singleton=singleton)) and letting the caller decide.Functionally this is fine as-is, so treat this as a readability tweak rather than a blocker.
backend/infrahub/cli/db.py (1)
606-618: LGTM! Improved code clarity with tuples and descriptive names.The changes improve code quality:
- Using tuples instead of lists for immutable collections of schema classes is more appropriate
- Renaming loop variables from generic
graph_schemato specificgraph_node_schemaandgraph_edge_schemaimproves readability- No functional impact
The same loop pattern appears in the
load_exportfunction (around line 762-775 based on context). Consider applying the same tuple and naming improvements there for consistency.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
uv.lockis excluded by!**/*.lock
📒 Files selected for processing (37)
.devcontainer/Dockerfile(1 hunks).github/workflows/ci.yml(17 hunks).github/workflows/define-versions.yml(1 hunks).github/workflows/keyword-scan.yml(1 hunks).github/workflows/publish-pypi.yml(1 hunks).github/workflows/release.yml(1 hunks).github/workflows/update-compose-file-and-chart.yml(1 hunks).github/workflows/uv-check.yml(1 hunks).github/workflows/version-upgrade.yml(1 hunks)backend/infrahub/cli/db.py(1 hunks)backend/infrahub/core/diff/model/diff.py(1 hunks)backend/infrahub/core/graph/constraints.py(1 hunks)backend/infrahub/core/graph/schema.py(2 hunks)backend/infrahub/core/models.py(5 hunks)backend/infrahub/core/node/standard.py(1 hunks)backend/infrahub/core/schema/attribute_schema.py(1 hunks)backend/infrahub/core/schema/relationship_schema.py(1 hunks)backend/infrahub/core/validators/determiner.py(2 hunks)backend/infrahub/database/__init__.py(2 hunks)backend/infrahub/workers/dependencies.py(1 hunks)backend/tests/benchmark/conftest.py(3 hunks)backend/tests/conftest.py(4 hunks)backend/tests/helpers/test_app.py(2 hunks)backend/tests/helpers/utils.py(1 hunks)backend/tests/integration/diff/test_merge_rollback.py(1 hunks)backend/tests/unit/api/conftest.py(2 hunks)backend/tests/unit/api/test_50_internals.py(3 hunks)backend/tests/unit/core/test_branch_rebase.py(1 hunks)backend/tests/unit/git/conftest.py(1 hunks)backend/tests/unit/git/test_git_repository.py(8 hunks)backend/tests/unit/graphql/mutations/test_branch.py(1 hunks)development/Dockerfile(1 hunks)frontend/app/src/shared/api/rest/types.generated.ts(6 hunks)pyproject.toml(5 hunks)schema/openapi.json(7 hunks)tasks/docs.py(2 hunks)tasks/release.py(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (18)
- .devcontainer/Dockerfile
- .github/workflows/define-versions.yml
- backend/infrahub/core/validators/determiner.py
- .github/workflows/ci.yml
- development/Dockerfile
- tasks/docs.py
- backend/infrahub/workers/dependencies.py
- .github/workflows/publish-pypi.yml
- .github/workflows/version-upgrade.yml
- backend/infrahub/core/diff/model/diff.py
- .github/workflows/keyword-scan.yml
- backend/infrahub/core/graph/constraints.py
- backend/infrahub/core/schema/attribute_schema.py
- backend/tests/integration/diff/test_merge_rollback.py
- backend/tests/unit/git/conftest.py
- backend/tests/helpers/test_app.py
- backend/tests/helpers/utils.py
- backend/tests/benchmark/conftest.py
🧰 Additional context used
📓 Path-based instructions (6)
**/*.py
📄 CodeRabbit inference engine (.github/instructions/python-docstring.instructions.md)
**/*.py: Always use triple quotes (""") for Python docstrings
Follow Google-style docstring format for Python docstrings
Include brief one-line description in Python docstrings when applicable
Include detailed description in Python docstrings when applicable
Include Args/Parameters section without typing in Python docstrings when applicable
Include Returns section in Python docstrings when applicable
Include Raises section in Python docstrings when applicable
Include Examples section in Python docstrings when applicable
**/*.py: Use type hints for all function parameters and return values in Python
Use Async whenever possible in Python
Useasync deffor asynchronous functions in Python
Useawaitfor asynchronous calls in Python
Use Pydantic models for dataclasses in Python
Use ruff and mypy for type checking and code validation in PythonUse ruff and mypy to validate and lint Python files
Files:
backend/tests/unit/api/test_50_internals.pybackend/infrahub/cli/db.pybackend/infrahub/core/models.pybackend/infrahub/core/node/standard.pybackend/infrahub/database/__init__.pybackend/infrahub/core/graph/schema.pybackend/tests/unit/git/test_git_repository.pytasks/release.pybackend/infrahub/core/schema/relationship_schema.pybackend/tests/unit/core/test_branch_rebase.pybackend/tests/conftest.pybackend/tests/unit/api/conftest.pybackend/tests/unit/graphql/mutations/test_branch.py
backend/tests/**/*.py
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Run backend tests with
pytestor viainvoketasksName test files as
test_<module>.pyand mirror source structure in tests directory
Files:
backend/tests/unit/api/test_50_internals.pybackend/tests/unit/git/test_git_repository.pybackend/tests/unit/core/test_branch_rebase.pybackend/tests/conftest.pybackend/tests/unit/api/conftest.pybackend/tests/unit/graphql/mutations/test_branch.py
backend/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Use type hints for all Python code in the backend
Files:
backend/tests/unit/api/test_50_internals.pybackend/infrahub/cli/db.pybackend/infrahub/core/models.pybackend/infrahub/core/node/standard.pybackend/infrahub/database/__init__.pybackend/infrahub/core/graph/schema.pybackend/tests/unit/git/test_git_repository.pybackend/infrahub/core/schema/relationship_schema.pybackend/tests/unit/core/test_branch_rebase.pybackend/tests/conftest.pybackend/tests/unit/api/conftest.pybackend/tests/unit/graphql/mutations/test_branch.py
backend/infrahub/**/*.py
📄 CodeRabbit inference engine (backend/AGENTS.md)
backend/infrahub/**/*.py: Use async/await for all I/O operations to maintain async-first architecture
Type hint all function parameters and returns in Python code
Use Pydantic models for defining data structures instead of plain dictionaries
Use Query class pattern (extending infrahub.core.query.Query) for all database operations instead of unparameterized Cypher queries
Use Google-style docstrings with Args, Returns, and Raises sections for all functions
Use snake_case for function and variable names
Use PascalCase for class names
Use UPPER_SNAKE_CASE for constant definitions
Do not use unparameterized Cypher queries; always use parameterized queries to prevent injection
Do not block the event loop with synchronous I/O operations
Files:
backend/infrahub/cli/db.pybackend/infrahub/core/models.pybackend/infrahub/core/node/standard.pybackend/infrahub/database/__init__.pybackend/infrahub/core/graph/schema.pybackend/infrahub/core/schema/relationship_schema.py
frontend/app/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript types for all frontend code
Files:
frontend/app/src/shared/api/rest/types.generated.ts
{pyproject.toml,uv.lock}
📄 CodeRabbit inference engine (.github/instructions/tooling.instructions.md)
Use uv to manage the Python project and its dependencies
Files:
pyproject.toml
🧠 Learnings (7)
📚 Learning: 2025-11-18T08:30:19.721Z
Learnt from: fatih-acar
Repo: opsmill/infrahub PR: 7669
File: .github/workflows/update-compose-file-and-chart.yml:52-53
Timestamp: 2025-11-18T08:30:19.721Z
Learning: The `uv version` command returns the project version from pyproject.toml (since astral-sh/uv PR #12349). Use `uv version --short` to extract project version for version checks and comparisons in workflows. The old behavior (showing UV's own tool version) is now `uv self version`.
Applied to files:
.github/workflows/uv-check.yml
📚 Learning: 2025-12-01T22:15:47.401Z
Learnt from: CR
Repo: opsmill/infrahub PR: 0
File: .github/instructions/tooling.instructions.md:0-0
Timestamp: 2025-12-01T22:15:47.401Z
Learning: Applies to {pyproject.toml,uv.lock} : Use uv to manage the Python project and its dependencies
Applied to files:
.github/workflows/uv-check.yml.github/workflows/update-compose-file-and-chart.yml.github/workflows/release.yml
📚 Learning: 2025-12-01T22:15:34.303Z
Learnt from: CR
Repo: opsmill/infrahub PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-01T22:15:34.303Z
Learning: Applies to backend/pyproject.toml : Use `uv` for dependency management in backend Python projects
Applied to files:
.github/workflows/uv-check.yml.github/workflows/update-compose-file-and-chart.yml.github/workflows/release.ymlpyproject.toml
📚 Learning: 2025-12-01T22:16:13.680Z
Learnt from: CR
Repo: opsmill/infrahub PR: 0
File: backend/AGENTS.md:0-0
Timestamp: 2025-12-01T22:16:13.680Z
Learning: Applies to backend/infrahub/**/*.py : Use Pydantic models for defining data structures instead of plain dictionaries
Applied to files:
backend/infrahub/core/models.py
📚 Learning: 2025-12-01T22:16:13.680Z
Learnt from: CR
Repo: opsmill/infrahub PR: 0
File: backend/AGENTS.md:0-0
Timestamp: 2025-12-01T22:16:13.680Z
Learning: Applies to backend/infrahub/**/*.py : Type hint all function parameters and returns in Python code
Applied to files:
pyproject.toml
📚 Learning: 2025-12-01T22:16:13.680Z
Learnt from: CR
Repo: opsmill/infrahub PR: 0
File: backend/AGENTS.md:0-0
Timestamp: 2025-12-01T22:16:13.680Z
Learning: Applies to backend/infrahub/**/*.py : Use PascalCase for class names
Applied to files:
pyproject.toml
📚 Learning: 2025-12-01T22:16:13.680Z
Learnt from: CR
Repo: opsmill/infrahub PR: 0
File: backend/AGENTS.md:0-0
Timestamp: 2025-12-01T22:16:13.680Z
Learning: Applies to backend/infrahub/**/*.py : Use UPPER_SNAKE_CASE for constant definitions
Applied to files:
pyproject.toml
🧬 Code graph analysis (7)
backend/tests/unit/api/test_50_internals.py (2)
backend/tests/helpers/test_app.py (1)
client(161-188)backend/tests/unit/api/conftest.py (1)
client(18-26)
backend/infrahub/cli/db.py (1)
backend/infrahub/core/graph/schema.py (5)
GraphNodeProperties(37-45)GraphRelationshipProperties(81-84)GraphAttributeProperties(112-115)GraphRelationshipIsPartOf(216-219)GraphRelationshipDefault(222-234)
backend/infrahub/core/graph/schema.py (1)
backend/infrahub/types.py (1)
Any(312-319)
backend/tests/unit/core/test_branch_rebase.py (3)
backend/tests/conftest.py (2)
dependency_provider(121-122)db(126-146)backend/tests/helpers/test_app.py (1)
dependency_provider(80-81)backend/infrahub/workers/dependencies.py (1)
build_database(63-72)
backend/tests/conftest.py (3)
backend/infrahub/database/__init__.py (1)
InfrahubDatabase(141-445)backend/infrahub/workers/dependencies.py (2)
build_database(63-72)get_database(76-77)backend/tests/unit/api/conftest.py (1)
_db(22-23)
backend/tests/unit/api/conftest.py (2)
backend/infrahub/workers/dependencies.py (1)
build_database(63-72)backend/tests/conftest.py (2)
dependency_provider(121-122)_db(137-138)
backend/tests/unit/graphql/mutations/test_branch.py (3)
backend/tests/conftest.py (2)
dependency_provider(121-122)db(126-146)backend/tests/helpers/test_app.py (1)
dependency_provider(80-81)backend/infrahub/workers/dependencies.py (1)
build_database(63-72)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
- GitHub Check: E2E-testing-version-upgrade / From 1.3.0
- GitHub Check: backend-tests-unit
- GitHub Check: documentation
- GitHub Check: backend-tests-functional
- GitHub Check: E2E-testing-playwright
- GitHub Check: backend-benchmark
- GitHub Check: validate-generated-documentation
- GitHub Check: backend-tests-integration
- GitHub Check: backend-docker-integration
- GitHub Check: frontend-tests
- GitHub Check: Cloudflare Pages
🔇 Additional comments (28)
.github/workflows/release.yml (1)
28-32: Python version consistently parameterized across job chain.The check_release job now uses the dynamic Python version from prepare-environment, consistent with the pattern in other workflows. The dependency chain is properly maintained for all downstream jobs that rely on check_release outputs.
.github/workflows/uv-check.yml (1)
22-25: Reusable workflow properly parameterized for dynamic Python version.The uv_check workflow correctly uses the dynamic Python version. This is important for a reusable workflow since it ensures consistent Python versions across all callers of this workflow.
.github/workflows/update-compose-file-and-chart.yml (1)
38-41: Dynamic Python version properly parameterized.The workflow correctly sources the Python version from the prepare-environment job output, which invokes define-versions.yml where PYTHON_VERSION is defined as a workflow output. The job dependency is properly declared and the output reference syntax is correct.
backend/tests/unit/graphql/mutations/test_branch.py (1)
281-286: LGTM!The updated lambda signature with
singleton=Truekeyword argument correctly matches thebuild_databasefunction signature frombackend/infrahub/workers/dependencies.py. The# noqa: ARG005comment appropriately suppresses the unused argument warning since the test fixture intentionally ignores the singleton flag and always returns the test database instance.backend/tests/unit/core/test_branch_rebase.py (1)
101-118: LGTM!The lambda signature update is consistent with the dependency injection pattern used throughout this PR. The test correctly scopes the database dependency for the branch rebase conflict test.
backend/tests/unit/api/test_50_internals.py (3)
96-105: LGTM!Wrapping the TestClient usage in a context manager ensures proper startup/shutdown lifecycle handling. This aligns with the pattern already used in other tests in this file (e.g.,
test_config_endpoint,test_info_endpoint).
107-116: LGTM!Consistent application of the context manager pattern.
118-128: LGTM!Consistent application of the context manager pattern for the missing search index test case.
backend/infrahub/database/__init__.py (2)
495-497: Configuration parameter renamed to match new Neo4j API.The driver configuration correctly uses
notifications_disabled_classificationswithNotificationDisabledClassification.UNRECOGNIZEDto match the updated import. This is consistent with the import change on line 16.
16-16: The import is correct and already uses the current Neo4j Python driver API.NotificationDisabledClassificationis the valid enum in Neo4j driver v5.22+ (stabilized in v6.0), and the parameternotifications_disabled_classificationsmatches the current API. No legacy API references exist in the codebase.backend/tests/unit/git/test_git_repository.py (8)
481-488: LGTM!The
@pytest.mark.httpx_mock(should_mock=...)decorator correctly filters out Prefect HTTP requests based on User-Agent header while still allowing other requests to be mocked. This is a cleaner approach than modifyingnon_mocked_hostswhen you need header-based filtering.
505-507: LGTM!Adding
is_reusable=Trueallows this mock response to be consumed multiple times during the test, which is appropriate when the same admin mutation may be called more than once.
582-588: LGTM!Consistent application of the httpx_mock filter pattern.
644-650: LGTM!Consistent application of the httpx_mock filter pattern.
667-680: LGTM!Consistent application of the httpx_mock filter pattern for artifact generation tests.
703-714: LGTM!Consistent application of the httpx_mock filter pattern.
737-750: LGTM!Consistent application of the httpx_mock filter pattern.
773-786: LGTM!Consistent application of the httpx_mock filter pattern for Jinja2 artifact generation test.
backend/tests/unit/api/conftest.py (1)
17-26: LGTM!The fixture correctly implements the dependency injection pattern for database scoping. The
_dbfunction accepts thesingletonparameter for signature compatibility but correctly forcessingleton=Falseto ensure test isolation. This is consistent with the pattern used inbackend/tests/conftest.py.backend/tests/conftest.py (2)
13-13: Imports for async testing and database DI look consistentThe added
pytest_asyncioimport and the switch to usingInfrahubDatabaseplusbuild_database/get_databasefrominfrahub.workers.dependenciesalign with the new async/DI setup and are consistent with the rest of the file. I don’t see issues here.Also applies to: 50-50, 58-58
113-117: Async test collection hook is aligned with pytest-asyncio’s loop scopingUsing
pytest_collection_modifyitems(items)withpytest_asyncio.is_async_test(item)and addingpytest.mark.asyncio(loop_scope="session")is a valid way to force all async tests onto a session-scoped loop with pytest-asyncio ≥0.17. Combined withasyncio_mode = "auto"andasyncio_default_fixture_loop_scope = "session"inpyproject.toml, this should effectively recreate your old session-wide loop behavior.Please watch for any tests that accidentally rely on per-test loop isolation (e.g., background tasks leaking between tests) and adjust marks or scopes if you see flakiness.
pyproject.toml (1)
6-6: Python 3.14 support, async-testing stack, and neo4j VCS sources look coherent; verify across environments
- Expanding
requires-pythonto>=3.12,<3.15and adding 3.13/3.14 classifiers matches the PR goal and is in line with current pytest-asyncio and pytest support for Python 3.14 and pytest 9.- Upgrading to
pytest>=9.0,<9.1pluspytest-asyncio>=1.3,<1.4and configuringasyncio_mode="auto"together withasyncio_default_fixture_loop_scope = "session"fits the new async test strategy you wired inbackend/tests/conftest.py(session-scoped loop for async tests/fixtures).- Moving
neo4j/neo4j-rust-extto bare names in[project.dependencies]and pinning them via[tool.uv.sources]to specific git revisions is a good fit for uv-based workflows and reproducibility. Just be aware that non-uv installers (plainpip install infrahub-server) will ignore[tool.uv.sources]and pull the published PyPI versions ofneo4j/neo4j-rust-extinstead; if you still support that path, you may want to document the expectation that uv is the supported resolver. Based on learnings, this aligns with the “use uv for dependency management” guidance.- Removing upper bounds for
pyarrowandnumpyincreases flexibility but also trusts future releases not to break you; given the breadth of your test suite this is probably acceptable, but keep an eye on CI when those libraries ship major updates.Given the number of coordinated upgrades (Python range, pytest/pytest-asyncio, neo4j driver, numerical/telemetry stack), I’d strongly recommend re-running the matrix (at least 3.12, 3.13, 3.14) with
uvto confirm there are no hidden resolver or runtime issues.Also applies to: 14-15, 19-22, 23-24, 32-33, 47-55, 59-61, 63-66, 77-82, 89-89, 107-108, 145-145
schema/openapi.json (1)
979-987: Loosening schema contracts for dynamic payloads looks intentional; ensure client expectations matchAllowing
additionalProperties: trueon GraphQL responses,ComputedAttribute-Output, JSONSchema sub-schemas, andQueryPayload.variablesmakes sense for inherently dynamic shapes and should reduce spurious validation errors. It does, however, weaken strict contract guarantees, so it’s worth double‑checking that:
- Any codegen/typed clients aren’t relying on the previous, stricter schemas.
- Server‑side validation for security/consistency still happens at the application/model level rather than assuming OpenAPI will catch unknown keys.
Also applies to: 1091-1099, 3971-3974, 4478-4583, 5306-5311
backend/infrahub/core/models.py (1)
270-281: Switch to class-levelmodel_fieldsis consistent with Pydantic v2 usageUsing
field.__class__.model_fields[...],schema.__class__.model_fields[...], and iterating overself/other.__class__.model_fields.keys()keeps behavior aligned with how model metadata is exposed in Pydantic v2 and should be equivalent to the previous instance access for theseBaseModelsubclasses. It also future‑proofs against possible removal of instance‑levelmodel_fields.I’d just recommend re‑running the existing tests that cover:
SchemaUpdateValidationResult._process_attrs_rels/_process_node_attributesHashableModel.get_hash(),.update(), and.diff()to catch any subtle regressions in hashing, diffing, or schema‑update routing.
Also applies to: 308-325, 425-443, 580-607, 615-617
tasks/release.py (1)
407-420: Class-levelmodel_fieldsinfetch_fieldskeeps env discovery consistent with Settings metadataIterating over
subset.__class__.model_fields.items()while still recursing via the actualsubsetinstance preserves the previous behavior and matches howBaseSettingsexposes field definitions in current Pydantic Settings. No new edge cases stand out, given that defaults are still taken fromfield.get_default()and env names fromEnvSettingsSource._extract_field_info.It’s worth sanity‑checking this by running
gen_config_envagainst a representativeSettingstree to confirm that:
- Nested settings still have their env vars discovered.
env_defaultsmatches the expected defaults (including those from default factories).backend/infrahub/core/schema/relationship_schema.py (1)
84-91: LGTM! Class-level model_fields access aligns with Pydantic v2 patterns.The change from
self.model_fieldstoself.__class__.model_fieldsis more explicit about accessing class-level metadata and aligns with the broader pattern applied across the codebase. In Pydantic v2,model_fieldsis aClassVar, so this change clarifies intent without altering behavior.backend/infrahub/core/graph/schema.py (1)
237-264: LGTM! Improved type precision for graph schema.The type annotations have been refined from
dict[str, Any]todict[str, type[Any]]for the inner dictionary values. This accurately reflects that the values are class types (likeGraphNodeNode,GraphRelationshipNode) rather than arbitrary values, improving static type checking.backend/infrahub/core/node/standard.py (1)
257-289: LGTM! Consistent class-level model_fields access.The change from
self.model_fieldstoself.__class__.model_fieldsin theto_db()method is consistent with the pattern applied across the codebase and follows Pydantic v2 best practices for accessing class-level field metadata.
| "ComputedAttribute-Output": { | ||
| [key: string]: unknown; | ||
| }; |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# First, check if the file exists and examine the specific lines
echo "=== Checking TypeScript file ==="
if [ -f "frontend/app/src/shared/api/rest/types.generated.ts" ]; then
wc -l "frontend/app/src/shared/api/rest/types.generated.ts"
echo "--- Lines 1306-1308 ---"
sed -n '1306,1308p' "frontend/app/src/shared/api/rest/types.generated.ts"
else
echo "File not found at frontend/app/src/shared/api/rest/types.generated.ts"
# Try to find it
find . -name "types.generated.ts" -type f 2>/dev/null | head -5
fiRepository: opsmill/infrahub
Length of output: 258
🏁 Script executed:
#!/bin/bash
# Check if OpenAPI schema exists and examine the specified sections
echo "=== Checking OpenAPI schema ==="
if [ -f "schema/openapi.json" ]; then
echo "--- ComputedAttribute-Output schema ---"
cat schema/openapi.json | jq '.components.schemas."ComputedAttribute-Output"' 2>/dev/null || echo "Schema path not found"
echo -e "\n--- JSONSchema schema ---"
cat schema/openapi.json | jq '.components.schemas.JSONSchema' 2>/dev/null || echo "Schema path not found"
echo -e "\n--- QueryPayload schema ---"
cat schema/openapi.json | jq '.components.schemas.QueryPayload' 2>/dev/null || echo "Schema path not found"
else
echo "OpenAPI schema not found at schema/openapi.json"
find . -name "openapi.json" -type f 2>/dev/null | head -5
fiRepository: opsmill/infrahub
Length of output: 2699
🏁 Script executed:
#!/bin/bash
# Search for how the TypeScript types file is generated
echo "=== Searching for code generation configuration ==="
find . -type f \( -name "*.json" -o -name "*.yaml" -o -name "*.yml" -o -name "*.config.js" -o -name "*.config.ts" \) 2>/dev/null | xargs grep -l "types.generated" 2>/dev/null | head -10Repository: opsmill/infrahub
Length of output: 225
🏁 Script executed:
#!/bin/bash
# Look for Record<string, never> vs { [key: string]: unknown } types in the file
echo "=== Searching for type patterns in generated file ==="
if [ -f "frontend/app/src/shared/api/rest/types.generated.ts" ]; then
echo "--- Occurrences of Record<string, never> ---"
grep -n "Record<string, never>" "frontend/app/src/shared/api/rest/types.generated.ts" | wc -l
echo "--- Occurrences of [key: string]: unknown ---"
grep -n "\[key: string\]: unknown" "frontend/app/src/shared/api/rest/types.generated.ts" | wc -l
echo "--- ComputedAttribute-Output context (lines 1300-1315) ---"
sed -n '1300,1315p' "frontend/app/src/shared/api/rest/types.generated.ts"
fiRepository: opsmill/infrahub
Length of output: 781
🏁 Script executed:
#!/bin/bash
# Check package.json for code generation configuration
echo "=== Checking frontend/app/package.json for generation config ==="
cat frontend/app/package.json | jq '.scripts | keys[] | select(. | contains("generate") or contains("api") or contains("openapi"))'
cat frontend/app/package.json | jq '.devDependencies | keys[] | select(. | contains("openapi") or contains("swagger") or contains("codegen"))'Repository: opsmill/infrahub
Length of output: 216
🏁 Script executed:
#!/bin/bash
# Look for generation configuration files
echo "=== Searching for OpenAPI/CodeGen config ==="
find . -type f \( -name "*openapi*" -o -name "*codegen*" -o -name "*.openapirc*" \) 2>/dev/null | grep -v node_modules | grep -v ".git" | head -20Repository: opsmill/infrahub
Length of output: 170
🏁 Script executed:
#!/bin/bash
# Check for git history of the OpenAPI schema
echo "=== Git history of OpenAPI schema changes ==="
git log --oneline -20 -- schema/openapi.json 2>/dev/null || echo "Git history not available"Repository: opsmill/infrahub
Length of output: 153
🏁 Script executed:
#!/bin/bash
# Check if there are Python dependencies or setup files related to OpenAPI generation
echo "=== Looking for Python-related OpenAPI generation ==="
find . -maxdepth 2 -type f \( -name "pyproject.toml" -o -name "setup.py" -o -name "setup.cfg" \) 2>/dev/null | head -5
ls -la | grep -E "pyproject|setup|requirements"Repository: opsmill/infrahub
Length of output: 236
🏁 Script executed:
#!/bin/bash
# Search for configuration that might be generating the types file
echo "=== Searching for openapi-generator or similar configuration ==="
grep -r "openapi" frontend/app/package.json 2>/dev/null | head -10
grep -r "swagger" frontend/app/package.json 2>/dev/null | head -10Repository: opsmill/infrahub
Length of output: 316
🏁 Script executed:
#!/bin/bash
# Check the actual git diff of the OpenAPI schema
echo "=== Recent changes to OpenAPI schema ==="
git log -p --follow -5 -- schema/openapi.json 2>/dev/null | grep -A 50 "ComputedAttribute-Output" | head -100 || echo "Could not retrieve full git history"Repository: opsmill/infrahub
Length of output: 100
🏁 Script executed:
#!/bin/bash
# Check the commit that modified the schema
echo "=== Checking commit b96e0ab46 ==="
git show b96e0ab46 --stat 2>/dev/null | head -50Repository: opsmill/infrahub
Length of output: 2827
🏁 Script executed:
#!/8in/bash
# Look for actual PR or recent changes mentioning ComputedAttribute or Python 3.14
echo "=== Searching for Python 3.14 or related changes ==="
grep -r "3.14" . --include="*.toml" --include="*.txt" --include="*.yml" --include="*.yaml" 2>/dev/null | head -20
grep -r "python_requires" . --include="*.toml" --include="*.py" 2>/dev/null | head -10Repository: opsmill/infrahub
Length of output: 438
🏁 Script executed:
#!/bin/bash
# Check if the generated file actually shows a change or if it was always like this
echo "=== Git history of types.generated.ts for ComputedAttribute-Output ==="
git log --oneline -10 -- frontend/app/src/shared/api/rest/types.generated.ts 2>/dev/null || echo "No history found"
git log -p -2 -- frontend/app/src/shared/api/rest/types.generated.ts 2>/dev/null | grep -A 5 -B 5 "ComputedAttribute-Output" | head -50Repository: opsmill/infrahub
Length of output: 178
🏁 Script executed:
#!/bin/bash
# Check the backend code that generates the OpenAPI schema
echo "=== Looking at backend OpenAPI generation ==="
grep -r "ComputedAttribute" backend/ --include="*.py" | grep -i "additional\|schema" | head -20Repository: opsmill/infrahub
Length of output: 2443
🏁 Script executed:
#!/bin/bash
# Check what files were modified in the last commit
echo "=== Files modified in latest commit ==="
git show --name-status b96e0ab46 2>/dev/null | head -50
git show --name-status b96e0ab46 2>/dev/null | grep -E "types.generated|openapi.json"Repository: opsmill/infrahub
Length of output: 1881
🏁 Script executed:
#!/bin/bash
# Check the OpenAPI schema generation in backend
echo "=== Looking for OpenAPI schema generation code ==="
find backend/ -name "*.py" -type f -exec grep -l "openapi\|OpenAPI" {} \; 2>/dev/null | head -10Repository: opsmill/infrahub
Length of output: 240
🏁 Script executed:
#!/bin/bash
# Verify the ComputedAttribute schema definition in backend
echo "=== ComputedAttribute schema definition ==="
grep -A 20 "class ComputedAttribute" backend/infrahub/core/schema/computed_attribute.py 2>/dev/null | head -30Repository: opsmill/infrahub
Length of output: 945
🏁 Script executed:
#!/bin/bash
# Check if there's a specific Pydantic model that generates the schema
echo "=== Searching for model_json_schema or similar ==="
grep -r "model_json_schema\|schema_extra\|ConfigDict" backend/infrahub/core/schema/computed_attribute.py 2>/dev/null | head -20Repository: opsmill/infrahub
Length of output: 226
🏁 Script executed:
#!/bin/bash
# Check the full ComputedAttribute model configuration
echo "=== Full ComputedAttribute model definition ==="
cat backend/infrahub/core/schema/computed_attribute.pyRepository: opsmill/infrahub
Length of output: 1916
🏁 Script executed:
#!/bin/bash
# Check if there's a separate output/response model for ComputedAttribute
echo "=== Searching for ComputedAttribute response/output models ==="
grep -r "ComputedAttribute.*Output\|ComputedAttribute.*Response" backend/ --include="*.py" 2>/dev/null | head -20Repository: opsmill/infrahub
Length of output: 122
🏁 Script executed:
#!/bin/bash
# Check the OpenAPI generation to understand where ComputedAttribute-Output comes from
echo "=== Checking API endpoints that use ComputedAttribute ==="
grep -r "ComputedAttribute" backend/infrahub/api/ --include="*.py" 2>/dev/null | head -20Repository: opsmill/infrahub
Length of output: 117
🏁 Script executed:
#!/bin/bash
# Check the server/API initialization for OpenAPI schema generation
echo "=== Checking OpenAPI schema generation setup ==="
cat backend/infrahub/server.py | grep -A 30 -B 5 "openapi\|OpenAPI" | head -100Repository: opsmill/infrahub
Length of output: 1276
🏁 Script executed:
#!/bin/bash
# Look for FastAPI app setup that might generate the schemas
echo "=== Searching for schemas generation in API init ==="
cat backend/infrahub/api/__init__.py | head -150Repository: opsmill/infrahub
Length of output: 2294
🏁 Script executed:
#!/bin/bash
# Check if there's a custom OpenAPI schema generator
echo "=== Checking for custom schema generation ==="
grep -r "get_openapi\|OpenAPI\|schema" backend/infrahub/api/__init__.py 2>/dev/null | head -30Repository: opsmill/infrahub
Length of output: 276
🏁 Script executed:
#!/bin/bash
# Look for where the "-Output" suffix might be added
echo "=== Searching for Output suffix in schema generation ==="
grep -r "\-Output\|Output" backend/infrahub/api/ --include="*.py" 2>/dev/null | grep -i "schema\|model" | head -20Repository: opsmill/infrahub
Length of output: 116
🏁 Script executed:
#!/bin/bash
# Check if ComputedAttribute appears in route handlers
echo "=== Checking for ComputedAttribute in routes ==="
find backend/infrahub/api/routes -name "*.py" -exec grep -l "ComputedAttribute\|computed" {} \; 2>/dev/nullRepository: opsmill/infrahub
Length of output: 108
🏁 Script executed:
#!/bin/bash
# Check if the schema/openapi.json and types.generated.ts are new files (initial commit)
echo "=== Checking if files were newly added ==="
git log --oneline --all -- schema/openapi.json frontend/app/src/shared/api/rest/types.generated.ts 2>/dev/null
# Check previous commits to see if there's any history
git log --oneline --all 2>/dev/null | head -10Repository: opsmill/infrahub
Length of output: 276
🏁 Script executed:
#!/bin/bash
# Check the total number of commits
echo "=== Repository commit history ==="
git rev-list --all --count 2>/dev/null
git log --oneline --all 2>/dev/null | tail -20Repository: opsmill/infrahub
Length of output: 182
🏁 Script executed:
#!/bin/bash
# Verify the mismatch: backend forbids extra properties but schema allows them
echo "=== Backend model configuration ==="
grep -A 50 "model_config = ConfigDict" backend/infrahub/core/schema/computed_attribute.py | head -60
echo ""
echo "=== OpenAPI schema for ComputedAttribute-Output ==="
cat schema/openapi.json | jq '.components.schemas."ComputedAttribute-Output"'Repository: opsmill/infrahub
Length of output: 1265
🏁 Script executed:
#!/bin/bash
# Double-check the backend model to confirm it forbids extra properties
echo "=== Backend ComputedAttribute model configuration (full) ==="
grep -B 5 -A 60 "class ComputedAttribute" backend/infrahub/core/schema/computed_attribute.py | grep -E "extra|forbid|class|json_schema"Repository: opsmill/infrahub
Length of output: 212
🏁 Script executed:
#!/bin/bash
# Check if there's any conversion or transformation that might explain the discrepancy
echo "=== Searching for OpenAPI schema generation customization ==="
grep -r "additionalProperties\|extra" backend/infrahub/api/ --include="*.py" 2>/dev/null | head -20Repository: opsmill/infrahub
Length of output: 1133
🏁 Script executed:
#!/bin/bash
# Check the test file for OpenAPI to see what's expected
echo "=== OpenAPI tests ==="
cat backend/tests/unit/api/test_70_openapi.py | head -100Repository: opsmill/infrahub
Length of output: 484
🏁 Script executed:
#!/bin/bash
# Check the schema.py file for additionalProperties handling
echo "=== Backend schema.py - additionalProperties handling ==="
grep -B 10 -A 10 "additionalProperties" backend/infrahub/api/schema.pyRepository: opsmill/infrahub
Length of output: 1435
🏁 Script executed:
#!/bin/bash
# Check if JSONSchema model has special handling
echo "=== Looking for JSONSchema model definition ==="
grep -r "class JSONSchema" backend/ --include="*.py" 2>/dev/nullRepository: opsmill/infrahub
Length of output: 167
🏁 Script executed:
#!/bin/bash
# Look at how FastAPI generates the schema from Pydantic models
echo "=== Checking for model_serializer impact on schema generation ==="
grep -B 20 -A 5 "model_serializer" backend/infrahub/core/schema/computed_attribute.pyRepository: opsmill/infrahub
Length of output: 927
🏁 Script executed:
#!/bin/bash
# Check if there's a custom OpenAPI schema customization function
echo "=== Searching for custom OpenAPI generation hooks ==="
grep -r "get_openapi\|modify_openapi_schema\|openapi_schema" backend/infrahub/ --include="*.py" 2>/dev/null | head -20Repository: opsmill/infrahub
Length of output: 113
🏁 Script executed:
#!/bin/bash
# Check the git diff for the initial commit to see if Record<string, never> ever existed
echo "=== Checking the actual diff from initial commit ==="
git show b96e0ab46:frontend/app/src/shared/api/rest/types.generated.ts 2>/dev/null | grep -A 3 -B 3 "ComputedAttribute-Output" | head -20Repository: opsmill/infrahub
Length of output: 659
🏁 Script executed:
#!/bin/bash
# Verify the schema generation matches what the backend model should produce
echo "=== Checking if schema contradicts backend model ==="
echo "Backend says: extra='forbid'"
echo "Schema says: additionalProperties: true"
echo ""
echo "This is a contract violation - the schema allows what the backend forbids."Repository: opsmill/infrahub
Length of output: 257
The schema-to-implementation contract is violated: backend forbids extra properties while the OpenAPI schema declares additionalProperties: true.
The backend ComputedAttribute model has extra="forbid" in its Pydantic config, but the OpenAPI schema for ComputedAttribute-Output allows arbitrary properties via additionalProperties: true. This creates a mismatch between what the backend will actually reject at runtime and what the generated TypeScript type ({ [key: string]: unknown }) suggests is valid, risking integration failures.
Either:
- The backend model should have
extra="allow"if the schema intends to support dynamic properties, or - The schema should have
additionalProperties: falseto match the backend's strict validation
Verify that the OpenAPI schema generation intentionally overrides the backend model's extra="forbid" setting, or correct the schema to match the backend constraints.
Stay with 3.13 due to compat issues with external packages. Signed-off-by: Fatih Acar <[email protected]>
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
pyproject.toml (1)
62-63: Consider adding upper bounds for stability.Removing upper bounds on
pyarrowandnumpyprovides flexibility but may expose the project to unexpected breaking changes in future major versions. If stability is a concern, consider adding upper bounds likepyarrow>=14,<19andnumpy>=1.26.2,<3.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
uv.lockis excluded by!**/*.lock
📒 Files selected for processing (5)
.devcontainer/Dockerfile(1 hunks).github/workflows/define-versions.yml(1 hunks).github/workflows/keyword-scan.yml(1 hunks)development/Dockerfile(1 hunks)pyproject.toml(5 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- development/Dockerfile
- .devcontainer/Dockerfile
- .github/workflows/keyword-scan.yml
🧰 Additional context used
📓 Path-based instructions (1)
{pyproject.toml,uv.lock}
📄 CodeRabbit inference engine (.github/instructions/tooling.instructions.md)
Use uv to manage the Python project and its dependencies
Files:
pyproject.toml
🧠 Learnings (2)
📚 Learning: 2025-12-01T22:15:34.303Z
Learnt from: CR
Repo: opsmill/infrahub PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-01T22:15:34.303Z
Learning: Applies to backend/pyproject.toml : Use `uv` for dependency management in backend Python projects
Applied to files:
pyproject.toml
📚 Learning: 2025-12-01T22:16:13.680Z
Learnt from: CR
Repo: opsmill/infrahub PR: 0
File: backend/AGENTS.md:0-0
Timestamp: 2025-12-01T22:16:13.680Z
Learning: Applies to backend/infrahub/**/*.py : Type hint all function parameters and returns in Python code
Applied to files:
pyproject.toml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: yaml-lint
🔇 Additional comments (6)
.github/workflows/define-versions.yml (1)
9-10: LGTM! Valid Python version.Python 3.13.11 is a valid maintenance release, and this change correctly establishes a centralized version definition that can be consumed by multiple workflows. The PR title mentions "Python 3.14" while using 3.13.11, which makes sense as Python 3.14 is now the latest feature release, and the project appears to be ensuring compatibility with 3.13 while preparing for 3.14 support (as indicated by the pyproject.toml range
<3.14mentioned in the AI summary).pyproject.toml (5)
6-6: LGTM!The Python version constraint correctly expands support to include Python 3.13 while maintaining 3.12 compatibility. The classifier accurately reflects the supported versions.
Also applies to: 14-14
18-20: LGTM!Exact version pinning for
neo4jandneo4j-rust-extensures a known-good combination, andpydantic>=2.12includes improved Python 3.13 compatibility.
50-53: LGTM!OpenTelemetry packages are correctly pinned and the instrumentation (0.60b0) and exporter (1.39.0) versions are properly aligned as expected for their release cadence.
31-31: LGTM!Minor and patch version updates for
prefect-redis,aiodataloader, and dev dependencies are straightforward. The inline comments on API server dependencies improve maintainability.Also applies to: 45-48, 57-57, 103-104
58-58: Verify if fast-depends 3.0.5 has breaking changes from 2.4.12.The codebase uses standard FastDepends APIs (Depends, inject, Provider, dependency_provider.scope()) that appear compatible with version 3.0.5 based on current documentation. However, confirm the major version upgrade (2.x → 3.x) introduces no breaking changes affecting these APIs by reviewing the official FastDepends 3.0 release notes or changelog.
| "mypy>=1.15,<1.16", | ||
| "ipython>=8,<9", | ||
| "pytest-asyncio>=0.21.1,<0.22", | ||
| "pytest-asyncio>=1.3,<1.4", |
There was a problem hiding this comment.
Correct asyncio_default_fixture_loop_scope to function scope.
The configuration should be set to "function" to address the deprecation warning about the unset configuration option. The default value should be function, and asyncio_default_fixture_loop_scope should not be set explicitly unless necessary. By default, each test runs in the event loop provided by the Function collector, which uses the loop with the narrowest scope and gives the highest level of isolation between tests. Setting this to "session" can cause compatibility issues with fixture management.
🤖 Prompt for AI Agents
In pyproject.toml around line 85, the pytest-asyncio configuration currently
sets asyncio_default_fixture_loop_scope incorrectly (or to session); change this
option to "function" (or remove the explicit setting to rely on the default) to
eliminate the deprecation/compatibility warning and ensure each test uses a
function-scoped event loop for proper fixture isolation.
Summary by CodeRabbit
Infrastructure
API Changes
Dependencies
Tests
Frontend
✏️ Tip: You can customize this high-level summary in your review settings.