Skip to content

1.3.0 [2026-08-29]

Latest

Choose a tag to compare

@nemesifier nemesifier released this 29 Aug 15:29
· 14 commits to master since this release
1.3.0

Features

  • Implemented sub-filter functionality in Django admin #700
    Introduced SubFilterMixin to allow admin filters to be displayed and applied only when a parent filter has specific values. This enhances the admin interface by enabling hierarchical filtering.
    The filter rendering system has been updated to group parent filters with their sub-filters, displaying sub-filters vertically below their parents. Client-side JavaScript logic dynamically shows or hides sub-filters based on parent filter selections.
    Invalid sub-filter usage, such as providing a sub-filter value when its parent is inactive, will now raise IncorrectLookupParameters. Misconfigured orphaned sub-filters will be logged as errors and not rendered.

  • Add OpenWispPagination class with default values #586
    Introduces the OpenWispPagination class, inheriting from DRF's PageNumberPagination. This class provides sensible default values for pagination across OpenWISP modules, configurable via settings.
    The default page size is set to 10 and the maximum page size to 100. These can be overridden by OPENWISP\_API\_DEFAULT\_PAGE\_SIZE and OPENWISP\_API\_MAX\_PAGE\_SIZE respectively. Views can also set a pagination\_page\_size attribute to override the default for specific endpoints.

  • Added changelog entry bot #523

  • Automate assigning/unassigning issues #571
    Added auto-assignment bot with issue assignment, management of stale PR, reassignment on PR reopen and shared helpers in utils.py.

  • Added CI build failure bot #524
    When a CI workflow fails, the bot examines the failure logs and repository context with AI to offer specific guidance for fixing QA check issues, test failures and other common bugs.

  • Added reusable backport workflow #501
    Automates cherry-picking fixes to stable branches via [backport X.Y] in commit messages or /backport X.Y comments, with conflict notification.

  • Standardized commit messages using commitizen #110
    Commitizen has been integrated in openwisp-utils to standardize how commit messages are written across the project. It introduces an interactive commit workflow that guides contributors to use the correct OpenWISP commit format, ensures commit titles are properly structured, and enforces the presence of an issue reference. The commit message footer is generated automatically using the provided issue number, improving consistency and making commits easier to review and track.

  • Releaser: added support for non-python packages #522

Changes

Backward-incompatible changes

  • Removed deprecated UUIDAdmin class #328
    The deprecated UUIDAdmin class has been removed. For equivalent functionality, use CopyableFieldsAdmin with copyable\_fields = ('uuid',).

Other changes

  • Included commit bodies in releaser changelog

  • Allowed cascade deletions in ReadOnlyAdmin
    ReadOnlyAdmin.has\_delete\_permission previously returned False unconditionally, which blocked cascade deletions from parent models (like Organization).
    Added openwisp\_utils.admin.BlockDeleteAllowCascadeMixin to allow reusability of this logic in other OpenWISP modules.

  • Excluded local python venv dirs from QA checks #720

  • Made menu item registration idempotent #641
    Previously, calling register\_menu\_group or register\_menu\_subitem twice with the same configuration at the same position would always raise an ImproperlyConfigured exception. This behavior prevented re-registration, even when the same application was re-initializing its menu items during testing.
    This change modifies these functions to check if the configuration being registered is identical to the one already present at that position. If the configurations match, the function now logs an informational message and skips the re-registration instead of raising an error. This makes the menu item registration process idempotent, improving testability and handling of repeated app initializations.

  • Releaser: defined a generic package type to use as fallback
    The logic which detected OpenWrt packages has been generalized so that any file which doesn't fall under well defined categories like "python package", "npm package", "ansible role", etc., can fall under the "generic package" type, as long as a VERSION file is defined in the top level directory of the repository, the releaser tool will be able to deal with it, regardless of the tech stack used.

  • Made changelog bot model configurable and quota-resilient
    The changelog bot kept failing with Gemini free-tier quota errors (RequestsPerDayPerProjectPerModel, 20/day) and marked the workflow as failed, while the CI failure bot stayed green because it swallows the same error. The changelog bot also had no way to switch models and could spend up to three requests per pull request.
    Forward GEMINI\_MODEL through the action and reusable workflow so a single variable controls both bots, harden model resolution so an empty value falls back to the default, lower the generation retries from three to two, and exit cleanly on quota errors so the workflow no longer turns red on exhaustion.
    Also document the GEMINI\_MODEL variable for both bots.

  • SeleniumTestMixin now requires two successful retries after an initial failure

  • Added default uuid method to CopyableFieldsAdmin #328
    CopyableFieldsAdmin now ships with a default uuid() method that returns obj.pk and has short\_description set to 'UUID'. This allows subclasses to use copyable\_fields = ('uuid',) without defining their own uuid method when their model uses a UUID primary key.
    The uuid field is not automatically added to copyable\_fields, that's still the developer's explicit decision.

  • Releaser: removed chatGPT integration #645

  • Releaser: automated branch selection in changelog porting step #646

Dependencies

Bugfixes

  • Reload DRF settings after configuring defaults
    Bug: ApiAppConfig.configure\_rest\_framework\_defaults updated Django's settings.REST\_FRAMEWORK, but DRF's api\_settings had already loaded its own copy of the configuration. As a result, changes made by apps initialized after rest\_framework were not reflected in the settings actually used by DRF.
    Fix: Reload rest\_framework.settings.api\_settings after updating settings.REST\_FRAMEWORK so DRF uses the latest configuration.

  • Prevented capture decorators from polluting exceptions
    CaptureOutput previously tried injecting streams and retried any TypeError. A real failure in a no-argument decorated test retained the expected signature mismatch as exception context, obscuring the regression traceback.
    The decorator now selects the valid call signature before executing the test, while preserving support for explicit captured streams, variadic arguments, and stacked mock.patch decorators.

  • Prevented FallbackMixin from generating spurious migrations #1231

  • Collect Firefox console logs via WebDriver BiDi #696
    Firefox >= 135 no longer loads the Manifest v2 console-capture extension, and Manifest v3 content scripts are not granted host permissions for temporarily installed add-ons, so the content script never runs. As a result get\_browser\_logs() returned undefined (which translated to None in Python) instead of the captured logs on modern Firefox versions, which in turn broke CI builds.
    The extension was replaced with WebDriver BiDi: a console message handler records every console entry, including those emitted during page load, and the log buffer is reset on each navigation to preserve the previous per-page semantics.
    This fixes console capture for every OpenWISP module that relies on SeleniumTestMixin without changing its public API.

  • Excluded node\_modules dir and other hidden directories from the ReStructuredText QA check

  • Fixed ValidatedModelSerializer validation of PUT/PATCH and relationships #633
    Updated ValidatedModelSerializer.validate() to:

  • Use copy() for existing instances to avoid mutating the original. - Skip reverse relations (ForeignObjectRel) during setattr. - Skip nested relationships. - Convert Django ValidationError to DRF ValidationError so errors are properly serialized in API responses and picklable in the parallel test runner.

  • Triggered changelog bot for backward incompatible changes
    Accept [change!] entries in the changelog bot trigger and validation so backward incompatible PRs receive generated changelog suggestions.

  • Fixed double encoding of device model labels in dashboard #651
    Fixed the double-encoding issue in admin dashboard charts where device models with special characters (like &) generated malformed URLs.

  • Fixed broken skipped Selenium tests in Django parallel runner #619

  • Fixed gemini call

  • Switched to django-minify-compress-staticfiles #565
    Replaced the unmaintained django-compress-staticfiles with the new django-minify-compress-staticfiles package for static file minification and compression.

  • Releaser: perform git pull --tags before changelog generation