Story #2586 :: Task: Wire the Library Maintenance achievement, counting libraries and not versions - #2587
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review. 📝 WalkthroughWalkthroughAdds an automatic library maintenance achievement source. It deduplicates maintenance across library versions, excludes sub-libraries, registers the source, and validates achievement and badge creation. ChangesLibrary maintenance achievement
Estimated code review effort: 2 (Simple) | ~10 minutes Merge Risk: ⚪ Minimal · up to This localized change deduplicates library maintainers across versions while preserving the intended achievement source and is supported by targeted tests and a passing suite; no actionable merge-blocking risk remains. Sequence Diagram(s)sequenceDiagram
participant LibraryVersion
participant _iter_library_maintenance
participant backfill_achievements
participant UserAchievement
participant UserBadge
LibraryVersion->>_iter_library_maintenance: provide library versions and maintainers
_iter_library_maintenance->>backfill_achievements: yield unique user and library pairs
backfill_achievements->>UserAchievement: create library-maintenance achievement
backfill_achievements->>UserBadge: create matching badge
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
32fb541 to
07a2b1c
Compare
07a2b1c to
d3c392d
Compare
d3c392d to
1696c2c
Compare
1696c2c to
a253833
Compare
| def test_iter_library_maintenance_dedupes_versions(plain_user): | ||
| """Maintaining many versions of one library yields a single pair.""" | ||
| library = baker.make("libraries.Library") | ||
| for _ in range(3): | ||
| version = baker.make("libraries.LibraryVersion", library=library) | ||
| version.maintainers.add(plain_user) | ||
|
|
||
| pairs = list(sources._iter_library_maintenance()) | ||
| assert pairs == [(plain_user, library)] |
There was a problem hiding this comment.
Nit suggestion: Perhaps we can update this test to add another library here, and assert that pairs == [(plain_user, library), (plain_user, another library)] to ensure we can cover that common case as well!
a253833 to
2703076
Compare
2703076 to
53d58b6
Compare
53d58b6 to
6319f28
Compare
6319f28 to
6f3b5a0
Compare
6f3b5a0 to
3d63eb3
Compare
105b2b5 to
54b0426
Compare
54b0426 to
929f3c3
Compare
929f3c3 to
ee1f698
Compare
ee1f698 to
7434935
Compare
7434935 to
7b668c2
Compare
7b668c2 to
0ab9848
Compare
0ab9848 to
b531f6c
Compare
QA: Maintainer badgeThe Maintainer badge starts filling itself in from the library data, instead of only being
What this change does
The whole point of this change is that de-duplication. Without it, anyone maintaining a single What it does not do
Before you start
If it still shows a cross, stop and tell Teo - the change is not deployed.
Test 1: make yourself a maintainer several times over
Test 2: three versions, one achievement
Expected:
If you see three rows here, that is the bug this change exists to prevent. Report it. Test 3: a different library does move the count
Expected: you now have two achievements and hold Maintainer / Silver. This is what proves the rule is "one per library", not "one per person". Test 4: running it twice changes nothingPress Backfill achievements once more without changing any data, then open Expected: the newest Test 5: removing a maintainer demotes, but only on Reconcile
Expected: nothing changes. You still have two achievements and Silver. Backfill only ever adds.
Expected on the preview: 1 removal, and nothing has happened yet.
Expected after applying:
Test 6: sanity-check against the real data (the most valuable check)
Expected: every Diamond holder genuinely has 20 or more rows, and each row's Source If someone is sitting at Diamond with only a handful of libraries, or with several rows pointing at If you can't find a Diamond ranked user for this achievement, you can redo the steps above checking Platinum users and they should have only 10 rows, Gold 5, Silver 2 and Bronze 1 (like shown in the ladder at the top) Things that look wrong but are meant to be that way
Reporting anything you findPlease include the run number from |
b531f6c to
16257a1
Compare
a9d7c60 to
9dd3f99
Compare
9dd3f99 to
60458e8
Compare
Issue: #2586
teo/2541-source-library-authoringSummary & Context
Wires the Library Maintenance achievement. The one thing worth reviewing here is the grain:
maintainers are recorded per
LibraryVersion, but the badge counts libraries maintained(1 / 2 / 5 / 10 / 20), so the iterator deduplicates across versions and yields the
Libraryasthe achievement source.
Without that, a maintainer of one library with 40 releases would hold diamond.
Changes
_iter_library_maintenancewalksLibraryVersionwith its maintainers prefetched and yields(user, library)once per(user, library)pair, tracking what it has already seen.BACKFILL_ITERATORS.test_iter_library_maintenance_dedupes_versions- three versions of one library yield exactlyone pair.
test_backfill_library_maintenance- two versions, one grant, one badge.(user, library)pair,bounded by the number of maintainer relationships, not by the number of versions - a few
thousand entries at Boost's scale.
Library, not theLibraryVersion. This iswhat makes the grant idempotent under
unique_automatic_user_achievement_sourceand what letsreconciliation match it. An earlier iteration of this feature recorded versions and had to be
cleaned up with a data migration; a fresh install never creates those rows.
reconcile, the two-way command, not on a backfill. That is by design.
Screenshots
n/a - no UI.
Peer-review testing steps
The dedup is basically the whole PR, and it is visible on a changelist.
The source is wired.
/admin/badges/badge/- the Maintainer row's Automatic column is atick and its ladder reads
1 / 2 / 5 / 10 / 20.Make yourself a maintainer of one library, several times over.
/admin/libraries/libraryversion/, filter by a single library, then open three of its versionsand add your own user to Maintainers on each.
Backfill.
/admin/badges/userachievement/-> Backfill achievements with Source set toLibrary Maintenance.
Three versions, one grant. Filter that changelist by Achievement: Library Maintenance: you
have exactly one row, and its Source column links to the library, not to any of the
three versions. Without the dedup this step is where you would see three.
/admin/badges/userbadge/shows Maintainer / Bronze; the per-member page (your name, linked from either badge changelist)
reads one valid grant and 1 to go to Silver.
A second library does move the count. Add yourself to Maintainers on one version of a
different library and press Backfill again: two grants, and Maintainer / Silver is
awarded. This is what proves the dedup is per (member, library) and not just "one grant per member".
Removal is a reconcile, and it demotes. Drop yourself from all three versions of the first
library. Backfill changes nothing. Then Reconcile achievements with Source on Library
Maintenance: the preview reports one removal, Apply, and the Silver row is revoked with
Count at revocation 1 while Bronze stays held.
/admin/badges/achievementsyncrun/shows the runwith Removed 1, and the revoked badge's notes name it.
Sanity-check against real data. Backfill All sources on a production copy, then filter
/admin/badges/userbadge/to Badge: Maintainer and Rank: Diamond. Every name there must genuinelymaintain 20 or more libraries - filter
/admin/badges/userachievement/by Achievement: LibraryMaintenance, search their email, and count the rows, whose Source links must all be distinct
libraries. Without the dedup, anyone maintaining a single long-lived library would be sitting in that
Diamond list, which is the failure this PR exists to prevent.
Self-review Checklist
Backend
Summary by CodeRabbit