Update readme and changelog#1239
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
WalkthroughAdds optional readme and changelog override support across stack. Frontend: form types, file inputs, and API client payload accept readme/changelog content. Backend: migration adds readme_override and changelog_override to PackageVersion; models and API views/serializers prefer override fields when present; PackageListing update endpoint persists overrides and triggers cache busting. Tests added to verify model and API override behavior. Possibly related PRs
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 📝 Coding Plan
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 |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (5)
django/thunderstore/repository/tests/test_package.py (1)
49-70: Nice coverage; add blank/Noneoverride cases too.These tests validate the happy path well. Adding
override=""andoverride=Noneassertions would lock fallback semantics and prevent regressions.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@django/thunderstore/repository/tests/test_package.py` around lines 49 - 70, Add assertions that an empty-string override and a None override fall back to the base value for both readme and changelog. Update the test functions test_package_readme_uses_override_when_present and test_package_changelog_uses_override_when_present (or add new parametrized tests) to include cases where PackageVersionFactory is created with readme_override="" and readme_override=None (and similarly changelog_override="" and changelog_override=None) and assert package.readme() returns the base readme and package.changelog() returns the base changelog respectively; ensure the package.latest assignment and save(update_fields=("latest",)) are preserved for each case so behavior is measured against the latest version.builder/src/api/api.ts (1)
78-79: Align client payload type with backend nullability.Backend accepts
nullfor these fields, but client typing currently excludes it, which blocks explicit clear semantics at type level.Proposed fix
- readme?: string; - changelog?: string; + readme?: string | null; + changelog?: string | null;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@builder/src/api/api.ts` around lines 78 - 79, The client payload type currently declares optional fields readme?: string and changelog?: string but the backend accepts null; update the type declarations so both readme and changelog allow null (e.g. readme?: string | null, changelog?: string | null) so callers can explicitly send null to clear values; locate and change the fields in the payload/interface definition where readme and changelog are declared (file contains the readme and changelog symbols) and run type checks to ensure no downstream call sites need minor adjustments to handle nullable values.django/thunderstore/api/cyberstorm/tests/test_markdown.py (1)
113-128: Add achangelog=None+ override test case.That edge case is currently untested and helps guard the fallback ordering in the changelog view.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@django/thunderstore/api/cyberstorm/tests/test_markdown.py` around lines 113 - 128, Add a new test next to test_changelog_api_view__uses_override_when_present that verifies the view prefers changelog_override even when changelog is explicitly None: create a PackageVersionFactory with changelog=None and changelog_override="Override changelog", call api_client.get on the same endpoint used in test_changelog_api_view__uses_override_when_present, parse response.json(), and assert actual["html"] == "<p>Override changelog</p>\n"; reference PackageVersionFactory, changelog, and changelog_override to locate where to add the case.django/thunderstore/community/api/experimental/tests/test_api_package_listing.py (1)
117-118: Strengthen mock assertions for both invalidation calls.At Line 117,
assert_called_with(...)checks only the last invocation. With Line 118, this can still miss a wrong first argument. Prefer asserting the full call list.Proposed test assertion update
+from unittest.mock import call @@ - mocked_invalidate.assert_called_with(CacheBustCondition.any_package_updated) - assert mocked_invalidate.call_count == 2 + mocked_invalidate.assert_has_calls( + [ + call(CacheBustCondition.any_package_updated), + call(CacheBustCondition.any_package_updated), + ] + ) + assert mocked_invalidate.call_count == 2🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@django/thunderstore/community/api/experimental/tests/test_api_package_listing.py` around lines 117 - 118, Replace the two separate assertions on mocked_invalidate with a single assertion that verifies both calls and their arguments together (e.g., assert_has_calls or comparing mocked_invalidate.call_args_list) so you check the exact sequence/contents of both invocations; update the test around the mocked_invalidate usage (referencing mocked_invalidate and CacheBustCondition.any_package_updated) to assert the full call list instead of only assert_called_with and call_count.builder/src/components/PackageManagement/Modal.tsx (1)
48-56: Allow re-selecting the same file in one session.After Line 55, reset the input value so choosing the same file again still fires
onChange.Small UX tweak
const content = await file.text(); props.form.setValue(field, { fileName: file.name, content: content }); + e.target.value = "";🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@builder/src/components/PackageManagement/Modal.tsx` around lines 48 - 56, The file input change handler handleFile reads the selected file but doesn't reset the input, so selecting the same file again in the same session won't trigger onChange; after awaiting file.text() and calling props.form.setValue(field, { fileName: file.name, content }), reset the input element's value (use e.currentTarget.value = '' or equivalent) so the same file can be re-selected and onChange will fire again.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@builder/src/components/PackageManagement/hooks.ts`:
- Around line 38-42: The payload building in the update call uses
data.categories.map(...) which will throw if categories is undefined; update the
logic in the function that constructs data: either initialize categories to an
empty array when undefined (e.g., ensure data.categories ?? [] is used) or only
include the categories property in the payload when data.categories is defined;
target the object construction where data: { categories:
data.categories.map(...), readme: data.readme?.content, changelog:
data.changelog?.content } is created (and consider the related
canUpdateCategories / CategoriesSelect rendering path) so users without the
categories field won't crash updates.
In `@builder/src/components/PackageManagement/Modal.tsx`:
- Around line 77-83: The file input elements inside the PackageManagement Modal
are using style={{ display: "none" }}, which makes them unfocusable and breaks
keyboard accessibility; update the inputs used for readme and other uploads (the
<input> elements that call handleFile in the Modal component) to remain in the
DOM and focusable while visually hidden (e.g. use a
screen-reader/visually-hidden class or style such as position: "absolute",
width/height: "1px", opacity: 0, overflow: "hidden", clip: "rect(0 0 0 0)") so
the <label> can trigger them via keyboard and screen readers; ensure the label
still wraps the input or uses htmlFor with matching id and that handleFile
continues to be called onChange.
In `@django/thunderstore/api/cyberstorm/views/markdown.py`:
- Around line 34-35: The current guard returns early when
package_version.readme_override is falsy, which incorrectly treats empty strings
as missing and can ignore valid overrides; update the checks in the markdown
view(s) to use explicit None checks (e.g., package_version.readme_override is
not None) so empty-string overrides are respected, and ensure the changelog
override (package_version.changelog_override / render_markdown) is evaluated
before any None-guard that would prematurely 404—adjust the logic around
render_markdown and the changelog handling in the same way (lines handling
readme_override and the section around changelog_override).
In `@django/thunderstore/community/api/experimental/views/listing.py`:
- Around line 50-60: Guard against a null latest on the listing and write both
overrides in one save: check that listing.package.latest is not None (raise a
ValidationError on request_serializer or return a 400) before touching it, then
set latest.readme_override and latest.changelog_override from
request_serializer.validated_data (only when present) and call latest.save()
once, followed by a single
invalidate_cache_on_commit_async(CacheBustCondition.any_package_updated); update
the code paths that currently call listing.package.latest.save() twice to use
this single-save, single-cache-bust flow (symbols: listing, request_serializer,
listing.package.latest, invalidate_cache_on_commit_async,
CacheBustCondition.any_package_updated).
In `@django/thunderstore/repository/models/package.py`:
- Around line 244-250: The readme() and changelog() methods currently use truthy
checks on self.latest.readme_override and self.latest.changelog_override which
treat empty strings as falsy and incorrectly fall back to base values; update
both methods to test for None instead (e.g., "if self.latest.readme_override is
not None") so an explicit empty-string override is returned, and do the same for
changelog using self.latest.changelog_override.
---
Nitpick comments:
In `@builder/src/api/api.ts`:
- Around line 78-79: The client payload type currently declares optional fields
readme?: string and changelog?: string but the backend accepts null; update the
type declarations so both readme and changelog allow null (e.g. readme?: string
| null, changelog?: string | null) so callers can explicitly send null to clear
values; locate and change the fields in the payload/interface definition where
readme and changelog are declared (file contains the readme and changelog
symbols) and run type checks to ensure no downstream call sites need minor
adjustments to handle nullable values.
In `@builder/src/components/PackageManagement/Modal.tsx`:
- Around line 48-56: The file input change handler handleFile reads the selected
file but doesn't reset the input, so selecting the same file again in the same
session won't trigger onChange; after awaiting file.text() and calling
props.form.setValue(field, { fileName: file.name, content }), reset the input
element's value (use e.currentTarget.value = '' or equivalent) so the same file
can be re-selected and onChange will fire again.
In `@django/thunderstore/api/cyberstorm/tests/test_markdown.py`:
- Around line 113-128: Add a new test next to
test_changelog_api_view__uses_override_when_present that verifies the view
prefers changelog_override even when changelog is explicitly None: create a
PackageVersionFactory with changelog=None and changelog_override="Override
changelog", call api_client.get on the same endpoint used in
test_changelog_api_view__uses_override_when_present, parse response.json(), and
assert actual["html"] == "<p>Override changelog</p>\n"; reference
PackageVersionFactory, changelog, and changelog_override to locate where to add
the case.
In
`@django/thunderstore/community/api/experimental/tests/test_api_package_listing.py`:
- Around line 117-118: Replace the two separate assertions on mocked_invalidate
with a single assertion that verifies both calls and their arguments together
(e.g., assert_has_calls or comparing mocked_invalidate.call_args_list) so you
check the exact sequence/contents of both invocations; update the test around
the mocked_invalidate usage (referencing mocked_invalidate and
CacheBustCondition.any_package_updated) to assert the full call list instead of
only assert_called_with and call_count.
In `@django/thunderstore/repository/tests/test_package.py`:
- Around line 49-70: Add assertions that an empty-string override and a None
override fall back to the base value for both readme and changelog. Update the
test functions test_package_readme_uses_override_when_present and
test_package_changelog_uses_override_when_present (or add new parametrized
tests) to include cases where PackageVersionFactory is created with
readme_override="" and readme_override=None (and similarly changelog_override=""
and changelog_override=None) and assert package.readme() returns the base readme
and package.changelog() returns the base changelog respectively; ensure the
package.latest assignment and save(update_fields=("latest",)) are preserved for
each case so behavior is measured against the latest version.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: c0baf00c-f364-4db3-b44b-e5ba1c26ecb4
📒 Files selected for processing (12)
builder/src/api/api.tsbuilder/src/components/PackageManagement/Modal.tsxbuilder/src/components/PackageManagement/hooks.tsdjango/thunderstore/api/cyberstorm/tests/test_markdown.pydjango/thunderstore/api/cyberstorm/views/markdown.pydjango/thunderstore/community/api/experimental/serializers.pydjango/thunderstore/community/api/experimental/tests/test_api_package_listing.pydjango/thunderstore/community/api/experimental/views/listing.pydjango/thunderstore/repository/migrations/0065_add_readme_override.pydjango/thunderstore/repository/models/package.pydjango/thunderstore/repository/models/package_version.pydjango/thunderstore/repository/tests/test_package.py
| data: { | ||
| categories: data.categories.map((x) => x.value), | ||
| readme: data.readme?.content, | ||
| changelog: data.changelog?.content, | ||
| }, |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify whether `categories` is optional end-to-end and whether form state guarantees it.
set -euo pipefail
echo "1) Serializer requirements:"
rg -n -C3 'class PackageListingUpdateRequestSerializer|categories\s*=|readme\s*=|changelog\s*=' \
django/thunderstore/community/api/experimental/serializers.py
echo
echo "2) Frontend API contract:"
rg -n -C3 'updatePackageListing|UpdatePackageListingResponse|categories\??|readme\??|changelog\??' \
builder/src/api -g '*.ts'
echo
echo "3) Form defaults / category initialization:"
rg -n -C4 'useForm<PackageListingUpdateFormValues>|defaultValues|setValue\("categories"|name:\s*"categories"|canUpdateCategories' \
builder/src/components/PackageManagement -g '*.ts' -g '*.tsx'Repository: thunderstore-io/Thunderstore
Length of output: 7120
🏁 Script executed:
#!/bin/bash
# Check PackageListingUpdateFormValues type definition and full onSubmit logic
echo "1) PackageListingUpdateFormValues type definition:"
rg -n -C8 'type PackageListingUpdateFormValues|interface PackageListingUpdateFormValues' \
builder/src/components/PackageManagement/
echo
echo "2) Full usePackageListingUpdateForm hook with context:"
head -100 builder/src/components/PackageManagement/hooks.ts | cat -n
echo
echo "3) CategoriesSelect component to confirm conditional rendering:"
rg -n -B5 -A10 'export.*CategoriesSelect|function CategoriesSelect' \
builder/src/components/PackageManagement/Repository: thunderstore-io/Thunderstore
Length of output: 5808
Guard categories mapping to prevent runtime crash when field is unregistered.
Line 39's data.categories.map(...) crashes when the categories field is not registered (e.g., when canUpdateCategories is false and CategoriesSelect is not rendered). This blocks updates for users with readme/changelog-only permissions. Either initialize categories with a default value even when unrenderable, or conditionally include it in the payload only when defined.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@builder/src/components/PackageManagement/hooks.ts` around lines 38 - 42, The
payload building in the update call uses data.categories.map(...) which will
throw if categories is undefined; update the logic in the function that
constructs data: either initialize categories to an empty array when undefined
(e.g., ensure data.categories ?? [] is used) or only include the categories
property in the payload when data.categories is defined; target the object
construction where data: { categories: data.categories.map(...), readme:
data.readme?.content, changelog: data.changelog?.content } is created (and
consider the related canUpdateCategories / CategoriesSelect rendering path) so
users without the categories field won't crash updates.
| <label className="btn btn-primary btn-lg btn-block"> | ||
| <input | ||
| type="file" | ||
| accept=".md" | ||
| style={{ display: "none" }} | ||
| onChange={(e) => handleFile(e, "readme")} | ||
| /> |
There was a problem hiding this comment.
File upload controls are not keyboard-accessible.
Using display: "none" on the file inputs (Line 81 and Line 93) removes the focusable control; keyboard users may not be able to trigger uploads reliably.
Also applies to: 89-95
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@builder/src/components/PackageManagement/Modal.tsx` around lines 77 - 83, The
file input elements inside the PackageManagement Modal are using style={{
display: "none" }}, which makes them unfocusable and breaks keyboard
accessibility; update the inputs used for readme and other uploads (the <input>
elements that call handleFile in the Modal component) to remain in the DOM and
focusable while visually hidden (e.g. use a screen-reader/visually-hidden class
or style such as position: "absolute", width/height: "1px", opacity: 0,
overflow: "hidden", clip: "rect(0 0 0 0)") so the <label> can trigger them via
keyboard and screen readers; ensure the label still wraps the input or uses
htmlFor with matching id and that handleFile continues to be called onChange.
| if "readme" in request_serializer.validated_data: | ||
| readme = request_serializer.validated_data["readme"] | ||
| listing.package.latest.readme_override = readme | ||
| listing.package.latest.save() | ||
| invalidate_cache_on_commit_async(CacheBustCondition.any_package_updated) | ||
|
|
||
| if "changelog" in request_serializer.validated_data: | ||
| changelog = request_serializer.validated_data["changelog"] | ||
| listing.package.latest.changelog_override = changelog | ||
| listing.package.latest.save() | ||
| invalidate_cache_on_commit_async(CacheBustCondition.any_package_updated) |
There was a problem hiding this comment.
Guard nullable latest and persist overrides in one write.
listing.package.latest can be None, which would 500 here. Also, separate saves create avoidable partial-write behavior and duplicate cache-bust tasks.
Proposed fix
- if "readme" in request_serializer.validated_data:
- readme = request_serializer.validated_data["readme"]
- listing.package.latest.readme_override = readme
- listing.package.latest.save()
- invalidate_cache_on_commit_async(CacheBustCondition.any_package_updated)
-
- if "changelog" in request_serializer.validated_data:
- changelog = request_serializer.validated_data["changelog"]
- listing.package.latest.changelog_override = changelog
- listing.package.latest.save()
- invalidate_cache_on_commit_async(CacheBustCondition.any_package_updated)
+ latest = listing.package.latest
+ if latest is None:
+ raise serializers.ValidationError("Package has no latest version")
+
+ update_fields = []
+ if "readme" in request_serializer.validated_data:
+ latest.readme_override = request_serializer.validated_data["readme"]
+ update_fields.append("readme_override")
+ if "changelog" in request_serializer.validated_data:
+ latest.changelog_override = request_serializer.validated_data["changelog"]
+ update_fields.append("changelog_override")
+
+ if update_fields:
+ latest.save(update_fields=update_fields)
+ invalidate_cache_on_commit_async(CacheBustCondition.any_package_updated)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if "readme" in request_serializer.validated_data: | |
| readme = request_serializer.validated_data["readme"] | |
| listing.package.latest.readme_override = readme | |
| listing.package.latest.save() | |
| invalidate_cache_on_commit_async(CacheBustCondition.any_package_updated) | |
| if "changelog" in request_serializer.validated_data: | |
| changelog = request_serializer.validated_data["changelog"] | |
| listing.package.latest.changelog_override = changelog | |
| listing.package.latest.save() | |
| invalidate_cache_on_commit_async(CacheBustCondition.any_package_updated) | |
| latest = listing.package.latest | |
| if latest is None: | |
| raise serializers.ValidationError("Package has no latest version") | |
| update_fields = [] | |
| if "readme" in request_serializer.validated_data: | |
| latest.readme_override = request_serializer.validated_data["readme"] | |
| update_fields.append("readme_override") | |
| if "changelog" in request_serializer.validated_data: | |
| latest.changelog_override = request_serializer.validated_data["changelog"] | |
| update_fields.append("changelog_override") | |
| if update_fields: | |
| latest.save(update_fields=update_fields) | |
| invalidate_cache_on_commit_async(CacheBustCondition.any_package_updated) |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@django/thunderstore/community/api/experimental/views/listing.py` around lines
50 - 60, Guard against a null latest on the listing and write both overrides in
one save: check that listing.package.latest is not None (raise a ValidationError
on request_serializer or return a 400) before touching it, then set
latest.readme_override and latest.changelog_override from
request_serializer.validated_data (only when present) and call latest.save()
once, followed by a single
invalidate_cache_on_commit_async(CacheBustCondition.any_package_updated); update
the code paths that currently call listing.package.latest.save() twice to use
this single-save, single-cache-bust flow (symbols: listing, request_serializer,
listing.package.latest, invalidate_cache_on_commit_async,
CacheBustCondition.any_package_updated).
There was a problem hiding this comment.
♻️ Duplicate comments (1)
django/thunderstore/api/cyberstorm/views/markdown.py (1)
59-64:⚠️ Potential issue | 🟠 MajorChangelog override is bypassed when base changelog is None.
The
Noneguard on line 59-60 raisesHttp404before the override is checked on line 62. If a user sets achangelog_overridebut the originalchangelogwasNone, the request 404s instead of serving the override.Proposed fix
- if package_version.changelog is None: - raise Http404 - if package_version.changelog_override is not None: return {"html": render_markdown(package_version.changelog_override)} + + if package_version.changelog is None: + raise Http404 + return {"html": render_markdown(package_version.changelog)}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@django/thunderstore/api/cyberstorm/views/markdown.py` around lines 59 - 64, The current logic raises Http404 when package_version.changelog is None before checking package_version.changelog_override, so changelog_override is never served if base changelog is missing; change the order and check package_version.changelog_override first (return {"html": render_markdown(package_version.changelog_override)}) and only if that's None decide whether to raise Http404 or render package_version.changelog using render_markdown; update the conditional flow in the markdown view that references package_version.changelog and package_version.changelog_override accordingly.
🧹 Nitpick comments (1)
django/thunderstore/repository/api/experimental/tests/test_package_version.py (1)
28-46: Good coverage of happy path; consider empty-string edge case.Tests verify overrides take precedence, but don't cover empty-string overrides (e.g.,
changelog_override = ""). A parameterized test with""would confirm theis not Nonelogic works end-to-end.Example extension
`@pytest.mark.django_db` `@pytest.mark.parametrize`("override", ("Override changelog", "")) def test_api_experimental_package_version_changelog_uses_override( api_client: APIClient, package_version: PackageVersion, override: str, ) -> None: package_version.changelog = "Base changelog" package_version.changelog_override = override package_version.save() # ... rest of test assert result["markdown"] == overrideAlso applies to: 68-86
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@django/thunderstore/repository/api/experimental/tests/test_package_version.py` around lines 28 - 46, Update the test function test_api_experimental_package_version_changelog_uses_override to parameterize the override value to include both a non-empty string and an empty string (e.g., parametrize "override" with ("Override changelog", "")); set package_version.changelog_override = override, save, call the same API endpoint, and assert result["markdown"] == override to exercise the empty-string edge case; apply the same parameterized pattern to the other similar test referenced around lines 68-86 so both tests verify that an empty string override is treated as a valid override.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@django/thunderstore/api/cyberstorm/views/markdown.py`:
- Around line 59-64: The current logic raises Http404 when
package_version.changelog is None before checking
package_version.changelog_override, so changelog_override is never served if
base changelog is missing; change the order and check
package_version.changelog_override first (return {"html":
render_markdown(package_version.changelog_override)}) and only if that's None
decide whether to raise Http404 or render package_version.changelog using
render_markdown; update the conditional flow in the markdown view that
references package_version.changelog and package_version.changelog_override
accordingly.
---
Nitpick comments:
In
`@django/thunderstore/repository/api/experimental/tests/test_package_version.py`:
- Around line 28-46: Update the test function
test_api_experimental_package_version_changelog_uses_override to parameterize
the override value to include both a non-empty string and an empty string (e.g.,
parametrize "override" with ("Override changelog", "")); set
package_version.changelog_override = override, save, call the same API endpoint,
and assert result["markdown"] == override to exercise the empty-string edge
case; apply the same parameterized pattern to the other similar test referenced
around lines 68-86 so both tests verify that an empty string override is treated
as a valid override.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 35cc4fee-8e29-4f47-8a1e-843792909f84
📒 Files selected for processing (4)
django/thunderstore/api/cyberstorm/views/markdown.pydjango/thunderstore/repository/api/experimental/tests/test_package_version.pydjango/thunderstore/repository/api/experimental/views/package_version.pydjango/thunderstore/repository/models/package.py
| if instance.changelog_override is not None: | ||
| serializer = self.get_serializer({"markdown": instance.changelog_override}) | ||
| else: | ||
| serializer = self.get_serializer({"markdown": instance.changelog}) |
There was a problem hiding this comment.
Empty string overrides will be used instead of falling back to the original changelog. The serializer allows allow_blank=True, so an empty string "" can be set as an override. The check if instance.changelog_override is not None: evaluates to True for empty strings, causing an empty changelog to be returned instead of the original.
Fix: Check for both None and empty string:
if instance.changelog_override:
serializer = self.get_serializer({"markdown": instance.changelog_override})
else:
serializer = self.get_serializer({"markdown": instance.changelog})| if instance.changelog_override is not None: | |
| serializer = self.get_serializer({"markdown": instance.changelog_override}) | |
| else: | |
| serializer = self.get_serializer({"markdown": instance.changelog}) | |
| if instance.changelog_override: | |
| serializer = self.get_serializer({"markdown": instance.changelog_override}) | |
| else: | |
| serializer = self.get_serializer({"markdown": instance.changelog}) | |
Spotted by Graphite
Is this helpful? React 👍 or 👎 to let us know.
Allows the user to update the readme and changelog, without having to bump a new version.
This intentionally adds the readme_override and changelog_override to a specific PackageVersion, therefore being handled as a temporary override until the next package version is bumped. It also does not modify existing package zips, the readme and changelog are only visible on the website and API.
The UI for updating is inside the Manage Package modal. It's a file upload to prevent modders from making changes in place and uploading an outdated readme next time. The file upload is only browser site, the content is transmitted as plain text over the API.
I'm not 100% sure if the invalidate_cache_on_commit_async is actually needed here.
Solves #16, #101