-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Account: Allow choosing commit name attribution #17778
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Adds configurable/anonymized commit-name attribution (similar to private commit e-mail) to improve privacy/GDPR compliance and make commit-name preference persist via an explicit state.
Changes:
- Add
Profile.commit_namewith logic to choose public vs anonymized name based on explicit user choice and global defaults. - Use
Profile.get_commit_name()for VCS author attribution and expose the setting in the profile “Commit” form. - Add Docker env-var support plus docs/tests for the new settings and behavior.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| weblate/settings_docker.py | Adds env var parsing for commit-name template and opt-in/out default. |
| weblate/auth/models.py | Switches commit author name to Profile.get_commit_name() for attribution. |
| weblate/accounts/models.py | Introduces commit_name field, new settings defaults, and commit-name generation logic. |
| weblate/accounts/migrations/0022_add_commit_name.py | Adds DB migration for the new commit_name field. |
| weblate/accounts/forms.py | Adds commit-name radio setting and populates choices based on defaults/template. |
| weblate/accounts/tests/test_models.py | Adds unit tests for commit-name generation and default/explicit behaviors. |
| docs/admin/install/docker.rst | Documents new Docker env vars for commit-name anonymization. |
| docs/admin/config.rst | Documents new settings and expands template placeholder docs. |
weblate/accounts/forms.py
Outdated
| self.fields["commit_name"].choices = [ | ||
| ("", gettext_lazy("Use anonymous account name")) |
Copilot
AI
Jan 26, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When PRIVATE_COMMIT_NAME_OPT_IN is false but PRIVATE_COMMIT_NAME_TEMPLATE is blank/disabled, site_name will be empty and the anonymized option is not available, yet the default radio choice label is changed to “Use anonymous account name”. This becomes misleading because the effective behavior falls back to the visible account name. Consider only switching the default label when an anonymized site_name is actually available (or adjust the label to reflect the real default).
| self.fields["commit_name"].choices = [ | |
| ("", gettext_lazy("Use anonymous account name")) | |
| default_label = ( | |
| gettext_lazy("Use anonymous account name") | |
| if site_name | |
| else gettext_lazy("Use account name") | |
| ) | |
| self.fields["commit_name"].choices = [ | |
| ("", default_label), |
weblate/accounts/models.py
Outdated
| commit_name = models.CharField( | ||
| verbose_name=gettext_lazy("Commit name"), | ||
| blank=True, | ||
| max_length=200, |
Copilot
AI
Jan 26, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Profile.commit_name is being used as an enum-like state field (values are expected to be "", "public", or "private"), but the model field has no choices/validation. This allows arbitrary values to be stored (e.g., via admin/DB/API), which will silently fall through to the global default path in get_commit_name(). Consider adding choices (or a TextChoices) and constraining max_length accordingly to prevent invalid states.
| commit_name = models.CharField( | |
| verbose_name=gettext_lazy("Commit name"), | |
| blank=True, | |
| max_length=200, | |
| class CommitNameChoices(models.TextChoices): | |
| DEFAULT = "", gettext_lazy("Use global default") | |
| PUBLIC = "public", gettext_lazy("Public") | |
| PRIVATE = "private", gettext_lazy("Private") | |
| commit_name = models.CharField( | |
| verbose_name=gettext_lazy("Commit name"), | |
| blank=True, | |
| default=CommitNameChoices.DEFAULT, | |
| max_length=7, | |
| choices=CommitNameChoices.choices, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think using IntegerChoices and IntegerField will work better for this purpose.
| ) | ||
| def test_get_commit_name_empty_template_fallback(self) -> None: | ||
| self.profile.commit_name = Profile.COMMIT_NAME_PRIVATE | ||
| self.assertTrue(len(self.profile.get_commit_name()) > 0) |
Copilot
AI
Jan 26, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assertTrue(a > b) cannot provide an informative message. Using assertGreater(a, b) instead will give more informative messages.
| self.assertTrue(len(self.profile.get_commit_name()) > 0) | |
| self.assertGreater(len(self.profile.get_commit_name()), 0) |
Codecov Report❌ Patch coverage is
❌ Your patch check has failed because the patch coverage (95.89%) is below the target coverage (100.00%). You can increase the patch coverage or adjust the target coverage. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
nijel
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the feature. This might be useful for some users even though you can use already any name in the profile (unlike with e-mail which is also used for notifications or password recovery).
Please refer to my review comments and add a changelog entry.
docs/admin/install/docker.rst
Outdated
|
|
||
| .. envvar:: WEBLATE_PRIVATE_COMMIT_NAME_TEMPLATE | ||
|
|
||
| .. versionadded:: 5.1x |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's focus on 5.16
weblate/accounts/models.py
Outdated
| commit_name = models.CharField( | ||
| verbose_name=gettext_lazy("Commit name"), | ||
| blank=True, | ||
| max_length=200, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think using IntegerChoices and IntegerField will work better for this purpose.
| username=self.user.username, | ||
| site_title=settings.SITE_TITLE, | ||
| site_domain=settings.SITE_DOMAIN.rsplit(":", 1)[0], | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think renaming format_private_email, extending it to support site_title and reusing it here would be a better approach.
for more information, see https://pre-commit.ci
Co-authored-by: Copilot <[email protected]>
fc2096a to
f4cd2b9
Compare
| * Added new management command :wladmin:`list_change_events`, which lists all possible change events, :ref:`addon-choice-events`. | ||
| * Added Anthropic machinery integration, see :ref:`mt-anthropic`. | ||
| * Encoding for :ref:`formats` can now be configured using :ref:`file_format_params` (e.g., ``csv_encoding``, ``properties_encoding``). | ||
| * Added support for anonymous commit names via :setting:`PRIVATE_COMMIT_NAME_TEMPLATE`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we also update /accounts/snippets/login-info.html?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, it indeed makes sense to adjust it.
|
|
||
| if site_name: | ||
| name_choices.append((Profile.CommitNameChoices.PRIVATE, site_name)) | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we add a comprobation here?
if instance.commit_name == Profile.CommitNameChoices.PRIVATE and not site_name: self.initial["commit_name"] = Profile.CommitNameChoices.DEFAULT
this implies that if the user saves the form, their 'Private' setting will be overwritten with 'Default'. The setting wouldn't automatically revert to 'Private' if the template is re-enabled later, but I assume this implicit cleanup is the desired behavior when the feature is disabled.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The cleanup would only happen for users saving the settings, so I don't think it's worth of the effort.
Summary
This PR introduces anonymized commit names to complement the existing private e-mail feature, improving GDPR compliance.
It implements an explicit state logic for this new field. Currently, with e-mails, users relying on a "private-by-default" setting become unintentionally public if the administrator later toggles the global default. This PR ensures that a user's commit name privacy preference is locked in and preserved, regardless of future changes to the global
PRIVATE_COMMIT_NAME_OPT_INsetting.Changes
commit_nametoProfilewith fallbacks to prevent Git fatal errors (empty idents).weblate.auth.models.User.get_author_name()for proper Git attribution.PRIVATE_COMMIT_NAME_TEMPLATEandPRIVATE_COMMIT_NAME_OPT_IN. Added{user_id}and{site_domain}support for both name and e-mail templates.Checklist
docs/admin/config.rst).