diff --git a/docs/using-branches/syncing-merging.md b/docs/using-branches/syncing-merging.md index af3c8f9..3c7d0cd 100644 --- a/docs/using-branches/syncing-merging.md +++ b/docs/using-branches/syncing-merging.md @@ -6,6 +6,9 @@ Synchronizing a branch replicates all recent changes from main into the branch. To synchronize a branch, click the "Sync" button. (If this button is not visible, verify that the branch status shows "ready" and that you have permission to synchronize the branch.) +!!! warning + A branch must be synchronized frequently enough to avoid exceeding NetBox's configured [changelog retention period](https://netboxlabs.com/docs/netbox/en/stable/configuration/miscellaneous/#changelog_retention) (which defaults to 90 days). This is to protect against data loss when replicating changes from main. A branch whose `last_sync` time exceeds the configured retention window can no longer be synced. + While a branch is being synchronized, its status will show "synchronizing." !!! tip diff --git a/netbox_branching/models/branches.py b/netbox_branching/models/branches.py index 5cc2a2a..6ace090 100644 --- a/netbox_branching/models/branches.py +++ b/netbox_branching/models/branches.py @@ -1,6 +1,7 @@ import logging import random import string +from datetime import timedelta from functools import cached_property, partial from django.conf import settings @@ -15,6 +16,7 @@ from django.utils.translation import gettext_lazy as _ from core.models import ObjectChange as ObjectChange_ +from netbox.config import get_config from netbox.context import current_request from netbox.context_managers import event_tracking from netbox.models import PrimaryModel @@ -121,7 +123,7 @@ def schema_name(self): def connection_name(self): return f'schema_{self.schema_name}' - @cached_property + @property def synced_time(self): return self.last_sync or self.created @@ -240,6 +242,16 @@ def get_event_history(self): last_time = event.time return history + @property + def is_stale(self): + """ + Indicates whether the branch is too far out of date to be synced. + """ + if not (changelog_retention := get_config().CHANGELOG_RETENTION): + # Changelog retention is disabled + return False + return self.synced_time < timezone.now() - timedelta(days=changelog_retention) + def sync(self, user, commit=True): """ Apply changes from the main schema onto the Branch's schema. @@ -249,6 +261,8 @@ def sync(self, user, commit=True): if not self.ready: raise Exception(f"Branch {self} is not ready to sync") + if self.is_stale: + raise Exception(f"Branch {self} is stale and can no longer be synced") # Emit pre-sync signal pre_sync.send(sender=self.__class__, branch=self, user=user) diff --git a/netbox_branching/tables/tables.py b/netbox_branching/tables/tables.py index b1165b3..8d90a59 100644 --- a/netbox_branching/tables/tables.py +++ b/netbox_branching/tables/tables.py @@ -56,8 +56,16 @@ class BranchTable(NetBoxTable): verbose_name=_('Name'), linkify=True ) + is_active = columns.BooleanColumn( + verbose_name=_('Active') + ) status = columns.ChoiceFieldColumn( - verbose_name=_('Status'), + verbose_name=_('Status') + ) + is_stale = columns.BooleanColumn( + true_mark=mark_safe(''), + false_mark=None, + verbose_name=_('Stale') ) conflicts = ConflictsColumn( verbose_name=_('Conflicts') @@ -72,11 +80,11 @@ class BranchTable(NetBoxTable): class Meta(NetBoxTable.Meta): model = Branch fields = ( - 'pk', 'id', 'name', 'is_active', 'status', 'conflicts', 'schema_id', 'description', 'owner', 'tags', - 'created', 'last_updated', + 'pk', 'id', 'name', 'is_active', 'status', 'is_stale', 'conflicts', 'schema_id', 'description', 'owner', + 'tags', 'created', 'last_updated', ) default_columns = ( - 'pk', 'name', 'is_active', 'status', 'owner', 'conflicts', 'schema_id', 'description', + 'pk', 'name', 'is_active', 'status', 'is_stale', 'owner', 'conflicts', 'schema_id', 'description', ) def render_is_active(self, value): diff --git a/netbox_branching/templates/netbox_branching/branch.html b/netbox_branching/templates/netbox_branching/branch.html index 75eff0c..08705d8 100644 --- a/netbox_branching/templates/netbox_branching/branch.html +++ b/netbox_branching/templates/netbox_branching/branch.html @@ -82,11 +82,24 @@