Conversation
WalkthroughThis pull request introduces a comprehensive release infrastructure for the project. It adds a GitHub Actions CI/CD workflow for publishing packages, a Python release automation script, release process documentation, Makefile targets, version management via a dedicated Changes
Sequence Diagram(s)sequenceDiagram
actor Maintainer
participant Make as Make/CLI
participant ReleaseScript as Release Script
participant Git
participant Build as Build System
participant Twine as Twine/PyPI
participant GitHub as GitHub Actions
Maintainer->>Make: make release [VERSION=x.y.z]
Make->>ReleaseScript: python scripts/release.py
ReleaseScript->>ReleaseScript: Parse version from CHANGELOG or CLI
ReleaseScript->>Git: Validate branch (main), check dirty worktree
ReleaseScript->>Git: Verify tag doesn't exist
ReleaseScript->>ReleaseScript: Run optional checks (Ruff, Pytest, E2E)
ReleaseScript->>Build: Build source & wheel distributions
ReleaseScript->>Twine: Run twine check on artifacts
ReleaseScript->>ReleaseScript: Update __about__.py __version__
ReleaseScript->>Git: Stage & commit CHANGELOG.md, __about__.py
ReleaseScript->>Git: Create annotated git tag
ReleaseScript->>Twine: Upload artifacts to TestPyPI/PyPI (if selected)
ReleaseScript->>Git: Push branch + tags to origin
ReleaseScript-->>Maintainer: Release summary & confirmation
Note over GitHub: GitHub Actions workflow triggered on tag<br/>re-runs tests & publishes using OIDC
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ 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 |
Greptile SummaryThis PR introduces a local
Confidence Score: 4/5Safe to merge after resolving the post-commit version-restore bug in One P1 defect: scripts/release.py — the Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A([make release]) --> B[resolve_target_version\nCHANGELOG or --version]
B --> C[validate_repo_state\nbranch · dirty check · tag · changelog section]
C --> D[resolve_upload_plan\nskip / testpypi / pypi]
D --> E[print_release_summary\n+ interactive confirm]
E --> F[prepared_version\nwrite target version to __about__.py]
F --> G[run_release_checks\nruff · pytest · npm ci · test-ci]
G --> H[build_distributions\npython -m build + twine check]
H --> I{dry_run?}
I -- yes --> J[restore __about__.py\nclean dist/\nreturn 0]
I -- no --> K[stage_and_commit_release_files\ngit add + git commit]
K --> L[create_tag\ngit tag -a vX.Y.Z]
L --> M{upload_plan.repository?}
M -- yes --> N[upload_distributions\ntwine upload]
M -- no --> O{skip_push?}
N --> O
O -- no --> P[push_release\ngit push origin branch --follow-tags]
O -- yes --> Q
P --> Q[clean_build_artifacts\nrm -rf dist/]
Q --> R([Release complete])
F -. exception after commit .-> S[restore __about__.py ⚠️\nleaves worktree inconsistent]
S --> T([ReleaseError printed])
|
| if [[ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" && -n "${INPUT_VERSION}" && "${INPUT_VERSION}" != "${PACKAGE_VERSION}" ]]; then | ||
| echo "Requested version ${INPUT_VERSION} does not match package version ${PACKAGE_VERSION}." | ||
| exit 1 | ||
| fi | ||
|
|
||
| - name: Install build tooling |
There was a problem hiding this comment.
Unreachable push-trigger validation branch
The push branch of the version check can never execute because the workflow only declares a workflow_dispatch trigger — GITHUB_EVENT_NAME will always be "workflow_dispatch", never "push". The guard on lines 139–142 is dead code. Either add a push: tags: ["v*"] trigger to make it reachable, or remove the push block to avoid confusion.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 34bb66eb4f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| **os.environ, | ||
| "REACT_ON_DJANGO_EXAMPLE_PYTHON": sys.executable, | ||
| }, |
There was a problem hiding this comment.
Use effective Python override for example release checks
This sets REACT_ON_DJANGO_EXAMPLE_PYTHON, but the invoked path (example/bin/test-ci -> example/bin/dev) currently hardcodes /workspace/.../.venv/bin/python3.14 and does not read that variable, so make release PYTHON=... still fails on machines without that exact interpreter path. In practice this blocks the new release flow in common maintainer environments unless they happen to match the hardcoded .venv layout.
Useful? React with 👍 / 👎.
| if selected is not None: | ||
| return UploadPlan(repository=selected, source="explicit option") | ||
| if yes: | ||
| return UploadPlan(repository=None, source="non-interactive default") | ||
| return prompt_upload_repository() |
There was a problem hiding this comment.
Respect explicit skip upload choice
Passing --repository skip is parsed to None, and this branch treats None as "no explicit choice" and re-prompts interactively unless --yes is also set. That means an explicit opt-out of upload is ignored in normal interactive runs, which can lead to accidental uploads if the prompt is answered incorrectly.
Useful? React with 👍 / 👎.
| except Exception: | ||
| if should_update: | ||
| VERSION_FILE.write_text(original) | ||
| raise |
There was a problem hiding this comment.
Avoid reverting version file after post-commit failures
On any exception inside the release block, this restores __about__.py to its original contents. If the failure happens after the release commit/tag is created (for example during twine upload or git push), the worktree is left dirty and out of sync with HEAD, making retry/recovery error-prone and potentially leading to accidental follow-up commits that undo the version bump.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
pyproject.toml (1)
29-33:⚠️ Potential issue | 🔴 Critical
django-rspack>=0.1.0does not exist on PyPI and blocks the build.The package is not available on PyPI (HTTP 404 from the package index API). This breaks
pip install -e .[dev]in.github/workflows/release.yml(lines 43, 73) and the documented maintainer setup inRELEASING.md. Publish the package to PyPI, use the correct package name, pin to an available version, or use a VCS URL (e.g.,django-rspack @ git+https://...).🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pyproject.toml` around lines 29 - 33, The pyproject dependency "django-rspack>=0.1.0" is not published on PyPI and breaks installs; update the pyproject.toml dependencies to a valid source by either replacing "django-rspack>=0.1.0" with the correct PyPI package name and an available version, replacing it with a VCS spec like "django-rspack @ git+https://..." pointing to the repo/commit, or removing it if unused; ensure the same identifier is updated where referenced in CI/release workflows and docs (the dependency list in pyproject.toml and any occurrences in release workflows/RELEASING.md).
🧹 Nitpick comments (6)
.github/workflows/release.yml (2)
43-43: Quote the.[dev]pip target.Unquoted
.[dev]is a shell glob (dotfile charclass). Bash with default settings passes it through when there's no match, but the script is fragile against accidental dotfile matches (e.g.,.d/.e/.v) and zsh behavior. Use'.[dev]'.♻️ Proposed fix
- python -m pip install "Django==${{ matrix.django-version }}" -e .[dev] + python -m pip install "Django==${{ matrix.django-version }}" -e '.[dev]'- python -m pip install -e .[dev] + python -m pip install -e '.[dev]'Also applies to: 73-73
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/release.yml at line 43, The pip editable extras target -e .[dev] is unquoted and can be expanded by the shell; change it to use quoted extras like -e ".[dev]" (or -e '.[dev]') in the pip install command that currently reads python -m pip install "Django==${{ matrix.django-version }}" -e .[dev], and apply the same quoting fix to the other occurrence of .[dev] in the workflow so both editable extras are safely quoted.
131-141: Dead branch: thepushcheck cannot fire under the currenton:config.
on:only includesworkflow_dispatch, soGITHUB_EVENT_NAME == "push"is never true. Either wire up apush: { tags: ['v*'] }trigger (if tag-based publishing is intended perscripts/release.pytagging) or drop the block to reduce confusion.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In @.github/workflows/release.yml around lines 131 - 141, The release workflow contains a dead branch checking GITHUB_EVENT_NAME == "push" (comparing GITHUB_REF_NAME to expected_tag) but the workflow's on: only declares workflow_dispatch, so that branch never runs; either add a push trigger that matches tags (e.g., push: tags: ['v*']) so the push-based tag check (expected_tag / GITHUB_REF_NAME) is meaningful, or remove the entire push-check block (the if that tests GITHUB_EVENT_NAME == "push" and the expected_tag comparison) to avoid confusion—make the change around the expected_tag / GITHUB_EVENT_NAME / GITHUB_REF_NAME logic to keep behavior consistent with scripts/release.py tagging flow.tests/test_release.py (2)
117-126: Brittle reliance oncommands[-1]ordering.Asserting the E2E step is the last element of
release_check_commands(...)couples the test to ordering that may legitimately change. Prefer filtering by command name, e.g.,next(c for c in commands if c[0] == ["./bin/test-ci"]), then assert on that tuple.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/test_release.py` around lines 117 - 126, The test test_release_check_commands_sets_example_python_for_e2e is brittle because it assumes the E2E tuple is at commands[-1]; instead locate the tuple by filtering the iterable returned by release.release_check_commands(skip_checks=False) (e.g., find the entry where the command list equals ["./bin/test-ci"] or where the second element's name == "example") and then assert on that found tuple's environment value; update the test to use next(...) or a comprehension to select the matching tuple from commands before asserting that example_test[2]["REACT_ON_DJANGO_EXAMPLE_PYTHON"] == release.sys.executable.
8-15: Consider a module-scoped fixture forload_release_module().Each test re-executes
scripts/release.pyviaimportlib.util.spec_from_file_location, which reimports/re-parses the module (and re-registerssys.modules["react_on_django_release"]) per test. A@pytest.fixture(scope="module")would cut duplication and avoid repeated loads.♻️ Optional refactor
-def load_release_module(): - module_path = Path(__file__).resolve().parents[1] / "scripts" / "release.py" - spec = importlib.util.spec_from_file_location("react_on_django_release", module_path) - module = importlib.util.module_from_spec(spec) - assert spec.loader is not None - sys.modules[spec.name] = module - spec.loader.exec_module(module) - return module +@pytest.fixture(scope="module") +def release(): + module_path = Path(__file__).resolve().parents[1] / "scripts" / "release.py" + spec = importlib.util.spec_from_file_location("react_on_django_release", module_path) + module = importlib.util.module_from_spec(spec) + assert spec.loader is not None + sys.modules[spec.name] = module + spec.loader.exec_module(module) + return moduleThen drop
release = load_release_module()from each test body and acceptreleaseas a fixture parameter.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/test_release.py` around lines 8 - 15, The tests repeatedly re-import scripts/release.py by calling load_release_module() in each test; convert load_release_module into a module-scoped pytest fixture (e.g., add `@pytest.fixture`(scope="module") above load_release_module) so the module is imported once per test module, register it in sys.modules as before and return the loaded module, then update tests to accept a release fixture parameter instead of calling load_release_module() inside each test to remove duplication and repeated imports.Makefile (1)
6-6: Boolean flag vars treat any non-empty value as truthy (including0/false).
$(if $(YES),--yes,)(andSKIP_CHECKS/SKIP_PUSH) will pass the flag forYES=0,YES=false, orYES=no. Consider documenting that these vars are "set to any value to enable" (which matchesRELEASING.mdexamplesYES=1,SKIP_PUSH=1), or normalize to truthy tokens, e.g.:♻️ Optional normalization
-release: - $(PYTHON) scripts/release.py $(if $(VERSION),--version $(VERSION),) $(if $(REPOSITORY),--repository $(REPOSITORY),) $(if $(YES),--yes,) $(if $(SKIP_CHECKS),--skip-checks,) $(if $(SKIP_PUSH),--skip-push,) +# Treat these as boolean: enabled only when set to 1/true/yes. +_truthy = $(filter 1 true yes TRUE YES,$(1)) +release: + $(PYTHON) scripts/release.py $(if $(VERSION),--version $(VERSION),) $(if $(REPOSITORY),--repository $(REPOSITORY),) $(if $(call _truthy,$(YES)),--yes,) $(if $(call _truthy,$(SKIP_CHECKS)),--skip-checks,) $(if $(call _truthy,$(SKIP_PUSH)),--skip-push,)Also applies to: 9-9
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@Makefile` at line 6, The Makefile currently treats any non-empty value as truthy for flags YES, SKIP_CHECKS, and SKIP_PUSH when building the release command invoking $(PYTHON) scripts/release.py; either update the Makefile to normalize these variables (e.g., explicitly test for common truthy tokens like "1", "true", or "yes" before expanding to --yes/--skip-checks/--skip-push) or add a short comment next to the $(PYTHON) ... line documenting that these vars must be "set to any value to enable" (or list accepted truthy tokens) so consumers know how to enable the flags correctly when using VERSION/REPOSITORY/YES/SKIP_CHECKS/SKIP_PUSH.scripts/release.py (1)
384-397: Optional: surface that--repositoryis ignored under--dry-run.Passing
--dry-run --repository pypitoday silently drops the explicit repository and reportsUpload: skip (dry-run). A brief warning (or an explicit argparse conflict) would avoid a surprising silent override in scripts that compose these flags.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@scripts/release.py` around lines 384 - 397, The resolve_upload_plan function currently ignores a provided repository when dry_run is true; update resolve_upload_plan to detect when repository is non-None and dry_run is True and surface that the --repository value is being ignored (e.g., emit a warning via the existing logger or raise an argparse conflict earlier). Specifically, in resolve_upload_plan (and/or where parse_repository_name is called) add a conditional before returning the dry-run UploadPlan that logs a clear message stating the explicit repository was ignored due to --dry-run so users scripting with --repository won't be surprised; keep the returned UploadPlan(repository=None, source="dry-run") behavior but ensure the warning references the provided repository string and the dry_run flag.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@scripts/release.py`:
- Around line 130-138: The current context manager only catches Exception, so
KeyboardInterrupt/BaseException bypasses the cleanup and leaves VERSION_FILE
modified; change the control flow in the generator (the try/yield/except/else
block around VERSION_FILE, should_update and restore_after_success) to ensure
cleanup on all terminations by using a try/finally (or catching BaseException)
with a success flag: set success=False before yield, set success=True in the
normal path after yield, and in the finally block restore
VERSION_FILE.write_text(original) when should_update and (not success or
restore_after_success) so run_release_checks/build_distributions interruptions
still revert __about__.py.
- Around line 517-522: The release flow currently calls
upload_distributions(...) before push_release(...), which can publish artifacts
to PyPI without a matching remote git ref; reorder the steps so you
stage_and_commit_release_files(context.target_version) and
create_tag(context.target_version) as before, then call
push_release(context.branch) (respecting args.skip_push and failing fast if push
fails), and only after a successful push call
upload_distributions(upload_plan.repository); additionally consider gating or
erroring when args.skip_push is true but upload_plan.repository is present to
prevent unpushed uploads.
- Around line 98-116: Update all Path.read_text() and Path.write_text() calls to
explicitly use encoding="utf-8". Specifically, in get_version()/the code that
calls VERSION_FILE.read_text() and in update_version_file() replace
VERSION_FILE.read_text() and VERSION_FILE.write_text(updated) with calls that
pass encoding="utf-8" so the version file I/O uses UTF-8 regardless of locale;
do the same for any other read_text()/write_text() calls in this script (e.g.,
changelog/ABOUT file reads/writes) to cover the lines noted in the review.
---
Outside diff comments:
In `@pyproject.toml`:
- Around line 29-33: The pyproject dependency "django-rspack>=0.1.0" is not
published on PyPI and breaks installs; update the pyproject.toml dependencies to
a valid source by either replacing "django-rspack>=0.1.0" with the correct PyPI
package name and an available version, replacing it with a VCS spec like
"django-rspack @ git+https://..." pointing to the repo/commit, or removing it if
unused; ensure the same identifier is updated where referenced in CI/release
workflows and docs (the dependency list in pyproject.toml and any occurrences in
release workflows/RELEASING.md).
---
Nitpick comments:
In @.github/workflows/release.yml:
- Line 43: The pip editable extras target -e .[dev] is unquoted and can be
expanded by the shell; change it to use quoted extras like -e ".[dev]" (or -e
'.[dev]') in the pip install command that currently reads python -m pip install
"Django==${{ matrix.django-version }}" -e .[dev], and apply the same quoting fix
to the other occurrence of .[dev] in the workflow so both editable extras are
safely quoted.
- Around line 131-141: The release workflow contains a dead branch checking
GITHUB_EVENT_NAME == "push" (comparing GITHUB_REF_NAME to expected_tag) but the
workflow's on: only declares workflow_dispatch, so that branch never runs;
either add a push trigger that matches tags (e.g., push: tags: ['v*']) so the
push-based tag check (expected_tag / GITHUB_REF_NAME) is meaningful, or remove
the entire push-check block (the if that tests GITHUB_EVENT_NAME == "push" and
the expected_tag comparison) to avoid confusion—make the change around the
expected_tag / GITHUB_EVENT_NAME / GITHUB_REF_NAME logic to keep behavior
consistent with scripts/release.py tagging flow.
In `@Makefile`:
- Line 6: The Makefile currently treats any non-empty value as truthy for flags
YES, SKIP_CHECKS, and SKIP_PUSH when building the release command invoking
$(PYTHON) scripts/release.py; either update the Makefile to normalize these
variables (e.g., explicitly test for common truthy tokens like "1", "true", or
"yes" before expanding to --yes/--skip-checks/--skip-push) or add a short
comment next to the $(PYTHON) ... line documenting that these vars must be "set
to any value to enable" (or list accepted truthy tokens) so consumers know how
to enable the flags correctly when using
VERSION/REPOSITORY/YES/SKIP_CHECKS/SKIP_PUSH.
In `@scripts/release.py`:
- Around line 384-397: The resolve_upload_plan function currently ignores a
provided repository when dry_run is true; update resolve_upload_plan to detect
when repository is non-None and dry_run is True and surface that the
--repository value is being ignored (e.g., emit a warning via the existing
logger or raise an argparse conflict earlier). Specifically, in
resolve_upload_plan (and/or where parse_repository_name is called) add a
conditional before returning the dry-run UploadPlan that logs a clear message
stating the explicit repository was ignored due to --dry-run so users scripting
with --repository won't be surprised; keep the returned
UploadPlan(repository=None, source="dry-run") behavior but ensure the warning
references the provided repository string and the dry_run flag.
In `@tests/test_release.py`:
- Around line 117-126: The test
test_release_check_commands_sets_example_python_for_e2e is brittle because it
assumes the E2E tuple is at commands[-1]; instead locate the tuple by filtering
the iterable returned by release.release_check_commands(skip_checks=False)
(e.g., find the entry where the command list equals ["./bin/test-ci"] or where
the second element's name == "example") and then assert on that found tuple's
environment value; update the test to use next(...) or a comprehension to select
the matching tuple from commands before asserting that
example_test[2]["REACT_ON_DJANGO_EXAMPLE_PYTHON"] == release.sys.executable.
- Around line 8-15: The tests repeatedly re-import scripts/release.py by calling
load_release_module() in each test; convert load_release_module into a
module-scoped pytest fixture (e.g., add `@pytest.fixture`(scope="module") above
load_release_module) so the module is imported once per test module, register it
in sys.modules as before and return the loaded module, then update tests to
accept a release fixture parameter instead of calling load_release_module()
inside each test to remove duplication and repeated imports.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: deea7b76-4bde-4dbe-88cb-b0fd3dc9b2e8
📒 Files selected for processing (9)
.github/workflows/release.ymlCHANGELOG.mdMakefileRELEASING.mdpyproject.tomlscripts/release.pysrc/react_on_django/__about__.pysrc/react_on_django/__init__.pytests/test_release.py
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Changelog header regex matches too many heading levels
- Restricted
CHANGELOG_HEADER_REfrom matching##+to exactly##, so only level-2 release headings are treated as changelog version boundaries.
- Restricted
Or push these changes by commenting:
@cursor push a22557ab54
Preview (a22557ab54)
diff --git a/scripts/release.py b/scripts/release.py
--- a/scripts/release.py
+++ b/scripts/release.py
@@ -26,7 +26,7 @@
r"^(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)"
r"(?:(?P<pre>a|b|rc)(?P<pre_n>\d+))?$"
)
-CHANGELOG_HEADER_RE = re.compile(r"^##+\s+\[(?P<version>[^\]]+)\](?:\s+-\s+.+)?$")
+CHANGELOG_HEADER_RE = re.compile(r"^##\s+\[(?P<version>[^\]]+)\](?:\s+-\s+.+)?$")
class ReleaseError(RuntimeError):You can send follow-ups to the cloud agent here.
Reviewed by Cursor Bugbot for commit d5b5ad8. Configure here.
| r"^(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)" | ||
| r"(?:(?P<pre>a|b|rc)(?P<pre_n>\d+))?$" | ||
| ) | ||
| CHANGELOG_HEADER_RE = re.compile(r"^##+\s+\[(?P<version>[^\]]+)\](?:\s+-\s+.+)?$") |
There was a problem hiding this comment.
Changelog header regex matches too many heading levels
Low Severity
CHANGELOG_HEADER_RE uses ##+ which matches headings with two or more # characters. This means ### [Breaking] or any subsection header containing square brackets would be treated as a version boundary. In latest_changelog_version, such a header would cause a ReleaseError from parse_version. In extract_changelog_section, it would prematurely terminate section collection, potentially making changelog_has_section return False for a valid section. The intent is to match only ##-level version headings.
Additional Locations (2)
Reviewed by Cursor Bugbot for commit d5b5ad8. Configure here.



Summary
make releasemaintainer flow with changelog-driven version resolution, release checks, tagging, and optional local PyPI/TestPyPI uploadsrc/react_on_django/__about__.pyand document the simplified release processValidation
.venv/bin/python3.14 -m pytest tests/test_release.py -q.venv/bin/python3.14 -m ruff check scripts/release.py tests/test_release.py.venv/bin/python3.14 -m build --no-isolation.venv/bin/python3.14 -m twine check dist/*make release VERSION=0.1.0a1 REPOSITORY=skip YES=1 SKIP_PUSH=1 PYTHON=.venv/bin/python3.14after committing the tooling and adding a temporary changelog entry; this passed through ruff, full pytest,example/bin/test-ci, build, twine check, release commit, and tag creationNotes
Note
Medium Risk
Medium risk because it introduces new release automation (git tagging/pushing and optional PyPI uploads) and changes package version metadata sourcing, which can affect packaging/publishing if misconfigured.
Overview
Adds a maintainer release flow via
scripts/release.pyandmake release, including changelog-driven version resolution, repo cleanliness/branch/tag validation, running ruff/pytest/example e2e checks, building dists, tagging/pushing, and optionaltwineupload totestpypi/pypi.Switches package versioning to be single-sourced from
src/react_on_django/__about__.py(andpyproject.tomlnow uses Hatch dynamic versioning), plus addsRELEASING.mdand expandsCHANGELOG.mdscaffolding.Updates CI to install
django-rspackfrom a pinned Git commit, adds a manual.github/workflows/release.ymltrusted-publishing workflow, makes the examplebin/devresolve Python more robustly, and extends asset helper logic/tests to fall back todjango_rspack.manifestAPIs when top-level helpers are unavailable.Reviewed by Cursor Bugbot for commit d5b5ad8. Bugbot is set up for automated code reviews on this repo. Configure here.
Summary by CodeRabbit
Release Notes
Documentation
Chores