Skip to content

Commit 3332632

Browse files
Merge pull request #79 from netboxlabs/develop
Release v0.4.0
2 parents 1158ef6 + dd3885b commit 3332632

File tree

17 files changed

+362
-71
lines changed

17 files changed

+362
-71
lines changed

.github/workflows/lint-tests.yaml

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
name: Lint and tests
2+
on:
3+
workflow_dispatch:
4+
pull_request:
5+
push:
6+
branches:
7+
- "!release"
8+
9+
concurrency:
10+
group: ${{ github.workflow }}
11+
cancel-in-progress: false
12+
13+
permissions:
14+
contents: write
15+
checks: write
16+
pull-requests: write
17+
18+
jobs:
19+
lint:
20+
runs-on: ubuntu-latest
21+
timeout-minutes: 10
22+
steps:
23+
- name: Checkout
24+
uses: actions/checkout@v4
25+
- name: Setup Python
26+
uses: actions/setup-python@v5
27+
with:
28+
python-version: "3.10"
29+
- name: Install dependencies
30+
run: |
31+
python -m pip install --upgrade pip
32+
pip install .
33+
pip install .[dev]
34+
pip install .[test]
35+
- name: Build documentation
36+
run: mkdocs build
37+
- name: Run pycodestyle
38+
run: |
39+
pycodestyle --ignore=W504,E501 netbox_branching/
40+
tests:
41+
runs-on: ubuntu-latest
42+
timeout-minutes: 10
43+
strategy:
44+
matrix:
45+
python-version: [ "3.10", "3.11", "3.12" ]
46+
services:
47+
redis:
48+
image: redis
49+
ports:
50+
- 6379:6379
51+
postgres:
52+
image: postgres
53+
env:
54+
POSTGRES_USER: netbox
55+
POSTGRES_PASSWORD: netbox
56+
options: >-
57+
--health-cmd pg_isready
58+
--health-interval 10s
59+
--health-timeout 5s
60+
--health-retries 5
61+
ports:
62+
- 5432:5432
63+
steps:
64+
- name: Checkout netbox-branching
65+
uses: actions/checkout@v4
66+
with:
67+
path: netbox-branching
68+
- name: Setup Python ${{ matrix.python-version }}
69+
uses: actions/setup-python@v5
70+
with:
71+
python-version: ${{ matrix.python-version }}
72+
- name: Checkout netbox
73+
uses: actions/checkout@v4
74+
with:
75+
repository: "netbox-community/netbox"
76+
path: netbox
77+
- name: Install netbox-branching
78+
working-directory: netbox-branching
79+
run: |
80+
# Include tests directory for test
81+
sed -i 's/exclude-package-data/#exclude-package-data/g' pyproject.toml
82+
python -m pip install --upgrade pip
83+
pip install .
84+
pip install .[test]
85+
- name: Install dependencies & configure plugin
86+
working-directory: netbox
87+
run: |
88+
ln -s $(pwd)/../netbox-branching/testing/configuration.py netbox/netbox/configuration.py
89+
ln -s $(pwd)/../netbox-branching/testing/local_settings.py netbox/netbox/local_settings.py
90+
91+
python -m pip install --upgrade pip
92+
pip install -r requirements.txt -U
93+
- name: Run tests
94+
working-directory: netbox
95+
run: |
96+
python netbox/manage.py test netbox_branching.tests --keepdb

docs/changelog.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,24 @@
11
# Change Log
22

