Skip to content

Conversation

@Tschuppi81
Copy link
Contributor

@Tschuppi81 Tschuppi81 commented Dec 16, 2025

Directory: Fix directory migration crash when renaming option labels

TYPE: Bugfix
LINK: ogc-2353

@linear
Copy link

linear bot commented Dec 16, 2025

@codecov
Copy link

codecov bot commented Dec 16, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 85.41%. Comparing base (cadf75d) to head (3e342ac).
✅ All tests successful. No failed tests found.

Additional details and impacted files
Files with missing lines Coverage Δ
src/onegov/directory/migration.py 98.44% <100.00%> (+5.91%) ⬆️
src/onegov/org/views/directory.py 81.65% <100.00%> (+1.65%) ⬆️

... and 2 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update cadf75d...3e342ac. Read the comment docs.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@Tschuppi81 Tschuppi81 requested a review from Daverball December 18, 2025 08:37
Copy link
Member

@Daverball Daverball left a comment

Choose a reason for hiding this comment

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

This looks like a decent start, but we need to allow more operations than renaming a single option, there's many other legal changes, that will not result in form validation errors on existing entries.

Comment on lines 393 to 405
def detect_changed_options(self) -> None:
self.renamed_options: list[tuple[str, str]] = []

for old_id, old_field in self.old.items():
if isinstance(old_field, OptionsField) and old_id in self.new:
new_field = self.new[old_id]
if isinstance(new_field, OptionsField):
old_labels = [r.label for r in old_field.choices]
new_labels = [r.label for r in new_field.choices]

for o, n in zip(old_labels, new_labels):
if o != n:
self.renamed_options.append((o, n))
Copy link
Member

Choose a reason for hiding this comment

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

How do you distinguish between someone renaming an existing option, removing an existing option and inserting a new option between two existing options? Also someone might just rearrange the options into a new order, which should be allowed, since the underlying data doesn't have to change for that.

You can't just assume that every change in this list is intended to rename an existing option. I'd say the only time you could treat a change as renaming an option, is if the options are exactly the same as before, apart from a single options, that now has changed its label.

So legal operations:

  1. reorder options without changing the options
  2. rename a single option without changing anything else
  3. remove an arbitrary number of options (potentially only if they haven't been selected before, but we could also display a warning instead, one case that definitely should be handled however is removing this option would turn a required field into a field with no value for an existing entry, which I believe is the original impetus for this change and the Sentry issue we got, since the form generated a validation error after the option was removed)
  4. add an arbitrary number of new options without changing anything else (they can be inserted between existing options, but the existing options have to appear in the same order as before)

Any other change is ambiguous and we should disallow it on princriple

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants