Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
d9a636a
fix(core): cap and consolidate group mutation event related resources
ogenstad Aug 7, 2026
b8deb26
fix(pytest-plugin): run repository smoke tests first (#10171)
gmazoyer Aug 10, 2026
ff8a1fd
chore(deps): bump dorny/paths-filter from 4.0.2 to 4.0.3
dependabot[bot] Aug 10, 2026
3577946
Merge pull request #10190 from opsmill/dependabot/github_actions/stab…
saltas888 Aug 10, 2026
487e55d
fix(frontend): render date-format previews in the timezone being edited
saltas888 Aug 10, 2026
76f8fe3
fix(frontend): show far-future dates in the preferred format, not rel…
saltas888 Aug 10, 2026
21483b4
fix(frontend): keep the time on DateTime attributes on object details
saltas888 Aug 10, 2026
3daed1d
chore(deps): bump CodSpeedHQ/action from 4 to 5 (#10191)
dependabot[bot] Aug 10, 2026
d0f22cf
chore(deps): bump actions/stale from 10 to 11 (#10192)
dependabot[bot] Aug 10, 2026
0f67085
fix(frontend): preview the inherited zone when a personal timezone is…
saltas888 Aug 10, 2026
e1f27bf
docs(frontend): tighten the inheritedTimezone contract comment
saltas888 Aug 10, 2026
9a4b9c0
fix(frontend): link repositories to concrete kind and request profile…
claude[bot] Aug 10, 2026
60facc0
fix(frontend): treat only the global layer as inherited for the zone …
saltas888 Aug 10, 2026
2504d21
Clone git repositories on their own default branch (#10141)
gmazoyer Aug 10, 2026
28599fc
Merge remote-tracking branch 'origin/release-1.11' into feat/user-pre…
saltas888 Aug 10, 2026
5589a5d
fix(e2e): match the default badge exactly on the branch-details page
saltas888 Aug 10, 2026
f77cf88
fix(backend): delete branch data in bounded batches (#10132)
ajtmccarty Aug 10, 2026
eaa5414
Merge branch 'stable' into stable-to-release-1.11 with conflicts
ajtmccarty Aug 10, 2026
d2eb74d
resolve backend test import conflict
ajtmccarty Aug 10, 2026
8e2b70a
resolve BranchDelete mutation conflict
ajtmccarty Aug 10, 2026
5be5ac8
update delete_branch task to use WorkflowPriority.LOW
ajtmccarty Aug 10, 2026
ffc1e0c
resolve frontend conflicts from concrete-kind repository links
ajtmccarty Aug 10, 2026
ae3dae8
clean up comment
ajtmccarty Aug 10, 2026
e35e2d7
fix BranchDeleteCoordinator tests for expected workflow calls
ajtmccarty Aug 10, 2026
9b570f6
match on exact "default" for visibility check
ajtmccarty Aug 10, 2026
ad4bdf9
fix: create branches imported from git with sync_with_git enabled [IF…
ogenstad Aug 11, 2026
1dda41c
test(frontend): pre-bundle react-dropdown-menu so it cannot reload mi…
saltas888 Aug 11, 2026
07d86fb
Merge branch 'release-1.11' into feat/user-preferences-issue-ce071b
saltas888 Aug 11, 2026
8238a57
Merge branch 'release-1.11' into feat/user-preferences-issue-ce071b
saltas888 Aug 11, 2026
c7b34de
Merge pull request #10163 from opsmill/pog-droped-group-events-IFC-2971
ogenstad Aug 11, 2026
293dba3
test: pin import_sync_branch_names so the git sync flag test ignores …
ogenstad Aug 11, 2026
04c37fb
Merge pull request #10205 from opsmill/stable-to-release-1.11
bilalabbad Aug 11, 2026
9513cbd
Merge remote-tracking branch 'origin/release-1.11' into feat/user-pre…
saltas888 Aug 11, 2026
362ef68
Merge pull request #10193 from opsmill/feat/user-preferences-issue-ce…
saltas888 Aug 11, 2026
3993523
fix: keep kinds with no read field as a kind-level dependency (#10189)
gmazoyer Aug 11, 2026
b1c8b71
fix: reject artifacts whose transform returned no payload (closes #53…
saltas888 Aug 11, 2026
449be3d
fix: reliably write merge back to non-main default branch on multi-wo…
polmichel Aug 11, 2026
1a29ee2
Merge pull request #10209 from opsmill/pog-create-git-branch-with-syn…
ogenstad Aug 11, 2026
caf17bf
docs(knowledge): correct observer fan-out description in api-backpres…
polmichel Aug 11, 2026
f431abb
docs(guidelines): fix double-attribution in testing adapters example …
polmichel Aug 11, 2026
3b826db
docs(objects): clarify kind/identifier are required but ignored with …
polmichel Aug 11, 2026
c81961c
Backport rebase common ancestor schema (#10207)
ajtmccarty Aug 11, 2026
08c1c96
Merge branch 'stable' into stable-to-release-1.11
ajtmccarty Aug 11, 2026
509e3a6
Prep release 1.10.7 (#10221)
ajtmccarty Aug 11, 2026
356c8e4
chore: update docker-compose
opsmill-bot Aug 11, 2026
47da2c6
fix: resolve stable merge conflicts in the schema update coordinator
ajtmccarty Aug 11, 2026
9a1d662
fix(tests): repoint group-action test imports at the task_manager eve…
ajtmccarty Aug 11, 2026
7e2dede
Merge remote-tracking branch 'origin/stable' into stable-to-release-1.11
ajtmccarty Aug 11, 2026
72f5157
chore: retrigger CI
claude Aug 11, 2026
ec28987
Merge pull request #10223 from opsmill/stable-to-release-1.11
ogenstad Aug 12, 2026
f4e7473
Update frontend dependencies (#10225)
bilalabbad Aug 12, 2026
bc7a578
docs: link marketplace page to marketplace.infrahub.app (#10222)
yjouffrault Aug 12, 2026
24cebd1
Merge pull request #10235 from opsmill/stable
infrahub-github-bot-app[bot] Aug 12, 2026
4016772
fix: advance number pool past values already present on the target ki…
iddocohen Aug 13, 2026
4273ec7
fix: forbid unknown fields in the exported node JSON Schema [INFP-234…
ogenstad Aug 13, 2026
624eeb4
docs: Rework learn documentation (#10212)
BaptisteGi Aug 13, 2026
7b36dc0
docs(objects): add Create objects overview page (#10233)
BaptisteGi Aug 13, 2026
ce445fd
fix(recompute): keep the branch and node tags on a task that writes (…
gmazoyer Aug 13, 2026
2ffcc79
fix: narrow Python transform closure to its own file (#10240)
ogenstad Aug 13, 2026
5cad1f7
Merge pull request #10239 from opsmill/stable
saltas888 Aug 13, 2026
353a386
fix: validate preference timezone at write and correct the UI source …
polmichel Aug 13, 2026
a95933f
fix(core): reserve headroom below the Prefect related-resources maxim…
ogenstad Aug 13, 2026
e330c24
test(events): prove an event on the maximum is rejected after the run…
ogenstad Aug 13, 2026
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
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ jobs:
with:
submodules: true
- name: Check for file changes
uses: dorny/paths-filter@v4.0.2
uses: dorny/paths-filter@v4.0.3
id: changes
with:
token: ${{ github.token }}
Expand Down Expand Up @@ -1532,7 +1532,7 @@ jobs:

- name: Run all benchmarks
if: contains(github.event.pull_request.labels.*.name, 'ci/run-intensive-benchmarks')
uses: CodSpeedHQ/action@v4
uses: CodSpeedHQ/action@v5
with:
token: ${{ secrets.CODSPEED_TOKEN }}
mode: instrumentation
Expand All @@ -1541,7 +1541,7 @@ jobs:
- name: Run non-intensive benchmarks
if: |
!contains(github.event.pull_request.labels.*.name, 'ci/run-intensive-benchmarks')
uses: CodSpeedHQ/action@v4
uses: CodSpeedHQ/action@v5
with:
token: ${{ secrets.CODSPEED_TOKEN }}
mode: instrumentation
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/manage-stale-prs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
if: github.repository == 'opsmill/infrahub'
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v10
- uses: actions/stale@v11
with:
# Only manage PRs, not issues
days-before-issue-stale: -1
Expand Down
2 changes: 2 additions & 0 deletions .vale/styles/spelling-exceptions.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Ceph
changelog
conftest
Conftest
cron
check_color_tags_name
check_definitions
class_name
Expand Down Expand Up @@ -175,6 +176,7 @@ Observium
OIDC
Okta
Onboarding
onboarding
OpenAPI
order_by
order_weight
Expand Down
25 changes: 25 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,31 @@ This project uses [*towncrier*](https://towncrier.readthedocs.io/) and the chang

<!-- towncrier release notes start -->

## [Infrahub - v1.10.7](https://github.com/opsmill/infrahub/tree/infrahub-v1.10.7) - 2026-08-11

### Changed

- Improved the performance of GraphQL queries that only request the `id` of a cardinality-one relationship's peer. When no properties, metadata, or additional node fields are requested, the resolver now returns the peer ID already loaded on the parent instead of hydrating a full peer node, reducing database work on relationship-heavy queries.

### Fixed

- Fixed artifact generation storing the text None when a transform returned no data, it now fails with an error naming the transform instead. ([#5303](https://github.com/opsmill/infrahub/issues/5303))
- Fixed node creation failing when a Jinja2 computed attribute formatted a value sourced from a number pool; the computed attribute now renders once the pool value has been allocated. ([#7836](https://github.com/opsmill/infrahub/issues/7836))
- Fixed artifact generation failing for repositories whose default branch is not named main. ([#8749](https://github.com/opsmill/infrahub/issues/8749))
- Merging an Infrahub branch now reliably writes the merge back to a repository's non-`main` default branch on the remote, regardless of which task worker executes the merge. ([#9568](https://github.com/opsmill/infrahub/issues/9568))
- Fixed the object creation form auto-selecting the first available object in the parent filter of a relationship to a hierarchical node (e.g. the **Device** filter when adding an interface's lag). The parent filter now starts empty and is only pre-filled from an existing relationship value or parent context. ([#9634](https://github.com/opsmill/infrahub/issues/9634))
- Fixed deleting a large branch failing with a database out-of-memory error and leaving the branch and its data behind. Branches left behind by an earlier failure are now cleaned up on upgrade. ([#9889](https://github.com/opsmill/infrahub/issues/9889))
- Fixed git repository synchronization halting when a branch that had been merged still existed on the remote. ([#9931](https://github.com/opsmill/infrahub/issues/9931))
- Fixed group mutation events (`member_added` / `member_removed`) being silently dropped when a single mutation changed a few hundred members or more. The event's related resources are now consolidated to one entry per member and per ancestor and capped at the Prefect maximum, so the event is always recorded and membership-driven automations keep firing regardless of how many members change at once. The full member list remains available in the event payload. ([#10127](https://github.com/opsmill/infrahub/issues/10127))
- Fixed the ordering of repository tests in a proposed change. Smoke tests now run before unit tests, and unit tests before integration tests, instead of being ordered by resource kind only. ([#10170](https://github.com/opsmill/infrahub/issues/10170))
- Fixed branches imported from a Git repository being created without the sync with Git flag, which caused merges to skip the Git side. ([#10208](https://github.com/opsmill/infrahub/issues/10208))
- Fixed relationship selectors in object forms not honoring the `common_parent` schema property. The options are now filtered to peers that share the same parent as the value picked for the referenced relationship in the same form, instead of listing every peer. Changing that parent clears a now-invalid selection, and the inline "Add new" form pre-fills the parent when one is already selected so a created peer stays valid.
- Fixed the Git repositories homepage widget linking to the generic `CoreGenericRepository` kind: repositories now open on their own kind, so the details page and edit form show all of their fields.
- Fixed the object edit form failing with a GraphQL `profiles` error when an object is opened through a kind whose GraphQL type has no `profiles` field, such as `CoreGenericRepository`. The form now requests `profiles` only for kinds that expose it.
- Fixed the task status button in the header sending you to the tasks page on the default branch instead of the branch you were working on.
- Fixed schema migrations during a branch rebase using the destination branch's current schema as their baseline instead of the schema the branch was created from. Any schema element that was added on the destination branch after the branch forked already looked pre-existing to the migrations, so the work needed to bring branch data in line was skipped. Migrations now run against the branch-creation schema, which still reflects what changed on either side.
- Fixed a branch rebase that fails while running its migrations restoring the wrong schema for the branch. The branch was left with the schema it was created from, silently dropping any schema change made on the branch itself, and the recorded schema hash was wrong as a result. The rollback now restores the schema the branch had immediately before the rebase started.

## [Infrahub - v1.10.6](https://github.com/opsmill/infrahub/tree/infrahub-v1.10.6) - 2026-07-28

### Changed
Expand Down
1 change: 1 addition & 0 deletions backend/infrahub/api/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,7 @@ async def load_schema(
updated_hash = await coordinator.execute(
branch=branch,
origin_schema=origin_schema,
rollback_schema=origin_schema,
candidate_schema=candidate_schema,
at=Timestamp(),
# The caller blocks on this request: a priority stamped into the
Expand Down
1 change: 1 addition & 0 deletions backend/infrahub/cli/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -844,6 +844,7 @@ async def update_core_schema(db: InfrahubDatabase, initialize: bool = True, debu
await coordinator.execute(
branch=default_branch,
origin_schema=origin_schema,
rollback_schema=origin_schema,
candidate_schema=candidate_schema,
at=Timestamp(),
migration_executor=MigrationExecutor.DIRECT,
Expand Down
3 changes: 2 additions & 1 deletion backend/infrahub/cli/dev.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
)
from infrahub.core.schema import SchemaRoot, core_models, internal_schema
from infrahub.core.schema.schema_branch import SchemaBranch
from infrahub.core.schema.write_json_schema import build_write_json_schema
from infrahub.core.utils import delete_all_nodes
from infrahub.graphql.manager import GraphQLSchemaManager
from infrahub.graphql.schema_sort import sort_schema_ast
Expand Down Expand Up @@ -79,7 +80,7 @@ async def export_node_schema(
) -> None:
"""Export the repository configuration to a file."""
config.load_and_exit(config_file_name=config_file)
schema = SchemaLoadAPI.model_json_schema()
schema = build_write_json_schema(schema=SchemaLoadAPI.model_json_schema())
schema["title"] = "InfrahubSchema"
content = json.dumps(schema, indent=4)
out.parent.mkdir(parents=True, exist_ok=True)
Expand Down
151 changes: 151 additions & 0 deletions backend/infrahub/core/branch/data_deleter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
from __future__ import annotations

from dataclasses import dataclass
from typing import TYPE_CHECKING, Any, Protocol

from infrahub.core.branch.enums import BranchStatus
from infrahub.core.constants.database import DatabaseEdgeType
from infrahub.core.query.branch import (
DeleteBranchAgnosticAttributesQuery,
DeleteBranchAgnosticRelationshipsQuery,
DeleteBranchEdgesQuery,
)
from infrahub.core.query.standard_node import StandardNodeDeleteQuery
from infrahub.exceptions import ValidationError
from infrahub.log import get_logger

if TYPE_CHECKING:
from infrahub.core.branch.models import Branch
from infrahub.database import InfrahubDatabase

# The agnostic cleanup batches Nodes, and each one can drag an unbounded number of peer vertices
# into the transaction with it, so its batch is capped low.
MAX_AGNOSTIC_PEER_BATCH_SIZE = 500


@dataclass(frozen=True)
class BranchDeleteResult:
"""What a delete attempt actually did.

`branch_deleted` is false when the branch had already been removed by the time this attempt got
to it, which is how a caller knows not to repeat the work that follows a delete.
"""

branch_deleted: bool
edges_removed: int


class BranchDataDeleterInterface(Protocol):
"""The database side of a branch delete."""

async def delete(self, branch: Branch) -> BranchDeleteResult: ...


class LoggerInterface(Protocol):
"""Just enough of a logger for progress reporting."""

def info(self, message: str, /) -> Any: ...


class BranchDataDeleter:
"""Remove a branch, every edge belonging to it, and the vertices that only it kept alive.

The graph work is split into one bounded query per batch so that no single transaction has to
hold the whole branch in memory. Each query is its own auto-commit transaction, which also means
an interrupted delete can be resumed by running the whole thing again.
"""

def __init__(self, db: InfrahubDatabase, batch_size: int, log: LoggerInterface | None = None) -> None:
self.db = db
self.batch_size = batch_size
self.log = log or get_logger()

async def delete(self, branch: Branch) -> BranchDeleteResult:
"""Remove the branch's data and then the branch itself.

Returns whether the Branch object was actually deleted in case multiple processes try to
delete concurrently so the caller can know which delete really succeeded.

Raises:
ValidationError: When the branch is the default branch or an internal one.

"""
if branch.is_default:
raise ValidationError(f"Unable to delete {branch.name} it is the default branch.")
if branch.is_global:
raise ValidationError(f"Unable to delete {branch.name} this is an internal branch.")

if branch.status != BranchStatus.DELETING:
branch.status = BranchStatus.DELETING
await branch.save(db=self.db)

edges_removed = await self.delete_branch_data(branch_name=branch.name)

query = await StandardNodeDeleteQuery.init(db=self.db, node=branch)
await query.execute(db=self.db)
branch_deleted = query.stats.get_counter("nodes_deleted") > 0

return BranchDeleteResult(branch_deleted=branch_deleted, edges_removed=edges_removed)

async def delete_branch_data(self, branch_name: str) -> int:
"""Remove a branch's data without requiring the branch itself to still exist.

Returns the number of edges removed, so a caller whose own logging is the only thing the
operator can see is able to report progress.
"""
agnostic_edges_count = await self._delete_agnostic_peers(branch_name=branch_name)
branch_edges_count = await self._delete_edges(branch_name=branch_name)
return agnostic_edges_count + branch_edges_count

async def _delete_agnostic_peers(self, branch_name: str) -> int:
"""Drop the agnostic attributes and relationships of Nodes that exist on no other branch.

Both queries locate those Nodes through the branch's IS_PART_OF edges, so this has to
finish before the edge deletion starts removing them. Resuming a delete that failed part
way through this stage is safe for the same reason: no IS_PART_OF edge has been touched yet.

Returns the number of edges removed, which is every edge of the peers detached here, not
only the agnostic ones that led to them.
"""
batch_size = min(self.batch_size, MAX_AGNOSTIC_PEER_BATCH_SIZE)

relationships_query = await DeleteBranchAgnosticRelationshipsQuery.init(
db=self.db, branch_name=branch_name, batch_size=batch_size
)
await relationships_query.execute(db=self.db)

attributes_query = await DeleteBranchAgnosticAttributesQuery.init(
db=self.db, branch_name=branch_name, batch_size=batch_size
)
await attributes_query.execute(db=self.db)

edges_removed = relationships_query.stats.get_counter(
"relationships_deleted"
) + attributes_query.stats.get_counter("relationships_deleted")
if edges_removed:
self.log.info(
f"Deleted agnostic peers of nodes only on branch '{branch_name}', {edges_removed} edge(s) removed"
)
return edges_removed

async def _delete_edges(self, branch_name: str) -> int:
edges_removed = 0
for edge_type in DatabaseEdgeType:
deleted_total = 0
while True:
# A fresh query per batch: the stats counters accumulate per instance, so a reused
# one would never report zero again and the loop would not end.
query = await DeleteBranchEdgesQuery.init(
db=self.db, branch_name=branch_name, edge_type=edge_type, batch_size=self.batch_size
)
await query.execute(db=self.db)
deleted = query.deleted_edge_count()
if not deleted:
break
deleted_total += deleted

if deleted_total:
edges_removed += deleted_total
self.log.info(f"Deleted {deleted_total} {edge_type.value} edge(s) on branch '{branch_name}'")

return edges_removed
96 changes: 96 additions & 0 deletions backend/infrahub/core/branch/delete_coordinator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
from __future__ import annotations

from typing import TYPE_CHECKING, Protocol

from infrahub.events.branch_action import BranchDeletedEvent
from infrahub.events.models import EventMeta
from infrahub.exceptions import ValidationError
from infrahub.workflows.catalogue import BRANCH_CANCEL_PROPOSED_CHANGES, GIT_REPOSITORIES_DELETE_BRANCH

if TYPE_CHECKING:
from infrahub.context import InfrahubContext
from infrahub.core.branch.data_deleter import BranchDataDeleterInterface, BranchDeleteResult, LoggerInterface
from infrahub.core.branch.models import Branch
from infrahub.services.adapters.event import InfrahubEventService
from infrahub.services.adapters.workflow import InfrahubWorkflow


class DiffFreezerInterface(Protocol):
"""Interface for freezing diffs."""

async def freeze_diffs_for_branch(self, branch_name: str) -> None: ...


class BranchDeleteOrchestrator:
"""Delete a branch and do the work that follows from it.

Holds no database of its own: the deletion is delegated, which is what keeps the ordering and the
post-delete decisions here testable without one.
"""

def __init__(
self,
data_deleter: BranchDataDeleterInterface,
diff_freezer: DiffFreezerInterface,
event_service: InfrahubEventService,
workflow: InfrahubWorkflow,
log: LoggerInterface,
global_branch: Branch,
delete_git_branch_after_merge: bool,
) -> None:
self.data_deleter = data_deleter
self.diff_freezer = diff_freezer
self.event_service = event_service
self.workflow = workflow
self.log = log
self.global_branch = global_branch
self.delete_git_branch_after_merge = delete_git_branch_after_merge

async def delete(
self,
branch: Branch,
context: InfrahubContext,
delete_from_git: bool = False,
proposed_change_id: str | None = None,
) -> BranchDeleteResult:
"""Remove the branch, then cancel its proposed changes, announce it, and drop its Git branch.

Raises:
ValidationError: When the branch is the default branch or an internal one.

"""
# Before the freeze, not after: a refused delete has to leave the branch's diffs alone.
if branch.is_default:
raise ValidationError(f"Unable to delete {branch.name} it is the default branch.")
if branch.is_global:
raise ValidationError(f"Unable to delete {branch.name} this is an internal branch.")

# Freezing has to precede the deletion, which takes away the branch name they are found by.
await self.diff_freezer.freeze_diffs_for_branch(branch_name=branch.name)

result = await self.data_deleter.delete(branch=branch)

if result.branch_deleted:
await self.workflow.submit_workflow(
workflow=BRANCH_CANCEL_PROPOSED_CHANGES, context=context, parameters={"branch_name": branch.name}
)
await self.event_service.send(
event=BranchDeletedEvent(
branch_name=branch.name,
branch_id=str(branch.uuid),
sync_with_git=branch.sync_with_git,
meta=EventMeta.from_context(context=context.to_event_context(), branch=self.global_branch),
proposed_change_id=proposed_change_id,
)
)
else:
# Another attempt removed the branch, so the work above is already its responsibility.
self.log.info(f"Branch '{branch.name}' was already deleted")

# Always execute in case concurrent delete process with delete_from_git=False won the delete race.
if (self.delete_git_branch_after_merge or delete_from_git) and branch.sync_with_git:
await self.workflow.submit_workflow(
workflow=GIT_REPOSITORIES_DELETE_BRANCH, context=context, parameters={"branch": branch.name}
)

return result
18 changes: 8 additions & 10 deletions backend/infrahub/core/branch/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
from infrahub.core.query import Query, QueryType
from infrahub.core.query.branch import (
BranchNodeGetListQuery,
DeleteBranchRelationshipsQuery,
RebaseBranchQuery,
)
from infrahub.core.registry import registry
Expand Down Expand Up @@ -335,17 +334,16 @@ async def create(self, db: InfrahubDatabase, user_id: str = SYSTEM_USER_ID) -> b
return await super().create(db=db, user_id=user_id)

async def delete(self, db: InfrahubDatabase) -> None:
if self.is_default:
raise ValidationError(f"Unable to delete {self.name} it is the default branch.")
if self.is_global:
raise ValidationError(f"Unable to delete {self.name} this is an internal branch.")
"""Not supported on a Branch.

self.status = BranchStatus.DELETING
await self.save(db=db)
The inherited implementation would drop the Branch vertex and silently leave every edge and
vertex belonging to the branch behind, so it is refused rather than overridden.

query = await DeleteBranchRelationshipsQuery.init(db=db, branch_name=self.name)
await query.execute(db=db)
await super().delete(db=db)
Raises:
NotImplementedError: Always.

"""
raise NotImplementedError("Unable to delete a Branch directly, use BranchDataDeleter instead.")

def get_query_filter_relationships(
self, rel_labels: list, at: Optional[Timestamp] = None, include_outside_parentheses: bool = False
Expand Down
Loading
Loading