3+
## v0.4.0
4+
5+
### Enhancements
6+
7+
* [#52](https://github.com/netboxlabs/nbl-netbox-branching/issues/52) - Introduce the `max_branches` config parameter
8+
* [#71](https://github.com/netboxlabs/nbl-netbox-branching/issues/71) - Ensure the consistent application of logging messages
9+
* [#76](https://github.com/netboxlabs/nbl-netbox-branching/issues/76) - Validate required configuration items on initialization
10+
11+
### Bug Fixes
12+
13+
* [#57](https://github.com/netboxlabs/nbl-netbox-branching/issues/57) - Avoid recording ChangeDiff records for unsupported object types
14+
* [#59](https://github.com/netboxlabs/nbl-netbox-branching/issues/59) - `BranchAwareRouter` should consider branching support for model when determining database connection to use
15+
* [#61](https://github.com/netboxlabs/nbl-netbox-branching/issues/61) - Fix transaction rollback when performing a dry run sync
16+
* [#66](https://github.com/netboxlabs/nbl-netbox-branching/issues/66) - Capture object representation on ChangeDiff when creating a new object within a branch
17+
* [#69](https://github.com/netboxlabs/nbl-netbox-branching/issues/69) - Represent null values for ChangeDiff fields consistently in REST API
18+
* [#73](https://github.com/netboxlabs/nbl-netbox-branching/issues/73) - Ensure all relevant branch diffs are updated when an object is modified in main
19+
20+
---
21+
322
## v0.3.1
423

524
### Bug Fixes

docs/configuration.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Configuration Parameters
2+
3+
## `max_branches`
4+
5+
Default: None
6+
7+
The maximum number of branches that can exist simultaneously, including merged branches that have not been deleted. It may be desirable to limit the total number of provisioned branches to safeguard against excessive database size.
8+
9+
---
10+
11+
## `schema_prefix`
12+
13+
Default: `branch_`
14+
15+
The string to prefix to the unique branch ID when provisioning the PostgreSQL schema for a branch. Per [the PostgreSQL documentation](https://www.postgresql.org/docs/16/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS), this string must begin with a letter or underscore.
16+
17+
Note that a valid prefix is required, as the randomly-generated branch ID alone may begin with a digit, which would not qualify as a valid schema name.

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ nav:
4343
- Syncing & Merging: 'using-branches/syncing-merging.md'
4444
- Reverting a Branch: 'using-branches/reverting-a-branch.md'
4545
- REST API: 'rest-api.md'
46+
- Configuration: 'configuration.md'
4647
- Data Model:
4748
- Branch: 'models/branch.md'
4849
- BranchEvent: 'models/branchevent.md'

netbox_branching/__init__.py

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,49 @@
1+
from django.conf import settings
2+
from django.core.exceptions import ImproperlyConfigured
3+
14
from netbox.plugins import PluginConfig
5+
from netbox.registry import registry
26

37

48
class AppConfig(PluginConfig):
59
name = 'netbox_branching'
610
verbose_name = 'NetBox Branching'
711
description = 'A git-like branching implementation for NetBox'
8-
version = '0.3.1'
12+
version = '0.4.0'
913
base_url = 'branching'
1014
min_version = '4.1'
1115
middleware = [
1216
'netbox_branching.middleware.BranchMiddleware'
1317
]
1418
default_settings = {
19+
# The maximum number of branches which can be provisioned simultaneously
20+
'max_branches': None,
21+
1522
# This string is prefixed to the name of each new branch schema during provisioning
1623
'schema_prefix': 'branch_',
1724
}
1825

1926
def ready(self):
2027
super().ready()
21-
from . import events, search, signal_receivers
28+
from . import constants, events, search, signal_receivers
29+
from .utilities import DynamicSchemaDict
30+
31+
# Validate required settings
32+
if type(settings.DATABASES) is not DynamicSchemaDict:
33+
raise ImproperlyConfigured(
34+
"netbox_branching: DATABASES must be a DynamicSchemaDict instance."
35+
)
36+
if 'netbox_branching.database.BranchAwareRouter' not in settings.DATABASE_ROUTERS:
37+
raise ImproperlyConfigured(
38+
"netbox_branching: DATABASE_ROUTERS must contain 'netbox_branching.database.BranchAwareRouter'."
39+
)
40+
41+
# Record all object types which support branching in the NetBox registry
42+
if 'branching' not in registry['model_features']:
43+
registry['model_features']['branching'] = {
44+
k: v for k, v in registry['model_features']['change_logging'].items()
45+
if k not in constants.EXCLUDED_APPS
46+
}
2247

2348

2449
config = AppConfig

netbox_branching/constants.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,9 @@
99

1010
# URL query parameter name
1111
QUERY_PARAM = '_branch'
12+
13+
# Apps which are explicitly excluded from branching
14+
EXCLUDED_APPS = (
15+
'netbox_branching',
16+
'netbox_changes',
17+
)

netbox_branching/database.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from netbox.registry import registry
2+
13
from .contextvars import active_branch
24

35

@@ -11,15 +13,21 @@ class BranchAwareRouter:
1113
A Django database router that returns the appropriate connection/schema for
1214
the active branch (if any).
1315
"""
14-
def db_for_read(self, model, **hints):
16+
def _get_db(self, model, **hints):
17+
# Bail if the model does not support branching
18+
app_label, model_name = model._meta.label.lower().split('.')
19+
if model_name not in registry['model_features']['branching'].get(app_label, []):
20+
return
21+
22+
# Return the schema for the active branch (if any)
1523
if branch := active_branch.get():
1624
return f'schema_{branch.schema_name}'
17-
return None
25+
26+
def db_for_read(self, model, **hints):
27+
return self._get_db(model, **hints)
1828

1929
def db_for_write(self, model, **hints):
20-
if branch := active_branch.get():
21-
return f'schema_{branch.schema_name}'
22-
return None
30+
return self._get_db(model, **hints)
2331

2432
def allow_relation(self, obj1, obj2, **hints):
2533
# Permit relations from the branch schema to the main (public) schema

netbox_branching/migrations/0001_initial.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class Migration(migrations.Migration):
1313
dependencies = [
1414
('contenttypes', '0002_remove_content_type_name'),
1515
('core', '0011_move_objectchange'),
16-
('extras', '0118_notifications'),
16+
('extras', '0119_notifications'),
1717
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
1818
]
1919

0 commit comments

Comments
 (0)