The extension can be published to PyPI and npm manually or using the Jupyter Releaser.
This extension can be distributed as Python packages. All of the Python
packaging instructions are in the pyproject.toml file to wrap your extension in a
Python package. Before generating a package, you first need to install some tools:
pip install build twine hatchBump the version using hatch. By default this will create a tag.
See the docs on hatch-nodejs-version for details.
hatch version <new-version>Make sure to clean up all the development files before building the package:
jlpm clean:allYou could also clean up the local git repository:
git clean -dfXTo create a Python source package (.tar.gz) and the binary package (.whl) in the dist/ directory, do:
python -m build
python setup.py sdist bdist_wheelis deprecated and will not work for this package.
Then to upload the package to PyPI, do:
twine upload dist/*To publish the frontend part of the extension as a NPM package, do:
npm login
npm publish --access publicThe extension repository should already be compatible with the Jupyter Releaser.
Check out the workflow documentation for more information.
Here is a summary of the steps to cut a new release:
- Add tokens to the Github Secrets in the repository:
ADMIN_GITHUB_TOKEN(with "public_repo" and "repo:status" permissions); see the documentationNPM_TOKEN(with "automation" permission); see the documentation
- Set up PyPI
Using PyPI trusted publisher (modern way)
- Set up your PyPI project by adding a trusted publisher
- The workflow name is
publish-release.ymland the environment should be left blank.
- The workflow name is
- Ensure the publish release job as
permissions:id-token : write(see the documentation)
Using PyPI token (legacy way)
-
If the repo generates PyPI release(s), create a scoped PyPI token. We recommend using a scoped token for security reasons.
-
You can store the token as
PYPI_TOKENin your fork'sSecrets.-
Advanced usage: if you are releasing multiple repos, you can create a secret named
PYPI_TOKEN_MAPinstead ofPYPI_TOKENthat is formatted as follows:owner1/repo1,token1 owner2/repo2,token2If you have multiple Python packages in the same repository, you can point to them as follows:
owner1/repo1/path/to/package1,token1 owner1/repo1/path/to/package2,token2
-
- Go to the Actions panel
- Run the "Step 1: Prep Release" workflow
- Check the draft changelog
- Run the "Step 2: Publish Release" workflow
This extension can be built in two consent mode variants, controlled by the
CONSENT_MODE environment variable baked into the JavaScript bundle at build time:
| Mode | Behavior | Default |
|---|---|---|
consent |
Shows a one-time dialog; user opts in or out | |
silent |
Data collection enabled by default, no dialog shown; user can still opt out via settings | ✓ (default) |
Use the named npm scripts to build a specific variant:
# silent variant (no dialog, collection always on — same as omitting CONSENT_MODE)
jlpm build:prod:silent
# consent variant (dialog shown)
jlpm build:prod:consentThe "Step 2: Publish Release" workflow includes a pypi_mode dropdown
(default: silent) that controls which variant is published to PyPI.
The other variant is automatically built, renamed with a +<mode> version
suffix (e.g. …5.0.1+consent-py3-none-any.whl), and attached to the
GitHub release as a downloadable asset.
Normal release (silent on PyPI, consent as asset):
- Run "Step 2: Publish Release" with
pypi_mode = silent(or leave it at the default).
To publish the consent variant to PyPI instead:
- Run "Step 2: Publish Release" with
pypi_mode = consent. - The silent variant will be attached as a GitHub release asset instead.
Note: Wheels with a local version suffix (
+consent,+silent) are intentionally rejected by PyPI and can only be installed directly from the.whlfile:pip install <filename>.whl
If the package is not on conda forge yet, check the documentation to learn how to add it: https://conda-forge.org/docs/maintainer/adding_pkgs.html
Otherwise a bot should pick up the new version publish to PyPI, and open a new PR on the feedstock repository automatically.