Robust solution for filtering unpublishable changes on frontend#5844
Conversation
rtibblesbot
left a comment
There was a problem hiding this comment.
Correct fix for the P0 regression — the two-part approach (restoring created_by_id so the Celery task can authenticate, plus returning unpublishable to the frontend) addresses both failure modes cleanly.
CI: frontend tests, linting, and build passing; Python unit tests still running. No screenshots in PR; serverSync.js is a data-layer file whose Publish-button behavior can't be screenshot-verified without a running server — author's manual verification steps are documented in the PR.
- suggestion: see inline on
test_community_library_submission.py - suggestion: see inline on
serverSync.spec.js - praise: see inline on
community_library_submission.py
@rtibblesbot's comments are generated by an LLM, and should be evaluated accordingly
How was this generated?
Reviewed the pull request diff checking for:
- Correctness: bugs, edge cases, undocumented behavior, resource leaks, hardcoded values
- Design: unnecessary complexity, naming, readability, comment accuracy, redundant state
- Architecture: duplicated concerns, minimal interfaces, composition over inheritance
- Testing: behavior-based assertions, mocks only at hard boundaries, accurate coverage
- Completeness: missing dependencies, unupdated usages, i18n, accessibility, security
- Principles: DRY (same reason to change), SRP, Rule of Three (no premature abstraction)
- Checked CI status and linked issue acceptance criteria
- For UI changes: inspected screenshots for layout, visual completeness, and consistency
| ), | ||
| created_by_id=submission.resolved_by_id, | ||
| # This change is not publishable and should not trigger publish-related logic | ||
| unpublishable=True, |
There was a problem hiding this comment.
praise: Clear, self-documenting comment on why unpublishable=True — makes the intent explicit so future readers don't accidentally remove it thinking it's redundant.
| categories=submission.categories, | ||
| country_codes=country_codes, | ||
| ), | ||
| created_by_id=submission.resolved_by_id, |
There was a problem hiding this comment.
suggestion: The existing test_resolve_submission__accept_correct verifies that a Change with change_type=ADDED_TO_COMMUNITY_LIBRARY is created, but doesn't assert created_by_id or unpublishable=True. Since restoring created_by_id is the root cause of the P0, consider adding assertions like:
change = Change.objects.get(
channel=self.submission.channel,
change_type=ADDED_TO_COMMUNITY_LIBRARY,
)
self.assertEqual(change.created_by_id, self.admin_user.id)
self.assertTrue(change.unpublishable)This guards against the specific regression being fixed.
| !c.user_id && | ||
| c.created_by_id && | ||
| c.type !== CHANGE_TYPES.PUBLISHED && | ||
| !c.unpublishable, |
There was a problem hiding this comment.
suggestion: The handleMaxRevs logic change (filtering !c.unpublishable) isn't covered by any test in serverSync.spec.js. The handleMaxRevs function as a whole has no unit test. A case like:
// response contains only an unpublishable change → unpublished_changes should NOT be set...would lock in the fix and catch any future regression. Not strictly blocking for a P0 hotfix, but worth tracking.
105dbe2 to
bc02793
Compare
rtibblesbot
left a comment
There was a problem hiding this comment.
Both prior suggestions addressed — no new findings.
Prior findings
Resolved:
- Test assertions for
created_by_idandunpublishable(suggestion) — test now uses.get()and asserts both fields at lines 727-728 handleMaxRevsunpublishable filtering test (suggestion) — new test added covering the all-unpublishable case
2/2 prior findings resolved.
CI passing (linting). Frontend changes are data-layer only (serverSync.js) with no visual component — behaviour is covered by the new serverSync.spec.js test.
@rtibblesbot's comments are generated by an LLM, and should be evaluated accordingly
How was this generated?
Compared the current PR state against findings from a prior review:
- Retrieved prior bot reviews deterministically via the GitHub API
- Classified each prior finding as RESOLVED, UNADDRESSED, ACKNOWLEDGED, or CONTESTED
- Only raised NEW findings for newly introduced code
- Reviewed the pull request diff checking for correctness, design, architecture, testing, completeness, and adherence to DRY/SRP principles
- Checked CI status and linked issue acceptance criteria
rtibbles
left a comment
There was a problem hiding this comment.
Code changes are very straight forward. One possible small bit of future cleanup, but also not required now.
| !c.errors && | ||
| !c.user_id && | ||
| c.created_by_id && | ||
| c.type !== CHANGE_TYPES.PUBLISHED && |
There was a problem hiding this comment.
I mean.. I guess it would make sense for "PUBLISHED" to just be an unpublishable_change!
Summary
In #5825, I noticed that
unpublishablechanges were still changing theunpublished_changescondition on the frontend because we weren't returning this from the backend, and less so acknowledging it on the frontend. I just followed the tendency to just remove thecreated_by_idattribute from the change, just to not mess with the sync endpoint.However, didn't notice that in the add_to_community_library flow, we use get_edit_queryset to filter the channel, so we needed the
created_by_id. This PR returns theunpublishablefield to the frontend, and filters changes to compute theunpublished_changesfield.Verification steps
unpublished_changesfield properly.References
Fixes #5843.
Reviewer guidance