Skip to content

netbox-branching 1.2.0: branch revert fails for deleted COTs and dropped fields #689

Description

@bctiemann

Summary

netbox-branching 1.2.0 (released 2026-09-02, adds NetBox v4.7 support) fixes the CI version-gate crash the "main, branching" leg was hitting under NetBox 4.7.0, but introduces two new, genuine failures in netbox_custom_objects/tests/test_branching.py: 61 tests run, 2 failures + 2 errors. Confirmed on main with no other code changes (dispatched lint-tests.yaml directly against main: https://github.com/netboxlabs/netbox-custom-objects/actions/runs/33695787237), so this is a genuine compatibility gap with 1.2.0, not specific to any open PR.

Failure 1: revert() on a deleted COT fails with a NOT NULL violation

ERROR: test_cot_deleted_in_branch_merge_and_revert (IterativeBranchingTestCase and SquashBranchingTestCase)

psycopg.errors.NotNullViolation: null value in column "cache_timestamp" of
relation "netbox_custom_objects_customobjecttype" violates not-null constraint
DETAIL:  Failing row contains (19, null, null, {}, , , doomed_cot, ...).

  File ".../netbox_branching/models/changes.py", line 189, in undo
    deserialized.save(using=using)
  File ".../django/core/serializers/base.py", line 294, in save
    models.Model.save_base(self.object, using=using, raw=True, **kwargs)

branch.revert() replays a serialized ObjectChange to recreate the deleted CustomObjectType row, via Django's deserializer -> save_base(..., raw=True). cache_timestamp is a NOT NULL column on CustomObjectType that's presumably populated by a save() override or a signal under normal circumstances, but raw=True skips those, and the serialized snapshot captured at delete time apparently didn't include a value for it -- or something in 1.2.0's undo/redeserialization path handles that column differently than 1.1.x did.

Failure 2: dropped field's column is not restored on revert

FAIL: test_single_field_delete_merge_and_revert (IterativeBranchingTestCase and SquashBranchingTestCase)

AssertionError: 'drop_me' not found in {'keep_me', 'owner_id', 'created', 'id', 'last_updated'}
: drop_me column must be restored after revert

After deleting one field from a COT inside a branch and reverting, the dropped column doesn't come back. netbox-branching 1.2.0's release notes state it "replaces django-mptt with a PostgreSQL ltree implementation and moves the maintenance of ltree and denormalized fields into database triggers," and that "branch provisioning now replicates those triggers into each branch schema" -- this rework of trigger/schema provisioning is a plausible culprit for column-level DDL not being correctly captured/replayed during revert, though this hasn't been root-caused yet.

Scope

Neither failure touches code from #687 (the get_models() reentrancy guard) or any other currently-open PR -- confirmed by reproducing both on main directly. This needs investigation against netbox-branching 1.2.0's actual behavior change (ltree/trigger migration) before a fix can be scoped.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions