Skip to content

[chores:fix] Overrided default commitizen plugin entrypoint #110#591

Merged
nemesifier merged 1 commit intomasterfrom
made-ow-rules-standard
Feb 7, 2026
Merged

[chores:fix] Overrided default commitizen plugin entrypoint #110#591
nemesifier merged 1 commit intomasterfrom
made-ow-rules-standard

Conversation

@nemesifier
Copy link
Member

Changed the commitizen entry point from 'openwisp' to 'cz_conventional_commits' to make the OpenWISP commit message standard the default across all OpenWISP repositories. Dropped toml config file as not needed anymore.

Related to #110

Changed the commitizen entry point from 'openwisp' to
'cz_conventional_commits' to make the OpenWISP commit message
standard the default across all OpenWISP repositories.
Dropped toml config file as not needed anymore.

Related to #110
@coderabbitai
Copy link

coderabbitai bot commented Feb 7, 2026

Walkthrough

The changes modify the commitizen plugin configuration. The .cz.toml file is stripped of its commitizen configuration block, removing settings for plugin name, version provider, tag format, and changelog behavior. Simultaneously, setup.py updates the commitizen plugin entry point from the key "openwisp" to "cz_conventional_commits", while maintaining the reference to the same OpenWispCommitizen callable.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Possibly related PRs

Suggested labels

releaser

🚥 Pre-merge checks | ✅ 1 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description check ⚠️ Warning The pull request description is incomplete. While it explains the changes, it does not follow the required template with sections like Checklist, Screenshot, and proper issue reference formatting. Complete the PR description by including all required template sections: the checklist, proper issue reference (Closes #110), and any relevant screenshots or additional context.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title references overriding the default commitizen plugin entrypoint, which directly matches the main change in the pull request (changing the entry point from 'openwisp' to 'cz_conventional_commits').

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch made-ow-rules-standard

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai bot added the helper-bots Helper bots, release management automation label Feb 7, 2026
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@setup.py`:
- Around line 23-28: The entry point currently registers as
"cz_conventional_commits" which overrides Commitizen's default globally; change
the entry point key to a unique name (e.g., "openwisp" or "openwisp_commitizen")
instead of "cz_conventional_commits" so it registers as "openwisp =
openwisp_utils.releaser.commitizen:OpenWispCommitizen" (or similar) and add a
short note in the README/CONTRIBUTING explaining the global-install caveat and
how to opt-in per-repo (or set name="openwisp" in local commitizen config).
- Around line 27-29: The setup.py entry point registration for
"cz_conventional_commits"
(openwisp_utils.releaser.commitizen:OpenWispCommitizen) can be overridden
unpredictably due to unstable entry-point ordering; instead, make the override
explicit by adding a Commitizen configuration that sets name =
"cz_conventional_commits" and points to the openwisp implementation (e.g., in
pyproject.toml under [tool.commitizen] or a .commitizen.cfg) so Commitizen will
deterministically load the openwisp_utils.releaser.commitizen:OpenWispCommitizen
implementation rather than relying on entry-point order.
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8cbf453 and 13a06ce.

📒 Files selected for processing (2)
  • .cz.toml
  • setup.py
💤 Files with no reviewable changes (1)
  • .cz.toml
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: nemesifier
Repo: openwisp/openwisp-utils PR: 560
File: openwisp_utils/commitizen/openwisp.py:9-25
Timestamp: 2026-02-06T20:46:32.980Z
Learning: In openwisp-utils, the commit message prefix "chores" (plural) is intentionally used instead of "chore" (singular) in the Commitizen ALLOWED_PREFIXES configuration.
📚 Learning: 2026-02-06T20:46:32.980Z
Learnt from: nemesifier
Repo: openwisp/openwisp-utils PR: 560
File: openwisp_utils/commitizen/openwisp.py:9-25
Timestamp: 2026-02-06T20:46:32.980Z
Learning: In openwisp-utils, the commit message prefix "chores" (plural) is intentionally used instead of "chore" (singular) in the Commitizen ALLOWED_PREFIXES configuration.

Applied to files:

  • setup.py
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (14)
  • GitHub Check: Python==3.12 | django~=5.0.0
  • GitHub Check: Python==3.12 | django~=5.2.0
  • GitHub Check: Python==3.11 | django~=4.2.0
  • GitHub Check: Python==3.13 | django~=5.2.0
  • GitHub Check: Python==3.13 | django~=5.1.0
  • GitHub Check: Python==3.12 | django~=5.1.0
  • GitHub Check: Python==3.11 | django~=5.1.0
  • GitHub Check: Python==3.12 | django~=4.2.0
  • GitHub Check: Python==3.11 | django~=5.2.0
  • GitHub Check: Python==3.11 | django~=5.0.0
  • GitHub Check: Python==3.10 | django~=5.1.0
  • GitHub Check: Python==3.10 | django~=5.0.0
  • GitHub Check: Python==3.10 | django~=5.2.0
  • GitHub Check: Python==3.10 | django~=4.2.0

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment on lines +23 to +28
# We override the default 'cz_conventional_commits' plugin to enforce the OpenWISP
# commit message standard across all OpenWISP repositories without requiring
# additional configuration in each repo. This ensures consistency and reduces
# maintenance overhead.
"commitizen.plugin": [
"openwisp = openwisp_utils.releaser.commitizen:OpenWispCommitizen",
"cz_conventional_commits = openwisp_utils.releaser.commitizen:OpenWispCommitizen",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Global override of the default commitizen plugin has environment-wide side effects.

By registering as cz_conventional_commits, this entry point will shadow the built-in commitizen default plugin for every project in the same Python environment where openwisp-utils is installed — not just OpenWISP repos. If a developer (or CI) shares a virtualenv or has openwisp-utils installed globally, any non-OpenWISP project using commitizen's default plugin will silently get OpenWISP commit rules.

This is likely acceptable if OpenWISP repos always use dedicated virtualenvs, but it's worth documenting this caveat (e.g., in README/contributing docs) so contributors and downstream users are aware. If scoped isolation is desired later, an alternative would be to keep the custom name (openwisp) and set name = "openwisp" in each repo's config.

🤖 Prompt for AI Agents
In `@setup.py` around lines 23 - 28, The entry point currently registers as
"cz_conventional_commits" which overrides Commitizen's default globally; change
the entry point key to a unique name (e.g., "openwisp" or "openwisp_commitizen")
instead of "cz_conventional_commits" so it registers as "openwisp =
openwisp_utils.releaser.commitizen:OpenWispCommitizen" (or similar) and add a
short note in the README/CONTRIBUTING explaining the global-install caveat and
how to opt-in per-repo (or set name="openwisp" in local commitizen config).

Comment on lines 27 to 29
"commitizen.plugin": [
"openwisp = openwisp_utils.releaser.commitizen:OpenWispCommitizen",
"cz_conventional_commits = openwisp_utils.releaser.commitizen:OpenWispCommitizen",
],
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Check if commitizen is used in the codebase and how
rg -n 'commitizen' -i --type py --type toml --type txt --type cfg

Repository: openwisp/openwisp-utils

Length of output: 94


🏁 Script executed:

# Look for setup.py details and entry point configuration
fd -n 'setup.py|setup.cfg|pyproject.toml' -x cat -n {}

Repository: openwisp/openwisp-utils

Length of output: 297


🌐 Web query:

commitizen plugin entry point resolution order multiple packages

💡 Result:

For cz-cli (the Node “Commitizen” CLI) the “plugin/adapter entry point” is whatever you configure in config.commitizen.path (in package.json) or in a .czrc file, and it’s resolved like this:

1) Which config wins (when multiple configs exist)

Priority is project-level first, then global: a repo’s package.json (config.commitizen) or a repo .czrc is used in preference to the user’s home ~/.czrc (“If your repository is already Commitizen friendly, the local … adapter will be used, instead of globally installed one.”). [1]
(Commitizen’s config system is described as loading from multiple sources with a defined priority order; project vs global is the key practical distinction.) [2]

If you run npx cz in a repo that is not Commitizen-configured, it falls back to using the streamich/git-cz adapter. [1]

2) How the adapter “entry point” is resolved (and what happens with multiple packages)

config.commitizen.path is resolved via Node’s require.resolve and supports:

  • npm module names
  • directories / files relative to process.cwd()
  • absolute paths
    [1]

So in a monorepo / multi-package setup, the adapter you actually load is determined by Node resolution starting from the current working directory (process.cwd()):

  • If multiple packages/workspaces contain different adapters (or different versions), the one that’s resolvable from the directory you run cz in (typically the closest node_modules up the directory tree) is the one that will be used. This is a direct consequence of require.resolve + process.cwd()-relative resolution. [1]

Practical rule: run cz from (or set cwd to) the package you want to control the adapter/config for, and ensure that package has the intended config.commitizen.path. [1]

Sources:
[1] commitizen/cz-cli README (adapter config, local-vs-global behavior, and require.resolve-based resolution)
[2] DeepWiki summary of cz-cli configuration system (multiple sources + priority order)


🌐 Web query:

Python importlib.metadata entry_points duplicate names same group resolution

💡 Result:

importlib.metadata.entry_points() does not define any special “winner” when multiple entry points share the same (group, name).

  • Duplicates are preserved. EntryPoints.select(group=..., name=...) is just a filter and can return multiple EntryPoint objects with the same name/group (e.g., editable-install metadata duplication can produce literal duplicates). [1]
  • Indexing picks the first match. EntryPoints.__getitem__(name) is implemented as next(iter(self.select(name=name))), so if more than one match exists, eps['x'] returns whichever matching entry point happens to come first in the underlying iteration order. [2]
  • Order/precedence is not a stable contract. Since entry_points() is an environment-wide collection, the “first” one should be treated as effectively arbitrary (i.e., not a reliable conflict-resolution mechanism). The docs also note you can’t currently query by EntryPoint.dist via entry_points(..., dist=...), so you must implement your own selection if you care which distribution won. [3]

Practical resolution pattern: always use select(group=..., name=...) and handle 0/1/N results explicitly (choose by ep.dist, by ep.value, or error on ambiguity). If the duplicates are truly identical, de-duplication with set(...) works because the duplicates may compare equal in practice (as reported in the editable-install duplication case). [1]

Sources:
[1] setuptools issue showing duplicated entry points can be returned and suggesting set() to remove equal duplicates: (github.com)
[2] EntryPoints.__getitem__ implementation returning the first select(name=...) result: (sandialabs.github.io)
[3] Python docs note: entry_points(**select_params) passes params to select() and it’s not currently possible to query based on EntryPoint.dist: (docs.python.org)

Citations:


🏁 Script executed:

# Look for setup.py and related config files
find . -maxdepth 2 -type f \( -name "setup.py" -o -name "setup.cfg" -o -name "pyproject.toml" -o -name "requirements*.txt" \)

Repository: openwisp/openwisp-utils

Length of output: 113


🏁 Script executed:

# Search for commitizen mentions in the codebase
rg -n 'commitizen' --type py --type toml --type txt

Repository: openwisp/openwisp-utils

Length of output: 373


🏁 Script executed:

# Check the setup.py file to see dependencies
head -50 setup.py

Repository: openwisp/openwisp-utils

Length of output: 2028


🌐 Web query:

Python commitizen library entry points plugin resolution PyPI

💡 Result:

Commitizen resolves “cz” plugins via Python package entry points, not by PyPI package name.

  • Discovery mechanism: since Commitizen v3.0.0 (2023-04-23), plugins must be exposed as commitizen.plugin entry points (loaded via importlib.metadata.EntryPoint). The old “discover_this” legacy mechanism is no longer used. [3], [1]
  • How Commitizen selects a plugin: your config name = "..." (e.g., in [tool.commitizen]) is the plugin name Commitizen looks up; that name must match an installed entry point under the commitizen.plugin group. The default is cz_conventional_commits. [2]
  • How a plugin package registers itself (so it can be resolved):
    • setuptools example: entry_points={"commitizen.plugin": ["cz_jira = cz_jira:JiraCz"]} [1]
    • Poetry example: [tool.poetry.plugins."commitizen.plugin"] cz_emoji = "cz_emoji:CzEmoji" [3]
  • How to verify what’s installed in an environment:
    • If a package is installed from PyPI but doesn’t declare a commitizen.plugin entry point, Commitizen won’t find it. (PyPI hosting alone isn’t sufficient.) [1], [3]
    • You can inspect entry points locally:
      python -c "import importlib.metadata as m; print([ (ep.group, ep.name, ep.value) for ep in m.entry_points() if ep.group=='commitizen.plugin' ])"
  • Current context: Commitizen’s latest PyPI release is 4.13.6 (Feb 7, 2026). [4]

Sources: Customization / plugin authoring & migration notes [1], configuration name setting [2], v3.0.0 release notes describing the entry-point plugin system [3], Commitizen PyPI page (latest release date/version) [4].


Entry point override for cz_conventional_commits may not resolve reliably due to unstable entry point ordering.

When both commitizen and openwisp-utils register the same entry point name (commitizen.plugin:cz_conventional_commits), the resolver uses importlib.metadata.EntryPoint.__getitem__(), which returns the first match. However, the iteration order of duplicate entry points is not stable and depends on installation order and environment state, meaning the override may not consistently select the openwisp version. Consider making the override explicit via commitizen configuration (e.g., name = "cz_conventional_commits" in [tool.commitizen] or .commitizen.cfg with a path that explicitly references openwisp-utils) to guarantee the intended plugin is loaded.

🤖 Prompt for AI Agents
In `@setup.py` around lines 27 - 29, The setup.py entry point registration for
"cz_conventional_commits"
(openwisp_utils.releaser.commitizen:OpenWispCommitizen) can be overridden
unpredictably due to unstable entry-point ordering; instead, make the override
explicit by adding a Commitizen configuration that sets name =
"cz_conventional_commits" and points to the openwisp implementation (e.g., in
pyproject.toml under [tool.commitizen] or a .commitizen.cfg) so Commitizen will
deterministically load the openwisp_utils.releaser.commitizen:OpenWispCommitizen
implementation rather than relying on entry-point order.

@github-project-automation github-project-automation bot moved this from To do (general) to In progress in OpenWISP Contributor's Board Feb 7, 2026
@coveralls
Copy link

Coverage Status

coverage: 97.238%. remained the same
when pulling 13a06ce on made-ow-rules-standard
into 8cbf453 on master.

@nemesifier nemesifier merged commit 13a06ce into master Feb 7, 2026
35 checks passed
@nemesifier nemesifier deleted the made-ow-rules-standard branch February 7, 2026 17:07
@github-project-automation github-project-automation bot moved this from In progress to Done in OpenWISP Contributor's Board Feb 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement helper-bots Helper bots, release management automation

Projects

Development

Successfully merging this pull request may close these issues.

2 participants