You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 41bd4b1
Browse filesBrowse the repository at this point in the historyBrowse files
Copy file name to clipboardExpand all lines: CHANGELOG.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,6 +6,7 @@
6
6
7
7
- The **Conflicts** column on the change request list now matches netbox-branching: a red octagon when there are conflicts, a dash when there are none.
8
8
- The README now warns that the plugin is below 1.0 and that models, settings and the REST API can still change.
> Give that policy a rule as well. A change request is not satisfied while no rule applies to it, so a checks-only policy which is the only one matching a branch leaves the request unable to be approved. The approval panel says "No policy rules apply to this change request" when this happens.
77
+
> A change request is not satisfied while no rule applies to it, so a checks-only policy which is the only one matching a branch leaves the request unable to be approved. The approval panel says "No policy rules apply to this change request" when this happens.
A skipped check clears the gate, so this blocks only the changes it is about. The cost is a visible row on every request carrying the policy, whatever the answer. Use both together: the policy narrows the check to the changes it could apply to, and the skip handles what a policy cannot express.
163
-
164
-
> [!TIP]
165
-
> `threads-resolved` is the one to consider carefully. It means an open question about any single object blocks the whole merge, which is strict but stops a concern being lost when the branch diff disappears on merge. Name it only on the policies where that strictness is wanted, rather than on your catch-all.
Copy file name to clipboardExpand all lines: docs/conflicts.md
-3Lines changed: 0 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -63,6 +63,3 @@ Branching has no merge-conflict editor. It does not blend the two values. Either
63
63
2.**Make the two sides agree.** Edit the object in main to match your branch, or activate the branch and edit it there to match main. Either way the conflict clears on its own, and the banner and the check follow immediately.
64
64
65
65
Syncing does not resolve a conflict on its own. It applies main's value onto the branch, which clears the flag at that moment, and it only replays changes newer than the last sync. If main has not moved since your last sync, syncing again does nothing.
66
-
67
-
> [!NOTE]
68
-
> We would rather delete this code. If `netbox-branching` advanced a diff's baseline on sync, the way git moves the merge base, its own flag would be correct and this plugin could simply trust it.
Copy file name to clipboardExpand all lines: docs/custom-checks.md
+3-6Lines changed: 3 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -70,7 +70,7 @@ class MyPluginConfig(PluginConfig):
70
70
The check now runs whenever checks are refreshed: when the branch is synced or reverted, when a comment thread changes, and when someone presses **Re-run checks**.
71
71
72
72
> [!TIP]
73
-
> A check that raises is recorded as `error` with the exception text as its summary. A broken check blocks the merge but never breaks the page, so you can ship one without fear of taking NetBox down.
73
+
> A check that raises is recorded as `error` with the exception text as its summary. A broken check blocks the merge but never breaks the page.
74
74
75
75
> [!IMPORTANT]
76
76
> `name` is the database key. Renaming it creates a new check and deletes the old one, discarding its history. Change the `label` freely; leave the `name` alone.
@@ -159,13 +159,10 @@ Register it as **advisory**:
> Register an AI check with `required=False`. A model's opinion should inform a human reviewer, not silently block a merge, and it will sometimes be wrong in both directions. Make it required only once you have watched its verdicts on real changes for a while.
164
-
165
162
> [!WARNING]
166
-
> Every check runs on **every** refresh, including each time a comment thread changes. An API call there costs money and adds latency to saving a comment. Before shipping this, consider caching the verdict against the branch's last change time, or moving the call into a background job that reports its result through the REST API like any other external check.
163
+
> Every check runs on **every** refresh, including each time a comment thread changes. An API call there costs money and adds latency to saving a comment.
167
164
168
-
Two more things worth knowing. The whole diff goes to a third party, so do not use this if your inventory is sensitive without checking that first. And the model sees only what `_summarise` sends: it has no view of the wider network, so it cannot reason about anything outside the diff.
165
+
The whole diff goes to a third party. The model sees only what `_summarise` sends: it has no view of the wider network, so it cannot reason about anything outside the diff.
Copy file name to clipboardExpand all lines: docs/extending.md
+1-22Lines changed: 1 addition & 22 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,34 +1,13 @@
1
1
# Extending this plugin
2
2
3
-
Another plugin can add content to this plugin's pages, tabs to its models, and checks to its merge gate. Nothing special is required of you.
3
+
Another plugin can add content to this plugin's pages, and checks to its merge gate. Nothing special is required of you.
4
4
5
5
## Injecting content into a page
6
6
7
7
Every model here supports NetBox's standard `PluginTemplateExtension` hooks. This is a NetBox feature, and the [NetBox documentation](https://netboxlabs.com/docs/netbox/en/stable/plugins/development/views/#extra-template-content) is the reference for it.
8
8
9
9
All six hooks (`buttons`, `alerts`, `left_page`, `right_page`, `full_width_page` and `list_buttons`) work on `policy`, `policyrule`, `changerequest`, `review` and `mergecheck`.
10
10
11
-
> [!NOTE]
12
-
> Page content appears on an object's own page, not on its tabs. This matches core NetBox, where the Changes and Reviews tabs render their own templates.
13
-
14
-
## Adding a tab
15
-
16
-
`register_model_view` attaches a tab to any of this plugin's models:
17
-
18
-
```python
19
-
from netbox.views import generic
20
-
from utilities.views import ViewTab, register_model_view
21
-
22
-
from netbox_change_control.models import ChangeRequest
Copy file name to clipboardExpand all lines: docs/merging.md
-3Lines changed: 0 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -79,6 +79,3 @@ Fix it either way round: widen the window, or lower `auto_merge_interval`. Leave
79
79
Setting `enable_auto_merge` to `False` skips registering the job entirely, so a site that does not use auto-merge gets no periodic job and no Job records from this plugin.
80
80
81
81
The merge runs as the requester. Set `enable_auto_merge` to `False` to disable the feature globally without editing any request.
82
-
83
-
> [!CAUTION]
84
-
> Auto-merge removes the last human pause before a change reaches production. Pair it with a change window, and consider leaving it off for policies that govern high-risk object types.
Copy file name to clipboardExpand all lines: docs/permissions.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -24,7 +24,7 @@ The two exemptions are **custom actions on an object type**. Grant them under **
24
24
Enter the action in the permission's *additional actions* field, not the view/add/change/delete checkboxes.
25
25
26
26
> [!NOTE]
27
-
> Superusers hold every permission, so they are always exempt from both. Test an exemption with an ordinary account.
27
+
> Superusers hold every permission, so they are always exempt from both.
28
28
29
29
> [!IMPORTANT]
30
30
> NetBox resolves a permission name as `<app_label>.<action>_<model>`, splitting on the **last** underscore. A custom permission whose trailing component is not a real model name can never be granted by an object permission, and the exemption silently ends up superuser-only. This is why the bypass lives on `Policy` and the window override on `ChangeRequest`.
Copy file name to clipboardExpand all lines: docs/policy-conditions.md
+5-8Lines changed: 5 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -47,10 +47,10 @@ Three things decide whether the condition matches.
47
47
**Related objects appear as numeric ids**, because the diff stores them that way. So a site is `{"attr": "site", "value": 5}`, not the site's name. Use the object type scope for anything you would otherwise express as a name, and keep conditions for plain values such as status, a boolean flag, or a string.
48
48
49
49
> [!TIP]
50
-
> A condition naming a field the object does not have simply does not match; it does not error. That means a typo in `attr` silently produces a policy that never applies. Check a new condition against a real branch before relying on it.
50
+
> A condition naming a field the object does not have simply does not match; it does not error. That means a typo in `attr` silently produces a policy that never applies.
51
51
52
52
> [!NOTE]
53
-
> Conditions cost a scan of the branch diff per condition-bearing policy. Policies scoped only by object type cost nothing extra, so prefer the object type scope where it is sufficient.
53
+
> Conditions cost a scan of the branch diff per condition-bearing policy. Policies scoped only by object type cost nothing extra.
54
54
55
55
## Which side a condition reads
56
56
@@ -70,11 +70,8 @@ The default is **either**, because a policy exists to catch changes. When a cond
70
70
71
71
A creation has no before, and a deletion has no after, so each of those is matched on the one side it has whatever the setting.
72
72
73
-
> [!IMPORTANT]
74
-
> `after` and `before` are deliberate narrowings, and getting one wrong fails quietly: no policy attaches, no review is asked for, and nothing on the change request says a protection you expected did not apply. Leave the setting on **either** unless you can say precisely why not.
73
+
### Main is never read directly
75
74
76
-
### Main is never consulted
75
+
The diff also holds `current`, the object as it stands in main right now. Conditions never read it. A colleague editing that same object on main cannot, on their own, pull your change request into a policy or push it out of one. Which policies govern a change depends on the change.
77
76
78
-
The diff also holds `current`, the object as it stands in main right now. Conditions never read it.
79
-
80
-
If they did, a colleague editing the same object on main could pull your change request into a policy, or push it out of one, without touching your branch. Which policies govern a change should depend on the change.
77
+
A sync is different, and deliberately so. Syncing makes main's values your branch's values, and branching writes them into `modified`. A condition then reads them like anything else in the branch. A branch which touches only a device's description will still see `modified` carry `status: offline` once it syncs that change from main, so a policy conditioned on `status == active` and read **after** stops matching. Read against **either** side it keeps matching, because `original` still holds `active`.
0 commit comments