Skip to content

ci: publish to PyPI and npm via trusted publishers#1701

Merged
maartenbreddels merged 3 commits into
bqplot:0.12.xfrom
maartenbreddels:ci/trusted-publishers
Apr 28, 2026
Merged

ci: publish to PyPI and npm via trusted publishers#1701
maartenbreddels merged 3 commits into
bqplot:0.12.xfrom
maartenbreddels:ci/trusted-publishers

Conversation

@maartenbreddels
Copy link
Copy Markdown
Member

Summary

  • Reuse the dist/ artifact already produced by the build job (wheel, sdist, npm tarball) instead of rebuilding at release time. The artifact that visual regression tests validate is the one that gets uploaded.
  • New publish-pypi and publish-npm jobs gated on [build, visual-regression-tests]. They run on every PR/push in dry-run mode (twine check, npm publish --dry-run) and only do real uploads when triggered by a release: published event, via OIDC trusted publishers (no PYPI_TOKEN or NPM_TOKEN).
  • Version-sanity check on real release: fails if the GitHub Release tag doesn't match the wheel version, or if the npm version is already published.
  • Added twine check dist/* to the build job so PR CI catches metadata issues early.

Inspired by the test/release workflows in solara and ipyvuetify.

One-time setup (already done by maintainer)

  • PyPI Trusted Publisher entry added at https://pypi.org/manage/project/bqplot/settings/publishing/ (workflow build.yml, environment release-pypi).
  • npm Trusted Publisher entry added on npmjs.com (workflow build.yml, environment release-npm).
  • GitHub Environments release-pypi and release-npm created in the repo.

Release flow after this lands

  1. Bump bqplot/_version.py and js/package.json, commit, push.
  2. Cut a GitHub Release with tag matching the Python version (e.g. 0.12.46, no v prefix).
  3. Workflow builds, tests, version-checks, then publishes via OIDC. If required reviewers are set on the environments, GitHub pauses for approval before each upload.

Test plan

  • PR CI runs build, then publish-pypi (dry-run) and publish-npm (dry-run) without any environment-approval prompt and without touching the registries.
  • twine check passes on the built wheel/sdist.
  • npm publish --dry-run reports the expected tarball contents.
  • First real release of 0.12.46 uploads to both registries via OIDC. (Verifies the trusted-publisher config; if it fails, re-run the failed job after fixing the registry-side config — the dist artifact is preserved.)

🤖 Generated with Claude Code

Copy link
Copy Markdown
Member

@martinRenou martinRenou left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

maartenbreddels and others added 2 commits April 28, 2026 11:25
Reuse the wheel/sdist/tgz artifacts already produced by the `build`
job instead of rebuilding at release time. The artifact that visual
regression tests validate is the one that gets uploaded.

Two new jobs (`publish-pypi`, `publish-npm`) gated on `[build,
visual-regression-tests]`. They run on every PR/push in dry-run
mode (`twine check`, `npm publish --dry-run`) and only do real
uploads when triggered by a `release: published` event, via OIDC
trusted publishers — no PYPI_TOKEN, no NPM_TOKEN. The npm dry-run
is skipped with a notice when the version is already published,
since `npm publish --dry-run` still validates against the registry
and would otherwise fail every PR that doesn't bump the version.

Version-sanity check on real release: fails if the GitHub Release
tag doesn't match the wheel version, or if the npm version is
already on the registry.

Also added `twine check` to the `build` job so PR CI catches metadata
issues early, and Python 3.12 to the install matrix.

Inspired by the test/release workflows in widgetti/solara and
widgetti/ipyvuetify.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Document the GitHub-Release-driven flow as the primary path; keep
the legacy manual process as a deprecated fallback section.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bump python (0.12.45 → 0.12.46) and js (0.5.46 → 0.5.47) versions
to exercise the trusted-publisher dry-run path on this PR.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@maartenbreddels maartenbreddels merged commit ab06f3e into bqplot:0.12.x Apr 28, 2026
14 checks passed
@martinRenou
Copy link
Copy Markdown
Member

martinRenou commented Apr 30, 2026

@meeseeksdev backport to master

1 similar comment
@martinRenou
Copy link
Copy Markdown
Member

@meeseeksdev backport to master

@lumberbot-app
Copy link
Copy Markdown

lumberbot-app Bot commented Apr 30, 2026

Owee, I'm MrMeeseeks, Look at me.

There seem to be a conflict, please backport manually. Here are approximate instructions:

  1. Checkout backport branch and update it.
git checkout master
git pull
  1. Cherry pick the first parent branch of the this PR on top of the older branch:
git cherry-pick -x -m1 ab06f3e6ac7fceb009ed3b54211fc7a278f49746
  1. You will likely have some merge/cherry-pick conflict here, fix them and commit:
git commit -am 'Backport PR #1701: ci: publish to PyPI and npm via trusted publishers'
  1. Push to a named branch:
git push YOURFORK master:auto-backport-of-pr-1701-on-master
  1. Create a PR against branch master, I would have named this PR:

"Backport PR #1701 on branch master (ci: publish to PyPI and npm via trusted publishers)"

And apply the correct labels and milestones.

Congratulations — you did some good work! Hopefully your backport PR will be tested by the continuous integration and merged soon!

Remember to remove the Still Needs Manual Backport label once the PR gets merged.

If these instructions are inaccurate, feel free to suggest an improvement.

martinRenou added a commit that referenced this pull request Apr 30, 2026
* ci: publish to PyPI and npm via trusted publishers

Reuse the wheel/sdist/tgz artifacts already produced by the `build`
job instead of rebuilding at release time. The artifact that visual
regression tests validate is the one that gets uploaded.

Two new jobs (`publish-pypi`, `publish-npm`) gated on `[build,
visual-regression-tests]`. They run on every PR/push in dry-run
mode (`twine check`, `npm publish --dry-run`) and only do real
uploads when triggered by a `release: published` event, via OIDC
trusted publishers — no PYPI_TOKEN, no NPM_TOKEN. The npm dry-run
is skipped with a notice when the version is already published,
since `npm publish --dry-run` still validates against the registry
and would otherwise fail every PR that doesn't bump the version.

Version-sanity check on real release: fails if the GitHub Release
tag doesn't match the wheel version, or if the npm version is
already on the registry.

Also added `twine check` to the `build` job so PR CI catches metadata
issues early, and Python 3.12 to the install matrix.

Inspired by the test/release workflows in widgetti/solara and
widgetti/ipyvuetify.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs: update RELEASE.md for trusted-publisher release flow

Document the GitHub-Release-driven flow as the primary path; keep
the legacy manual process as a deprecated fallback section.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Fix conflict

* Fix dist name

---------

Co-authored-by: Maarten Breddels <maartenbreddels@gmail.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants