Pin Ruff to v0.15.2 in CI and pre-commit to avoid breakages from
upstream releases. Run Ruff via astral-sh/ruff-action (pinned by SHA)
instead of installing Ruff via pip.
Document where Ruff is pinned and keep the release checklist/style guide
in sync.
Fixes#21472Fixes#21497
Apply consistent alphabetical ordering to `__all__` lists in the
circuits module. Enhances readability and alignment with established
linting guidelines.
Enable `RUF022` to enforce sorted `__all__` lists. Adjust comment
alignment and whitespace for improved readability and consistency
in ruff.toml configuration.
Add declarative layout panels for Cluster, Cluster Group, Cluster Type,
Virtual Disk, and VM Interface, including addressing, VLAN assignment,
and FHRP group handling.
Expand the declarative layout primitives:
- add GFK attribute rendering support
- add panel for rendering context-provided tables
- update templates to support new panels/attrs
Closes#20923
Explicitly set `select` rules to maintain compatibility with
Ruff 0.15.1. Ensures deterministic linting behavior despite changes in
Ruff 0.15.2 defaults.
See https://github.com/astral-sh/ruff/releases/tag/0.15.2 for more
details.
Introduces `load_lazy` and `decoding` parameters to `ImageAttr` for
enhanced image handling. Lazy loading improves page performance, while
configurable decoding options provide greater flexibility. Updates the
template to conditionally include these attributes in rendered HTML.
Fixes#21369
Fixes a typo in the `resolve_type` method where `ConsolePortType` was
mistakenly referenced instead of `ConsolePort`. Ensures the correct
GraphQL type is returned for ConsolePort instances.
Fixes#21478
Adopt Ruff `RET` to improve return-flow consistency across the codebase.
Simplify control flow by removing redundant `else` blocks after
`return`, and add explicit `return None` (or equivalent) fallbacks
where appropriate to preserve existing behavior.
Fixes#21411
Update `ruff.toml` with additional exclusions, linting rules, and
formatting preferences. Includes support for respecting `.gitignore`
and a consistent coding style.
Fixes#21410
Fallback to the associated user when username is missing from job
lifecycle event contexts. Add a regression test to ensure JOB_COMPLETED
webhooks are enqueued without a request context.
Fixes#21371
CircuitTypeForm rendered `owner` twice and did not persist ownership
because the displayed fields didn't match the fields processed by the
form. Remove `owner` from the fieldset and include it in `Meta.fields`
to keep rendering and form processing in sync.
Fixes#21397
Replace per-row `save()` calls with `bulk_update` when populating
VLANGroup VLAN ID ranges during migration.
This avoids triggering post_save handlers (e.g. search cache/indexing)
on existing VLANGroup records and updates only the relevant fields,
improving both reliability and performance on larger databases.
Fixes#21375
Use `TemplatedAttr` for device height and render using Django's
`floatformat` filter so 0.0 is displayed as `0U` (and whole-U values
omit the decimal).
Fixes#21267
Add alters_data=True to methods that modify database or filesystem state
and are accessible from Jinja2 sandbox template contexts:
- UserConfig.set(), clear(): Persist preference changes when commit=True
- ManagedFile.sync_data(): Writes files to scripts/reports storage
- ScriptModule.sync_classes(), sync_data(): Creates/deletes Script objects
- Job.start(), terminate(): Updates job status, creates notifications
Methods intentionally not protected:
- DataFile.refresh_from_disk(): Only modifies instance attributes in memory
- Overridden save()/delete(): Django's AltersData mixin auto-propagates
- Properties like Script.python_class: Not callable in template context
Ref: #20356 for exploit details demonstrating the vulnerability
When editing a cable to remove an interface from the B side, the _path
field on the removed interface was not being cleared. This caused the
interface table to display stale connection info via _path.destinations.
Two changes:
- Signal handler now clears _path when termination removed from origins
- CablePath.delete() clears _path on origins (mirrors save() behavior)
Upgrade django-mptt to 0.18.0 and add empty indexes tuple to MPTT model
Meta classes. The empty tuple triggers Django's migration detection for
indexes that django-mptt adds dynamically (see
django-mptt/django-mptt#682). We cannot define the indexes explicitly
because the MPTT fields don't exist when the Meta class is evaluated.
Affected models: Region, SiteGroup, Location, DeviceRole, Platform,
ModuleBay, InventoryItem, InventoryItemTemplate, TenantGroup,
ContactGroup, WirelessLANGroup
* Pass distinct=False to all ModelMultipleChoiceFilters associated with a ForeignKey field
* Pass distinct=False to all MultipleChoiceFilters associated with a concrete model
* Allow REDIS KWARGS to be set in configuration.py
* cleanup
* cleanup
* cleanup
* Update netbox/netbox/settings.py
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* Update netbox/netbox/settings.py
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
* document in REDIS config section
---------
Co-authored-by: Jeremy Stretch <jstretch@netboxlabs.com>
Override Tabler's problematic margin-left: calc(100vw - 100%) rule that
causes a gap between the sidebar and main content when vertical scrollbar
is present on Windows/Linux browsers.
Uses scrollbar-gutter: stable to match the upstream fix in Tabler PR #2548.
Mark the `token` TemplateColumn as non-orderable since it maps to a
Python property rather than a database field, causing a FieldError
when django-tables2 attempts to sort by it.
Add a regression test for TokenTable following the existing pattern
in circuits and vpn test suites.
Expose additional properties of the device installed in each bay as
configurable table columns.
- Rename `role` → `installed_role`
- Rename `device_type` → `installed_device_type`
- Add `installed_description`, `installed_serial`, and
`installed_asset_tag` columns to `DeviceBayTable`
---------
Co-authored-by: Martin Hauser <mhauser@netboxlabs.com>