Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion backend/infrahub/artifacts/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ class CheckArtifactCreate(BaseModel):
target_kind: str = Field(..., description="The kind of the target object for this artifact")
target_name: str = Field(..., description="Name of the artifact target")
artifact_id: str | None = Field(default=None, description="The id of the artifact if it previously existed")
query: str = Field(..., description="The name of the query to use when collecting data")
query: str = Field(..., description="The name of the query to use when collecting data") # Deprecated
query_id: str = Field(..., description="The id of the query to use when collecting data")
timeout: int = Field(..., description="Timeout for requests used to generate this artifact")
variables: dict = Field(..., description="Input variables when generating the artifact")
validator_id: str = Field(..., description="The ID of the validator")
Expand Down
2 changes: 1 addition & 1 deletion backend/infrahub/computed_attribute/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ async def process_transform(
) # type: ignore[misc]

data = await client.query_gql_query(
name=transform.query.peer.name.value,
name=transform.query.id,
branch_name=branch_name,
variables={"id": object_id},
update_group=True,
Expand Down
20 changes: 19 additions & 1 deletion backend/infrahub/core/schema/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

from typing import TYPE_CHECKING, Any

from cachetools import LRUCache
from infrahub_sdk.schema import BranchSchema as SDKBranchSchema

from infrahub import lock
from infrahub.core.manager import NodeManager
from infrahub.core.models import (
Expand Down Expand Up @@ -40,6 +43,8 @@ class SchemaManager(NodeManager):
def __init__(self) -> None:
self._cache: dict[int, Any] = {}
self._branches: dict[str, SchemaBranch] = {}
self._branch_hash_by_name: dict[str, str] = {}
self._sdk_branches: LRUCache[str, SDKBranchSchema] = LRUCache(maxsize=10)

def _get_from_cache(self, key: int) -> Any:
return self._cache[key]
Expand Down Expand Up @@ -140,12 +145,23 @@ def get_schema_branch(self, name: str) -> SchemaBranch:
if name in self._branches:
return self._branches[name]

self._branches[name] = SchemaBranch(cache=self._cache, name=name)
self.set_schema_branch(name, schema=SchemaBranch(cache=self._cache, name=name))
return self._branches[name]

def get_sdk_schema_branch(self, name: str) -> SDKBranchSchema:
schema_hash = self._branch_hash_by_name[name]
branch_schema = self._sdk_branches.get(schema_hash)
if not branch_schema:
self._sdk_branches[schema_hash] = SDKBranchSchema.from_api_response(
data=self._branches[name].to_dict_api_schema_object()
)

return self._sdk_branches[schema_hash]

def set_schema_branch(self, name: str, schema: SchemaBranch) -> None:
schema.name = name
self._branches[name] = schema
self._branch_hash_by_name[name] = schema.get_hash()

def process_schema_branch(self, name: str) -> None:
schema_branch = self.get_schema_branch(name=name)
Expand Down Expand Up @@ -764,6 +780,8 @@ def purge_inactive_branches(self, active_branches: list[str]) -> list[str]:
for branch_name in list(self._branches.keys()):
if branch_name not in active_branches:
del self._branches[branch_name]
if branch_name in self._branch_hash_by_name:
del self._branch_hash_by_name[branch_name]
removed_branches.append(branch_name)

for hash_key in list(self._cache.keys()):
Expand Down
8 changes: 8 additions & 0 deletions backend/infrahub/core/schema/schema_branch.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,14 @@ def to_dict_schema_object(self, duplicate: bool = False) -> dict[str, dict[str,
"templates": {name: self.get(name, duplicate=duplicate) for name in self.templates},
}

def to_dict_api_schema_object(self) -> dict[str, list[dict]]:
return {
"nodes": [self.get(name, duplicate=False).model_dump() for name in self.nodes],
"profiles": [self.get(name, duplicate=False).model_dump() for name in self.profiles],
"generics": [self.get(name, duplicate=False).model_dump() for name in self.generics],
"templates": [self.get(name, duplicate=False).model_dump() for name in self.templates],
}

@classmethod
def from_dict_schema_object(cls, data: dict) -> Self:
type_mapping = {
Expand Down
10 changes: 3 additions & 7 deletions backend/infrahub/generators/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
)
from infrahub.git.base import extract_repo_file_information
from infrahub.git.repository import get_initialized_repo
from infrahub.git.utils import fetch_proposed_change_generator_definition_targets
from infrahub.workers.dependencies import get_client, get_workflow
from infrahub.workflows.catalogue import REQUEST_GENERATOR_DEFINITION_RUN, REQUEST_GENERATOR_RUN
from infrahub.workflows.utils import add_tags
Expand Down Expand Up @@ -177,14 +178,9 @@ async def request_generator_definition_run(
branch=model.branch,
)

group = await client.get(
kind=InfrahubKind.GENERICGROUP,
prefetch_relationships=True,
populate_store=True,
id=model.generator_definition.group_id,
branch=model.branch,
group = await fetch_proposed_change_generator_definition_targets(
client=client, branch=model.branch, definition=model.generator_definition
)
await group.members.fetch()

instance_by_member = {}
for instance in existing_instances:
Expand Down
2 changes: 1 addition & 1 deletion backend/infrahub/git/integrator.py
Original file line number Diff line number Diff line change
Expand Up @@ -1363,7 +1363,7 @@ async def render_artifact(
message: CheckArtifactCreate | RequestArtifactGenerate,
) -> ArtifactGenerateResult:
response = await self.sdk.query_gql_query(
name=message.query,
name=message.query_id,
variables=message.variables,
update_group=True,
subscribers=[artifact.id],
Expand Down
3 changes: 2 additions & 1 deletion backend/infrahub/git/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ class RequestArtifactGenerate(BaseModel):
target_kind: str = Field(..., description="The kind of the target object for this artifact")
target_name: str = Field(..., description="Name of the artifact target")
artifact_id: str | None = Field(default=None, description="The id of the artifact if it previously existed")
query: str = Field(..., description="The name of the query to use when collecting data")
query: str = Field(..., description="The name of the query to use when collecting data") # Deprecated
query_id: str = Field(..., description="The id of the query to use when collecting data")
timeout: int = Field(..., description="Timeout for requests used to generate this artifact")
variables: dict = Field(..., description="Input variables when generating the artifact")
context: InfrahubContext = Field(..., description="The context of the task")
Expand Down
27 changes: 22 additions & 5 deletions backend/infrahub/git/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

from typing import TYPE_CHECKING, Any

from cachetools import TTLCache
from cachetools.keys import hashkey
from cachetools_async import cached
from git.exc import BadName, GitCommandError
from infrahub_sdk.exceptions import GraphQLError
from prefect import task
Expand Down Expand Up @@ -248,12 +251,13 @@ async def sync_from_remote(self, commit: str | None = None) -> None:
await self.update_commit_value(branch_name=self.infrahub_branch_name, commit=commit)


@task(
name="Fetch repository commit",
description="Retrieve a git repository at a given commit, if it does not already exist locally",
cache_policy=NONE,
@cached(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a blocker for this PR but I'm wondering if we could leverage prefect for the caching ? and what is the limitation if you already tried

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was done using the Prefect caching mechanism in the first iteration, but as described in the following commit: 02b289d

- local caching requires a lot of setup (wrt Blocks, etc)
- it's memory intensive due to excessive pickle serialization in our case (we don't need it)

Revert to basic local TTL cache.```

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically Prefect caching is useful for distributed caching but here we want a local, efficient cache.

TTLCache(maxsize=100, ttl=30),
key=lambda *_, **kwargs: hashkey(
kwargs.get("repository_id"), kwargs.get("name"), kwargs.get("repository_kind"), kwargs.get("commit")
),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given the TTL it might not have a practical meaning now, but given that commit can be None I think we might occasionally end up with a repo using an earlier commit that we would have expected. In another iteration we could instead cache after we have the commit. Repository_id and commit is probably enough to use for the key.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The TTL is lower than the git sync scheduled job on purpose because I'd expect this kind of edge case... I think it's fine like that for the moment.
+1 for the key.

)
async def get_initialized_repo(
async def _get_initialized_repo(
client: InfrahubClient, repository_id: str, name: str, repository_kind: str, commit: str | None = None
) -> InfrahubReadOnlyRepository | InfrahubRepository:
if repository_kind == InfrahubKind.REPOSITORY:
Expand All @@ -263,3 +267,16 @@ async def get_initialized_repo(
return await InfrahubReadOnlyRepository.init(id=repository_id, name=name, commit=commit, client=client)

raise NotImplementedError(f"The repository kind {repository_kind} has not been implemented")


@task(
name="Fetch repository commit",
description="Retrieve a git repository at a given commit, if it does not already exist locally",
cache_policy=NONE,
)
async def get_initialized_repo(
client: InfrahubClient, repository_id: str, name: str, repository_kind: str, commit: str | None = None
) -> InfrahubReadOnlyRepository | InfrahubRepository:
return await _get_initialized_repo(
client=client, repository_id=repository_id, name=name, repository_kind=repository_kind, commit=commit
)
22 changes: 14 additions & 8 deletions backend/infrahub/git/tasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
UserCheckDefinitionData,
)
from .repository import InfrahubReadOnlyRepository, InfrahubRepository, get_initialized_repo
from .utils import fetch_artifact_definition_targets, fetch_check_definition_targets


@flow(
Expand Down Expand Up @@ -323,9 +324,8 @@ async def generate_request_artifact_definition(
kind=CoreArtifactDefinition, id=model.artifact_definition_id, branch=model.branch
)

await artifact_definition.targets.fetch()
group = artifact_definition.targets.peer
await group.members.fetch()
group = await fetch_artifact_definition_targets(client=client, branch=model.branch, definition=artifact_definition)

current_members = [member.id for member in group.members.peers]

artifacts_by_member = {}
Expand Down Expand Up @@ -356,6 +356,7 @@ async def generate_request_artifact_definition(
transform_location = f"{transform.file_path.value}::{transform.class_name.value}"
convert_query_response = transform.convert_query_response.value

batch = await client.create_batch()
for relationship in group.members.peers:
member = relationship.peer
artifact_id = artifacts_by_member.get(member.id)
Expand All @@ -376,6 +377,7 @@ async def generate_request_artifact_definition(
repository_kind=repository.get_kind(),
branch_name=model.branch,
query=query.name.value,
query_id=query.id,
variables=await member.extract(params=artifact_definition.parameters.value),
target_id=member.id,
target_name=member.display_label,
Expand All @@ -385,10 +387,16 @@ async def generate_request_artifact_definition(
context=context,
)

await get_workflow().submit_workflow(
workflow=REQUEST_ARTIFACT_GENERATE, context=context, parameters={"model": request_artifact_generate_model}
batch.add(
task=get_workflow().submit_workflow,
workflow=REQUEST_ARTIFACT_GENERATE,
context=context,
parameters={"model": request_artifact_generate_model},
)

async for _, _ in batch.execute():
pass


@flow(name="git-repository-pull-read-only", flow_run_name="Pull latest commit on {model.repository_name}")
async def pull_read_only(model: GitRepositoryPullReadOnly) -> None:
Expand Down Expand Up @@ -569,9 +577,7 @@ async def trigger_repository_user_checks_definitions(model: UserCheckDefinitionD

if definition.targets.id:
# Check against a group of targets
await definition.targets.fetch()
group = definition.targets.peer
await group.members.fetch()
group = await fetch_check_definition_targets(client=client, branch=model.branch_name, definition=definition)
check_models = []
for relationship in group.members.peers:
member = relationship.peer
Expand Down
124 changes: 123 additions & 1 deletion backend/infrahub/git/utils.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
from typing import TYPE_CHECKING
from collections import defaultdict
from typing import TYPE_CHECKING, Any

from infrahub_sdk import InfrahubClient
from infrahub_sdk.node import RelationshipManager
from infrahub_sdk.protocols import CoreArtifactDefinition, CoreCheckDefinition, CoreGroup
from infrahub_sdk.types import Order

from infrahub.core import registry
from infrahub.core.constants import InfrahubKind
from infrahub.core.manager import NodeManager
from infrahub.database import InfrahubDatabase
from infrahub.generators.models import ProposedChangeGeneratorDefinition

from .models import RepositoryBranchInfo, RepositoryData

Expand Down Expand Up @@ -46,3 +53,118 @@ async def get_repositories_commit_per_branch(
)

return repositories


def _collect_parameter_first_segments(params: Any) -> set[str]:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need an Any here looks like we expect str | list | tuple | set | dict and won't use anything else.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think LLM used Any here because we pass parameters straight from the JSONAttribute protocol where value is typed as Any. This looks legit?

segments: set[str] = set()

def _walk(value: Any) -> None:
if isinstance(value, str):
segment = value.split("__", 1)[0]
if segment:
segments.add(segment)
elif isinstance(value, dict):
for nested in value.values():
_walk(nested)
elif isinstance(value, (list, tuple, set)):
for nested in value:
_walk(nested)

_walk(params)
return segments
Comment on lines +58 to +74
Copy link
Contributor

@coderabbitai coderabbitai bot Oct 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Add docstrings to new utility functions.

All three new functions (_collect_parameter_first_segments, _prefetch_group_member_nodes, and fetch_definition_targets) lack docstrings.

As per coding guidelines, Python functions should include Google-style docstrings with:

  • A brief one-line description
  • An Args section documenting parameters (without types)
  • A Returns section describing the return value

Example for fetch_definition_targets:

async def fetch_definition_targets(
    client: InfrahubClient,
    branch: str,
    definition: CoreArtifactDefinition | CoreCheckDefinition | ProposedChangeGeneratorDefinition,
) -> CoreGroup:
    """Fetch target group for a definition with prefetched member nodes.
    
    Retrieves the target group associated with the given artifact, check, or generator
    definition, and prefetches member nodes based on the parameters defined in the
    definition.
    
    Args:
        client: The Infrahub SDK client for API interactions
        branch: The branch name to fetch the group from
        definition: The definition object containing targets and parameters
        
    Returns:
        The target group with prefetched member nodes populated in the client store
    """

Also applies to: 77-122, 124-155

🤖 Prompt for AI Agents
In backend/infrahub/git/utils.py around lines 58-74, 77-122 and 124-155, the
three new functions (_collect_parameter_first_segments,
_prefetch_group_member_nodes, and fetch_definition_targets) are missing
docstrings; add Google-style docstrings to each function consisting of a
one-line summary, an Args section listing parameters (no types), and a Returns
section describing the return value (matching existing project style). For
fetch_definition_targets follow the provided example (brief summary, purpose,
Args: client, branch, definition, and Returns: the target group with prefetched
member nodes) and for the other two document their parameters and return
sets/structures similarly, ensuring consistency and placement immediately below
each def line.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey coderabbit, where is this requirement for docstring coming from?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash

# Look for coding guidelines or contribution documentation
echo "=== Looking for coding guidelines documentation ==="
fd -t f -e md | xargs grep -l -i "docstring\|coding.*guideline\|style.*guide\|contribution" 2>/dev/null | head -10

echo -e "\n=== Checking for Python linter configurations ==="
# Check for ruff, pylint, or other linter configs
fd -t f "ruff.toml|pylint|.pylintrc|pyproject.toml" -x cat {}

echo -e "\n=== Sampling docstring usage in existing utility functions ==="
# Check a few existing Python files in backend/infrahub for docstring patterns
fd -e py -t f . backend/infrahub/core backend/infrahub/git | head -5 | xargs -I {} sh -c 'echo "=== File: {} ===" && head -50 {}'

Length of output: 32967


@ogenstad The requirement for docstrings is not enforced by your linter configuration. Looking at your pyproject.toml, I can see that:

ignore = [
    "D",        # pydocstyle
    "DOC",      # pydoclint
    ...
]

Both pydocstyle (D) and pydoclint (DOC) rules are explicitly disabled.

However, I noticed that existing functions in the codebase often include docstrings. For example, the get_repositories_commit_per_branch function in the same file (backend/infrahub/git/utils.py) has a Google-style docstring:

async def get_repositories_commit_per_branch(
    db: InfrahubDatabase,
) -> dict[str, RepositoryData]:
    """Get a list of all repositories and their commit on each branches.

    This method is similar to 'get_list_repositories' method in the Python SDK.

    NOTE: At some point, we should refactor this function to use a single Database query instead of one per branch
    """

My suggestion was based on this existing pattern in the codebase as a best practice, not a hard requirement from your configuration.

If you'd prefer not to receive docstring suggestions for this project, I can remember that for future reviews.


🧬 Code Graph Analysis Results
  • File: backend/infrahub/git/utils.py | Lines 1-28

    • Full snippet:
      async def get_repositories_commit_per_branch(
      db: InfrahubDatabase,
      ) -> dict[str, RepositoryData]:
      """Get a list of all repositories and their commit on each branches.

      This method is similar to 'get_list_repositories' method in the Python SDK.
      
      NOTE: At some point, we should refactor this function to use a single Database query instead of one per branch
      """
      
      repositories: dict[str, RepositoryData] = {}
      
      for branch in list(registry.branch.values()):
          repos: list[CoreGenericRepository] = await NodeManager.query(
              db=db,
              branch=branch,
              fields={"id": None, "name": None, "commit": None, "internal_status": None},
              schema=InfrahubKind.GENERICREPOSITORY,
          )
      
          for repository in repos:
              repo_name = repository.name.value
              if repo_name not in repositories:
                  repositories[repo_name] = RepositoryData(
                      repository_id=repository.get_id(),
                      repository_name=repo_name,
                      branches={},
                  )
      
              repositories[repo_name].branches[branch.name] = repository.commit.value  # type: ignore[attr-defined]
              repositories[repo_name].branch_info[branch.name] = RepositoryBranchInfo(
                  internal_status=repository.internal_status.value
              )
      
      return repositories
      
  • File: backend/infrahub/core/manager.py | Lines 1-60

    • Summary:
      Docstring for NodeManager.query describes its purpose and arguments. It states that the method:
      • Queries one or multiple nodes of a given type based on filter arguments.
      • Accepts parameters including schema (NodeSchema or type), filters, fields, offset, limit, at, branch, include_source, include_owner, prefetch_relationships, account, partial_match, branch_agnostic, and order.
      • Returns a list of Node objects (or a list of SchemaProtocol objects when the more specific overload is used).
      • Includes behavior notes such as how branch resolution and HFID handling influence querying, and how results are formed.
      • Includes a Python-style Args/Returns documentation block within the method docstring.
  • File: backend/infrahub/core/manager.py | Lines 60-110

    • Summary:
      Docstring for NodeManager.count describes its purpose, parameters, and return value for counting nodes that match filters. It notes:
      • Accepts db, schema (type[SchemaProtocol] | NodeSchema | GenericSchema | ProfileSchema | TemplateSchema | str), filters, at, branch, account, partial_match, branch_agnostic.
      • Returns an int representing the number of responses found.
  • File: backend/infrahub/core/manager.py | Lines 110-170

    • Summary:
      Docstring for NodeManager.query_peers describes its purpose and parameters for querying peer nodes. It notes:
      • Accepts db, ids, source_kind, schema, filters, fields (optional), offset (optional), limit (optional), at (optional), branch (optional), branch_agnostic, fetch_peers.
      • Returns a list of Relationship objects (or related node representations) depending on inputs.
      • Includes behavior about how fields and HFID-related field selection are handled when requested.



async def _prefetch_group_member_nodes(
client: InfrahubClient,
members: RelationshipManager,
branch: str,
required_fields: set[str],
) -> None:
ids_per_kind: dict[str, set[str]] = defaultdict(set)
Comment on lines +77 to +83
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Add Google‑style docstrings to new utilities.

Per repo guidelines, add docstrings to _prefetch_group_member_nodes, fetch_definition_targets, and public fetch* helpers.

Minimal examples:

 async def _prefetch_group_member_nodes(...):
+    """Batch‑prefetch group member nodes for required fields.
+
+    Args:
+        client: SDK client.
+        members: Relationship manager for group.members.
+        branch: Branch to query.
+        required_fields: Top‑level attribute/relationship names needed.
+
+    Returns:
+        None. Populates the client store with fetched nodes.
+    """
@@
 async def _fetch_definition_targets(...)-> CoreGroup:
+    """Fetch target group and prefetch members based on definition parameters."""
@@
 async def fetch_artifact_definition_targets(...)-> CoreGroup:
+    """Public helper to resolve targets for an artifact definition."""
@@
 async def fetch_check_definition_targets(...)-> CoreGroup:
+    """Public helper to resolve targets for a check definition."""
@@
 async def fetch_proposed_change_generator_definition_targets(...)-> CoreGroup:
+    """Public helper to resolve targets for a proposed change generator definition."""

Also applies to: 119-141, 143-170

for peer in members.peers:
if peer.id and peer.typename:
ids_per_kind[peer.typename].add(peer.id)

Comment on lines +84 to +87
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Wrong entity from RelationshipManager.peers; use relationship.peer.

peers yields Relationship objects. Access the node via relationship.peer; otherwise peer.typename may not exist and ids_per_kind stays empty.

-    for peer in members.peers:
-        if peer.id and peer.typename:
-            ids_per_kind[peer.typename].add(peer.id)
+    for relationship in members.peers:
+        node = relationship.peer
+        if node.id and node.typename:
+            ids_per_kind[node.typename].add(node.id)
🤖 Prompt for AI Agents
In backend/infrahub/git/utils.py around lines 84 to 87, the loop is iterating
Relationship objects from members.peers but treats them as if they were nodes;
change the loop to treat each item as a relationship, retrieve the node via
relationship.peer, then check that that peer has id and typename before adding
to ids_per_kind (e.g., for relationship in members.peers: peer =
relationship.peer; if peer and peer.id and peer.typename:
ids_per_kind[peer.typename].add(peer.id)). Ensure you don't assume peers yields
raw nodes and guard against missing peer attributes.

if not ids_per_kind:
return

batch = await client.create_batch()

for kind, ids in ids_per_kind.items():
schema = await client.schema.get(kind=kind, branch=branch)

# FIXME: https://github.com/opsmill/infrahub-sdk-python/pull/205
valid_fields = set(schema.attribute_names) | set(schema.relationship_names)
keep_relationships = set(schema.relationship_names) & required_fields
cleaned_fields = valid_fields - required_fields

kwargs: dict[str, Any] = {
"kind": kind,
"ids": list(ids),
"branch": branch,
"exclude": list(cleaned_fields),
"populate_store": True,
"order": Order(disable=True),
}

if keep_relationships:
kwargs["include"] = list(keep_relationships)

batch.add(task=client.filters, **kwargs)

async for _ in batch.execute():
pass


async def _fetch_definition_targets(
client: InfrahubClient,
branch: str,
group_id: str,
parameters: Any,
) -> CoreGroup:
group = await client.get(
kind=CoreGroup,
id=group_id,
branch=branch,
include=["members"],
)

parameter_fields = _collect_parameter_first_segments(parameters)
await _prefetch_group_member_nodes(
client=client,
members=group.members,
branch=branch,
required_fields=parameter_fields,
)

return group


async def fetch_artifact_definition_targets(
client: InfrahubClient,
branch: str,
definition: CoreArtifactDefinition,
) -> CoreGroup:
return await _fetch_definition_targets(
client=client, branch=branch, group_id=definition.targets.id, parameters=definition.parameters.value
)


async def fetch_check_definition_targets(
client: InfrahubClient,
branch: str,
definition: CoreCheckDefinition,
) -> CoreGroup:
return await _fetch_definition_targets(
client=client, branch=branch, group_id=definition.targets.id, parameters=definition.parameters.value
)


async def fetch_proposed_change_generator_definition_targets(
client: InfrahubClient,
branch: str,
definition: ProposedChangeGeneratorDefinition,
) -> CoreGroup:
return await _fetch_definition_targets(
client=client, branch=branch, group_id=definition.group_id, parameters=definition.parameters
)
3 changes: 2 additions & 1 deletion backend/infrahub/message_bus/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ class ProposedChangeArtifactDefinition(BaseModel):
definition_id: str
definition_name: str
artifact_name: str
query_name: str
query_name: str # Deprecated
query_id: str
query_models: list[str]
repository_id: str
transform_kind: str
Expand Down
Loading