Convert a Repo to Use Releaser from Repo#

Follow the steps below to convert a repository to use Jupyter Releaser for releases, where maintainers make releases from the repository itself.


See checklist below for details:

  • Markdown changelog

  • Bump version configuration (if using Python), for example hatch

  • Add a trusted publisher to your PyPI project

  • If needed, access token for npm.

Checklist for Adoption#

  • Set up a GitHub App on your organization (or personal account for a personal project).

    • Disable the web hook

    • Enable Repository permissions > Contents > Read and write

    • Select “Only on this account”

    • Click “Create GitHub App”

    • Browse to the App Settings

    • Select “Install App” and install on all repositories

    • Under “General” click “Generate a private key”

    • Store the APP_ID and the private key in a secure location (Jupyter Vault if using a Jupyter Org)

  • Create a “release” environment on your repository and add an APP_ID Environment Variable and APP_PRIVATE_KEY secret. The environment should be enabled for “Protected branches only”.

  • Configure Rulesets for the repository

    • Set up branch protection (with default rules) on publication branches

    • Remove global tag protection.

    • Add a branch Ruleset for all branches

      • Allow the GitHub App to bypass protections

      • Set up Pull Request and Required Checks

    • Add a tags Ruleset for all tags

      • Allow the GitHub App to bypass protections

  • Copy prep-release.yml and publish-release.yml (or only full-release.yml) from the example-workflows folder in this repository.

  • Set up PyPI:

    • Set up your PyPI project by adding a trusted publisher

      • if you use the example workflows, the workflow name is publish-release.yml (or full-release.yml) and the environment should be release (the name of the GitHub environment).

    • Ensure the publish release job as permissions: id-token : write (see the documentation)

  • If needed, add access token for npm, saved as NPM_TOKEN. Again this should be created using a machine account that only has publish access.

  • Ensure that only trusted users with 2FA have admin access to the repository, since they will be able to trigger releases.

  • Switch to Markdown Changelog

    • We recommend MyST, especially if some of your docs are in reStructuredText.

    • Can use pandoc -s changelog.rst -o and some hand edits as needed.

    • Note that directives can still be used

  • Add HTML start and end comment markers to Changelog file

# Changelog


  • We recommend using hatch for your build system and for version handling.

    • If previously providing version_info like version_info = (1, 7, 0, '.dev', '0'), use a pattern like the one below in your version file:

import re
from typing import List

# Version string must appear intact for hatch versioning
__version__ = "6.16.0"

# Build up version_info tuple for backwards compatibility
pattern = r"(?P<major>\d+).(?P<minor>\d+).(?P<patch>\d+)(?P<rest>.*)"
match = re.match(pattern, __version__)
assert match is not None
parts: List[object] = [int(match[part]) for part in ["major", "minor", "patch"]]
if match["rest"]:
version_info = tuple(parts)
  • If you need to keep node and python versions in sync, use hatch-nodejs-version.

  • Add a GitHub Actions CI step to run the check_release action. For example:

    • This should be run on push and pull request events. You can copy the check-release.yml from this repo as an example.

- name: Check Release
  uses: jupyter-server/jupyter_releaser/.github/actions/check-release@v2
    token: ${{ secrets.GITHUB_TOKEN }}
  • If you would like the release assets to be uploaded as artifacts, add the following step after the check_release action:

- name: Upload Distributions
  uses: actions/upload-artifact@v4
    name: dist-${{ github.run_number }}
    path: .jupyter_releaser_checkout/dist
  • Add a workflow that uses the enforce-label action from jupyterlab/maintainer-tools to ensure that all PRs have on of the triage labels used to categorize the changelog.

name: Enforce PR label

    types: [labeled, unlabeled, opened, edited, synchronize]

    runs-on: ubuntu-latest
      pull-requests: write
      - name: enforce-triage-label
        uses: jupyterlab/maintainer-tools/.github/actions/enforce-label@v1
  • Update or add that describes the onboarding and release process, e.g. jupyter_server.

  • Optionally add configuration to the repository if non-standard options or hooks are needed.

  • If desired, add check_release job, changelog, and hatch support to other active release branches

Initial Release Workflow#

  • Try out the Prep Release and Publish Release process against a fork of the target repo first so you don’t accidentally push tags and GitHub releases to the source repository. Set the TWINE_REPOSITORY_URL environment variable to in the “Finalize Release” action part of the workflow

  • Try the Publish Release process using a prerelease version on the main repository before publishing a final version.

Backport Branches#

  • Create backport branches the usual way, e.g. git checkout -b 3.0.x v3.0.1; git push origin 3.0.x

  • When running the Publish Release Workflow, an automatic PR is generated for the default branch in the target repo, positioned in the appropriate place in the changelog.