Context
Follow-up work after #917 (folding web_fragments into the XBlock project).
Tasks
1. Drop __version__ from xblock/__init__.py and unused Sphinx import
As noted in this comment:
Ideally we should drop __version__ from xblock/__init__.py since we've shifted to semantic versioning. The only reason it still exists is that docs/conf.py imports it for Sphinx — but that import is unused too (no .rst file references version), so both can be removed together.
- Remove
__version__ from xblock/__init__.py
- Remove the corresponding unused import in
docs/conf.py
2. Migrate to src/ layout
Move both xblock and web_fragments packages under a src/ directory to follow modern Python packaging conventions and prevent accidental imports from the repo root during development.
- Create
src/ directory
- Move
xblock/ → src/xblock/
- Move
web_fragments/ → src/web_fragments/
- Update
pyproject.toml (package-dir = {"" = "src"}, where = ["src"])
3. Optimize bundling via MANIFEST.in
The current MANIFEST.in is a single line:
recursive-include xblock *.mo *.po
With include-package-data = true and no exclusions, the built wheel ends up bundling a large number of files that have no business being in a distribution — including the entire docs/ tree (79 files), CI configs, linting configs, lock files, and dev tooling. This inflates the master wheel to ~1.1MB when it should be well under 200KB.
Taking inspiration from openedx/xblocks-extra's MANIFEST.in, MANIFEST.in should be updated to explicitly prune everything that isn't needed by an end user:
recursive-include xblock *.mo *.po
recursive-include web_fragments *.html
# Exclude development, CI, and documentation folders
prune .github
prune docs
# Exclude root-level config and build files
exclude .coveragerc
exclude .gitignore
exclude .readthedocs.yaml
exclude Makefile
exclude catalog-info.yaml
exclude codecov.yml
exclude conftest.py
exclude openedx.yaml
exclude pylintrc
exclude pylintrc_tweaks
exclude tox.ini
exclude uv.lock
# Exclude nested test files
global-exclude tests/*
global-exclude test_*.py
Files currently git-tracked at the repo root that should be excluded:
| File |
Reason to exclude |
Makefile |
Developer tooling |
conftest.py |
pytest root config |
.coveragerc |
Coverage tooling |
.gitignore |
VCS config |
.readthedocs.yaml |
Docs CI config |
catalog-info.yaml |
Backstage catalog metadata |
codecov.yml |
CI coverage reporting |
openedx.yaml |
Open edX repo metadata |
pylintrc, pylintrc_tweaks |
Linting config |
tox.ini |
Test runner config |
uv.lock |
Dependency lock file |
docs/ |
Full documentation tree (79 files, major bloat source) |
.github/ |
GitHub Actions and templates |
Note: CHANGELOG.rst exclusion is covered by task 5.
4. Review whether tests should ship in the wheel
Currently both xblock/test/ and web_fragments/tests/ are included in the built wheel. This needs a deliberate decision:
- Some of
xblock/test/ contains base test classes and utilities (e.g. toy_runtime.py, tools.py) that downstream packages depend on — those should ship
- Pure test files (e.g.
test_fields.py, test_core.py) have no value for end users — those should not ship
web_fragments/tests/ — evaluate the same way
Suggested outcome: ship xblock/test/ selectively (keep test utilities) and exclude web_fragments/tests/ entirely.
5. Remove CHANGELOG.rst if no longer needed
Since XBlock has shifted to semantic release, release notes are managed via GitHub Releases automatically. CHANGELOG.rst may be redundant — study how openedx/xblocks-extra handles this.
In xblocks-extra, CHANGELOG.rst was dropped (along with its MANIFEST.in reference) because changelog: false is set in release.yml, meaning semantic release manages release notes entirely via GitHub Releases.
- Verify XBlock's
release.yml configuration
- If changelog generation is handled by semantic release, remove
CHANGELOG.rst and its reference in MANIFEST.in
Reference: openedx/xblocks-extra#50
6. Fix semantic release build failures and improve the release process
Two issues surfaced after #917 was merged, both worth addressing:
a) refactor commits silently skip a release
After #917 merged (using refactor: commit prefixes), the semantic release workflow ran but produced no release — because neither chore nor refactor is configured as a version-bumping commit type. The full log from that run:
INFO No commits found since the last release!
INFO The type of the next release release is: no_release
INFO No release will be made
Reference: actions/runs/27294163918, PR #917 comment
A refactor that adds new functionality (like absorbing web_fragments) is arguably a feat and warrants a release. The fix is twofold:
- Short-term: contributors should use
feat: when a refactor introduces new capabilities available to users.
- Long-term: consider adding
refactor as a patch-level trigger in the semantic release config so accidental use of the wrong prefix doesn't silently suppress a release.
b) uv: command not found during the build step
A follow-up force-release PR (#926) did trigger a release, but the build step failed with exit code 127:
bash: line 1: uv: command not found
ERROR Command '['bash', '-c', 'SETUPTOOLS_SCM_PRETEND_VERSION=$NEW_VERSION uv build']'
returned non-zero exit status 127.
ERROR Build command failed with exit code 127
Reference: actions/runs/27301129203/job/80647052902
The root cause: astral-sh/setup-uv (step 6 in release.yml) installs uv on the GitHub Actions runner, but python-semantic-release executes the build command inside its own Docker container — where uv is not present.
Possible fixes:
- Change
build_command in pyproject.toml from uv build to pip install uv && uv build so uv is installed inside the container before use.
- Or switch to
python -m build (requires build as a dev dependency) to avoid the uv-in-container problem entirely.
Testing
To verify bundling changes, build the package locally and inspect the wheel contents:
Then inspect what got bundled:
python3 -c "
import zipfile, sys
whl = sys.argv[1]
for f in sorted(zipfile.ZipFile(whl).namelist()):
print(f)
" dist/XBlock-*.whl
This makes it easy to catch regressions like docs bloat, missing templates, or unwanted test files shipping in the wheel.
Reference
openedx/xblocks-extra follows a modernized packaging approach and is a good reference for how the above tasks can be implemented — particularly the src/ layout, MANIFEST.in structure, and pyproject.toml conventions.
Related
🤖 Generated with Claude Code
Context
Follow-up work after #917 (folding
web_fragmentsinto the XBlock project).Tasks
1. Drop
__version__fromxblock/__init__.pyand unused Sphinx importAs noted in this comment:
__version__fromxblock/__init__.pydocs/conf.py2. Migrate to
src/layoutMove both
xblockandweb_fragmentspackages under asrc/directory to follow modern Python packaging conventions and prevent accidental imports from the repo root during development.src/directoryxblock/→src/xblock/web_fragments/→src/web_fragments/pyproject.toml(package-dir = {"" = "src"},where = ["src"])3. Optimize bundling via
MANIFEST.inThe current
MANIFEST.inis a single line:With
include-package-data = trueand no exclusions, the built wheel ends up bundling a large number of files that have no business being in a distribution — including the entiredocs/tree (79 files), CI configs, linting configs, lock files, and dev tooling. This inflates the master wheel to ~1.1MB when it should be well under 200KB.Taking inspiration from
openedx/xblocks-extra'sMANIFEST.in,MANIFEST.inshould be updated to explicitly prune everything that isn't needed by an end user:Files currently git-tracked at the repo root that should be excluded:
Makefileconftest.py.coveragerc.gitignore.readthedocs.yamlcatalog-info.yamlcodecov.ymlopenedx.yamlpylintrc,pylintrc_tweakstox.iniuv.lockdocs/.github/Note:
CHANGELOG.rstexclusion is covered by task 5.4. Review whether tests should ship in the wheel
Currently both
xblock/test/andweb_fragments/tests/are included in the built wheel. This needs a deliberate decision:xblock/test/contains base test classes and utilities (e.g.toy_runtime.py,tools.py) that downstream packages depend on — those should shiptest_fields.py,test_core.py) have no value for end users — those should not shipweb_fragments/tests/— evaluate the same waySuggested outcome: ship
xblock/test/selectively (keep test utilities) and excludeweb_fragments/tests/entirely.5. Remove
CHANGELOG.rstif no longer neededSince XBlock has shifted to semantic release, release notes are managed via GitHub Releases automatically.
CHANGELOG.rstmay be redundant — study howopenedx/xblocks-extrahandles this.In
xblocks-extra,CHANGELOG.rstwas dropped (along with itsMANIFEST.inreference) becausechangelog: falseis set inrelease.yml, meaning semantic release manages release notes entirely via GitHub Releases.release.ymlconfigurationCHANGELOG.rstand its reference inMANIFEST.inReference: openedx/xblocks-extra#50
6. Fix semantic release build failures and improve the release process
Two issues surfaced after #917 was merged, both worth addressing:
a)
refactorcommits silently skip a releaseAfter #917 merged (using
refactor:commit prefixes), the semantic release workflow ran but produced no release — because neitherchorenorrefactoris configured as a version-bumping commit type. The full log from that run:Reference: actions/runs/27294163918, PR #917 comment
A
refactorthat adds new functionality (like absorbingweb_fragments) is arguably afeatand warrants a release. The fix is twofold:feat:when a refactor introduces new capabilities available to users.refactoras apatch-level trigger in the semantic release config so accidental use of the wrong prefix doesn't silently suppress a release.b)
uv: command not foundduring the build stepA follow-up force-release PR (#926) did trigger a release, but the build step failed with exit code 127:
Reference: actions/runs/27301129203/job/80647052902
The root cause:
astral-sh/setup-uv(step 6 inrelease.yml) installsuvon the GitHub Actions runner, butpython-semantic-releaseexecutes the build command inside its own Docker container — whereuvis not present.Possible fixes:
build_commandinpyproject.tomlfromuv buildtopip install uv && uv buildsouvis installed inside the container before use.python -m build(requiresbuildas a dev dependency) to avoid theuv-in-container problem entirely.Testing
To verify bundling changes, build the package locally and inspect the wheel contents:
Then inspect what got bundled:
This makes it easy to catch regressions like docs bloat, missing templates, or unwanted test files shipping in the wheel.
Reference
openedx/xblocks-extrafollows a modernized packaging approach and is a good reference for how the above tasks can be implemented — particularly thesrc/layout,MANIFEST.instructure, andpyproject.tomlconventions.Related
🤖 Generated with Claude Code